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