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