• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- SPIRVValue.h - Class to represent a SPIR-V Value ----------*- 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 values defined in SPIR-V spec with op codes.
37 ///
38 /// The name of the SPIR-V values follow the op code name in the spec.
39 /// This is for readability and ease of using macro to handle types.
40 //
41 //===----------------------------------------------------------------------===//
42 
43 #ifndef SPIRVVALUE_HPP_
44 #define SPIRVVALUE_HPP_
45 
46 #include "SPIRVEntry.h"
47 #include "SPIRVType.h"
48 #include "SPIRVDecorate.h"
49 
50 #include <iostream>
51 #include <map>
52 #include <memory>
53 
54 namespace SPIRV{
55 
56 class SPIRVValue: public SPIRVEntry {
57 public:
58   // Complete constructor for value with id and type
SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVType * TheType,SPIRVId TheId)59   SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
60       SPIRVType *TheType, SPIRVId TheId)
61     :SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(TheType) {
62     validate();
63   }
64   // Complete constructor for value with type but without id
SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVType * TheType)65   SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
66       SPIRVType *TheType)
67     :SPIRVEntry(M, TheWordCount, TheOpCode), Type(TheType) {
68     setHasNoId();
69     validate();
70   }
71   // Complete constructor for value with id but without type
SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode,SPIRVId TheId)72   SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
73       SPIRVId TheId)
74     :SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(NULL) {
75     setHasNoType();
76     validate();
77   }
78   // Complete constructor for value without id and type
SPIRVValue(SPIRVModule * M,unsigned TheWordCount,Op TheOpCode)79   SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode)
80     :SPIRVEntry(M, TheWordCount, TheOpCode), Type(NULL) {
81     setHasNoId();
82     setHasNoType();
83     validate();
84   }
85   // Incomplete constructor
SPIRVValue(Op TheOpCode)86   SPIRVValue(Op TheOpCode):SPIRVEntry(TheOpCode), Type(NULL) {}
87 
hasType()88   bool hasType()const { return !(Attrib & SPIRVEA_NOTYPE);}
getType()89   SPIRVType *getType()const {
90     assert(hasType() && "value has no type");
91     return Type;
92   }
93   bool isVolatile()const;
94   bool hasAlignment(SPIRVWord *Result=0)const;
95 
96   void setAlignment(SPIRVWord);
97   void setVolatile(bool IsVolatile);
98 
validate()99   void validate()const {
100     SPIRVEntry::validate();
101     assert((!hasType() || Type) && "Invalid type");
102   }
103 
setType(SPIRVType * Ty)104   void setType(SPIRVType *Ty) {
105     Type = Ty;
106     assert(!Ty || !Ty->isTypeVoid() || OpCode == OpFunction);
107     if (Ty && (!Ty->isTypeVoid() || OpCode == OpFunction))
108       setHasType();
109     else
110       setHasNoType();
111   }
112 
getRequiredCapability()113   SPIRVCapVec getRequiredCapability() const {
114     SPIRVCapVec CV;
115     if (!hasType())
116       return CV;
117     return Type->getRequiredCapability();
118   }
119 
120 protected:
setHasNoType()121   void setHasNoType() { Attrib |= SPIRVEA_NOTYPE;}
setHasType()122   void setHasType() { Attrib &= ~SPIRVEA_NOTYPE;}
123 
124   SPIRVType *Type;                 // Value Type
125 };
126 
127 class SPIRVConstant: public SPIRVValue {
128 public:
129   // Complete constructor for integer constant
SPIRVConstant(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,uint64_t TheValue)130   SPIRVConstant(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
131       uint64_t TheValue)
132     :SPIRVValue(M, 0, OpConstant, TheType, TheId){
133     Union.UInt64Val = TheValue;
134     recalculateWordCount();
135     validate();
136   }
137   // Complete constructor for float constant
SPIRVConstant(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,float TheValue)138   SPIRVConstant(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, float TheValue)
139     :SPIRVValue(M, 0, OpConstant, TheType, TheId){
140     Union.FloatVal = TheValue;
141     recalculateWordCount();
142     validate();
143   }
144   // Complete constructor for double constant
SPIRVConstant(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,double TheValue)145   SPIRVConstant(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, double TheValue)
146     :SPIRVValue(M, 0, OpConstant, TheType, TheId){
147     Union.DoubleVal = TheValue;
148     recalculateWordCount();
149     validate();
150   }
151   // Incomplete constructor
SPIRVConstant()152   SPIRVConstant():SPIRVValue(OpConstant), NumWords(0){}
getZExtIntValue()153   uint64_t getZExtIntValue() const { return Union.UInt64Val;}
getFloatValue()154   float getFloatValue() const { return Union.FloatVal;}
getDoubleValue()155   double getDoubleValue() const { return Union.DoubleVal;}
156 protected:
recalculateWordCount()157   void recalculateWordCount() {
158     NumWords = Type->getBitWidth()/32;
159     if (NumWords < 1)
160       NumWords = 1;
161     WordCount = 3 + NumWords;
162   }
validate()163   void validate() const {
164     SPIRVValue::validate();
165     assert(NumWords >= 1 && NumWords <= 2 && "Invalid constant size");
166   }
encode(spv_ostream & O)167   void encode(spv_ostream &O) const {
168     getEncoder(O) << Type << Id;
169     for (unsigned i = 0; i < NumWords; ++i)
170       getEncoder(O) << Union.Words[i];
171   }
setWordCount(SPIRVWord WordCount)172   void setWordCount(SPIRVWord WordCount) {
173     SPIRVValue::setWordCount(WordCount);
174     NumWords = WordCount - 3;
175   }
decode(std::istream & I)176   void decode(std::istream &I) {
177     getDecoder(I) >> Type >> Id;
178     for (unsigned i = 0; i < NumWords; ++i)
179       getDecoder(I) >> Union.Words[i];
180   }
181 
182   unsigned NumWords;
183   union UnionType{
184     uint64_t UInt64Val;
185     float FloatVal;
186     double DoubleVal;
187     SPIRVWord Words[2];
UnionType()188     UnionType() {
189       UInt64Val = 0;
190     }
191   } Union;
192 };
193 
194 template<Op OC>
195 class SPIRVConstantEmpty: public SPIRVValue {
196 public:
197   // Complete constructor
SPIRVConstantEmpty(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId)198   SPIRVConstantEmpty(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
199     :SPIRVValue(M, 3, OC, TheType, TheId){
200     validate();
201   }
202   // Incomplete constructor
SPIRVConstantEmpty()203   SPIRVConstantEmpty():SPIRVValue(OC){}
204 protected:
validate()205   void validate() const {
206     SPIRVValue::validate();
207   }
208   _SPIRV_DEF_ENCDEC2(Type, Id)
209 };
210 
211 template<Op OC>
212 class SPIRVConstantBool: public SPIRVConstantEmpty<OC> {
213 public:
214   // Complete constructor
SPIRVConstantBool(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId)215   SPIRVConstantBool(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
216     :SPIRVConstantEmpty<OC>(M, TheType, TheId){}
217   // Incomplete constructor
SPIRVConstantBool()218   SPIRVConstantBool(){}
219 protected:
validate()220   void validate() const {
221     SPIRVConstantEmpty<OC>::validate();
222     assert(this->Type->isTypeBool() && "Invalid type");
223   }
224 };
225 
226 typedef SPIRVConstantBool<OpConstantTrue> SPIRVConstantTrue;
227 typedef SPIRVConstantBool<OpConstantFalse> SPIRVConstantFalse;
228 
229 class SPIRVConstantNull:
230     public SPIRVConstantEmpty<OpConstantNull> {
231 public:
232   // Complete constructor
SPIRVConstantNull(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId)233   SPIRVConstantNull(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
234     :SPIRVConstantEmpty(M, TheType, TheId){
235     validate();
236   }
237   // Incomplete constructor
SPIRVConstantNull()238   SPIRVConstantNull(){}
239 protected:
validate()240   void validate() const {
241     SPIRVConstantEmpty::validate();
242     assert((Type->isTypeComposite() ||
243             Type->isTypeOpaque() ||
244             Type->isTypeEvent() ||
245             Type->isTypePointer() ||
246             Type->isTypeReserveId() ||
247             Type->isTypeDeviceEvent()) &&
248             "Invalid type");
249   }
250 };
251 
252 class SPIRVUndef:
253     public SPIRVConstantEmpty<OpUndef> {
254 public:
255   // Complete constructor
SPIRVUndef(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId)256   SPIRVUndef(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
257     :SPIRVConstantEmpty(M, TheType, TheId){
258     validate();
259   }
260   // Incomplete constructor
SPIRVUndef()261   SPIRVUndef(){}
262 protected:
validate()263   void validate() const {
264     SPIRVConstantEmpty::validate();
265   }
266 };
267 
268 class SPIRVConstantComposite: public SPIRVValue {
269 public:
270   // Complete constructor for composite constant
SPIRVConstantComposite(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,const std::vector<SPIRVValue * > TheElements)271   SPIRVConstantComposite(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
272       const std::vector<SPIRVValue *> TheElements)
273     :SPIRVValue(M, TheElements.size()+3, OpConstantComposite, TheType,
274         TheId){
275     Elements = getIds(TheElements);
276     validate();
277   }
278   // Incomplete constructor
SPIRVConstantComposite()279   SPIRVConstantComposite():SPIRVValue(OpConstantComposite){}
getElements()280   std::vector<SPIRVValue*> getElements()const {
281     return getValues(Elements);
282   }
getNonLiteralOperands()283   std::vector<SPIRVEntry*> getNonLiteralOperands() const {
284     std::vector<SPIRVValue*> Elements = getElements();
285     return std::vector<SPIRVEntry*>(Elements.begin(), Elements.end());
286   }
287 protected:
validate()288   void validate() const {
289     SPIRVValue::validate();
290     for (auto &I:Elements)
291       getValue(I)->validate();
292   }
setWordCount(SPIRVWord WordCount)293   void setWordCount(SPIRVWord WordCount) {
294     Elements.resize(WordCount - 3);
295   }
296   _SPIRV_DEF_ENCDEC3(Type, Id, Elements)
297 
298   std::vector<SPIRVId> Elements;
299 };
300 
301 class SPIRVConstantSampler: public SPIRVValue {
302 public:
303   const static Op OC = OpConstantSampler;
304   const static SPIRVWord WC = 6;
305   // Complete constructor
SPIRVConstantSampler(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,SPIRVWord TheAddrMode,SPIRVWord TheNormalized,SPIRVWord TheFilterMode)306   SPIRVConstantSampler(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
307       SPIRVWord TheAddrMode, SPIRVWord TheNormalized, SPIRVWord TheFilterMode)
308     :SPIRVValue(M, WC, OC, TheType, TheId), AddrMode(TheAddrMode),
309      Normalized(TheNormalized), FilterMode(TheFilterMode){
310     validate();
311   }
312   // Incomplete constructor
SPIRVConstantSampler()313   SPIRVConstantSampler():SPIRVValue(OC), AddrMode(SPIRVSAM_Invalid),
314       Normalized(SPIRVWORD_MAX), FilterMode(SPIRVSFM_Invalid){}
315 
getAddrMode()316   SPIRVWord getAddrMode() const {
317     return AddrMode;
318   }
319 
getFilterMode()320   SPIRVWord getFilterMode() const {
321     return FilterMode;
322   }
323 
getNormalized()324   SPIRVWord getNormalized() const {
325     return Normalized;
326   }
getRequiredCapability()327   SPIRVCapVec getRequiredCapability() const {
328     return getVec(CapabilityLiteralSampler);
329   }
330 protected:
331   SPIRVWord AddrMode;
332   SPIRVWord Normalized;
333   SPIRVWord FilterMode;
validate()334   void validate() const {
335     SPIRVValue::validate();
336     assert(OpCode == OC);
337     assert(WordCount == WC);
338     assert(Type->isTypeSampler());
339   }
340   _SPIRV_DEF_ENCDEC5(Type, Id, AddrMode, Normalized, FilterMode)
341 };
342 
343 class SPIRVConstantPipeStorage : public SPIRVValue {
344 public:
345   const static Op OC = OpConstantPipeStorage;
346   const static SPIRVWord WC = 6;
347   // Complete constructor
SPIRVConstantPipeStorage(SPIRVModule * M,SPIRVType * TheType,SPIRVId TheId,SPIRVWord ThePacketSize,SPIRVWord ThePacketAlign,SPIRVWord TheCapacity)348   SPIRVConstantPipeStorage(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
349     SPIRVWord ThePacketSize, SPIRVWord ThePacketAlign, SPIRVWord TheCapacity)
350     :SPIRVValue(M, WC, OC, TheType, TheId), PacketSize(ThePacketSize),
351     PacketAlign(ThePacketAlign), Capacity(TheCapacity){
352     validate();
353   }
354   // Incomplete constructor
SPIRVConstantPipeStorage()355   SPIRVConstantPipeStorage() :SPIRVValue(OC), PacketSize(0),
356     PacketAlign(0), Capacity(0){}
357 
getPacketSize()358   SPIRVWord getPacketSize() const {
359     return PacketSize;
360   }
361 
getPacketAlign()362   SPIRVWord getPacketAlign() const {
363     return PacketAlign;
364   }
365 
getCapacity()366   SPIRVWord getCapacity() const {
367     return Capacity;
368   }
getRequiredCapability()369   SPIRVCapVec getRequiredCapability() const {
370     return getVec(CapabilityPipes, CapabilityPipeStorage);
371   }
372 protected:
373   SPIRVWord PacketSize;
374   SPIRVWord PacketAlign;
375   SPIRVWord Capacity;
validate()376   void validate() const {
377     SPIRVValue::validate();
378     assert(OpCode == OC);
379     assert(WordCount == WC);
380     assert(Type->isTypePipeStorage());
381   }
382   _SPIRV_DEF_ENCDEC5(Type, Id, PacketSize, PacketAlign, Capacity)
383 };
384 
385 class SPIRVForward:public SPIRVValue, public SPIRVComponentExecutionModes {
386 public:
387   const static Op OC = OpForward;
388   // Complete constructor
SPIRVForward(SPIRVModule * TheModule,SPIRVType * TheTy,SPIRVId TheId)389   SPIRVForward(SPIRVModule *TheModule, SPIRVType *TheTy, SPIRVId TheId):
390     SPIRVValue(TheModule, 0, OC, TheId){
391     if (TheTy)
392       setType(TheTy);
393   }
SPIRVForward()394   SPIRVForward():SPIRVValue(OC) {
395     assert(0 && "should never be called");
396   }
_SPIRV_DEF_ENCDEC1(Id)397   _SPIRV_DEF_ENCDEC1(Id)
398   friend class SPIRVFunction;
399 protected:
400   void validate() const {}
401 };
402 
403 }
404 
405 
406 #endif /* SPIRVVALUE_HPP_ */
407