Home | History | Annotate | Download | only in libSPIRV
      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