• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
SPIRVType(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVId TheId)61   SPIRVType(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
62       SPIRVId TheId)
63     :SPIRVEntry(M, TheWordCount, TheOpCode, TheId){}
64   // Incomplete constructor
SPIRVType(Op TheOpCode)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
SPIRVTypeVoid(SPIRVModule * M,SPIRVId TheId)109   SPIRVTypeVoid(SPIRVModule *M, SPIRVId TheId)
110     :SPIRVType(M, 2, OpTypeVoid, TheId){}
111   // Incomplete constructor
SPIRVTypeVoid()112   SPIRVTypeVoid():SPIRVType(OpTypeVoid){}
113 protected:
114   _SPIRV_DEF_ENCDEC1(Id)
115 };
116 
117 class SPIRVTypeBool:public SPIRVType {
118 public:
119   // Complete constructor
SPIRVTypeBool(SPIRVModule * M,SPIRVId TheId)120   SPIRVTypeBool(SPIRVModule *M, SPIRVId TheId)
121     :SPIRVType(M, 2, OpTypeBool, TheId){}
122   // Incomplete constructor
SPIRVTypeBool()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
SPIRVTypeInt(SPIRVModule * M,SPIRVId TheId,unsigned TheBitWidth,bool ItIsSigned)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
SPIRVTypeInt()139   SPIRVTypeInt():SPIRVType(OC), BitWidth(0), IsSigned(false){}
140 
getBitWidth()141   unsigned getBitWidth() const { return BitWidth;}
isSigned()142   bool isSigned() const { return IsSigned;}
getRequiredCapability()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:
_SPIRV_DEF_ENCDEC3(Id,BitWidth,IsSigned)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
SPIRVTypeFloat(SPIRVModule * M,SPIRVId TheId,unsigned TheBitWidth)167   SPIRVTypeFloat(SPIRVModule *M, SPIRVId TheId, unsigned TheBitWidth)
168     :SPIRVType(M, 3, OC, TheId), BitWidth(TheBitWidth){}
169   // Incomplete constructor
SPIRVTypeFloat()170   SPIRVTypeFloat():SPIRVType(OC), BitWidth(0){}
171 
getBitWidth()172   unsigned getBitWidth() const { return BitWidth;}
173 
getRequiredCapability()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:
_SPIRV_DEF_ENCDEC2(Id,BitWidth)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
SPIRVTypePointer(SPIRVModule * M,SPIRVId TheId,SPIRVStorageClassKind TheStorageClass,SPIRVType * ElementType)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
SPIRVTypePointer()205   SPIRVTypePointer():SPIRVType(OpTypePointer),
206       ElemStorageClass(StorageClassFunction),
207       ElemTypeId(0){}
208 
getElementType()209   SPIRVType *getElementType() const {
210     return static_cast<SPIRVType *>(getEntry(ElemTypeId));
211   }
getStorageClass()212   SPIRVStorageClassKind getStorageClass() const { return ElemStorageClass;}
getRequiredCapability()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   }
getNonLiteralOperands()221   virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
222     return std::vector<SPIRVEntry*>(1, getEntry(ElemTypeId));
223   }
224 
225 protected:
_SPIRV_DEF_ENCDEC3(Id,ElemStorageClass,ElemTypeId)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:
SPIRVTypeForwardPointer(SPIRVModule * M,SPIRVTypePointer * Pointer,SPIRVStorageClassKind SC)238   SPIRVTypeForwardPointer(SPIRVModule *M, SPIRVTypePointer *Pointer,
239                           SPIRVStorageClassKind SC)
240       : SPIRVEntryNoId(M, 3), Pointer(Pointer), SC(SC) {}
241 
SPIRVTypeForwardPointer()242   SPIRVTypeForwardPointer()
243       : Pointer(nullptr), SC(StorageClassUniformConstant) {}
244 
getPointer()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
SPIRVTypeVector(SPIRVModule * M,SPIRVId TheId,SPIRVType * TheCompType,SPIRVWord TheCompCount)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
SPIRVTypeVector()262   SPIRVTypeVector():SPIRVType(OpTypeVector), CompType(nullptr),
263       CompCount(0){}
264 
getComponentType()265   SPIRVType *getComponentType() const { return CompType;}
getComponentCount()266   SPIRVWord getComponentCount() const { return CompCount;}
isValidIndex(SPIRVWord Index)267   bool isValidIndex(SPIRVWord Index) const { return Index < CompCount;}
getRequiredCapability()268   SPIRVCapVec getRequiredCapability() const {
269     SPIRVCapVec V(getComponentType()->getRequiredCapability());
270     if (CompCount >= 8)
271       V.push_back(CapabilityVector16);
272     return V;
273   }
274 
getNonLiteralOperands()275   virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
276     return std::vector<SPIRVEntry*>(1, CompType);
277   }
278 
279 protected:
_SPIRV_DEF_ENCDEC3(Id,CompType,CompCount)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
SPIRVTypeArray()299   SPIRVTypeArray():SPIRVType(OpTypeArray), ElemType(nullptr),
300       Length(SPIRVID_INVALID){}
301 
getElementType()302   SPIRVType *getElementType() const { return ElemType;}
303   SPIRVConstant *getLength() const;
getRequiredCapability()304   SPIRVCapVec getRequiredCapability() const {
305     return getElementType()->getRequiredCapability();
306   }
getNonLiteralOperands()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
SPIRVTypeOpaque(SPIRVModule * M,SPIRVId TheId,const std::string & TheName)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
SPIRVTypeOpaque()331   SPIRVTypeOpaque():SPIRVType(OpTypeOpaque){}
332 
333 protected:
_SPIRV_DEF_ENCDEC2(Id,Name)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>
getAsTupleSPIRVTypeImageDescriptor349     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   }
SPIRVTypeImageDescriptorSPIRVTypeImageDescriptor353   SPIRVTypeImageDescriptor():Dim(Dim1D), Depth(0), Arrayed(0),
354       MS(0), Sampled(0), Format(0){}
SPIRVTypeImageDescriptorSPIRVTypeImageDescriptor355   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
init()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;
SPIRVTypeImage(SPIRVModule * M,SPIRVId TheId,SPIRVId TheSampledType,const SPIRVTypeImageDescriptor & TheDesc)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   }
SPIRVTypeImage(SPIRVModule * M,SPIRVId TheId,SPIRVId TheSampledType,const SPIRVTypeImageDescriptor & TheDesc,SPIRVAccessQualifierKind TheAcc)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   }
SPIRVTypeImage()406   SPIRVTypeImage():SPIRVType(OC), SampledType(SPIRVID_INVALID), Desc(){
407   }
getDescriptor()408   const SPIRVTypeImageDescriptor &getDescriptor()const {
409     return Desc;
410   }
isOCLImage()411   bool isOCLImage()const {
412     return Desc.Sampled == 0 && Desc.Format == 0;
413   }
hasAccessQualifier()414   bool hasAccessQualifier() const { return !Acc.empty();}
getAccessQualifier()415   SPIRVAccessQualifierKind getAccessQualifier() const {
416     assert(hasAccessQualifier());
417     return Acc[0];
418   }
getRequiredCapability()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   }
getSampledType()428   SPIRVType *getSampledType() const {
429     return get<SPIRVType>(SampledType);
430   }
431 
getNonLiteralOperands()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.
validate()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   }
setWordCount(SPIRVWord TheWC)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;
SPIRVTypeSampler(SPIRVModule * M,SPIRVId TheId)466   SPIRVTypeSampler(SPIRVModule *M, SPIRVId TheId)
467     :SPIRVType(M, FixedWC, OC, TheId){
468     validate();
469   }
SPIRVTypeSampler()470   SPIRVTypeSampler():SPIRVType(OC){
471   }
472 protected:
_SPIRV_DEF_ENCDEC1(Id)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;
SPIRVTypeSampledImage(SPIRVModule * M,SPIRVId TheId,SPIRVTypeImage * TheImgTy)484   SPIRVTypeSampledImage(SPIRVModule *M, SPIRVId TheId, SPIRVTypeImage *TheImgTy)
485     :SPIRVType(M, FixedWC, OC, TheId), ImgTy(TheImgTy){
486     validate();
487   }
SPIRVTypeSampledImage()488   SPIRVTypeSampledImage():SPIRVType(OC), ImgTy(nullptr){
489   }
490 
getImageType()491   const SPIRVTypeImage *getImageType() const {
492     return ImgTy;
493   }
494 
setImageType(SPIRVTypeImage * TheImgTy)495   void setImageType(SPIRVTypeImage *TheImgTy) {
496     ImgTy = TheImgTy;
497   }
498 
getNonLiteralOperands()499   virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
500     return std::vector<SPIRVEntry*>(1, ImgTy);
501   }
502 
503 protected:
504   SPIRVTypeImage *ImgTy;
_SPIRV_DEF_ENCDEC2(Id,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;
SPIRVTypePipeStorage(SPIRVModule * M,SPIRVId TheId)517   SPIRVTypePipeStorage(SPIRVModule *M, SPIRVId TheId)
518     :SPIRVType(M, FixedWC, OC, TheId){
519     validate();
520   }
SPIRVTypePipeStorage()521   SPIRVTypePipeStorage() :SPIRVType(OC){
522   }
523 protected:
_SPIRV_DEF_ENCDEC1(Id)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
SPIRVTypeStruct(SPIRVModule * M,SPIRVId TheId,const std::vector<SPIRVType * > & TheMemberTypes,const std::string & TheName)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   }
SPIRVTypeStruct(SPIRVModule * M,SPIRVId TheId,unsigned NumMembers,const std::string & TheName)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
SPIRVTypeStruct()552   SPIRVTypeStruct() : SPIRVType(OpTypeStruct) {}
553 
getMemberCount()554   SPIRVWord getMemberCount() const { return MemberTypeIdVec.size(); }
getMemberType(size_t I)555   SPIRVType *getMemberType(size_t I) const {
556     return static_cast<SPIRVType *>(getEntry(MemberTypeIdVec[I]));
557   }
setMemberType(size_t I,SPIRVType * Ty)558   void setMemberType(size_t I, SPIRVType *Ty) { MemberTypeIdVec[I] = Ty->getId(); }
559 
560   bool isPacked() const;
561   void setPacked(bool Packed);
562 
setWordCount(SPIRVWord WordCount)563   void setWordCount(SPIRVWord WordCount) {
564     SPIRVType::setWordCount(WordCount);
565     MemberTypeIdVec.resize(WordCount - 2);
566   }
567 
getNonLiteralOperands()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:
_SPIRV_DEF_ENCDEC2(Id,MemberTypeIdVec)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
SPIRVTypeFunction(SPIRVModule * M,SPIRVId TheId,SPIRVType * TheReturnType,const std::vector<SPIRVType * > & TheParameterTypes)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
SPIRVTypeFunction()594   SPIRVTypeFunction():SPIRVType(OpTypeFunction), ReturnType(NULL){}
595 
getReturnType()596   SPIRVType *getReturnType() const { return ReturnType;}
getNumParameters()597   SPIRVWord getNumParameters() const { return ParamTypeVec.size();}
getParameterType(unsigned I)598   SPIRVType *getParameterType(unsigned I) const { return ParamTypeVec[I];}
getNonLiteralOperands()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:
_SPIRV_DEF_ENCDEC3(Id,ReturnType,ParamTypeVec)606   _SPIRV_DEF_ENCDEC3(Id, ReturnType, ParamTypeVec)
607   void setWordCount(SPIRVWord WordCount) {
608     SPIRVType::setWordCount(WordCount);
609     ParamTypeVec.resize(WordCount - 3);
610   }
validate()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
SPIRVTypeOpaqueGeneric(Op TheOpCode,SPIRVModule * M,SPIRVId TheId)625   SPIRVTypeOpaqueGeneric(Op TheOpCode, SPIRVModule *M, SPIRVId TheId)
626     :SPIRVType(M, 2, TheOpCode, TheId){
627     validate();
628   }
629 
630   // Incomplete constructor
SPIRVTypeOpaqueGeneric(Op TheOpCode)631   SPIRVTypeOpaqueGeneric(Op TheOpCode):SPIRVType(TheOpCode),
632       Opn(SPIRVID_INVALID) {}
633 
getOperand()634   SPIRVValue *getOperand() {
635     return getValue(Opn);
636   }
637 protected:
_SPIRV_DEF_ENCDEC1(Id)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
SPIRVOpaqueGenericType(SPIRVModule * M,SPIRVId TheId)649   SPIRVOpaqueGenericType(SPIRVModule *M, SPIRVId TheId)
650     :SPIRVTypeOpaqueGeneric(TheOpCode, M, TheId){}
651   // Incomplete constructor
SPIRVOpaqueGenericType()652   SPIRVOpaqueGenericType():SPIRVTypeOpaqueGeneric(TheOpCode){}
653 };
654 
655 #define _SPIRV_OP(x) typedef SPIRVOpaqueGenericType<OpType##x> SPIRVType##x;
656 _SPIRV_OP(Event)
_SPIRV_OP(ReserveId)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
SPIRVTypeQueue(SPIRVModule * M,SPIRVId TheId)683   SPIRVTypeQueue(SPIRVModule *M, SPIRVId TheId)
684       : SPIRVType(M, 2, OpTypeQueue, TheId) {
685     validate();
686   }
687 
688   // Incomplete constructor
SPIRVTypeQueue()689   SPIRVTypeQueue() : SPIRVType(OpTypeQueue) {}
690 
getRequiredCapability()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
SPIRVTypePipe()710   SPIRVTypePipe() :SPIRVType(OpTypePipe),
711     AccessQualifier(AccessQualifierReadOnly){}
712 
getAccessQualifier()713   SPIRVAccessQualifierKind getAccessQualifier() const {
714       return AccessQualifier;
715   }
setPipeAcessQualifier(SPIRVAccessQualifierKind AccessQual)716   void setPipeAcessQualifier(SPIRVAccessQualifierKind AccessQual) {
717     AccessQualifier = AccessQual;
718     assert(isValid(AccessQualifier));
719   }
getRequiredCapability()720   SPIRVCapVec getRequiredCapability() const {
721     return getVec(CapabilityPipes);
722   }
723 protected:
_SPIRV_DEF_ENCDEC2(Id,AccessQualifier)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