Home | History | Annotate | Download | only in libSPIRV
      1 //===- SPIRVEntry.h - Base Class for SPIR-V Entities -------------*- 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 base class for SPIRV entities.
     37 ///
     38 //===----------------------------------------------------------------------===//
     39 
     40 #ifndef SPIRVENTRY_HPP_
     41 #define SPIRVENTRY_HPP_
     42 
     43 #include "SPIRVEnum.h"
     44 #include "SPIRVIsValidEnum.h"
     45 #include "SPIRVError.h"
     46 #include <cassert>
     47 #include <iostream>
     48 #include <map>
     49 #include <memory>
     50 #include <set>
     51 #include <string>
     52 #include <vector>
     53 
     54 namespace SPIRV{
     55 
     56 class SPIRVModule;
     57 class SPIRVEncoder;
     58 class SPIRVDecoder;
     59 class SPIRVType;
     60 class SPIRVValue;
     61 class SPIRVDecorate;
     62 class SPIRVForward;
     63 class SPIRVMemberDecorate;
     64 class SPIRVLine;
     65 class SPIRVString;
     66 class SPIRVExtInst;
     67 
     68 // Add declaration of encode/decode functions to a class.
     69 // Used inside class definition.
     70 #define _SPIRV_DCL_ENCDEC \
     71     void encode(spv_ostream &O) const; \
     72     void decode(std::istream &I);
     73 
     74 #define _REQ_SPIRV_VER(Version) \
     75     SPIRVWord getRequiredSPIRVVersion() const override { return Version; }
     76 
     77 // Add implementation of encode/decode functions to a class.
     78 // Used out side of class definition.
     79 #define _SPIRV_IMP_ENCDEC0(Ty) \
     80     void Ty::encode(spv_ostream &O) const {} \
     81     void Ty::decode(std::istream &I) {}
     82 #define _SPIRV_IMP_ENCDEC1(Ty,x) \
     83     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x; } \
     84     void Ty::decode(std::istream &I) { getDecoder(I) >> x;}
     85 #define _SPIRV_IMP_ENCDEC2(Ty,x,y) \
     86     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y; } \
     87     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y;}
     88 #define _SPIRV_IMP_ENCDEC3(Ty,x,y,z) \
     89     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z; } \
     90     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z;}
     91 #define _SPIRV_IMP_ENCDEC4(Ty,x,y,z,u) \
     92     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
     93       u; } \
     94     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u;}
     95 #define _SPIRV_IMP_ENCDEC5(Ty,x,y,z,u,v) \
     96     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
     97       u << v; } \
     98     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v;}
     99 #define _SPIRV_IMP_ENCDEC6(Ty,x,y,z,u,v,w) \
    100     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
    101       u << v << w; } \
    102     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
    103       v >> w;}
    104 #define _SPIRV_IMP_ENCDEC7(Ty,x,y,z,u,v,w,r) \
    105     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
    106       u << v << w << r; } \
    107     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
    108       v >> w >> r;}
    109 #define _SPIRV_IMP_ENCDEC8(Ty,x,y,z,u,v,w,r,s) \
    110     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
    111       u << v << w << r << s; } \
    112     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
    113       v >> w >> r >> s;}
    114 #define _SPIRV_IMP_ENCDEC9(Ty,x,y,z,u,v,w,r,s,t) \
    115     void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
    116       u << v << w << r << s << t; } \
    117     void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
    118       v >> w >> r >> s >> t;}
    119 
    120 // Add definition of encode/decode functions to a class.
    121 // Used inside class definition.
    122 #define _SPIRV_DEF_ENCDEC0 \
    123     void encode(spv_ostream &O) const {} \
    124     void decode(std::istream &I) {}
    125 #define _SPIRV_DEF_ENCDEC1(x) \
    126     void encode(spv_ostream &O) const { getEncoder(O) << x; } \
    127     void decode(std::istream &I) { getDecoder(I) >> x;}
    128 #define _SPIRV_DEF_ENCDEC2(x,y) \
    129     void encode(spv_ostream &O) const { getEncoder(O) << x << y; } \
    130     void decode(std::istream &I) { getDecoder(I) >> x >> y;}
    131 #define _SPIRV_DEF_ENCDEC3(x,y,z) \
    132     void encode(spv_ostream &O) const { getEncoder(O) << x << y << z; } \
    133     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z;}
    134 #define _SPIRV_DEF_ENCDEC4(x,y,z,u) \
    135     void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u; } \
    136     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u;}
    137 #define _SPIRV_DEF_ENCDEC5(x,y,z,u,v) \
    138     void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
    139       v; } \
    140     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v;}
    141 #define _SPIRV_DEF_ENCDEC6(x,y,z,u,v,w) \
    142     void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
    143       v << w; } \
    144     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> w;}
    145 #define _SPIRV_DEF_ENCDEC7(x,y,z,u,v,w,r) \
    146     void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
    147       v << w << r; } \
    148     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> \
    149       w >> r;}
    150 #define _SPIRV_DEF_ENCDEC8(x,y,z,u,v,w,r,s) \
    151     void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
    152       v << w << r << s; } \
    153     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> \
    154       w >> r >> s;}
    155 #define _SPIRV_DEF_ENCDEC9(x,y,z,u,v,w,r,s,t) \
    156     void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
    157       v << w << r << s << t; } \
    158     void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> \
    159       w >> r >> s >> t;}
    160 
    161 /// All SPIR-V in-memory-representation entities inherits from SPIRVEntry.
    162 /// Usually there are two flavors of constructors of SPIRV objects:
    163 ///
    164 /// 1. complete constructor: It requires all the parameters needed to create a
    165 ///    SPIRV entity with complete information which can be validated. It is
    166 ///    usually used by LLVM/SPIR-V translator to create SPIRV object
    167 ///    corresponding to LLVM object. Such constructor calls validate() at
    168 ///    the end of the construction.
    169 ///
    170 /// 2. incomplete constructor: For leaf classes, it has no parameters.
    171 ///    It is usually called by SPIRVEntry::make(opcode) to create an incomplete
    172 ///    object which should not be validated. Then setWordCount(count) is
    173 ///    called to fix the size of the object if it is variable, and then the
    174 ///    information is filled by the virtual function decode(istream).
    175 ///    After that the object can be validated.
    176 ///
    177 /// To add a new SPIRV class:
    178 ///
    179 /// 1. It is recommended to name the class as SPIRVXXX if it has a fixed op code
    180 ///    OpXXX. Although it is not mandatory, doing this facilitates adding it to
    181 ///    the table of the factory function SPIRVEntry::create().
    182 /// 2. Inherit from proper SPIRV class such as SPIRVType, SPIRVValue,
    183 ///    SPIRVInstruction, etc.
    184 /// 3. Implement virtual function encode(), decode(), validate().
    185 /// 4. If the object has variable size, implement virtual function
    186 ///    setWordCount().
    187 /// 5. If the class has special attributes, e.g. having no id, or having no
    188 ///    type as a value, set them in the constructors.
    189 /// 6. If the class may represent SPIRV entity which has been added in version
    190 ///    later than 1.0, implement virtual function getRequiredSPIRVVersion().
    191 ///    To automaticly update module's version you can also call protected
    192 ///    function updateModuleVersion() in the constructor.
    193 /// 7. Add the class to the Table of SPIRVEntry::create().
    194 /// 8. Add the class to SPIRVToLLVM and LLVMToSPIRV.
    195 
    196 class SPIRVEntry {
    197 public:
    198   enum SPIRVEntryAttrib {
    199     SPIRVEA_DEFAULT     = 0,
    200     SPIRVEA_NOID        = 1,      // Entry has no valid id
    201     SPIRVEA_NOTYPE      = 2,      // Value has no type
    202   };
    203 
    204   // Complete constructor for objects with id
    205   SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
    206       SPIRVId TheId)
    207     :Module(M), OpCode(TheOpCode), Id(TheId), Attrib(SPIRVEA_DEFAULT),
    208      WordCount(TheWordCount), Line(nullptr){
    209     validate();
    210   }
    211 
    212   // Complete constructor for objects without id
    213   SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode)
    214     :Module(M), OpCode(TheOpCode), Id(SPIRVID_INVALID), Attrib(SPIRVEA_NOID),
    215      WordCount(TheWordCount), Line(nullptr){
    216     validate();
    217   }
    218 
    219   // Incomplete constructor
    220   SPIRVEntry(Op TheOpCode)
    221     :Module(NULL), OpCode(TheOpCode), Id(SPIRVID_INVALID),
    222      Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){}
    223 
    224   SPIRVEntry()
    225     :Module(NULL), OpCode(OpNop), Id(SPIRVID_INVALID),
    226      Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){}
    227 
    228 
    229   virtual ~SPIRVEntry(){}
    230 
    231   bool exist(SPIRVId)const;
    232   template<class T>
    233   T* get(SPIRVId TheId)const { return static_cast<T*>(getEntry(TheId));}
    234   SPIRVEntry *getEntry(SPIRVId) const;
    235   SPIRVEntry *getOrCreate(SPIRVId TheId) const;
    236   SPIRVValue *getValue(SPIRVId TheId)const;
    237   std::vector<SPIRVValue *> getValues(const std::vector<SPIRVId>&)const;
    238   std::vector<SPIRVId> getIds(const std::vector<SPIRVValue *>)const;
    239   SPIRVType *getValueType(SPIRVId TheId)const;
    240   std::vector<SPIRVType *> getValueTypes(const std::vector<SPIRVId>&)const;
    241 
    242   virtual SPIRVDecoder getDecoder(std::istream &);
    243   virtual SPIRVEncoder getEncoder(spv_ostream &)const;
    244   SPIRVErrorLog &getErrorLog()const;
    245   SPIRVId getId() const { assert(hasId()); return Id;}
    246   SPIRVLine *getLine() const { return Line;}
    247   SPIRVLinkageTypeKind getLinkageType() const;
    248   Op getOpCode() const { return OpCode;}
    249   SPIRVModule *getModule() const { return Module;}
    250   virtual SPIRVCapVec getRequiredCapability() const { return SPIRVCapVec();}
    251   const std::string& getName() const { return Name;}
    252   bool hasDecorate(Decoration Kind, size_t Index = 0,
    253       SPIRVWord *Result=0)const;
    254   std::set<SPIRVWord> getDecorate(Decoration Kind, size_t Index = 0)const;
    255   bool hasId() const { return !(Attrib & SPIRVEA_NOID);}
    256   bool hasLine() const { return Line != nullptr;}
    257   bool hasLinkageType() const;
    258   bool isAtomic() const { return isAtomicOpCode(OpCode);}
    259   bool isBasicBlock() const { return isLabel();}
    260   bool isBuiltinCall() const { return OpCode == OpExtInst;}
    261   bool isDecorate()const { return OpCode == OpDecorate;}
    262   bool isMemberDecorate()const { return OpCode == OpMemberDecorate;}
    263   bool isForward() const { return OpCode == OpForward;}
    264   bool isLabel() const { return OpCode == OpLabel;}
    265   bool isUndef() const { return OpCode == OpUndef;}
    266   bool isControlBarrier() const { return OpCode == OpControlBarrier;}
    267   bool isMemoryBarrier() const { return OpCode == OpMemoryBarrier;}
    268   bool isVariable() const { return OpCode == OpVariable;}
    269   virtual bool isInst() const { return false;}
    270   virtual bool isOperandLiteral(unsigned Index) const {
    271     assert(0 && "not implemented");
    272     return false;
    273   }
    274 
    275   void addDecorate(const SPIRVDecorate *);
    276   void addDecorate(Decoration Kind);
    277   void addDecorate(Decoration Kind, SPIRVWord Literal);
    278   void eraseDecorate(Decoration);
    279   void addMemberDecorate(const SPIRVMemberDecorate *);
    280   void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind);
    281   void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind,
    282       SPIRVWord Literal);
    283   void eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Kind);
    284   void setHasNoId() { Attrib |= SPIRVEA_NOID;}
    285   void setId(SPIRVId TheId) { Id = TheId;}
    286   void setLine(SPIRVLine*);
    287   void setLinkageType(SPIRVLinkageTypeKind);
    288   void setModule(SPIRVModule *TheModule);
    289   void setName(const std::string& TheName);
    290   virtual void setScope(SPIRVEntry *Scope){};
    291   void takeAnnotations(SPIRVForward *);
    292   void takeDecorates(SPIRVEntry *);
    293   void takeMemberDecorates(SPIRVEntry *);
    294   void takeLine(SPIRVEntry *);
    295 
    296   /// After a SPIRV entry is created during reading SPIRV binary by default
    297   /// constructor, this function is called to allow the SPIRV entry to resize
    298   /// its variable sized member before decoding the remaining words.
    299   virtual void setWordCount(SPIRVWord TheWordCount);
    300 
    301   /// Create an empty SPIRV object by op code, e.g. OpTypeInt creates
    302   /// SPIRVTypeInt.
    303   static SPIRVEntry *create(Op);
    304   static std::unique_ptr<SPIRVEntry> create_unique(Op);
    305 
    306   /// Create an empty extended instruction.
    307   static std::unique_ptr<SPIRVExtInst> create_unique(
    308       SPIRVExtInstSetKind Set,
    309       unsigned ExtOp);
    310 
    311   friend spv_ostream &operator<<(spv_ostream &O, const SPIRVEntry &E);
    312   friend std::istream &operator>>(std::istream &I, SPIRVEntry &E);
    313   virtual void encodeAll(spv_ostream &O) const;
    314   virtual void encodeName(spv_ostream &O) const;
    315   virtual void encodeChildren(spv_ostream &O)const;
    316   virtual void encodeDecorate(spv_ostream &O)const;
    317   virtual void encodeWordCountOpCode(spv_ostream &O)const;
    318   virtual void encode(spv_ostream &O) const;
    319   virtual void decode(std::istream &I);
    320 
    321   friend class SPIRVDecoder;
    322 
    323   /// Checks the integrity of the object.
    324   virtual void validate()const {
    325     assert(Module && "Invalid module");
    326     assert(OpCode != OpNop && "Invalid op code");
    327     assert((!hasId() || isValidId(Id)) && "Invalid Id");
    328   }
    329   void validateFunctionControlMask(SPIRVWord FCtlMask)const;
    330   void validateValues(const std::vector<SPIRVId> &)const;
    331   void validateBuiltin(SPIRVWord, SPIRVWord)const;
    332 
    333   // By default assume SPIRV 1.0 as required version
    334   virtual SPIRVWord getRequiredSPIRVVersion() const { return SPIRV_1_0; }
    335 
    336   virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
    337     return std::vector<SPIRVEntry*>();
    338   }
    339 
    340 protected:
    341   /// An entry may have multiple FuncParamAttr decorations.
    342   typedef std::multimap<Decoration, const SPIRVDecorate*> DecorateMapType;
    343   typedef std::map<std::pair<SPIRVWord, Decoration>,
    344       const SPIRVMemberDecorate*> MemberDecorateMapType;
    345 
    346   bool canHaveMemberDecorates() const {
    347     return OpCode == OpTypeStruct ||
    348         OpCode == OpForward;
    349   }
    350   MemberDecorateMapType& getMemberDecorates() {
    351     assert(canHaveMemberDecorates());
    352     return MemberDecorates;
    353   }
    354 
    355   void updateModuleVersion() const;
    356 
    357   SPIRVModule *Module;
    358   Op OpCode;
    359   SPIRVId Id;
    360   std::string Name;
    361   unsigned Attrib;
    362   SPIRVWord WordCount;
    363 
    364   DecorateMapType Decorates;
    365   MemberDecorateMapType MemberDecorates;
    366   SPIRVLine *Line;
    367 };
    368 
    369 class SPIRVEntryNoIdGeneric:public SPIRVEntry {
    370 public:
    371   SPIRVEntryNoIdGeneric(SPIRVModule *M, unsigned TheWordCount, Op OC)
    372     :SPIRVEntry(M, TheWordCount, OC){
    373     setAttr();
    374   }
    375   SPIRVEntryNoIdGeneric(Op OC):SPIRVEntry(OC){
    376     setAttr();
    377   }
    378 protected:
    379   void setAttr() {
    380     setHasNoId();
    381   }
    382 };
    383 
    384 template<Op OC>
    385 class SPIRVEntryNoId:public SPIRVEntryNoIdGeneric {
    386 public:
    387   SPIRVEntryNoId(SPIRVModule *M, unsigned TheWordCount)
    388     :SPIRVEntryNoIdGeneric(M, TheWordCount, OC){}
    389   SPIRVEntryNoId():SPIRVEntryNoIdGeneric(OC){}
    390 };
    391 
    392 template<Op TheOpCode>
    393 class SPIRVEntryOpCodeOnly:public SPIRVEntryNoId<TheOpCode> {
    394 public:
    395   SPIRVEntryOpCodeOnly(){
    396     SPIRVEntry::WordCount = 1;
    397     validate();
    398   }
    399 protected:
    400   _SPIRV_DEF_ENCDEC0
    401   void validate()const {
    402     assert(isValidId(SPIRVEntry::OpCode));
    403   }
    404 };
    405 
    406 class SPIRVAnnotationGeneric:public SPIRVEntryNoIdGeneric {
    407 public:
    408   // Complete constructor
    409   SPIRVAnnotationGeneric(SPIRVModule *TheModule, unsigned TheWordCount, Op OC,
    410                          SPIRVId TheTarget = SPIRVID_INVALID)
    411       : SPIRVEntryNoIdGeneric(TheModule, TheWordCount, OC), Target(TheTarget) {}
    412   // Incomplete constructor
    413   SPIRVAnnotationGeneric(Op OC):SPIRVEntryNoIdGeneric(OC),
    414       Target(SPIRVID_INVALID){}
    415 
    416   SPIRVId getTargetId()const { return Target;}
    417   SPIRVForward *getOrCreateTarget()const;
    418   void setTargetId(SPIRVId T) { Target = T;}
    419 protected:
    420   SPIRVId Target;
    421 };
    422 
    423 template<Op OC>
    424 class SPIRVAnnotation:public SPIRVAnnotationGeneric {
    425 public:
    426   // Complete constructor
    427   SPIRVAnnotation(const SPIRVEntry *TheTarget, unsigned TheWordCount)
    428       : SPIRVAnnotationGeneric(TheTarget->getModule(), TheWordCount, OC,
    429                                TheTarget->getId()) {}
    430   // Incomplete constructor
    431   SPIRVAnnotation():SPIRVAnnotationGeneric(OC){}
    432 };
    433 
    434 class SPIRVEntryPoint:public SPIRVAnnotation<OpEntryPoint> {
    435 public:
    436   SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind,
    437       SPIRVId TheId, const std::string &TheName);
    438   SPIRVEntryPoint():ExecModel(ExecutionModelKernel){}
    439   _SPIRV_DCL_ENCDEC
    440 protected:
    441   SPIRVExecutionModelKind ExecModel;
    442   std::string Name;
    443 };
    444 
    445 
    446 class SPIRVName:public SPIRVAnnotation<OpName> {
    447 public:
    448   // Complete constructor
    449   SPIRVName(const SPIRVEntry *TheTarget, const std::string& TheStr);
    450   // Incomplete constructor
    451   SPIRVName(){}
    452 protected:
    453   _SPIRV_DCL_ENCDEC
    454   void validate() const;
    455 
    456   std::string Str;
    457 };
    458 
    459 class SPIRVMemberName:public SPIRVAnnotation<OpName> {
    460 public:
    461   static const SPIRVWord FixedWC = 3;
    462   // Complete constructor
    463   SPIRVMemberName(const SPIRVEntry *TheTarget, SPIRVWord TheMemberNumber,
    464       const std::string& TheStr)
    465     :SPIRVAnnotation(TheTarget, FixedWC + getSizeInWords(TheStr)),
    466      MemberNumber(TheMemberNumber), Str(TheStr){
    467     validate();
    468   }
    469   // Incomplete constructor
    470   SPIRVMemberName():MemberNumber(SPIRVWORD_MAX){}
    471 protected:
    472   _SPIRV_DCL_ENCDEC
    473   void validate() const;
    474   SPIRVWord MemberNumber;
    475   std::string Str;
    476 };
    477 
    478 class SPIRVString:public SPIRVEntry {
    479   static const Op OC = OpString;
    480   static const SPIRVWord FixedWC = 2;
    481 public:
    482   SPIRVString(SPIRVModule *M, SPIRVId TheId, const std::string &TheStr)
    483     :SPIRVEntry(M, FixedWC + getSizeInWords(TheStr), OC, TheId), Str(TheStr){}
    484   SPIRVString():SPIRVEntry(OC){}
    485   _SPIRV_DCL_ENCDEC
    486   const std::string &getStr()const { return Str;}
    487 protected:
    488   std::string Str;
    489 };
    490 
    491 class SPIRVLine:public SPIRVAnnotation<OpLine> {
    492 public:
    493   static const SPIRVWord WC = 5;
    494   // Complete constructor
    495   SPIRVLine(const SPIRVEntry *TheTarget, SPIRVId TheFileName, SPIRVWord TheLine,
    496       SPIRVWord TheColumn)
    497     :SPIRVAnnotation(TheTarget, WC), FileName(TheFileName), Line(TheLine),
    498      Column(TheColumn){
    499     validate();
    500   }
    501   // Incomplete constructor
    502   SPIRVLine():FileName(SPIRVID_INVALID), Line(SPIRVWORD_MAX),
    503       Column(SPIRVWORD_MAX){}
    504 
    505   SPIRVWord getColumn() const {
    506     return Column;
    507   }
    508 
    509   void setColumn(SPIRVWord column) {
    510     Column = column;
    511   }
    512 
    513   SPIRVId getFileName() const {
    514     return FileName;
    515   }
    516 
    517   const std::string &getFileNameStr() const {
    518     return get<SPIRVString>(FileName)->getStr();
    519   }
    520 
    521   void setFileName(SPIRVId fileName) {
    522     FileName = fileName;
    523   }
    524 
    525   SPIRVWord getLine() const {
    526     return Line;
    527   }
    528 
    529   void setLine(SPIRVWord line) {
    530     Line = line;
    531   }
    532 
    533 protected:
    534   _SPIRV_DCL_ENCDEC
    535   void validate() const;
    536   SPIRVId FileName;
    537   SPIRVWord Line;
    538   SPIRVWord Column;
    539 };
    540 
    541 class SPIRVExecutionMode:public SPIRVAnnotation<OpExecutionMode> {
    542 public:
    543   // Complete constructor for LocalSize, LocalSizeHint
    544   SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode,
    545       SPIRVWord x, SPIRVWord y, SPIRVWord z)
    546   :SPIRVAnnotation(TheTarget, 6), ExecMode(TheExecMode){
    547     WordLiterals.push_back(x);
    548     WordLiterals.push_back(y);
    549     WordLiterals.push_back(z);
    550     updateModuleVersion();
    551   }
    552   // Complete constructor for VecTypeHint, SubgroupSize, SubgroupsPerWorkgroup
    553   SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode,
    554       SPIRVWord code)
    555   :SPIRVAnnotation(TheTarget, 4), ExecMode(TheExecMode){
    556     WordLiterals.push_back(code);
    557     updateModuleVersion();
    558   }
    559   // Complete constructor for ContractionOff
    560   SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode)
    561   :SPIRVAnnotation(TheTarget, 3), ExecMode(TheExecMode){
    562     updateModuleVersion();
    563   }
    564   // Incomplete constructor
    565   SPIRVExecutionMode():ExecMode(ExecutionModeInvocations){}
    566   SPIRVExecutionModeKind getExecutionMode()const { return ExecMode;}
    567   const std::vector<SPIRVWord>& getLiterals()const { return WordLiterals;}
    568   SPIRVCapVec getRequiredCapability() const {
    569     return getCapability(ExecMode);
    570   }
    571 
    572   SPIRVWord getRequiredSPIRVVersion() const override {
    573     switch (ExecMode) {
    574     case ExecutionModeFinalizer:
    575     case ExecutionModeInitializer:
    576     case ExecutionModeSubgroupSize:
    577     case ExecutionModeSubgroupsPerWorkgroup:
    578       return SPIRV_1_1;
    579 
    580     default:
    581       return SPIRV_1_0;
    582     }
    583   }
    584 
    585 protected:
    586   _SPIRV_DCL_ENCDEC
    587   SPIRVExecutionModeKind ExecMode;
    588   std::vector<SPIRVWord> WordLiterals;
    589 };
    590 
    591 
    592 class SPIRVComponentExecutionModes {
    593   typedef std::map<SPIRVExecutionModeKind, SPIRVExecutionMode*>
    594     SPIRVExecutionModeMap;
    595 public:
    596   void addExecutionMode(SPIRVExecutionMode *ExecMode) {
    597     ExecModes[ExecMode->getExecutionMode()] = ExecMode;
    598   }
    599   SPIRVExecutionMode *getExecutionMode(SPIRVExecutionModeKind EMK)const {
    600     auto Loc = ExecModes.find(EMK);
    601     if (Loc == ExecModes.end())
    602       return nullptr;
    603     return Loc->second;
    604   }
    605 protected:
    606   SPIRVExecutionModeMap ExecModes;
    607 };
    608 
    609 class SPIRVExtInstImport:public SPIRVEntry {
    610 public:
    611   const static Op OC = OpExtInstImport;
    612   // Complete constructor
    613   SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId,
    614       const std::string& TheStr);
    615   // Incomplete constructor
    616   SPIRVExtInstImport():SPIRVEntry(OC){}
    617 protected:
    618   _SPIRV_DCL_ENCDEC
    619   void validate() const;
    620 
    621   std::string Str;
    622 };
    623 
    624 class SPIRVMemoryModel:public SPIRVEntryNoId<OpMemoryModel> {
    625 public:
    626   SPIRVMemoryModel(SPIRVModule *M):SPIRVEntryNoId(M, 3){}
    627   SPIRVMemoryModel(){}
    628   _SPIRV_DCL_ENCDEC
    629   void validate() const;
    630 };
    631 
    632 class SPIRVSource:public SPIRVEntryNoId<OpSource> {
    633 public:
    634   SPIRVSource(SPIRVModule *M):SPIRVEntryNoId(M, 3){}
    635   SPIRVSource(){}
    636   _SPIRV_DCL_ENCDEC
    637 };
    638 
    639 class SPIRVSourceExtension:public SPIRVEntryNoId<OpSourceExtension> {
    640 public:
    641   SPIRVSourceExtension(SPIRVModule *M, const std::string &SS);
    642   SPIRVSourceExtension(){}
    643   _SPIRV_DCL_ENCDEC
    644 private:
    645   std::string S;
    646 };
    647 
    648 class SPIRVExtension:public SPIRVEntryNoId<OpExtension> {
    649 public:
    650   SPIRVExtension(SPIRVModule *M, const std::string &SS);
    651   SPIRVExtension(){}
    652   _SPIRV_DCL_ENCDEC
    653 private:
    654   std::string S;
    655 };
    656 
    657 class SPIRVCapability:public SPIRVEntryNoId<OpCapability> {
    658 public:
    659   SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K);
    660   SPIRVCapability():Kind(CapabilityMatrix){}
    661   _SPIRV_DCL_ENCDEC
    662 
    663   SPIRVWord getRequiredSPIRVVersion() const override {
    664     switch (Kind) {
    665     case CapabilityNamedBarrier:
    666     case CapabilitySubgroupDispatch:
    667     case CapabilityPipeStorage:
    668       return SPIRV_1_1;
    669 
    670     default:
    671       return SPIRV_1_0;
    672     }
    673   }
    674 private:
    675   SPIRVCapabilityKind Kind;
    676 };
    677 
    678 template<class T>
    679 T* bcast(SPIRVEntry *E) {
    680   return static_cast<T*>(E);
    681 }
    682 
    683 // ToDo: The following typedef's are place holders for SPIRV entity classes
    684 // to be implemented.
    685 // Each time a new class is implemented, remove the corresponding typedef.
    686 // This is also an indication of how much work is left.
    687 #define _SPIRV_OP(x, ...) typedef SPIRVEntryOpCodeOnly<Op##x> SPIRV##x;
    688 _SPIRV_OP(Nop)
    689 _SPIRV_OP(SourceContinued, 2)
    690 _SPIRV_OP(TypeMatrix)
    691 _SPIRV_OP(TypeRuntimeArray)
    692 _SPIRV_OP(SpecConstantTrue)
    693 _SPIRV_OP(SpecConstantFalse)
    694 _SPIRV_OP(SpecConstant)
    695 _SPIRV_OP(SpecConstantComposite)
    696 _SPIRV_OP(Image)
    697 _SPIRV_OP(ImageTexelPointer)
    698 _SPIRV_OP(CompositeConstruct)
    699 _SPIRV_OP(ImageSampleDrefImplicitLod)
    700 _SPIRV_OP(ImageSampleDrefExplicitLod)
    701 _SPIRV_OP(ImageSampleProjImplicitLod)
    702 _SPIRV_OP(ImageSampleProjExplicitLod)
    703 _SPIRV_OP(ImageSampleProjDrefImplicitLod)
    704 _SPIRV_OP(ImageSampleProjDrefExplicitLod)
    705 _SPIRV_OP(ImageFetch)
    706 _SPIRV_OP(ImageGather)
    707 _SPIRV_OP(ImageDrefGather)
    708 _SPIRV_OP(QuantizeToF16)
    709 _SPIRV_OP(Transpose)
    710 _SPIRV_OP(ArrayLength)
    711 _SPIRV_OP(SMod)
    712 _SPIRV_OP(FMod)
    713 _SPIRV_OP(VectorTimesScalar)
    714 _SPIRV_OP(MatrixTimesScalar)
    715 _SPIRV_OP(VectorTimesMatrix)
    716 _SPIRV_OP(MatrixTimesVector)
    717 _SPIRV_OP(MatrixTimesMatrix)
    718 _SPIRV_OP(OuterProduct)
    719 _SPIRV_OP(IAddCarry)
    720 _SPIRV_OP(ISubBorrow)
    721 _SPIRV_OP(SMulExtended)
    722 _SPIRV_OP(UMulExtended)
    723 _SPIRV_OP(BitFieldInsert)
    724 _SPIRV_OP(BitFieldSExtract)
    725 _SPIRV_OP(BitFieldUExtract)
    726 _SPIRV_OP(BitReverse)
    727 _SPIRV_OP(BitCount)
    728 _SPIRV_OP(DPdx)
    729 _SPIRV_OP(DPdy)
    730 _SPIRV_OP(Fwidth)
    731 _SPIRV_OP(DPdxFine)
    732 _SPIRV_OP(DPdyFine)
    733 _SPIRV_OP(FwidthFine)
    734 _SPIRV_OP(DPdxCoarse)
    735 _SPIRV_OP(DPdyCoarse)
    736 _SPIRV_OP(FwidthCoarse)
    737 _SPIRV_OP(EmitVertex)
    738 _SPIRV_OP(EndPrimitive)
    739 _SPIRV_OP(EmitStreamVertex)
    740 _SPIRV_OP(EndStreamPrimitive)
    741 _SPIRV_OP(LoopMerge)
    742 _SPIRV_OP(SelectionMerge)
    743 _SPIRV_OP(Kill)
    744 _SPIRV_OP(Unreachable)
    745 _SPIRV_OP(LifetimeStart)
    746 _SPIRV_OP(LifetimeStop)
    747 _SPIRV_OP(ImageSparseSampleImplicitLod, 305)
    748 _SPIRV_OP(ImageSparseSampleExplicitLod, 306)
    749 _SPIRV_OP(ImageSparseSampleDrefImplicitLod, 307)
    750 _SPIRV_OP(ImageSparseSampleDrefExplicitLod, 308)
    751 _SPIRV_OP(ImageSparseSampleProjImplicitLod, 309)
    752 _SPIRV_OP(ImageSparseSampleProjExplicitLod, 310)
    753 _SPIRV_OP(ImageSparseSampleProjDrefImplicitLod, 311)
    754 _SPIRV_OP(ImageSparseSampleProjDrefExplicitLod, 312)
    755 _SPIRV_OP(ImageSparseFetch, 313)
    756 _SPIRV_OP(ImageSparseGather, 314)
    757 _SPIRV_OP(ImageSparseDrefGather, 315)
    758 _SPIRV_OP(ImageSparseTexelsResident, 316)
    759 _SPIRV_OP(NoLine, 317)
    760 _SPIRV_OP(TypeNamedBarrier)
    761 _SPIRV_OP(NamedBarrierInitialize)
    762 _SPIRV_OP(MemoryNamedBarrier)
    763 _SPIRV_OP(GetKernelMaxNumSubgroups)
    764 _SPIRV_OP(GetKernelLocalSizeForSubgroupCount)
    765 _SPIRV_OP(SizeOf)
    766 #undef _SPIRV_OP
    767 
    768 }
    769 #endif /* SPIRVENTRY_HPP_ */
    770