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 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 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 220 SPIRVEntry(Op TheOpCode) 221 :Module(NULL), OpCode(TheOpCode), Id(SPIRVID_INVALID), 222 Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){} 223 224 SPIRVEntry() 225 :Module(NULL), OpCode(OpNop), Id(SPIRVID_INVALID), 226 Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){} 227 228 229 virtual ~SPIRVEntry(){} 230 231 bool exist(SPIRVId)const; 232 template<class T> 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; 245 SPIRVId getId() const { assert(hasId()); return Id;} 246 SPIRVLine *getLine() const { return Line;} 247 SPIRVLinkageTypeKind getLinkageType() const; 248 Op getOpCode() const { return OpCode;} 249 SPIRVModule *getModule() const { return Module;} 250 virtual SPIRVCapVec getRequiredCapability() const { return SPIRVCapVec();} 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; 255 bool hasId() const { return !(Attrib & SPIRVEA_NOID);} 256 bool hasLine() const { return Line != nullptr;} 257 bool hasLinkageType() const; 258 bool isAtomic() const { return isAtomicOpCode(OpCode);} 259 bool isBasicBlock() const { return isLabel();} 260 bool isBuiltinCall() const { return OpCode == OpExtInst;} 261 bool isDecorate()const { return OpCode == OpDecorate;} 262 bool isMemberDecorate()const { return OpCode == OpMemberDecorate;} 263 bool isForward() const { return OpCode == OpForward;} 264 bool isLabel() const { return OpCode == OpLabel;} 265 bool isUndef() const { return OpCode == OpUndef;} 266 bool isControlBarrier() const { return OpCode == OpControlBarrier;} 267 bool isMemoryBarrier() const { return OpCode == OpMemoryBarrier;} 268 bool isVariable() const { return OpCode == OpVariable;} 269 virtual bool isInst() const { return false;} 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); 284 void setHasNoId() { Attrib |= SPIRVEA_NOID;} 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); 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. 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 334 virtual SPIRVWord getRequiredSPIRVVersion() const { return SPIRV_1_0; } 335 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 346 bool canHaveMemberDecorates() const { 347 return OpCode == OpTypeStruct || 348 OpCode == OpForward; 349 } 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: 371 SPIRVEntryNoIdGeneric(SPIRVModule *M, unsigned TheWordCount, Op OC) 372 :SPIRVEntry(M, TheWordCount, OC){ 373 setAttr(); 374 } 375 SPIRVEntryNoIdGeneric(Op OC):SPIRVEntry(OC){ 376 setAttr(); 377 } 378 protected: 379 void setAttr() { 380 setHasNoId(); 381 } 382 }; 383 384 template<Op OC> 385 class SPIRVEntryNoId:public SPIRVEntryNoIdGeneric { 386 public: 387 SPIRVEntryNoId(SPIRVModule *M, unsigned TheWordCount) 388 :SPIRVEntryNoIdGeneric(M, TheWordCount, OC){} 389 SPIRVEntryNoId():SPIRVEntryNoIdGeneric(OC){} 390 }; 391 392 template<Op TheOpCode> 393 class SPIRVEntryOpCodeOnly:public SPIRVEntryNoId<TheOpCode> { 394 public: 395 SPIRVEntryOpCodeOnly(){ 396 SPIRVEntry::WordCount = 1; 397 validate(); 398 } 399 protected: 400 _SPIRV_DEF_ENCDEC0 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) 411 : SPIRVEntryNoIdGeneric(TheModule, TheWordCount, OC), Target(TheTarget) {} 412 // Incomplete constructor 413 SPIRVAnnotationGeneric(Op OC):SPIRVEntryNoIdGeneric(OC), 414 Target(SPIRVID_INVALID){} 415 416 SPIRVId getTargetId()const { return Target;} 417 SPIRVForward *getOrCreateTarget()const; 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 427 SPIRVAnnotation(const SPIRVEntry *TheTarget, unsigned TheWordCount) 428 : SPIRVAnnotationGeneric(TheTarget->getModule(), TheWordCount, OC, 429 TheTarget->getId()) {} 430 // Incomplete constructor 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); 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 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 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 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: 482 SPIRVString(SPIRVModule *M, SPIRVId TheId, const std::string &TheStr) 483 :SPIRVEntry(M, FixedWC + getSizeInWords(TheStr), OC, TheId), Str(TheStr){} 484 SPIRVString():SPIRVEntry(OC){} 485 _SPIRV_DCL_ENCDEC 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 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 502 SPIRVLine():FileName(SPIRVID_INVALID), Line(SPIRVWORD_MAX), 503 Column(SPIRVWORD_MAX){} 504 505 SPIRVWord getColumn() const { 506 return Column; 507 } 508 509 void setColumn(SPIRVWord column) { 510 Column = column; 511 } 512 513 SPIRVId getFileName() const { 514 return FileName; 515 } 516 517 const std::string &getFileNameStr() const { 518 return get<SPIRVString>(FileName)->getStr(); 519 } 520 521 void setFileName(SPIRVId fileName) { 522 FileName = fileName; 523 } 524 525 SPIRVWord getLine() const { 526 return Line; 527 } 528 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 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 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 560 SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode) 561 :SPIRVAnnotation(TheTarget, 3), ExecMode(TheExecMode){ 562 updateModuleVersion(); 563 } 564 // Incomplete constructor 565 SPIRVExecutionMode():ExecMode(ExecutionModeInvocations){} 566 SPIRVExecutionModeKind getExecutionMode()const { return ExecMode;} 567 const std::vector<SPIRVWord>& getLiterals()const { return WordLiterals;} 568 SPIRVCapVec getRequiredCapability() const { 569 return getCapability(ExecMode); 570 } 571 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: 596 void addExecutionMode(SPIRVExecutionMode *ExecMode) { 597 ExecModes[ExecMode->getExecutionMode()] = ExecMode; 598 } 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 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: 626 SPIRVMemoryModel(SPIRVModule *M):SPIRVEntryNoId(M, 3){} 627 SPIRVMemoryModel(){} 628 _SPIRV_DCL_ENCDEC 629 void validate() const; 630 }; 631 632 class SPIRVSource:public SPIRVEntryNoId<OpSource> { 633 public: 634 SPIRVSource(SPIRVModule *M):SPIRVEntryNoId(M, 3){} 635 SPIRVSource(){} 636 _SPIRV_DCL_ENCDEC 637 }; 638 639 class SPIRVSourceExtension:public SPIRVEntryNoId<OpSourceExtension> { 640 public: 641 SPIRVSourceExtension(SPIRVModule *M, const std::string &SS); 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); 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); 660 SPIRVCapability():Kind(CapabilityMatrix){} 661 _SPIRV_DCL_ENCDEC 662 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> 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