1 //===- SPIRVType.h - Class to represent a SPIR-V Type -----------*- 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 types defined in SPIRV spec with op codes. 37 /// 38 /// The name of the SPIR-V types follow the op code name in the spec, e.g. 39 /// SPIR-V type with op code name OpTypeInt is named as SPIRVTypeInt. This is 40 /// for readability and ease of using macro to handle types. 41 /// 42 //===----------------------------------------------------------------------===// 43 44 #ifndef SPIRVTYPE_HPP_ 45 #define SPIRVTYPE_HPP_ 46 47 #include "SPIRVEntry.h" 48 #include "SPIRVStream.h" 49 50 #include <cassert> 51 #include <tuple> 52 #include <vector> 53 #include <map> 54 #include <iostream> 55 56 namespace SPIRV{ 57 58 class SPIRVType: public SPIRVEntry { 59 public: 60 // Complete constructor 61 SPIRVType(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, 62 SPIRVId TheId) 63 :SPIRVEntry(M, TheWordCount, TheOpCode, TheId){} 64 // Incomplete constructor 65 SPIRVType(Op TheOpCode):SPIRVEntry(TheOpCode){} 66 67 SPIRVType *getArrayElementType() const; 68 uint64_t getArrayLength() const; 69 unsigned getBitWidth() const; 70 unsigned getFloatBitWidth() const; 71 SPIRVType *getFunctionReturnType() const; 72 unsigned getIntegerBitWidth() const; 73 SPIRVType *getPointerElementType() const; 74 SPIRVStorageClassKind getPointerStorageClass() const; 75 SPIRVType *getStructMemberType(size_t) const; 76 SPIRVWord getStructMemberCount() const; 77 SPIRVWord getVectorComponentCount() const; 78 SPIRVType *getVectorComponentType() const; 79 80 bool isTypeVoid() const; 81 bool isTypeArray() const; 82 bool isTypeBool() const; 83 bool isTypeComposite() const; 84 bool isTypeEvent() const; 85 bool isTypeDeviceEvent() const; 86 bool isTypeReserveId() const; 87 bool isTypeFloat(unsigned Bits = 0) const; 88 bool isTypeImage() const; 89 bool isTypeOCLImage() const; 90 bool isTypePipe()const; 91 bool isTypePipeStorage() const; 92 bool isTypeInt(unsigned Bits = 0) const; 93 bool isTypeOpaque() const; 94 bool isTypePointer() const; 95 bool isTypeSampler() const; 96 bool isTypeStruct() const; 97 bool isTypeVector() const; 98 bool isTypeVectorInt() const; 99 bool isTypeVectorFloat() const; 100 bool isTypeVectorBool() const; 101 bool isTypeVectorOrScalarInt() const; 102 bool isTypeVectorOrScalarFloat() const; 103 bool isTypeVectorOrScalarBool() const; 104 }; 105 106 class SPIRVTypeVoid:public SPIRVType { 107 public: 108 // Complete constructor 109 SPIRVTypeVoid(SPIRVModule *M, SPIRVId TheId) 110 :SPIRVType(M, 2, OpTypeVoid, TheId){} 111 // Incomplete constructor 112 SPIRVTypeVoid():SPIRVType(OpTypeVoid){} 113 protected: 114 _SPIRV_DEF_ENCDEC1(Id) 115 }; 116 117 class SPIRVTypeBool:public SPIRVType { 118 public: 119 // Complete constructor 120 SPIRVTypeBool(SPIRVModule *M, SPIRVId TheId) 121 :SPIRVType(M, 2, OpTypeBool, TheId){} 122 // Incomplete constructor 123 SPIRVTypeBool():SPIRVType(OpTypeBool){} 124 protected: 125 _SPIRV_DEF_ENCDEC1(Id) 126 }; 127 128 class SPIRVTypeInt:public SPIRVType { 129 public: 130 static const Op OC = OpTypeInt; 131 // Complete constructor 132 SPIRVTypeInt(SPIRVModule *M, SPIRVId TheId, unsigned TheBitWidth, 133 bool ItIsSigned) 134 :SPIRVType(M, 4, OC , TheId), BitWidth(TheBitWidth), 135 IsSigned(ItIsSigned){ 136 validate(); 137 } 138 // Incomplete constructor 139 SPIRVTypeInt():SPIRVType(OC), BitWidth(0), IsSigned(false){} 140 141 unsigned getBitWidth() const { return BitWidth;} 142 bool isSigned() const { return IsSigned;} 143 SPIRVCapVec getRequiredCapability() const { 144 SPIRVCapVec CV; 145 if (isTypeInt(16)) 146 CV.push_back(CapabilityInt16); 147 else if (isTypeInt(64)) 148 CV.push_back(CapabilityInt64); 149 return CV; 150 } 151 152 protected: 153 _SPIRV_DEF_ENCDEC3(Id, BitWidth, IsSigned) 154 void validate()const { 155 SPIRVEntry::validate(); 156 assert(BitWidth > 1 && BitWidth <= 64 && "Invalid bit width"); 157 } 158 private: 159 unsigned BitWidth; // Bit width 160 bool IsSigned; // Whether it is signed 161 }; 162 163 class SPIRVTypeFloat:public SPIRVType { 164 public: 165 static const Op OC = OpTypeFloat; 166 // Complete constructor 167 SPIRVTypeFloat(SPIRVModule *M, SPIRVId TheId, unsigned TheBitWidth) 168 :SPIRVType(M, 3, OC, TheId), BitWidth(TheBitWidth){} 169 // Incomplete constructor 170 SPIRVTypeFloat():SPIRVType(OC), BitWidth(0){} 171 172 unsigned getBitWidth() const { return BitWidth;} 173 174 SPIRVCapVec getRequiredCapability() const { 175 SPIRVCapVec CV; 176 if (isTypeFloat(16)) 177 CV.push_back(CapabilityFloat16); 178 else if (isTypeFloat(64)) 179 CV.push_back(CapabilityFloat64); 180 return CV; 181 } 182 183 184 protected: 185 _SPIRV_DEF_ENCDEC2(Id, BitWidth) 186 void validate()const { 187 SPIRVEntry::validate(); 188 assert(BitWidth >= 16 && BitWidth <= 64 && "Invalid bit width"); 189 } 190 private: 191 unsigned BitWidth; // Bit width 192 }; 193 194 class SPIRVTypePointer:public SPIRVType { 195 public: 196 // Complete constructor 197 SPIRVTypePointer(SPIRVModule *M, SPIRVId TheId, 198 SPIRVStorageClassKind TheStorageClass, 199 SPIRVType *ElementType) 200 :SPIRVType(M, 4, OpTypePointer, TheId), ElemStorageClass(TheStorageClass), 201 ElemTypeId(ElementType->getId()){ 202 validate(); 203 } 204 // Incomplete constructor 205 SPIRVTypePointer():SPIRVType(OpTypePointer), 206 ElemStorageClass(StorageClassFunction), 207 ElemTypeId(0){} 208 209 SPIRVType *getElementType() const { 210 return static_cast<SPIRVType *>(getEntry(ElemTypeId)); 211 } 212 SPIRVStorageClassKind getStorageClass() const { return ElemStorageClass;} 213 SPIRVCapVec getRequiredCapability() const { 214 auto Cap = getVec(CapabilityAddresses); 215 if (getElementType()->isTypeFloat(16)) 216 Cap.push_back(CapabilityFloat16Buffer); 217 auto C = getCapability(ElemStorageClass); 218 Cap.insert(Cap.end(), C.begin(), C.end()); 219 return Cap; 220 } 221 virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const { 222 return std::vector<SPIRVEntry*>(1, getEntry(ElemTypeId)); 223 } 224 225 protected: 226 _SPIRV_DEF_ENCDEC3(Id, ElemStorageClass, ElemTypeId) 227 void validate()const { 228 SPIRVEntry::validate(); 229 assert(isValid(ElemStorageClass)); 230 } 231 private: 232 SPIRVStorageClassKind ElemStorageClass; // Storage Class 233 SPIRVId ElemTypeId; 234 }; 235 236 class SPIRVTypeForwardPointer : public SPIRVEntryNoId<OpTypeForwardPointer> { 237 public: 238 SPIRVTypeForwardPointer(SPIRVModule *M, SPIRVTypePointer *Pointer, 239 SPIRVStorageClassKind SC) 240 : SPIRVEntryNoId(M, 3), Pointer(Pointer), SC(SC) {} 241 242 SPIRVTypeForwardPointer() 243 : Pointer(nullptr), SC(StorageClassUniformConstant) {} 244 245 SPIRVTypePointer *getPointer() const { return Pointer; } 246 _SPIRV_DCL_ENCDEC 247 private: 248 SPIRVTypePointer *Pointer; 249 SPIRVStorageClassKind SC; 250 }; 251 252 class SPIRVTypeVector:public SPIRVType { 253 public: 254 // Complete constructor 255 SPIRVTypeVector(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheCompType, 256 SPIRVWord TheCompCount) 257 :SPIRVType(M, 4, OpTypeVector, TheId), CompType(TheCompType), 258 CompCount(TheCompCount){ 259 validate(); 260 } 261 // Incomplete constructor 262 SPIRVTypeVector():SPIRVType(OpTypeVector), CompType(nullptr), 263 CompCount(0){} 264 265 SPIRVType *getComponentType() const { return CompType;} 266 SPIRVWord getComponentCount() const { return CompCount;} 267 bool isValidIndex(SPIRVWord Index) const { return Index < CompCount;} 268 SPIRVCapVec getRequiredCapability() const { 269 SPIRVCapVec V(getComponentType()->getRequiredCapability()); 270 if (CompCount >= 8) 271 V.push_back(CapabilityVector16); 272 return V; 273 } 274 275 virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const { 276 return std::vector<SPIRVEntry*>(1, CompType); 277 } 278 279 protected: 280 _SPIRV_DEF_ENCDEC3(Id, CompType, CompCount) 281 void validate()const { 282 SPIRVEntry::validate(); 283 CompType->validate(); 284 assert(CompCount == 2 || CompCount == 3 || CompCount == 4 || 285 CompCount == 8 || CompCount == 16); 286 } 287 private: 288 SPIRVType *CompType; // Component Type 289 SPIRVWord CompCount; // Component Count 290 }; 291 292 class SPIRVConstant; 293 class SPIRVTypeArray:public SPIRVType { 294 public: 295 // Complete constructor 296 SPIRVTypeArray(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheElemType, 297 SPIRVConstant* TheLength); 298 // Incomplete constructor 299 SPIRVTypeArray():SPIRVType(OpTypeArray), ElemType(nullptr), 300 Length(SPIRVID_INVALID){} 301 302 SPIRVType *getElementType() const { return ElemType;} 303 SPIRVConstant *getLength() const; 304 SPIRVCapVec getRequiredCapability() const { 305 return getElementType()->getRequiredCapability(); 306 } 307 virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const { 308 std::vector<SPIRVEntry*> Operands(2, ElemType); 309 Operands[1] = (SPIRVEntry*)getLength(); 310 return Operands; 311 } 312 313 314 protected: 315 _SPIRV_DCL_ENCDEC 316 void validate()const; 317 private: 318 SPIRVType *ElemType; // Element Type 319 SPIRVId Length; // Array Length 320 }; 321 322 class SPIRVTypeOpaque:public SPIRVType { 323 public: 324 // Complete constructor 325 SPIRVTypeOpaque(SPIRVModule *M, SPIRVId TheId, const std::string& TheName) 326 :SPIRVType(M, 2 + getSizeInWords(TheName), OpTypeOpaque, TheId) { 327 Name = TheName; 328 validate(); 329 } 330 // Incomplete constructor 331 SPIRVTypeOpaque():SPIRVType(OpTypeOpaque){} 332 333 protected: 334 _SPIRV_DEF_ENCDEC2(Id, Name) 335 void validate()const { 336 SPIRVEntry::validate(); 337 } 338 }; 339 340 struct SPIRVTypeImageDescriptor { 341 SPIRVImageDimKind Dim; 342 SPIRVWord Depth; 343 SPIRVWord Arrayed; 344 SPIRVWord MS; 345 SPIRVWord Sampled; 346 SPIRVWord Format; 347 static std::tuple<std::tuple<SPIRVImageDimKind, SPIRVWord, SPIRVWord, SPIRVWord, 348 SPIRVWord>, SPIRVWord> 349 getAsTuple (const SPIRVTypeImageDescriptor &Desc) { 350 return std::make_tuple(std::make_tuple(Desc.Dim, Desc.Depth, Desc.Arrayed, 351 Desc.MS, Desc.Sampled), Desc.Format); 352 } 353 SPIRVTypeImageDescriptor():Dim(Dim1D), Depth(0), Arrayed(0), 354 MS(0), Sampled(0), Format(0){} 355 SPIRVTypeImageDescriptor(SPIRVImageDimKind Dim, SPIRVWord Cont, SPIRVWord Arr, 356 SPIRVWord Comp, SPIRVWord Mult, SPIRVWord F):Dim(Dim), Depth(Cont), 357 Arrayed(Arr), MS(Comp), Sampled(Mult), Format(F){} 358 }; 359 360 template<> inline void 361 SPIRVMap<std::string, SPIRVTypeImageDescriptor>::init() { 362 #define _SPIRV_OP(x,...) {SPIRVTypeImageDescriptor S(__VA_ARGS__); \ 363 add(#x, S);} 364 _SPIRV_OP(image1d_t, Dim1D, 0, 0, 0, 0, 0) 365 _SPIRV_OP(image1d_buffer_t, DimBuffer, 0, 0, 0, 0, 0) 366 _SPIRV_OP(image1d_array_t, Dim1D, 0, 1, 0, 0, 0) 367 _SPIRV_OP(image2d_t, Dim2D, 0, 0, 0, 0, 0) 368 _SPIRV_OP(image2d_array_t, Dim2D, 0, 1, 0, 0, 0) 369 _SPIRV_OP(image2d_depth_t, Dim2D, 1, 0, 0, 0, 0) 370 _SPIRV_OP(image2d_array_depth_t, Dim2D, 1, 1, 0, 0, 0) 371 _SPIRV_OP(image2d_msaa_t, Dim2D, 0, 0, 1, 0, 0) 372 _SPIRV_OP(image2d_array_msaa_t, Dim2D, 0, 1, 1, 0, 0) 373 _SPIRV_OP(image2d_msaa_depth_t, Dim2D, 1, 0, 1, 0, 0) 374 _SPIRV_OP(image2d_array_msaa_depth_t, Dim2D, 1, 1, 1, 0, 0) 375 _SPIRV_OP(image3d_t, Dim3D, 0, 0, 0, 0, 0) 376 #undef _SPIRV_OP 377 } 378 typedef SPIRVMap<std::string, SPIRVTypeImageDescriptor> 379 OCLSPIRVImageTypeMap; 380 381 // Comparision function required to use the struct as map key. 382 inline bool 383 operator<(const SPIRVTypeImageDescriptor &A, 384 const SPIRVTypeImageDescriptor &B){ 385 return SPIRVTypeImageDescriptor::getAsTuple(A) < 386 SPIRVTypeImageDescriptor::getAsTuple(B); 387 } 388 389 class SPIRVTypeImage:public SPIRVType { 390 public: 391 const static Op OC = OpTypeImage; 392 const static SPIRVWord FixedWC = 9; 393 SPIRVTypeImage(SPIRVModule *M, SPIRVId TheId, SPIRVId TheSampledType, 394 const SPIRVTypeImageDescriptor &TheDesc) 395 :SPIRVType(M, FixedWC, OC, TheId), SampledType(TheSampledType), 396 Desc(TheDesc){ 397 validate(); 398 } 399 SPIRVTypeImage(SPIRVModule *M, SPIRVId TheId, SPIRVId TheSampledType, 400 const SPIRVTypeImageDescriptor &TheDesc, SPIRVAccessQualifierKind TheAcc) 401 :SPIRVType(M, FixedWC + 1, OC, TheId), SampledType(TheSampledType), 402 Desc(TheDesc){ 403 Acc.push_back(TheAcc); 404 validate(); 405 } 406 SPIRVTypeImage():SPIRVType(OC), SampledType(SPIRVID_INVALID), Desc(){ 407 } 408 const SPIRVTypeImageDescriptor &getDescriptor()const { 409 return Desc; 410 } 411 bool isOCLImage()const { 412 return Desc.Sampled == 0 && Desc.Format == 0; 413 } 414 bool hasAccessQualifier() const { return !Acc.empty();} 415 SPIRVAccessQualifierKind getAccessQualifier() const { 416 assert(hasAccessQualifier()); 417 return Acc[0]; 418 } 419 SPIRVCapVec getRequiredCapability() const { 420 SPIRVCapVec CV; 421 CV.push_back(CapabilityImageBasic); 422 if (Acc.size() > 0 && Acc[0] == AccessQualifierReadWrite) 423 CV.push_back(CapabilityImageReadWrite); 424 if (Desc.MS) 425 CV.push_back(CapabilityImageMipmap); 426 return CV; 427 } 428 SPIRVType *getSampledType() const { 429 return get<SPIRVType>(SampledType); 430 } 431 432 virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const { 433 return std::vector<SPIRVEntry*>(1, get<SPIRVType>(SampledType)); 434 } 435 436 protected: 437 _SPIRV_DEF_ENCDEC9(Id, SampledType, Desc.Dim, Desc.Depth, 438 Desc.Arrayed, Desc.MS, Desc.Sampled, Desc.Format, Acc) 439 // The validation assumes OpenCL image or sampler type. 440 void validate()const { 441 assert(OpCode == OC); 442 assert(WordCount == FixedWC + Acc.size()); 443 assert(SampledType != SPIRVID_INVALID && "Invalid sampled type"); 444 assert(Desc.Dim <= 5); 445 assert(Desc.Depth <= 1); 446 assert(Desc.Arrayed <= 1); 447 assert(Desc.MS <= 1); 448 assert(Desc.Sampled == 0); // For OCL only 449 assert(Desc.Format == 0); // For OCL only 450 assert(Acc.size() <= 1); 451 } 452 void setWordCount(SPIRVWord TheWC) { 453 WordCount = TheWC; 454 Acc.resize(WordCount - FixedWC); 455 } 456 private: 457 SPIRVId SampledType; 458 SPIRVTypeImageDescriptor Desc; 459 std::vector<SPIRVAccessQualifierKind> Acc; 460 }; 461 462 class SPIRVTypeSampler:public SPIRVType { 463 public: 464 const static Op OC = OpTypeSampler; 465 const static SPIRVWord FixedWC = 2; 466 SPIRVTypeSampler(SPIRVModule *M, SPIRVId TheId) 467 :SPIRVType(M, FixedWC, OC, TheId){ 468 validate(); 469 } 470 SPIRVTypeSampler():SPIRVType(OC){ 471 } 472 protected: 473 _SPIRV_DEF_ENCDEC1(Id) 474 void validate()const { 475 assert(OpCode == OC); 476 assert(WordCount == FixedWC); 477 } 478 }; 479 480 class SPIRVTypeSampledImage:public SPIRVType { 481 public: 482 const static Op OC = OpTypeSampledImage; 483 const static SPIRVWord FixedWC = 3; 484 SPIRVTypeSampledImage(SPIRVModule *M, SPIRVId TheId, SPIRVTypeImage *TheImgTy) 485 :SPIRVType(M, FixedWC, OC, TheId), ImgTy(TheImgTy){ 486 validate(); 487 } 488 SPIRVTypeSampledImage():SPIRVType(OC), ImgTy(nullptr){ 489 } 490 491 const SPIRVTypeImage *getImageType() const { 492 return ImgTy; 493 } 494 495 void setImageType(SPIRVTypeImage *TheImgTy) { 496 ImgTy = TheImgTy; 497 } 498 499 virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const { 500 return std::vector<SPIRVEntry*>(1, ImgTy); 501 } 502 503 protected: 504 SPIRVTypeImage *ImgTy; 505 _SPIRV_DEF_ENCDEC2(Id, ImgTy) 506 void validate()const { 507 assert(OpCode == OC); 508 assert(WordCount == FixedWC); 509 assert(ImgTy && ImgTy->isTypeImage()); 510 } 511 }; 512 513 class SPIRVTypePipeStorage :public SPIRVType { 514 public: 515 const static Op OC = OpTypePipeStorage; 516 const static SPIRVWord FixedWC = 2; 517 SPIRVTypePipeStorage(SPIRVModule *M, SPIRVId TheId) 518 :SPIRVType(M, FixedWC, OC, TheId){ 519 validate(); 520 } 521 SPIRVTypePipeStorage() :SPIRVType(OC){ 522 } 523 protected: 524 _SPIRV_DEF_ENCDEC1(Id) 525 void validate()const { 526 assert(OpCode == OC); 527 assert(WordCount == FixedWC); 528 } 529 }; 530 531 class SPIRVTypeStruct : public SPIRVType { 532 public: 533 // Complete constructor 534 SPIRVTypeStruct(SPIRVModule *M, SPIRVId TheId, 535 const std::vector<SPIRVType *> &TheMemberTypes, 536 const std::string &TheName) 537 : SPIRVType(M, 2 + TheMemberTypes.size(), OpTypeStruct, TheId) { 538 MemberTypeIdVec.resize(TheMemberTypes.size()); 539 for (auto &t : TheMemberTypes) 540 MemberTypeIdVec.push_back(t->getId()); 541 Name = TheName; 542 validate(); 543 } 544 SPIRVTypeStruct(SPIRVModule *M, SPIRVId TheId, unsigned NumMembers, 545 const std::string &TheName) 546 : SPIRVType(M, 2 + NumMembers, OpTypeStruct, TheId) { 547 Name = TheName; 548 validate(); 549 MemberTypeIdVec.resize(NumMembers); 550 } 551 // Incomplete constructor 552 SPIRVTypeStruct() : SPIRVType(OpTypeStruct) {} 553 554 SPIRVWord getMemberCount() const { return MemberTypeIdVec.size(); } 555 SPIRVType *getMemberType(size_t I) const { 556 return static_cast<SPIRVType *>(getEntry(MemberTypeIdVec[I])); 557 } 558 void setMemberType(size_t I, SPIRVType *Ty) { MemberTypeIdVec[I] = Ty->getId(); } 559 560 bool isPacked() const; 561 void setPacked(bool Packed); 562 563 void setWordCount(SPIRVWord WordCount) { 564 SPIRVType::setWordCount(WordCount); 565 MemberTypeIdVec.resize(WordCount - 2); 566 } 567 568 virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const { 569 std::vector<SPIRVEntry*> Operands(MemberTypeIdVec.size()); 570 for (size_t I = 0, E = MemberTypeIdVec.size(); I < E; ++I) 571 Operands[I] = getEntry(MemberTypeIdVec[I]); 572 return Operands; 573 } 574 575 protected: 576 _SPIRV_DEF_ENCDEC2(Id, MemberTypeIdVec) 577 578 void validate() const { SPIRVEntry::validate(); } 579 580 private: 581 std::vector<SPIRVId> MemberTypeIdVec; // Member Type Ids 582 }; 583 584 class SPIRVTypeFunction:public SPIRVType { 585 public: 586 // Complete constructor 587 SPIRVTypeFunction(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheReturnType, 588 const std::vector<SPIRVType *> &TheParameterTypes) 589 :SPIRVType(M, 3 + TheParameterTypes.size(), OpTypeFunction, TheId), 590 ReturnType(TheReturnType), ParamTypeVec(TheParameterTypes){ 591 validate(); 592 } 593 // Incomplete constructor 594 SPIRVTypeFunction():SPIRVType(OpTypeFunction), ReturnType(NULL){} 595 596 SPIRVType *getReturnType() const { return ReturnType;} 597 SPIRVWord getNumParameters() const { return ParamTypeVec.size();} 598 SPIRVType *getParameterType(unsigned I) const { return ParamTypeVec[I];} 599 virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const { 600 std::vector<SPIRVEntry*> Operands( 1 + ParamTypeVec.size(), ReturnType); 601 std::copy(ParamTypeVec.begin(), ParamTypeVec.end(), ++Operands.begin()); 602 return Operands; 603 } 604 605 protected: 606 _SPIRV_DEF_ENCDEC3(Id, ReturnType, ParamTypeVec) 607 void setWordCount(SPIRVWord WordCount) { 608 SPIRVType::setWordCount(WordCount); 609 ParamTypeVec.resize(WordCount - 3); 610 } 611 void validate()const { 612 SPIRVEntry::validate(); 613 ReturnType->validate(); 614 for (auto T:ParamTypeVec) 615 T->validate(); 616 } 617 private: 618 SPIRVType *ReturnType; // Return Type 619 std::vector<SPIRVType *> ParamTypeVec; // Parameter Types 620 }; 621 622 class SPIRVTypeOpaqueGeneric:public SPIRVType { 623 public: 624 // Complete constructor 625 SPIRVTypeOpaqueGeneric(Op TheOpCode, SPIRVModule *M, SPIRVId TheId) 626 :SPIRVType(M, 2, TheOpCode, TheId){ 627 validate(); 628 } 629 630 // Incomplete constructor 631 SPIRVTypeOpaqueGeneric(Op TheOpCode):SPIRVType(TheOpCode), 632 Opn(SPIRVID_INVALID) {} 633 634 SPIRVValue *getOperand() { 635 return getValue(Opn); 636 } 637 protected: 638 _SPIRV_DEF_ENCDEC1(Id) 639 void validate()const { 640 SPIRVEntry::validate(); 641 } 642 SPIRVId Opn; 643 }; 644 645 template<Op TheOpCode> 646 class SPIRVOpaqueGenericType:public SPIRVTypeOpaqueGeneric { 647 public: 648 // Complete constructor 649 SPIRVOpaqueGenericType(SPIRVModule *M, SPIRVId TheId) 650 :SPIRVTypeOpaqueGeneric(TheOpCode, M, TheId){} 651 // Incomplete constructor 652 SPIRVOpaqueGenericType():SPIRVTypeOpaqueGeneric(TheOpCode){} 653 }; 654 655 #define _SPIRV_OP(x) typedef SPIRVOpaqueGenericType<OpType##x> SPIRVType##x; 656 _SPIRV_OP(Event) 657 _SPIRV_OP(ReserveId) 658 #undef _SPIRV_OP 659 660 class SPIRVTypeDeviceEvent : public SPIRVType { 661 public: 662 // Complete constructor 663 SPIRVTypeDeviceEvent(SPIRVModule *M, SPIRVId TheId) 664 : SPIRVType(M, 2, OpTypeDeviceEvent, TheId) { 665 validate(); 666 } 667 668 // Incomplete constructor 669 SPIRVTypeDeviceEvent() : SPIRVType(OpTypeDeviceEvent) {} 670 671 SPIRVCapVec getRequiredCapability() const { 672 return getVec(CapabilityDeviceEnqueue); 673 } 674 675 protected: 676 _SPIRV_DEF_ENCDEC1(Id) 677 void validate() const { SPIRVEntry::validate(); } 678 }; 679 680 class SPIRVTypeQueue : public SPIRVType { 681 public: 682 // Complete constructor 683 SPIRVTypeQueue(SPIRVModule *M, SPIRVId TheId) 684 : SPIRVType(M, 2, OpTypeQueue, TheId) { 685 validate(); 686 } 687 688 // Incomplete constructor 689 SPIRVTypeQueue() : SPIRVType(OpTypeQueue) {} 690 691 SPIRVCapVec getRequiredCapability() const { 692 return getVec(CapabilityDeviceEnqueue); 693 } 694 695 protected: 696 _SPIRV_DEF_ENCDEC1(Id) 697 }; 698 699 class SPIRVTypePipe :public SPIRVType { 700 public: 701 // Complete constructor 702 SPIRVTypePipe(SPIRVModule *M, SPIRVId TheId, 703 SPIRVAccessQualifierKind AccessQual = AccessQualifierReadOnly) 704 :SPIRVType(M, 3, OpTypePipe, TheId), 705 AccessQualifier(AccessQual){ 706 validate(); 707 } 708 709 // Incomplete constructor 710 SPIRVTypePipe() :SPIRVType(OpTypePipe), 711 AccessQualifier(AccessQualifierReadOnly){} 712 713 SPIRVAccessQualifierKind getAccessQualifier() const { 714 return AccessQualifier; 715 } 716 void setPipeAcessQualifier(SPIRVAccessQualifierKind AccessQual) { 717 AccessQualifier = AccessQual; 718 assert(isValid(AccessQualifier)); 719 } 720 SPIRVCapVec getRequiredCapability() const { 721 return getVec(CapabilityPipes); 722 } 723 protected: 724 _SPIRV_DEF_ENCDEC2(Id, AccessQualifier) 725 void validate()const { 726 SPIRVEntry::validate(); 727 } 728 private: 729 SPIRVAccessQualifierKind AccessQualifier; // Access Qualifier 730 }; 731 732 template<typename T2, typename T1> 733 bool 734 isType(const T1 *Ty, unsigned Bits = 0) { 735 bool Is = Ty->getOpCode() == T2::OC; 736 if (!Is) 737 return false; 738 if (Bits == 0) 739 return true; 740 return static_cast<const T2*>(Ty)->getBitWidth() == Bits; 741 } 742 743 } 744 #endif // SPIRVTYPE_HPP_ 745