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