1 //===- SPIRVtype.cpp � 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 implements the types defined in SPIRV spec with op codes.
37 ///
38 //===----------------------------------------------------------------------===//
39
40 #include "SPIRVType.h"
41 #include "SPIRVModule.h"
42 #include "SPIRVDecorate.h"
43 #include "SPIRVValue.h"
44
45 #include <cassert>
46
47 namespace SPIRV{
48
49 SPIRVType*
getArrayElementType() const50 SPIRVType::getArrayElementType() const {
51 assert(OpCode == OpTypeArray && "Not array type");
52 return static_cast<const SPIRVTypeArray *const>(this)->getElementType();
53 }
54
55 uint64_t
getArrayLength() const56 SPIRVType::getArrayLength() const {
57 assert(OpCode == OpTypeArray && "Not array type");
58 return static_cast<const SPIRVTypeArray *const>(this)->getLength()->
59 getZExtIntValue();
60 }
61
62 SPIRVWord
getBitWidth() const63 SPIRVType::getBitWidth() const {
64 if (isTypeVector())
65 return getVectorComponentType()->getBitWidth();
66 if (isTypeBool())
67 return 1;
68 return isTypeInt()? getIntegerBitWidth() : getFloatBitWidth();
69 }
70
71 SPIRVWord
getFloatBitWidth() const72 SPIRVType::getFloatBitWidth()const {
73 assert(OpCode == OpTypeFloat && "Not an integer type");
74 return static_cast<const SPIRVTypeFloat *const>(this)->getBitWidth();
75 }
76
77 SPIRVWord
getIntegerBitWidth() const78 SPIRVType::getIntegerBitWidth()const {
79 assert((OpCode == OpTypeInt || OpCode == OpTypeBool) &&
80 "Not an integer type");
81 if (isTypeBool())
82 return 1;
83 return static_cast<const SPIRVTypeInt *const>(this)->getBitWidth();
84 }
85
86 SPIRVType *
getFunctionReturnType() const87 SPIRVType::getFunctionReturnType() const {
88 assert(OpCode == OpTypeFunction);
89 return static_cast<const SPIRVTypeFunction *const>(this)->getReturnType();
90 }
91
92 SPIRVType *
getPointerElementType() const93 SPIRVType::getPointerElementType()const {
94 assert(OpCode == OpTypePointer && "Not a pointer type");
95 return static_cast<const SPIRVTypePointer *const>(this)->getElementType();
96 }
97
98 SPIRVStorageClassKind
getPointerStorageClass() const99 SPIRVType::getPointerStorageClass() const {
100 assert(OpCode == OpTypePointer && "Not a pointer type");
101 return static_cast<const SPIRVTypePointer *const>(this)->getStorageClass();
102 }
103
104 SPIRVType*
getStructMemberType(size_t Index) const105 SPIRVType::getStructMemberType(size_t Index) const {
106 assert(OpCode == OpTypeStruct && "Not struct type");
107 return static_cast<const SPIRVTypeStruct *const>(this)->getMemberType(Index);
108 }
109
110 SPIRVWord
getStructMemberCount() const111 SPIRVType::getStructMemberCount() const {
112 assert(OpCode == OpTypeStruct && "Not struct type");
113 return static_cast<const SPIRVTypeStruct *const>(this)->getMemberCount();
114 }
115
116 SPIRVWord
getVectorComponentCount() const117 SPIRVType::getVectorComponentCount() const {
118 assert(OpCode == OpTypeVector && "Not vector type");
119 return static_cast<const SPIRVTypeVector *const>(this)->getComponentCount();
120 }
121
122 SPIRVType*
getVectorComponentType() const123 SPIRVType::getVectorComponentType() const {
124 assert(OpCode == OpTypeVector && "Not vector type");
125 return static_cast<const SPIRVTypeVector *const>(this)->getComponentType();
126 }
127
128 bool
isTypeVoid() const129 SPIRVType::isTypeVoid() const {
130 return OpCode == OpTypeVoid;
131 }
132 bool
isTypeArray() const133 SPIRVType::isTypeArray() const {
134 return OpCode == OpTypeArray;
135 }
136
137 bool
isTypeBool() const138 SPIRVType::isTypeBool()const {
139 return OpCode == OpTypeBool;
140 }
141
142 bool
isTypeComposite() const143 SPIRVType::isTypeComposite() const {
144 return isTypeVector() || isTypeArray() || isTypeStruct();
145 }
146
147 bool
isTypeFloat(unsigned Bits) const148 SPIRVType::isTypeFloat(unsigned Bits)const {
149 return isType<SPIRVTypeFloat>(this, Bits);
150 }
151
152 bool
isTypeOCLImage() const153 SPIRVType::isTypeOCLImage()const {
154 return isTypeImage() && static_cast<const SPIRVTypeImage *>(this)->
155 isOCLImage();
156 }
157
158 bool
isTypePipe() const159 SPIRVType::isTypePipe()const {
160 return OpCode == OpTypePipe;
161 }
162
163 bool
isTypePipeStorage() const164 SPIRVType::isTypePipeStorage() const {
165 return OpCode == OpTypePipeStorage;
166 }
167
168 bool
isTypeReserveId() const169 SPIRVType::isTypeReserveId() const {
170 return OpCode == OpTypeReserveId;
171 }
172
173 bool
isTypeInt(unsigned Bits) const174 SPIRVType::isTypeInt(unsigned Bits)const {
175 return isType<SPIRVTypeInt>(this, Bits);
176 }
177
178 bool
isTypePointer() const179 SPIRVType::isTypePointer()const {
180 return OpCode == OpTypePointer;
181 }
182
183 bool
isTypeOpaque() const184 SPIRVType::isTypeOpaque()const {
185 return OpCode == OpTypeOpaque;
186 }
187
188 bool
isTypeEvent() const189 SPIRVType::isTypeEvent()const {
190 return OpCode == OpTypeEvent;
191 }
192
193 bool
isTypeDeviceEvent() const194 SPIRVType::isTypeDeviceEvent()const {
195 return OpCode == OpTypeDeviceEvent;
196 }
197
198 bool
isTypeSampler() const199 SPIRVType::isTypeSampler()const {
200 return OpCode == OpTypeSampler;
201 }
202
203 bool
isTypeImage() const204 SPIRVType::isTypeImage()const {
205 return OpCode == OpTypeImage;
206 }
207
208 bool
isTypeStruct() const209 SPIRVType::isTypeStruct() const {
210 return OpCode == OpTypeStruct;
211 }
212
213 bool
isTypeVector() const214 SPIRVType::isTypeVector() const {
215 return OpCode == OpTypeVector;
216 }
217
218 bool
isTypeVectorBool() const219 SPIRVType::isTypeVectorBool() const {
220 return isTypeVector() && getVectorComponentType()->isTypeBool();
221 }
222
223 bool
isTypeVectorInt() const224 SPIRVType::isTypeVectorInt() const {
225 return isTypeVector() && getVectorComponentType()->isTypeInt();
226 }
227
228 bool
isTypeVectorFloat() const229 SPIRVType::isTypeVectorFloat() const {
230 return isTypeVector() && getVectorComponentType()->isTypeFloat();
231 }
232
233 bool
isTypeVectorOrScalarBool() const234 SPIRVType::isTypeVectorOrScalarBool() const {
235 return isTypeBool() || isTypeVectorBool();
236 }
237
238 bool
isTypeVectorOrScalarInt() const239 SPIRVType::isTypeVectorOrScalarInt() const {
240 return isTypeInt() || isTypeVectorInt();
241 }
242
243 bool
isTypeVectorOrScalarFloat() const244 SPIRVType::isTypeVectorOrScalarFloat() const {
245 return isTypeFloat() || isTypeVectorFloat();
246 }
247
248 bool
isPacked() const249 SPIRVTypeStruct::isPacked() const {
250 return hasDecorate(DecorationCPacked);
251 }
252
253 void
setPacked(bool Packed)254 SPIRVTypeStruct::setPacked(bool Packed) {
255 if (Packed)
256 addDecorate(new SPIRVDecorate(DecorationCPacked, this));
257 else
258 eraseDecorate(DecorationCPacked);
259 }
260
SPIRVTypeArray(SPIRVModule * M,SPIRVId TheId,SPIRVType * TheElemType,SPIRVConstant * TheLength)261 SPIRVTypeArray::SPIRVTypeArray(SPIRVModule *M, SPIRVId TheId, SPIRVType *TheElemType,
262 SPIRVConstant* TheLength)
263 :SPIRVType(M, 4, OpTypeArray, TheId), ElemType(TheElemType),
264 Length(TheLength->getId()){
265 validate();
266 }
267
268 void
validate() const269 SPIRVTypeArray::validate()const {
270 SPIRVEntry::validate();
271 ElemType->validate();
272 assert(getValue(Length)->getType()->isTypeInt() &&
273 get<SPIRVConstant>(Length)->getZExtIntValue() > 0);
274 }
275
276 SPIRVConstant*
getLength() const277 SPIRVTypeArray::getLength() const {
278 return get<SPIRVConstant>(Length);
279 }
280
_SPIRV_IMP_ENCDEC3(SPIRVTypeArray,Id,ElemType,Length)281 _SPIRV_IMP_ENCDEC3(SPIRVTypeArray, Id, ElemType, Length)
282
283 void SPIRVTypeForwardPointer::encode(spv_ostream &O) const {
284 getEncoder(O) << Pointer << SC;
285 }
286
decode(std::istream & I)287 void SPIRVTypeForwardPointer::decode(std::istream &I) {
288 auto Decoder = getDecoder(I);
289 SPIRVId PointerId;
290 Decoder >> PointerId >> SC;
291 }
292 }
293
294