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