1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 /*========================== begin_copyright_notice ============================
10 
11 This file is distributed under the University of Illinois Open Source License.
12 See LICENSE.TXT for details.
13 
14 ============================= end_copyright_notice ===========================*/
15 
16 /*========================== begin_copyright_notice ============================
17 
18 Copyright (C) 2014 Advanced Micro Devices, Inc. All rights reserved.
19 
20 Permission is hereby granted, free of charge, to any person obtaining a
21 copy of this software and associated documentation files (the "Software"),
22 to deal with the Software without restriction, including without limitation
23 the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 and/or sell copies of the Software, and to permit persons to whom the
25 Software is furnished to do so, subject to the following conditions:
26 
27 Redistributions of source code must retain the above copyright notice,
28 this list of conditions and the following disclaimers.
29 Redistributions in binary form must reproduce the above copyright notice,
30 this list of conditions and the following disclaimers in the documentation
31 and/or other materials provided with the distribution.
32 Neither the names of Advanced Micro Devices, Inc., nor the names of its
33 contributors may be used to endorse or promote products derived from this
34 Software without specific prior written permission.
35 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38 CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
41 THE SOFTWARE.
42 
43 ============================= end_copyright_notice ===========================*/
44 
45 // This file defines the base class for SPIRV entities.
46 
47 #ifndef SPIRVENTRY_HPP_
48 #define SPIRVENTRY_HPP_
49 
50 #include "SPIRVEnum.h"
51 #include "SPIRVError.h"
52 
53 #include <iostream>
54 #include <map>
55 #include <memory>
56 #include <set>
57 #include <string>
58 #include <vector>
59 #include "Probe/Assertion.h"
60 
61 namespace igc_spv{
62 
63 class SPIRVModule;
64 class SPIRVDecoder;
65 class SPIRVType;
66 class SPIRVValue;
67 class SPIRVDecorate;
68 class SPIRVDecorateId;
69 class SPIRVForward;
70 class SPIRVMemberDecorate;
71 class SPIRVLine;
72 class SPIRVString;
73 class SPIRVExtInst;
74 
75 // Add declaration of decode functions to a class.
76 // Used inside class definition.
77 #define _SPIRV_DCL_DEC \
78     void decode(std::istream &I);
79 
80 #define _SPIRV_DCL_DEC_OVERRIDE \
81     void decode(std::istream &I) override;
82 
83 // Add implementation of decode functions to a class.
84 // Used out side of class definition.
85 #define _SPIRV_IMP_DEC0(Ty)                                                              \
86     void Ty::decode(std::istream &I) {}
87 #define _SPIRV_IMP_DEC1(Ty,x)                                                            \
88     void Ty::decode(std::istream &I) { getDecoder(I) >> x;}
89 #define _SPIRV_IMP_DEC2(Ty,x,y)                                                          \
90     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y;}
91 #define _SPIRV_IMP_DEC3(Ty,x,y,z)                                                        \
92     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z;}
93 #define _SPIRV_IMP_DEC4(Ty,x,y,z,u)                                                      \
94     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u;}
95 #define _SPIRV_IMP_DEC5(Ty,x,y,z,u,v)                                                    \
96     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v;}
97 #define _SPIRV_IMP_DEC6(Ty,x,y,z,u,v,w)                                                  \
98     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> w;}
99 #define _SPIRV_IMP_DEC7(Ty,x,y,z,u,v,w,r)                                                \
100     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> w >> r;}
101 #define _SPIRV_IMP_DEC8(Ty,x,y,z,u,v,w,r,s)                                              \
102     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >>              \
103       v >> w >> r >> s;}
104 #define _SPIRV_IMP_DEC9(Ty,x,y,z,u,v,w,r,s,t)                                            \
105     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >>              \
106       v >> w >> r >> s >> t;}
107 
108 // Add definition of decode functions to a class.
109 // Used inside class definition.
110 #define _SPIRV_DEF_DEC0                                                                  \
111     void decode(std::istream &I) {}
112 #define _SPIRV_DEF_DEC1(x)                                                               \
113     void decode(std::istream &I) { getDecoder(I) >> x;}
114 #define _SPIRV_DEF_DEC1_OVERRIDE(x)                                                      \
115     void decode(std::istream &I) override { getDecoder(I) >> x;}
116 #define _SPIRV_DEF_DEC2(x,y)                                                             \
117     void decode(std::istream &I) override { getDecoder(I) >> x >> y;}
118 #define _SPIRV_DEF_DEC3(x,y,z)                                                           \
119     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z;}
120 #define _SPIRV_DEF_DEC3_OVERRIDE(x,y,z)                                                  \
121     void decode(std::istream &I) override { getDecoder(I) >> x >> y >> z;}
122 #define _SPIRV_DEF_DEC4(x,y,z,u)                                                         \
123     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u;}
124 #define _SPIRV_DEF_DEC4_OVERRIDE(x,y,z,u)                                                \
125     void decode(std::istream &I) override { getDecoder(I) >> x >> y >> z >> u;}
126 #define _SPIRV_DEF_DEC5(x,y,z,u,v)                                                       \
127     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v;}
128 #define _SPIRV_DEF_DEC6(x,y,z,u,v,w)                                                     \
129     void decode(std::istream &I) override { getDecoder(I) >> x >> y >> z >> u >> v >> w;}
130 #define _SPIRV_DEF_DEC7(x,y,z,u,v,w,r)                                                   \
131     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> w >> r;}
132 #define _SPIRV_DEF_DEC8(x,y,z,u,v,w,r,s)                                                 \
133     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >>             \
134       w >> r >> s;}
135 #define _SPIRV_DEF_DEC9(x,y,z,u,v,w,r,s,t)                                               \
136     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >>             \
137       w >> r >> s >> t;}
138 
139 /// All SPIR-V in-memory-representation entities inherits from SPIRVEntry.
140 /// Usually there are two flavors of constructors of SPIRV objects:
141 ///
142 /// 1. complete constructor: It requires all the parameters needed to create a
143 ///    SPIRV entity with complete information which can be validated. It is
144 ///    usually used by LLVM/SPIR-V translator to create SPIRV object
145 ///    corresponding to LLVM object. Such constructor calls validate() at
146 ///    the end of the construction.
147 ///
148 /// 2. incomplete constructor: For leaf classes, it has no parameters.
149 ///    It is usually called by SPIRVEntry::make(opcode) to create an incomplete
150 ///    object which should not be validated. Then setWordCount(count) is
151 ///    called to fix the size of the object if it is variable, and then the
152 ///    information is filled by the virtual function decode(istream).
153 ///    After that the object can be validated.
154 ///
155 /// To add a new SPIRV class:
156 ///
157 /// 1. It is recommended to name the class as SPIRVXXX if it has a fixed op code
158 ///    OpXXX. Although it is not mandatory, doing this facilitates adding it to
159 ///    the table of the factory function SPIRVEntry::create().
160 /// 2. Inherit from proper SPIRV class such as SPIRVType, SPIRVValue,
161 ///    SPIRVInstruction, etc.
162 /// 3. Implement virtual function decode(), validate().
163 /// 4. If the object has variable size, implement virtual function
164 ///    setWordCount().
165 /// 5. If the class has special attributes, e.g. having no id, or having no
166 ///    type as a value, set them in the constructors.
167 /// 6. Add the class to the Table of SPIRVEntry::create().
168 /// 7. Add the class to SPIRVToLLVM and LLVMToSPIRV.
169 
170 class SPIRVEntry {
171 public:
172   typedef std::vector<SPIRVCapabilityKind> CapVec;
173   enum SPIRVEntryAttrib {
174     SPIRVEA_DEFAULT     = 0,
175     SPIRVEA_NOID        = 1,      // Entry has no valid id
176     SPIRVEA_NOTYPE      = 2,      // Value has no type
177   };
178 
179   // Complete constructor for objects with id
SPIRVEntry(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVId TheId)180   SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
181       SPIRVId TheId)
182     :Module(M), OpCode(TheOpCode), Id(TheId), Attrib(SPIRVEA_DEFAULT),
183      WordCount(TheWordCount), Line(nullptr){
184     validate();
185   }
186 
187   // Complete constructor for objects without id
SPIRVEntry(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode)188   SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode)
189     :Module(M), OpCode(TheOpCode), Id(SPIRVID_INVALID), Attrib(SPIRVEA_NOID),
190      WordCount(TheWordCount), Line(nullptr){
191     validate();
192   }
193 
194   // Incomplete constructor
SPIRVEntry(Op TheOpCode)195   SPIRVEntry(Op TheOpCode)
196     :Module(NULL), OpCode(TheOpCode), Id(SPIRVID_INVALID),
197      Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){}
198 
SPIRVEntry()199   SPIRVEntry()
200     :Module(NULL), OpCode(OpNop), Id(SPIRVID_INVALID),
201      Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){}
202 
203 
~SPIRVEntry()204   virtual ~SPIRVEntry(){}
205 
206   bool exist(SPIRVId)const;
207   template<class T>
get(SPIRVId TheId)208   T* get(SPIRVId TheId)const { return static_cast<T*>(getEntry(TheId));}
209   SPIRVEntry *getEntry(SPIRVId) const;
210   SPIRVEntry *getOrCreate(SPIRVId TheId) const;
211   SPIRVValue *getValue(SPIRVId TheId)const;
212   std::vector<SPIRVValue *> getValues(const std::vector<SPIRVId>&)const;
213   std::vector<SPIRVId> getIds(const std::vector<SPIRVValue *>)const;
214   SPIRVType *getValueType(SPIRVId TheId)const;
215   std::vector<SPIRVType *> getValueTypes(const std::vector<SPIRVId>&)const;
216 
217   virtual SPIRVDecoder getDecoder(std::istream &);
218   SPIRVErrorLog &getErrorLog()const;
getId()219   SPIRVId getId() const { IGC_ASSERT(hasId()); return Id;}
getLine()220   SPIRVLine *getLine() const { return Line;}
221   SPIRVLinkageTypeKind getLinkageType() const;
getOpCode()222   Op getOpCode() const { return OpCode;}
getModule()223   SPIRVModule *getModule() const { return Module;}
getRequiredCapability()224   virtual CapVec getRequiredCapability() const { return CapVec();}
getName()225   const std::string& getName() const { return Name;}
226   bool hasDecorate(Decoration Kind, size_t Index = 0,
227       SPIRVWord *Result=0)const;
228   bool hasDecorateId(Decoration Kind, size_t Index = 0,
229       SPIRVId* Result = 0) const;
230   std::set<SPIRVWord> getDecorate(Decoration Kind, size_t Index = 0)const;
231   std::vector<SPIRVDecorate const*> getDecorations(Decoration Kind) const;
232   std::set<SPIRVId> getDecorateId(Decoration Kind, size_t Index = 0) const;
233   std::vector<SPIRVDecorateId const*> getDecorationIds(Decoration Kind) const;
234   std::vector<std::string> getDecorationStringLiteral(Decoration Kind) const;
235   std::vector<SPIRVId> getDecorationIdLiterals(Decoration Kind) const;
hasId()236   bool hasId() const { return !(Attrib & SPIRVEA_NOID);}
hasLine()237   bool hasLine() const { return Line != nullptr;}
238   bool hasLinkageType() const;
isAtomic()239   bool isAtomic() const { return isAtomicOpCode(OpCode);}
isBasicBlock()240   bool isBasicBlock() const { return isLabel();}
isBuiltinCall()241   bool isBuiltinCall() const { return OpCode == OpExtInst;}
isDecorate()242   bool isDecorate()const { return OpCode == OpDecorate;}
isDecorateId()243   bool isDecorateId() const { return OpCode == OpDecorateId; }
isMemberDecorate()244   bool isMemberDecorate()const { return OpCode == OpMemberDecorate;}
isForward()245   bool isForward() const { return OpCode == OpForward;}
isLabel()246   bool isLabel() const { return OpCode == OpLabel;}
isUndef()247   bool isUndef() const { return OpCode == OpUndef;}
isControlBarrier()248   bool isControlBarrier() const { return OpCode == OpControlBarrier;}
isMemoryBarrier()249   bool isMemoryBarrier() const { return OpCode == OpMemoryBarrier;}
isVariable()250   bool isVariable() const { return OpCode == OpVariable;}
isInst()251   virtual bool isInst() const { return false;}
252 
253   void addDecorate(const SPIRVDecorate *);
254   void addDecorate(SPIRVDecorateId*);
255   void addDecorate(Decoration Kind);
256   void addDecorate(Decoration Kind, SPIRVWord Literal);
257   void eraseDecorate(Decoration);
258   void eraseDecorateId(Decoration);
259   void addMemberDecorate(const SPIRVMemberDecorate *);
260   void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind);
261   void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind,
262       SPIRVWord Literal);
263   void eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Kind);
setHasNoId()264   void setHasNoId() { Attrib |= SPIRVEA_NOID;}
setId(SPIRVId TheId)265   void setId(SPIRVId TheId) { Id = TheId;}
266   void setLine(SPIRVLine*);
267   void setDIScope(SPIRVExtInst*);
268   SPIRVExtInst* getDIScope();
269   void setLinkageType(SPIRVLinkageTypeKind);
270   void setModule(SPIRVModule *TheModule);
271   void setName(const std::string& TheName);
setScope(SPIRVEntry * Scope)272   virtual void setScope(SPIRVEntry *Scope){};
273   void takeAnnotations(SPIRVForward *);
274   void takeDecorates(SPIRVEntry *);
275   void takeDecorateIds(SPIRVEntry*);
276   void takeMemberDecorates(SPIRVEntry *);
277   void takeLine(SPIRVEntry *);
278 
279   /// After a SPIRV entry is created during reading SPIRV binary by default
280   /// constructor, this function is called to allow the SPIRV entry to resize
281   /// its variable sized member before decoding the remaining words.
282   virtual void setWordCount(SPIRVWord TheWordCount);
283 
284   /// Create an empty SPIRV object by op code, e.g. OpTypeInt creates
285   /// SPIRVTypeInt.
286   static SPIRVEntry *create(Op);
287 
288   friend std::istream &operator>>(std::istream &I, SPIRVEntry &E);
289   virtual void decode(std::istream &I);
290 
291   friend class SPIRVDecoder;
292 
293   /// Checks the integrity of the object.
validate()294   virtual void validate()const {
295     IGC_ASSERT_MESSAGE(Module, "Invalid module");
296     IGC_ASSERT_MESSAGE(OpCode != OpNop, "Invalid op code");
297     IGC_ASSERT_MESSAGE((!hasId() || isValid(Id)), "Invalid Id");
298   }
299   void validateFunctionControlMask(SPIRVWord FCtlMask)const;
300   void validateValues(const std::vector<SPIRVId> &)const;
301   void validateBuiltin(SPIRVWord, SPIRVWord)const;
302 
hasNoScope()303   virtual bool hasNoScope() { return false; }
isOpLine()304   virtual bool isOpLine() { return false; }
isOpNoLine()305   virtual bool isOpNoLine() { return false; }
isScope()306   virtual bool isScope() { return false; }
startsScope()307   virtual bool startsScope() { return false; }
endsScope()308   virtual bool endsScope() { return false; }
isString()309   virtual bool isString() { return false; }
isConstant()310   virtual bool isConstant() { return false; }
311 
312 protected:
313   /// An entry may have multiple FuncParamAttr decorations.
314   typedef std::multimap<Decoration, const SPIRVDecorate*> DecorateMapType;
315   typedef std::multimap<Decoration, const SPIRVDecorateId*> DecorateIdMapType;
316   typedef std::map<std::pair<SPIRVWord, Decoration>,
317       const SPIRVMemberDecorate*> MemberDecorateMapType;
318 
canHaveMemberDecorates()319   bool canHaveMemberDecorates() const {
320     return OpCode == OpTypeStruct ||
321         OpCode == OpForward;
322   }
getMemberDecorates()323   MemberDecorateMapType& getMemberDecorates() {
324     IGC_ASSERT(canHaveMemberDecorates());
325     return MemberDecorates;
326   }
327 
328   SPIRVModule *Module;
329   Op OpCode;
330   SPIRVId Id;
331   std::string Name;
332   unsigned Attrib;
333   SPIRVWord WordCount;
334 
335   DecorateMapType Decorates;
336   DecorateIdMapType DecorateIds;
337   MemberDecorateMapType MemberDecorates;
338   SPIRVLine *Line;
339   SPIRVExtInst* diScope = nullptr;
340 };
341 
342 class SPIRVEntryNoIdGeneric:public SPIRVEntry {
343 public:
SPIRVEntryNoIdGeneric(SPIRVModule * M,unsigned TheWordCount,Op OC)344   SPIRVEntryNoIdGeneric(SPIRVModule *M, unsigned TheWordCount, Op OC)
345     :SPIRVEntry(M, TheWordCount, OC){
346     setAttr();
347   }
SPIRVEntryNoIdGeneric(Op OC)348   SPIRVEntryNoIdGeneric(Op OC):SPIRVEntry(OC){
349     setAttr();
350   }
351 protected:
setAttr()352   void setAttr() {
353     setHasNoId();
354   }
355 };
356 
357 template<Op OC>
358 class SPIRVEntryNoId:public SPIRVEntryNoIdGeneric {
359 public:
SPIRVEntryNoId(SPIRVModule * M,unsigned TheWordCount)360   SPIRVEntryNoId(SPIRVModule *M, unsigned TheWordCount)
361     :SPIRVEntryNoIdGeneric(M, TheWordCount, OC){}
SPIRVEntryNoId()362   SPIRVEntryNoId():SPIRVEntryNoIdGeneric(OC){}
363 };
364 
365 template<Op TheOpCode>
366 class SPIRVEntryOpCodeOnly:public SPIRVEntryNoId<TheOpCode> {
367 public:
SPIRVEntryOpCodeOnly()368   SPIRVEntryOpCodeOnly(){
369     SPIRVEntry::WordCount = 1;
370     validate();
371   }
372 protected:
373   _SPIRV_DEF_DEC0
validate()374   void validate()const {
375     IGC_ASSERT(isValid(SPIRVEntry::OpCode));
376   }
377 };
378 
379 class SPIRVAnnotationGeneric:public SPIRVEntryNoIdGeneric {
380 public:
381   // Complete constructor
SPIRVAnnotationGeneric(const SPIRVEntry * TheTarget,unsigned TheWordCount,Op OC)382   SPIRVAnnotationGeneric(const SPIRVEntry *TheTarget, unsigned TheWordCount,
383       Op OC)
384       :SPIRVEntryNoIdGeneric((TheTarget ? TheTarget->getModule() : NULL), TheWordCount, OC),
385      Target(TheTarget ? TheTarget->getId() : SPIRVID_INVALID){}
386   // Incomplete constructor
SPIRVAnnotationGeneric(Op OC)387   SPIRVAnnotationGeneric(Op OC):SPIRVEntryNoIdGeneric(OC),
388       Target(SPIRVID_INVALID){}
389 
getTargetId()390   SPIRVId getTargetId()const { return Target;}
391   SPIRVForward *getOrCreateTarget()const;
setTargetId(SPIRVId T)392   void setTargetId(SPIRVId T) { Target = T;}
393 protected:
394   SPIRVId Target;
395 };
396 
397 template<Op OC>
398 class SPIRVAnnotation:public SPIRVAnnotationGeneric {
399 public:
400   // Complete constructor
SPIRVAnnotation(const SPIRVEntry * TheTarget,unsigned TheWordCount)401   SPIRVAnnotation(const SPIRVEntry *TheTarget, unsigned TheWordCount)
402     :SPIRVAnnotationGeneric(TheTarget, TheWordCount, OC){}
403   // Incomplete constructor
SPIRVAnnotation()404   SPIRVAnnotation():SPIRVAnnotationGeneric(OC){}
405 };
406 
407 class SPIRVEntryPoint:public SPIRVAnnotation<OpEntryPoint> {
408 public:
409   SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind,
410       SPIRVId TheId, const std::string &TheName);
SPIRVEntryPoint()411   SPIRVEntryPoint():ExecModel(ExecutionModelKernel){}
412   _SPIRV_DCL_DEC
413 protected:
414   SPIRVExecutionModelKind ExecModel;
415   std::string Name;
getRequiredCapability()416   CapVec getRequiredCapability() const {
417     return getVec(getCapability(ExecModel));
418   }
419 };
420 
421 
422 class SPIRVName:public SPIRVAnnotation<OpName> {
423 public:
424   // Complete constructor
425   SPIRVName(const SPIRVEntry *TheTarget, const std::string& TheStr);
426   // Incomplete constructor
SPIRVName()427   SPIRVName(){}
428 protected:
429   _SPIRV_DCL_DEC
430   void validate() const;
431 
432   std::string Str;
433 };
434 
435 class SPIRVMemberName:public SPIRVAnnotation<OpName> {
436 public:
437   static const SPIRVWord FixedWC = 3;
438   // Complete constructor
SPIRVMemberName(const SPIRVEntry * TheTarget,SPIRVWord TheMemberNumber,const std::string & TheStr)439   SPIRVMemberName(const SPIRVEntry *TheTarget, SPIRVWord TheMemberNumber,
440       const std::string& TheStr)
441     :SPIRVAnnotation(TheTarget, FixedWC + getSizeInWords(TheStr)),
442      MemberNumber(TheMemberNumber), Str(TheStr){
443     validate();
444   }
445   // Incomplete constructor
SPIRVMemberName()446   SPIRVMemberName():MemberNumber(SPIRVWORD_MAX){}
447 protected:
448   _SPIRV_DCL_DEC
449   void validate() const;
450   SPIRVWord MemberNumber;
451   std::string Str;
452 };
453 
454 class SPIRVString:public SPIRVEntry {
455   static const Op OC = OpString;
456   static const SPIRVWord FixedWC = 2;
457 public:
SPIRVString(SPIRVModule * M,SPIRVId TheId,const std::string & TheStr)458   SPIRVString(SPIRVModule *M, SPIRVId TheId, const std::string &TheStr)
459     :SPIRVEntry(M, FixedWC + getSizeInWords(TheStr), OC, TheId), Str(TheStr){}
SPIRVString()460   SPIRVString():SPIRVEntry(OC){}
461   _SPIRV_DCL_DEC
getStr()462   const std::string &getStr()const { return Str;}
isString()463   bool isString() { return true; }
464 protected:
465   std::string Str;
466 };
467 
468 class SPIRVLine:public SPIRVEntryNoIdGeneric {
469 public:
470   static const SPIRVWord WC = 5;
471   // Complete constructor
SPIRVLine(SPIRVModule * M,SPIRVId TheFileName,SPIRVWord TheLine,SPIRVWord TheColumn)472   SPIRVLine(SPIRVModule* M, SPIRVId TheFileName, SPIRVWord TheLine,
473       SPIRVWord TheColumn)
474     :SPIRVEntryNoIdGeneric(M, WC, OpLine), FileName(TheFileName), Line(TheLine),
475      Column(TheColumn){
476     validate();
477   }
478   // Incomplete constructor
SPIRVLine()479   SPIRVLine(): SPIRVEntryNoIdGeneric(OpLine), FileName(SPIRVID_INVALID),
480     Line(SPIRVWORD_MAX), Column(SPIRVWORD_MAX) {}
481 
getColumn()482   SPIRVWord getColumn() const {
483     return Column;
484   }
485 
setColumn(SPIRVWord column)486   void setColumn(SPIRVWord column) {
487     Column = column;
488   }
489 
getFileName()490   SPIRVId getFileName() const {
491     return FileName;
492   }
493 
getFileNameStr()494   const std::string &getFileNameStr() const {
495     return get<SPIRVString>(FileName)->getStr();
496   }
497 
setFileName(SPIRVId fileName)498   void setFileName(SPIRVId fileName) {
499     FileName = fileName;
500   }
501 
getLine()502   SPIRVWord getLine() const {
503     return Line;
504   }
505 
setLine(SPIRVWord line)506   void setLine(SPIRVWord line) {
507     Line = line;
508   }
509 
isOpLine()510   bool isOpLine() { return true; }
511 
512 protected:
513   _SPIRV_DCL_DEC
514   void validate() const;
515   SPIRVId FileName;
516   SPIRVWord Line;
517   SPIRVWord Column;
518 };
519 
520 class SPIRVNoLine :public SPIRVEntryNoIdGeneric {
521 public:
522     static const SPIRVWord WC = 1;
523     // Complete constructor
SPIRVNoLine(SPIRVModule * M)524     SPIRVNoLine(SPIRVModule* M)
525         :SPIRVEntryNoIdGeneric(M, WC, OpNoLine)
526     {
527         validate();
528     }
529     // Incomplete constructor
SPIRVNoLine()530     SPIRVNoLine() : SPIRVEntryNoIdGeneric(OpNoLine) {}
531 
isOpLine()532     bool isOpLine() { return true; }
533 
534 protected:
535     _SPIRV_DCL_DEC
536         void validate() const;
537 };
538 
539 class SPIRVExecutionMode:public SPIRVAnnotation<OpExecutionMode> {
540 public:
541   // Complete constructor for LocalSize, LocalSizeHint
SPIRVExecutionMode(SPIRVEntry * TheTarget,SPIRVExecutionModeKind TheExecMode,SPIRVWord x,SPIRVWord y,SPIRVWord z)542   SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode,
543       SPIRVWord x, SPIRVWord y, SPIRVWord z)
544   :SPIRVAnnotation(TheTarget, 6), ExecMode(TheExecMode){
545     WordLiterals.push_back(x);
546     WordLiterals.push_back(y);
547     WordLiterals.push_back(z);
548   }
549   // Complete constructor for VecTypeHint
SPIRVExecutionMode(SPIRVEntry * TheTarget,SPIRVExecutionModeKind TheExecMode,SPIRVWord code)550   SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode,
551       SPIRVWord code)
552   :SPIRVAnnotation(TheTarget, 4),
553    ExecMode(TheExecMode) {
554     WordLiterals.push_back(code);
555   }
556   // Complete constructor for ContractionOff
SPIRVExecutionMode(SPIRVEntry * TheTarget,SPIRVExecutionModeKind TheExecMode)557   SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode)
558   :SPIRVAnnotation(TheTarget, 3), ExecMode(TheExecMode){}
559   // Incomplete constructor
SPIRVExecutionMode()560   SPIRVExecutionMode():ExecMode(ExecutionModeCount){}
getExecutionMode()561   SPIRVExecutionModeKind getExecutionMode()const { return ExecMode;}
getLiterals()562   const std::vector<SPIRVWord>& getLiterals()const { return WordLiterals;}
getRequiredCapability()563   CapVec getRequiredCapability() const {
564     return getVec(getCapability(ExecMode));
565   }
566 protected:
567   _SPIRV_DCL_DEC
568   SPIRVExecutionModeKind ExecMode;
569   std::vector<SPIRVWord> WordLiterals;
570 };
571 
572 
573 class SPIRVComponentExecutionModes {
574   typedef std::map<SPIRVExecutionModeKind, SPIRVExecutionMode*>
575     SPIRVExecutionModeMap;
576 public:
addExecutionMode(SPIRVExecutionMode * ExecMode)577   void addExecutionMode(SPIRVExecutionMode *ExecMode) {
578     ExecModes[ExecMode->getExecutionMode()] = ExecMode;
579   }
getExecutionMode(SPIRVExecutionModeKind EMK)580   SPIRVExecutionMode *getExecutionMode(SPIRVExecutionModeKind EMK)const {
581     auto Loc = ExecModes.find(EMK);
582     if (Loc == ExecModes.end())
583       return nullptr;
584     return Loc->second;
585   }
586 protected:
587   SPIRVExecutionModeMap ExecModes;
588 };
589 
590 class SPIRVExtInstImport:public SPIRVEntry {
591 public:
592   const static Op OC = OpExtInstImport;
593   // Complete constructor
594   SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId,
595       const std::string& TheStr);
596   // Incomplete constructor
SPIRVExtInstImport()597   SPIRVExtInstImport():SPIRVEntry(OC){}
598 protected:
599   _SPIRV_DCL_DEC
600   void validate() const;
601 
602   std::string Str;
603 };
604 
605 class SPIRVMemoryModel:public SPIRVEntryNoId<OpMemoryModel> {
606 public:
SPIRVMemoryModel(SPIRVModule * M)607   SPIRVMemoryModel(SPIRVModule *M):SPIRVEntryNoId(M, 3){}
SPIRVMemoryModel()608   SPIRVMemoryModel(){}
609   _SPIRV_DCL_DEC
610   void validate() const;
611 };
612 
613 class SPIRVSource:public SPIRVEntryNoId<OpSource> {
614 public:
SPIRVSource(SPIRVModule * M)615   SPIRVSource(SPIRVModule *M):SPIRVEntryNoId(M, 3){}
SPIRVSource()616   SPIRVSource(){}
617   _SPIRV_DCL_DEC
618 };
619 
620 class SPIRVSourceExtension:public SPIRVEntryNoId<OpSourceExtension> {
621 public:
622   SPIRVSourceExtension(SPIRVModule *M, const std::string &SS);
SPIRVSourceExtension()623   SPIRVSourceExtension(){}
624   _SPIRV_DCL_DEC
625 private:
626   std::string S;
627 };
628 
629 class SPIRVExtension:public SPIRVEntryNoId<OpExtension> {
630 public:
631   SPIRVExtension(SPIRVModule *M, const std::string &SS);
SPIRVExtension()632   SPIRVExtension(){}
633   _SPIRV_DCL_DEC
634 private:
635   std::string S;
636 };
637 
638 class SPIRVCapability:public SPIRVEntryNoId<OpCapability> {
639 public:
640   SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K);
SPIRVCapability()641   SPIRVCapability():Kind(CapabilityNone){}
642   _SPIRV_DCL_DEC
643 private:
644   SPIRVCapabilityKind Kind;
645 };
646 
647 class SPIRVModuleProcessed: public SPIRVEntryNoId<OpModuleProcessed> {
648 public:
SPIRVModuleProcessed(SPIRVModule * M)649   SPIRVModuleProcessed(SPIRVModule *M):SPIRVEntryNoId(M, 2){}
SPIRVModuleProcessed()650   SPIRVModuleProcessed(){}
651   _SPIRV_DCL_DEC
652 private:
653   std::string S;
654 };
655 
656 template<class T>
bcast(SPIRVEntry * E)657 T* bcast(SPIRVEntry *E) {
658   return static_cast<T*>(E);
659 }
660 
isa(SPIRVEntry * E)661 template <igc_spv::Op OC> bool isa(SPIRVEntry *E) {
662   return E ? E->getOpCode() == OC : false;
663 }
664 
665 template <igc_spv::Op OC>
666 class SPIRVContinuedInstINTELBase : public SPIRVEntryNoId<OC> {
667 public:
668     template <igc_spv::Op _OC, class T = void>
669     using EnableIfCompositeConst =
670         typename std::enable_if_t<_OC == OpConstantCompositeContinuedINTEL ||
671         _OC ==
672         OpSpecConstantCompositeContinuedINTEL,
673         T>;
674     // Complete constructor
SPIRVContinuedInstINTELBase(SPIRVModule * M,const std::vector<SPIRVValue * > & TheElements)675     SPIRVContinuedInstINTELBase(SPIRVModule* M,
676         const std::vector<SPIRVValue*>& TheElements)
677         : SPIRVEntryNoId<OC>(M, TheElements.size() + 1) {
678 
679         Elements = SPIRVEntry::getIds(TheElements);
680         validate();
681     }
682 
SPIRVContinuedInstINTELBase(SPIRVModule * M,unsigned NumOfElements)683     SPIRVContinuedInstINTELBase(SPIRVModule* M, unsigned NumOfElements)
684         : SPIRVEntryNoId<OC>(M, NumOfElements + 1) {
685         Elements.resize(NumOfElements, SPIRVID_INVALID);
686         validate();
687     }
688 
689     // Incomplete constructor
SPIRVContinuedInstINTELBase()690     SPIRVContinuedInstINTELBase() : SPIRVEntryNoId<OC>() {}
691 
692     template <igc_spv::Op OPC = OC>
getElements()693     EnableIfCompositeConst<OPC, std::vector<SPIRVValue*>> getElements() const {
694         return SPIRVEntry::getValues(Elements);
695     }
696 
getNumElements()697     SPIRVWord getNumElements() const { return Elements.size(); }
698 
699 protected:
700     void validate() const override;
701 
setWordCount(SPIRVWord WordCount)702     void setWordCount(SPIRVWord WordCount) override {
703         SPIRVEntry::setWordCount(WordCount);
704         Elements.resize(WordCount - 1);
705     }
706     _SPIRV_DCL_DEC_OVERRIDE
707 
708     std::vector<SPIRVId> Elements;
709 };
710 
711 class SPIRVTypeStructContinuedINTEL
712     : public SPIRVContinuedInstINTELBase<OpTypeStructContinuedINTEL> {
713 public:
714     constexpr static Op OC = OpTypeStructContinuedINTEL;
715     // Complete constructor
SPIRVTypeStructContinuedINTEL(SPIRVModule * M,unsigned NumOfElements)716     SPIRVTypeStructContinuedINTEL(SPIRVModule * M, unsigned NumOfElements)
717         : SPIRVContinuedInstINTELBase<OC>(M, NumOfElements) {}
718 
719     // Incomplete constructor
SPIRVTypeStructContinuedINTEL()720     SPIRVTypeStructContinuedINTEL() : SPIRVContinuedInstINTELBase<OC>() {}
721 
setElementId(size_t I,SPIRVId Id)722     void setElementId(size_t I, SPIRVId Id) { Elements[I] = Id; }
723 
724     SPIRVType* getMemberType(size_t I) const;
725 };
726 using SPIRVConstantCompositeContinuedINTEL =
727 SPIRVContinuedInstINTELBase<OpConstantCompositeContinuedINTEL>;
728 using SPIRVSpecConstantCompositeContinuedINTEL =
729 SPIRVContinuedInstINTELBase<OpSpecConstantCompositeContinuedINTEL>;
730 
731 template <igc_spv::Op OpCode> struct InstToContinued;
732 
733 template <> struct InstToContinued<OpTypeStruct> {
734     using Type = SPIRVTypeStructContinuedINTEL *;
735     constexpr static igc_spv::Op OpCode = OpTypeStructContinuedINTEL;
736 };
737 
738 template <> struct InstToContinued<OpConstantComposite> {
739     using Type = SPIRVConstantCompositeContinuedINTEL *;
740     constexpr static igc_spv::Op OpCode = OpConstantCompositeContinuedINTEL;
741 };
742 
743 template <> struct InstToContinued<OpSpecConstantComposite> {
744     using Type = SPIRVSpecConstantCompositeContinuedINTEL *;
745     constexpr static igc_spv::Op OpCode = OpSpecConstantCompositeContinuedINTEL;
746 };
747 
748 
749 // ToDo: The following typedef's are place holders for SPIRV entity classes
750 // to be implemented.
751 // Each time a new class is implemented, remove the corresponding typedef.
752 // This is also an indication of how much work is left.
753 #define _SPIRV_OP(x, ...) typedef SPIRVEntryOpCodeOnly<Op##x> SPIRV##x;
754 _SPIRV_OP(Nop)
755 _SPIRV_OP(SourceContinued)
756 _SPIRV_OP(TypeMatrix)
757 _SPIRV_OP(TypeRuntimeArray)
758 _SPIRV_OP(ImageTexelPointer)
759 _SPIRV_OP(ImageSampleDrefImplicitLod)
760 _SPIRV_OP(ImageSampleDrefExplicitLod)
761 _SPIRV_OP(ImageSampleProjImplicitLod)
762 _SPIRV_OP(ImageSampleProjExplicitLod)
763 _SPIRV_OP(ImageSampleProjDrefImplicitLod)
764 _SPIRV_OP(ImageSampleProjDrefExplicitLod)
765 _SPIRV_OP(ImageFetch)
766 _SPIRV_OP(ImageGather)
767 _SPIRV_OP(ImageDrefGather)
768 _SPIRV_OP(QuantizeToF16)
769 _SPIRV_OP(Transpose)
770 _SPIRV_OP(ArrayLength)
771 _SPIRV_OP(MatrixTimesScalar)
772 _SPIRV_OP(VectorTimesMatrix)
773 _SPIRV_OP(MatrixTimesVector)
774 _SPIRV_OP(MatrixTimesMatrix)
775 _SPIRV_OP(OuterProduct)
776 _SPIRV_OP(IAddCarry)
777 _SPIRV_OP(ISubBorrow)
778 _SPIRV_OP(BitFieldInsert)
779 _SPIRV_OP(BitFieldSExtract)
780 _SPIRV_OP(BitFieldUExtract)
781 _SPIRV_OP(DPdx)
782 _SPIRV_OP(DPdy)
783 _SPIRV_OP(Fwidth)
784 _SPIRV_OP(DPdxFine)
785 _SPIRV_OP(DPdyFine)
786 _SPIRV_OP(FwidthFine)
787 _SPIRV_OP(DPdxCoarse)
788 _SPIRV_OP(DPdyCoarse)
789 _SPIRV_OP(FwidthCoarse)
790 _SPIRV_OP(EmitVertex)
791 _SPIRV_OP(EndPrimitive)
792 _SPIRV_OP(EmitStreamVertex)
793 _SPIRV_OP(EndStreamPrimitive)
794 _SPIRV_OP(Kill)
795 _SPIRV_OP(ImageSparseSampleImplicitLod)
796 _SPIRV_OP(ImageSparseSampleExplicitLod)
797 _SPIRV_OP(ImageSparseSampleDrefImplicitLod)
798 _SPIRV_OP(ImageSparseSampleDrefExplicitLod)
799 _SPIRV_OP(ImageSparseSampleProjImplicitLod)
800 _SPIRV_OP(ImageSparseSampleProjExplicitLod)
801 _SPIRV_OP(ImageSparseSampleProjDrefImplicitLod)
802 _SPIRV_OP(ImageSparseSampleProjDrefExplicitLod)
803 _SPIRV_OP(ImageSparseFetch)
804 _SPIRV_OP(ImageSparseGather)
805 _SPIRV_OP(ImageSparseDrefGather)
806 _SPIRV_OP(ImageSparseTexelsResident)
807 #undef _SPIRV_OP
808 
809 }
810 #endif /* SPIRVENTRY_HPP_ */
811