Home | History | Annotate | Download | only in libSPIRV
      1 //===- SPIRVInstruction.h - Class to represent SPIRV instruction -*- 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 Instruction class for SPIR-V.
     37 ///
     38 //===----------------------------------------------------------------------===//
     39 
     40 #ifndef SPIRVINSTRUCTION_HPP_
     41 #define SPIRVINSTRUCTION_HPP_
     42 
     43 #include "SPIRVEnum.h"
     44 #include "SPIRVIsValidEnum.h"
     45 #include "SPIRVStream.h"
     46 #include "SPIRVValue.h"
     47 #include "SPIRVBasicBlock.h"
     48 #include "SPIRVOpCode.h"
     49 
     50 #include <cassert>
     51 #include <cstdint>
     52 #include <functional>
     53 #include <iostream>
     54 #include <map>
     55 #include <utility>
     56 #include <vector>
     57 #include <unordered_set>
     58 
     59 namespace SPIRV{
     60 
     61 typedef std::vector<SPIRVValue *> ValueVec;
     62 typedef std::pair<ValueVec::iterator, ValueVec::iterator> ValueRange;
     63 
     64 class SPIRVBasicBlock;
     65 class SPIRVFunction;
     66 
     67 bool isSpecConstantOpAllowedOp(Op OC);
     68 
     69 class SPIRVComponentExecutionScope {
     70 public:
     71   SPIRVComponentExecutionScope(Scope TheScope = ScopeInvocation):
     72     ExecScope(TheScope){}
     73   Scope ExecScope;
     74 };
     75 
     76 class SPIRVComponentMemorySemanticsMask {
     77 public:
     78   SPIRVComponentMemorySemanticsMask(SPIRVWord TheSema = SPIRVWORD_MAX):
     79     MemSema(TheSema){}
     80   SPIRVWord MemSema;
     81 };
     82 
     83 class SPIRVComponentOperands {
     84 public:
     85   SPIRVComponentOperands(){};
     86   SPIRVComponentOperands(const std::vector<SPIRVValue *> &TheOperands):
     87     Operands(TheOperands){};
     88   SPIRVComponentOperands(std::vector<SPIRVValue *> &&TheOperands):
     89     Operands(std::move(TheOperands)){};
     90   std::vector<SPIRVValue *> getCompOperands() {
     91     return Operands;
     92   }
     93   std::vector<SPIRVType *> getCompOperandTypes() {
     94     std::vector<SPIRVType *> Tys;
     95     for (auto &I:getCompOperands())
     96       Tys.push_back(I->getType());
     97     return Tys;
     98   }
     99 protected:
    100   std::vector<SPIRVValue *> Operands;
    101 };
    102 
    103 class SPIRVInstruction: public SPIRVValue {
    104 public:
    105   // Complete constructor for instruction with type and id
    106   SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType,
    107       SPIRVId TheId, SPIRVBasicBlock *TheBB);
    108   // Complete constructor for instruction with module, type and id
    109   SPIRVInstruction(unsigned TheWordCount, Op TheOC,
    110       SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB,
    111       SPIRVModule *TheBM);
    112   // Complete constructor for instruction with id but no type
    113   SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVId TheId,
    114       SPIRVBasicBlock *TheBB);
    115   // Complete constructor for instruction without type and id
    116   SPIRVInstruction(unsigned TheWordCount, Op TheOC,
    117       SPIRVBasicBlock *TheBB);
    118   // Complete constructor for instruction with type but no id
    119   SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType,
    120       SPIRVBasicBlock *TheBB);
    121   // Incomplete constructor
    122   SPIRVInstruction(Op TheOC = OpNop):SPIRVValue(TheOC), BB(NULL){}
    123 
    124   virtual bool isInst() const { return true;}
    125   SPIRVBasicBlock *getParent() const {return BB;}
    126   SPIRVInstruction *getPrevious() const { return BB->getPrevious(this);}
    127   SPIRVInstruction *getNext() const { return BB->getNext(this);}
    128   virtual std::vector<SPIRVValue *> getOperands();
    129   std::vector<SPIRVType*> getOperandTypes();
    130   static std::vector<SPIRVType*> getOperandTypes(
    131       const std::vector<SPIRVValue *> &Ops);
    132 
    133   void setParent(SPIRVBasicBlock *);
    134   void setScope(SPIRVEntry *);
    135   void addFPRoundingMode(SPIRVFPRoundingModeKind Kind) {
    136     addDecorate(DecorationFPRoundingMode, Kind);
    137   }
    138   void eraseFPRoundingMode() {
    139     eraseDecorate(DecorationFPRoundingMode);
    140   }
    141   void setSaturatedConversion(bool Enable) {
    142     if (Enable)
    143       addDecorate(DecorationSaturatedConversion);
    144     else
    145       eraseDecorate(DecorationSaturatedConversion);
    146   }
    147   bool hasFPRoundingMode(SPIRVFPRoundingModeKind *Kind = nullptr) {
    148     SPIRVWord V;
    149     auto Found = hasDecorate(DecorationFPRoundingMode, 0, &V);
    150     if (Found && Kind)
    151       *Kind = static_cast<SPIRVFPRoundingModeKind>(V);
    152     return Found;
    153   }
    154   bool isSaturatedConversion() {
    155     return hasDecorate(DecorationSaturatedConversion) ||
    156         OpCode == OpSatConvertSToU ||
    157         OpCode == OpSatConvertUToS;
    158   }
    159 
    160   SPIRVBasicBlock* getBasicBlock() const {
    161     return BB;
    162   }
    163 
    164   void setBasicBlock(SPIRVBasicBlock* TheBB) {
    165     BB = TheBB;
    166     if (TheBB)
    167       setModule(TheBB->getModule());
    168   }
    169 
    170 protected:
    171   void validate()const {
    172     SPIRVValue::validate();
    173   }
    174 private:
    175   SPIRVBasicBlock *BB;
    176 };
    177 
    178 class SPIRVInstTemplateBase:public SPIRVInstruction {
    179 public:
    180   /// Create an empty instruction. Mainly for getting format information,
    181   /// e.g. whether an operand is literal.
    182   static SPIRVInstTemplateBase *create(Op TheOC){
    183     auto Inst = static_cast<SPIRVInstTemplateBase *>(SPIRVEntry::create(TheOC));
    184     assert(Inst);
    185     Inst->init();
    186     return Inst;
    187   }
    188   /// Create a instruction without operands.
    189   static SPIRVInstTemplateBase *create(Op TheOC, SPIRVType *TheType,
    190       SPIRVId TheId, SPIRVBasicBlock *TheBB,
    191       SPIRVModule *TheModule){
    192     auto Inst = create(TheOC);
    193     Inst->init(TheType, TheId, TheBB, TheModule);
    194     return Inst;
    195   }
    196   /// Create a complete and valid instruction.
    197   static SPIRVInstTemplateBase *create(Op TheOC, SPIRVType *TheType,
    198       SPIRVId TheId, const std::vector<SPIRVWord> &TheOps, SPIRVBasicBlock *TheBB,
    199       SPIRVModule *TheModule){
    200     auto Inst = create(TheOC);
    201     Inst->init(TheType, TheId, TheBB, TheModule);
    202     Inst->setOpWords(TheOps);
    203     Inst->validate();
    204     return Inst;
    205   }
    206   SPIRVInstTemplateBase(Op OC = OpNop)
    207     :SPIRVInstruction(OC), HasVariWC(false){
    208     init();
    209   }
    210   virtual ~SPIRVInstTemplateBase(){}
    211   SPIRVInstTemplateBase *init(SPIRVType *TheType,
    212       SPIRVId TheId, SPIRVBasicBlock *TheBB,
    213       SPIRVModule *TheModule){
    214     assert((TheBB || TheModule) && "Invalid BB or Module");
    215     if (TheBB)
    216       setBasicBlock(TheBB);
    217     else {
    218       setModule(TheModule);
    219     }
    220     setId(hasId() ? TheId : SPIRVID_INVALID);
    221     setType(hasType() ? TheType : nullptr);
    222     return this;
    223   }
    224   virtual void init() {}
    225   virtual void initImpl(Op OC, bool HasId = true, SPIRVWord WC = 0,
    226       bool VariWC = false, unsigned Lit1 = ~0U,
    227       unsigned Lit2 = ~0U, unsigned Lit3 = ~0U){
    228     OpCode = OC;
    229     if (!HasId) {
    230       setHasNoId();
    231       setHasNoType();
    232     }
    233     if (WC)
    234       SPIRVEntry::setWordCount(WC);
    235     setHasVariableWordCount(VariWC);
    236     addLit(Lit1);
    237     addLit(Lit2);
    238     addLit(Lit3);
    239   }
    240   virtual bool isOperandLiteral(unsigned I) const {
    241     return Lit.count(I);
    242   }
    243   void addLit(unsigned L) {
    244     if (L != ~0U)
    245       Lit.insert(L);
    246   }
    247   /// \return Expected number of operands. If the instruction has variable
    248   /// number of words, return the minimum.
    249   SPIRVWord getExpectedNumOperands() const {
    250     assert(WordCount > 0 && "Word count not initialized");
    251     auto Exp = WordCount - 1;
    252     if (hasId())
    253       --Exp;
    254     if (hasType())
    255       --Exp;
    256     return Exp;
    257   }
    258   virtual void setOpWordsAndValidate(const std::vector<SPIRVWord> &TheOps) {
    259     setOpWords(TheOps);
    260     validate();
    261   }
    262   virtual void setOpWords(const std::vector<SPIRVWord> &TheOps) {
    263     SPIRVWord WC = TheOps.size() + 1;
    264     if (hasId())
    265       ++WC;
    266     if (hasType())
    267       ++WC;
    268     if (WordCount) {
    269       if (WordCount == WC) {
    270         // do nothing
    271       } else {
    272         assert(HasVariWC && WC >= WordCount && "Invalid word count");
    273         SPIRVEntry::setWordCount(WC);
    274       }
    275     } else
    276       SPIRVEntry::setWordCount(WC);
    277     Ops = TheOps;
    278   }
    279   virtual void setWordCount(SPIRVWord TheWordCount) {
    280     SPIRVEntry::setWordCount(TheWordCount);
    281     auto NumOps = WordCount - 1;
    282     if (hasId())
    283       --NumOps;
    284     if (hasType())
    285       --NumOps;
    286     Ops.resize(NumOps);
    287   }
    288 
    289   std::vector<SPIRVWord> &getOpWords() {
    290     return Ops;
    291   }
    292 
    293   const std::vector<SPIRVWord> &getOpWords() const {
    294     return Ops;
    295   }
    296 
    297   SPIRVWord getOpWord(int I) const {
    298     return Ops[I];
    299   }
    300 
    301   /// Get operand as value.
    302   /// If the operand is a literal, return it as a uint32 constant.
    303   SPIRVValue *getOpValue(int I) {
    304     return isOperandLiteral(I) ? Module->getLiteralAsConstant(Ops[I]) :
    305         getValue(Ops[I]);
    306   }
    307 
    308   // Get the offset of operands.
    309   // Some instructions skip literals when returning operands.
    310   size_t getOperandOffset() const {
    311     if (hasExecScope() && !isGroupOpCode(OpCode) && !isPipeOpCode(OpCode))
    312       return 1;
    313     return 0;
    314   }
    315 
    316   // Get operands which are values.
    317   // Drop execution scope and group operation literals.
    318   // Return other literals as uint32 constants.
    319   virtual std::vector<SPIRVValue *> getOperands() {
    320     std::vector<SPIRVValue*> VOps;
    321     auto Offset = getOperandOffset();
    322     for (size_t I = 0, E = Ops.size() - Offset; I != E; ++I)
    323       VOps.push_back(getOperand(I));
    324     return VOps;
    325   }
    326 
    327   virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
    328     std::vector<SPIRVEntry*> Operands;
    329     for (size_t I = getOperandOffset(), E = Ops.size(); I < E; ++I)
    330       if (!isOperandLiteral(I))
    331         Operands.push_back(getEntry(Ops[I]));
    332     return Operands;
    333   }
    334 
    335   virtual SPIRVValue *getOperand(unsigned I) {
    336     return getOpValue(I + getOperandOffset());
    337   }
    338 
    339   bool hasExecScope() const {
    340     return SPIRV::hasExecScope(OpCode);
    341   }
    342 
    343   bool hasGroupOperation() const {
    344     return SPIRV::hasGroupOperation(OpCode);
    345   }
    346 
    347   bool getSPIRVGroupOperation(SPIRVGroupOperationKind &GroupOp) const {
    348     if (!hasGroupOperation())
    349       return false;
    350     GroupOp = static_cast<SPIRVGroupOperationKind>(Ops[1]);
    351     return true;
    352   }
    353 
    354   Scope getExecutionScope() const {
    355     if(!hasExecScope())
    356       return ScopeInvocation;
    357     return static_cast<Scope>(
    358         static_cast<SPIRVConstant*>(getValue(Ops[0]))->getZExtIntValue());
    359   }
    360 
    361   bool hasVariableWordCount() const {
    362     return HasVariWC;
    363   }
    364 
    365   void setHasVariableWordCount(bool VariWC) {
    366     HasVariWC = VariWC;
    367   }
    368 
    369 protected:
    370   virtual void encode(spv_ostream &O) const {
    371     auto E = getEncoder(O);
    372     if (hasType())
    373       E << Type;
    374     if (hasId())
    375       E << Id;
    376     E << Ops;
    377   }
    378   virtual void decode(std::istream &I) {
    379     auto D = getDecoder(I);
    380     if (hasType())
    381       D >> Type;
    382     if (hasId())
    383       D >> Id;
    384     D >> Ops;
    385   }
    386   std::vector<SPIRVWord> Ops;
    387   bool HasVariWC;
    388   std::unordered_set<unsigned> Lit; // Literal operand index
    389 };
    390 
    391 template<typename BT        = SPIRVInstTemplateBase,
    392          Op OC              = OpNop,
    393          bool HasId         = true,
    394          SPIRVWord WC        = 0,
    395          bool HasVariableWC = false,
    396          unsigned Literal1  = ~0U,
    397          unsigned Literal2  = ~0U,
    398          unsigned Literal3  = ~0U>
    399 class SPIRVInstTemplate:public BT {
    400 public:
    401   typedef BT BaseTy;
    402   SPIRVInstTemplate(){
    403     init();
    404   }
    405   virtual ~SPIRVInstTemplate(){}
    406   virtual void init() {
    407     this->initImpl(OC, HasId, WC, HasVariableWC, Literal1, Literal2, Literal3);
    408   }
    409 };
    410 
    411 class SPIRVMemoryAccess {
    412 public:
    413   SPIRVMemoryAccess(const std::vector<SPIRVWord> &TheMemoryAccess):
    414     TheMemoryAccessMask(0), Alignment(0) {
    415     MemoryAccessUpdate(TheMemoryAccess);
    416   }
    417 
    418   SPIRVMemoryAccess() : TheMemoryAccessMask(0), Alignment(0){}
    419 
    420   void MemoryAccessUpdate(const std::vector<SPIRVWord> &MemoryAccess) {
    421     if (!MemoryAccess.size())
    422       return;
    423     assert((MemoryAccess.size() == 1 || MemoryAccess.size() == 2) && "Invalid memory access operand size");
    424     TheMemoryAccessMask = MemoryAccess[0];
    425     if (MemoryAccess[0] & MemoryAccessAlignedMask) {
    426       assert(MemoryAccess.size() == 2 && "Alignment operand is missing");
    427       Alignment = MemoryAccess[1];
    428     }
    429   }
    430   SPIRVWord isVolatile() const { return getMemoryAccessMask() & MemoryAccessVolatileMask; }
    431   SPIRVWord isNonTemporal() const { return getMemoryAccessMask() & MemoryAccessNontemporalMask; }
    432   SPIRVWord getMemoryAccessMask() const { return TheMemoryAccessMask; }
    433   SPIRVWord getAlignment() const { return Alignment; }
    434 
    435 protected:
    436   SPIRVWord TheMemoryAccessMask;
    437   SPIRVWord Alignment;
    438 };
    439 
    440 class SPIRVVariable : public SPIRVInstruction {
    441 public:
    442   // Complete constructor for integer constant
    443   SPIRVVariable(SPIRVType *TheType, SPIRVId TheId,
    444     SPIRVValue *TheInitializer, const std::string &TheName,
    445     SPIRVStorageClassKind TheStorageClass, SPIRVBasicBlock *TheBB,
    446     SPIRVModule *TheM)
    447     :SPIRVInstruction(TheInitializer ? 5 : 4, OpVariable, TheType,
    448         TheId, TheBB, TheM),
    449     StorageClass(TheStorageClass){
    450     if (TheInitializer)
    451       Initializer.push_back(TheInitializer->getId());
    452     Name = TheName;
    453     validate();
    454   }
    455   // Incomplete constructor
    456   SPIRVVariable() :SPIRVInstruction(OpVariable),
    457       StorageClass(StorageClassFunction){}
    458 
    459   SPIRVStorageClassKind getStorageClass() const { return StorageClass; }
    460   SPIRVValue *getInitializer() const {
    461     if (Initializer.empty())
    462       return nullptr;
    463     assert(Initializer.size() == 1);
    464     return getValue(Initializer[0]);
    465   }
    466   bool isConstant() const {
    467     return hasDecorate(DecorationConstant);
    468   }
    469   bool isBuiltin(SPIRVBuiltinVariableKind *BuiltinKind = nullptr) const {
    470     SPIRVWord Kind;
    471     bool Found = hasDecorate(DecorationBuiltIn, 0, &Kind);
    472     if (!Found)
    473       return false;
    474     if (BuiltinKind)
    475       *BuiltinKind = static_cast<SPIRVBuiltinVariableKind>(Kind);
    476     return true;
    477   }
    478   void setBuiltin(SPIRVBuiltinVariableKind Kind) {
    479     assert(isValid(Kind));
    480     addDecorate(new SPIRVDecorate(DecorationBuiltIn, this, Kind));
    481   }
    482   void setIsConstant(bool Is) {
    483     if (Is)
    484       addDecorate(new SPIRVDecorate(DecorationConstant, this));
    485     else
    486       eraseDecorate(DecorationConstant);
    487   }
    488   virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
    489     if (SPIRVValue *V = getInitializer())
    490       return std::vector<SPIRVEntry*>(1, V);
    491     return std::vector<SPIRVEntry*>();
    492   }
    493 protected:
    494   void validate() const {
    495     SPIRVValue::validate();
    496     assert(isValid(StorageClass));
    497     assert(Initializer.size() == 1 || Initializer.empty());
    498   }
    499   void setWordCount(SPIRVWord TheWordCount) {
    500     SPIRVEntry::setWordCount(TheWordCount);
    501     Initializer.resize(WordCount - 4);
    502   }
    503   _SPIRV_DEF_ENCDEC4(Type, Id, StorageClass, Initializer)
    504 
    505     SPIRVStorageClassKind StorageClass;
    506   std::vector<SPIRVId> Initializer;
    507 };
    508 
    509 class SPIRVStore:public SPIRVInstruction, public SPIRVMemoryAccess {
    510 public:
    511   const static SPIRVWord FixedWords = 3;
    512   // Complete constructor
    513   SPIRVStore(SPIRVId PointerId, SPIRVId ValueId,
    514       const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *TheBB)
    515     :SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OpStore,
    516         TheBB),
    517      SPIRVMemoryAccess(TheMemoryAccess),
    518      MemoryAccess(TheMemoryAccess),
    519      PtrId(PointerId),
    520      ValId(ValueId){
    521     setAttr();
    522     validate();
    523     assert(TheBB && "Invalid BB");
    524   }
    525   // Incomplete constructor
    526   SPIRVStore():SPIRVInstruction(OpStore), SPIRVMemoryAccess(),
    527       PtrId(SPIRVID_INVALID), ValId(SPIRVID_INVALID){
    528     setAttr();
    529   }
    530 
    531   SPIRVValue *getSrc() const { return getValue(ValId);}
    532   SPIRVValue *getDst() const { return getValue(PtrId);}
    533 protected:
    534   void setAttr() {
    535     setHasNoType();
    536     setHasNoId();
    537   }
    538 
    539   void setWordCount(SPIRVWord TheWordCount) {
    540     SPIRVEntry::setWordCount(TheWordCount);
    541     MemoryAccess.resize(TheWordCount - FixedWords);
    542   }
    543   void encode(spv_ostream &O) const {
    544     getEncoder(O) << PtrId << ValId << MemoryAccess;
    545   }
    546 
    547   void decode(std::istream &I) {
    548     getDecoder(I) >> PtrId >> ValId >> MemoryAccess;
    549     MemoryAccessUpdate(MemoryAccess);
    550   }
    551 
    552   void validate()const {
    553     SPIRVInstruction::validate();
    554     if (getSrc()->isForward() || getDst()->isForward())
    555       return;
    556     assert(getValueType(PtrId)->getPointerElementType() == getValueType(ValId)
    557         && "Inconsistent operand types");
    558   }
    559 private:
    560   std::vector<SPIRVWord> MemoryAccess;
    561   SPIRVId PtrId;
    562   SPIRVId ValId;
    563 };
    564 
    565 class SPIRVLoad:public SPIRVInstruction, public SPIRVMemoryAccess {
    566 public:
    567   const static SPIRVWord FixedWords = 4;
    568   // Complete constructor
    569   SPIRVLoad(SPIRVId TheId, SPIRVId PointerId,
    570       const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *TheBB)
    571     :SPIRVInstruction(FixedWords + TheMemoryAccess.size() , OpLoad,
    572         TheBB->getValueType(PointerId)->getPointerElementType(), TheId, TheBB),
    573         SPIRVMemoryAccess(TheMemoryAccess), PtrId(PointerId),
    574         MemoryAccess(TheMemoryAccess) {
    575       validate();
    576       assert(TheBB && "Invalid BB");
    577     }
    578   // Incomplete constructor
    579   SPIRVLoad():SPIRVInstruction(OpLoad), SPIRVMemoryAccess(),
    580       PtrId(SPIRVID_INVALID){}
    581 
    582   SPIRVValue *getSrc() const { return Module->get<SPIRVValue>(PtrId);}
    583 
    584 protected:
    585   void setWordCount(SPIRVWord TheWordCount) {
    586     SPIRVEntry::setWordCount(TheWordCount);
    587     MemoryAccess.resize(TheWordCount - FixedWords);
    588   }
    589 
    590   void encode(spv_ostream &O) const {
    591     getEncoder(O) << Type << Id << PtrId << MemoryAccess;
    592   }
    593 
    594   void decode(std::istream &I) {
    595     getDecoder(I) >> Type >> Id >> PtrId >> MemoryAccess;
    596     MemoryAccessUpdate(MemoryAccess);
    597   }
    598 
    599   void validate()const {
    600     SPIRVInstruction::validate();
    601     assert((getValue(PtrId)->isForward() ||
    602         Type == getValueType(PtrId)->getPointerElementType()) &&
    603         "Inconsistent types");
    604   }
    605 private:
    606   SPIRVId PtrId;
    607   std::vector<SPIRVWord> MemoryAccess;
    608 };
    609 
    610 class SPIRVBinary:public SPIRVInstTemplateBase {
    611 protected:
    612   void validate()const {
    613     SPIRVId Op1 = Ops[0];
    614     SPIRVId Op2 = Ops[1];
    615     SPIRVType *op1Ty, *op2Ty;
    616     SPIRVInstruction::validate();
    617     if (getValue(Op1)->isForward() || getValue(Op2)->isForward())
    618       return;
    619     if (getValueType(Op1)->isTypeVector()) {
    620       op1Ty = getValueType(Op1)->getVectorComponentType();
    621       op2Ty = getValueType(Op2)->getVectorComponentType();
    622       assert(getValueType(Op1)->getVectorComponentCount() ==
    623              getValueType(Op2)->getVectorComponentCount() &&
    624                "Inconsistent Vector component width");
    625     }
    626     else {
    627       op1Ty = getValueType(Op1);
    628       op2Ty = getValueType(Op2);
    629     }
    630 
    631     if (isBinaryOpCode(OpCode)) {
    632       assert(getValueType(Op1)== getValueType(Op2) &&
    633              "Invalid type for binary instruction");
    634       assert((op1Ty->isTypeInt() || op2Ty->isTypeFloat()) &&
    635                "Invalid type for Binary instruction");
    636       assert((op1Ty->getBitWidth() == op2Ty->getBitWidth()) &&
    637                "Inconsistent BitWidth");
    638     } else if (isShiftOpCode(OpCode)) {
    639       assert((op1Ty->isTypeInt() || op2Ty->isTypeInt()) &&
    640           "Invalid type for shift instruction");
    641     } else if (isLogicalOpCode(OpCode)) {
    642       assert((op1Ty->isTypeBool() || op2Ty->isTypeBool()) &&
    643           "Invalid type for logical instruction");
    644     } else if (isBitwiseOpCode(OpCode)) {
    645       assert((op1Ty->isTypeInt() || op2Ty->isTypeInt()) &&
    646           "Invalid type for bitwise instruction");
    647       assert((op1Ty->getIntegerBitWidth() == op2Ty->getIntegerBitWidth()) &&
    648           "Inconsistent BitWidth");
    649     } else {
    650       assert(0 && "Invalid op code!");
    651     }
    652   }
    653 };
    654 
    655 template<Op OC>
    656 class SPIRVBinaryInst:public SPIRVInstTemplate<SPIRVBinary, OC, true, 5, false> {
    657 };
    658 
    659 /* ToDo: SMod and FMod to be added */
    660 #define _SPIRV_OP(x) typedef SPIRVBinaryInst<Op##x> SPIRV##x;
    661 _SPIRV_OP(IAdd)
    662 _SPIRV_OP(FAdd)
    663 _SPIRV_OP(ISub)
    664 _SPIRV_OP(FSub)
    665 _SPIRV_OP(IMul)
    666 _SPIRV_OP(FMul)
    667 _SPIRV_OP(UDiv)
    668 _SPIRV_OP(SDiv)
    669 _SPIRV_OP(FDiv)
    670 _SPIRV_OP(SRem)
    671 _SPIRV_OP(FRem)
    672 _SPIRV_OP(UMod)
    673 _SPIRV_OP(ShiftLeftLogical)
    674 _SPIRV_OP(ShiftRightLogical)
    675 _SPIRV_OP(ShiftRightArithmetic)
    676 _SPIRV_OP(LogicalAnd)
    677 _SPIRV_OP(LogicalOr)
    678 _SPIRV_OP(LogicalEqual)
    679 _SPIRV_OP(LogicalNotEqual)
    680 _SPIRV_OP(BitwiseAnd)
    681 _SPIRV_OP(BitwiseOr)
    682 _SPIRV_OP(BitwiseXor)
    683 _SPIRV_OP(Dot)
    684 #undef _SPIRV_OP
    685 
    686 template<Op TheOpCode>
    687 class SPIRVInstNoOperand:public SPIRVInstruction {
    688 public:
    689   // Complete constructor
    690   SPIRVInstNoOperand(SPIRVBasicBlock *TheBB):SPIRVInstruction(1, TheOpCode,
    691       TheBB){
    692     setAttr();
    693     validate();
    694   }
    695   // Incomplete constructor
    696   SPIRVInstNoOperand():SPIRVInstruction(TheOpCode){
    697     setAttr();
    698   }
    699 protected:
    700   void setAttr() {
    701     setHasNoId();
    702     setHasNoType();
    703   }
    704   _SPIRV_DEF_ENCDEC0
    705 };
    706 
    707 typedef SPIRVInstNoOperand<OpReturn> SPIRVReturn;
    708 
    709 class SPIRVReturnValue:public SPIRVInstruction {
    710 public:
    711   static const Op OC = OpReturnValue;
    712   // Complete constructor
    713   SPIRVReturnValue(SPIRVValue *TheReturnValue, SPIRVBasicBlock *TheBB)
    714     :SPIRVInstruction(2, OC, TheBB), ReturnValueId(TheReturnValue->getId()){
    715     setAttr();
    716     validate();
    717     assert(TheBB && "Invalid BB");
    718   }
    719   // Incomplete constructor
    720   SPIRVReturnValue():SPIRVInstruction(OC), ReturnValueId(SPIRVID_INVALID) {
    721     setAttr();
    722   }
    723 
    724   SPIRVValue *getReturnValue() const {
    725     return getValue(ReturnValueId);
    726   }
    727 protected:
    728   void setAttr() {
    729     setHasNoId();
    730     setHasNoType();
    731   }
    732   _SPIRV_DEF_ENCDEC1(ReturnValueId)
    733   void validate()const {
    734     SPIRVInstruction::validate();
    735   }
    736   SPIRVId ReturnValueId;
    737 };
    738 
    739 class SPIRVBranch:public SPIRVInstruction {
    740 public:
    741   static const Op OC = OpBranch;
    742   // Complete constructor
    743   SPIRVBranch(SPIRVLabel *TheTargetLabel,SPIRVBasicBlock *TheBB)
    744     :SPIRVInstruction(2, OC, TheBB), TargetLabelId(TheTargetLabel->getId()) {
    745     validate();
    746     assert(TheBB && "Invalid BB");
    747   }
    748   // Incomplete constructor
    749   SPIRVBranch():SPIRVInstruction(OC), TargetLabelId(SPIRVID_INVALID) {
    750     setHasNoId();
    751     setHasNoType();
    752   }
    753   SPIRVValue *getTargetLabel() const {
    754     return getValue(TargetLabelId);
    755   }
    756 protected:
    757   _SPIRV_DEF_ENCDEC1(TargetLabelId)
    758   void validate()const {
    759     SPIRVInstruction::validate();
    760     assert(WordCount == 2);
    761     assert(OpCode == OC);
    762     assert(getTargetLabel()->isLabel() || getTargetLabel()->isForward());
    763   }
    764   SPIRVId TargetLabelId;
    765 };
    766 
    767 class SPIRVBranchConditional:public SPIRVInstruction {
    768 public:
    769   static const Op OC = OpBranchConditional;
    770   // Complete constructor
    771   SPIRVBranchConditional(SPIRVValue *TheCondition, SPIRVLabel *TheTrueLabel,
    772       SPIRVLabel *TheFalseLabel, SPIRVBasicBlock *TheBB)
    773     :SPIRVInstruction(4, OC, TheBB), ConditionId(TheCondition->getId()),
    774      TrueLabelId(TheTrueLabel->getId()), FalseLabelId(TheFalseLabel->getId()){
    775     validate();
    776   }
    777   SPIRVBranchConditional(SPIRVValue *TheCondition, SPIRVLabel *TheTrueLabel,
    778       SPIRVLabel *TheFalseLabel, SPIRVBasicBlock *TheBB, SPIRVWord TrueWeight,
    779       SPIRVWord FalseWeight)
    780     :SPIRVInstruction(6, OC, TheBB), ConditionId(TheCondition->getId()),
    781      TrueLabelId(TheTrueLabel->getId()), FalseLabelId(TheFalseLabel->getId()){
    782     BranchWeights.push_back(TrueWeight);
    783     BranchWeights.push_back(FalseWeight);
    784     validate();
    785     assert(TheBB && "Invalid BB");
    786   }
    787   // Incomplete constructor
    788   SPIRVBranchConditional():SPIRVInstruction(OC), ConditionId(SPIRVID_INVALID),
    789       TrueLabelId(SPIRVID_INVALID), FalseLabelId(SPIRVID_INVALID) {
    790     setHasNoId();
    791     setHasNoType();
    792   }
    793   SPIRVValue *getCondition() const {
    794     return getValue(ConditionId);
    795   }
    796   SPIRVLabel *getTrueLabel() const {
    797     return get<SPIRVLabel>(TrueLabelId);
    798   }
    799   SPIRVLabel *getFalseLabel() const {
    800     return get<SPIRVLabel>(FalseLabelId);
    801   }
    802 protected:
    803   void setWordCount(SPIRVWord TheWordCount) {
    804     SPIRVEntry::setWordCount(TheWordCount);
    805     BranchWeights.resize(TheWordCount - 4);
    806   }
    807   _SPIRV_DEF_ENCDEC4(ConditionId, TrueLabelId, FalseLabelId, BranchWeights)
    808   void validate()const {
    809     SPIRVInstruction::validate();
    810     assert(WordCount == 4 || WordCount == 6);
    811     assert(WordCount == BranchWeights.size() + 4);
    812     assert(OpCode == OC);
    813     assert(getCondition()->isForward() ||
    814         getCondition()->getType()->isTypeBool());
    815     assert(getTrueLabel()->isForward() || getTrueLabel()->isLabel());
    816     assert(getFalseLabel()->isForward() || getFalseLabel()->isLabel());
    817   }
    818   SPIRVId ConditionId;
    819   SPIRVId TrueLabelId;
    820   SPIRVId FalseLabelId;
    821   std::vector<SPIRVWord> BranchWeights;
    822 };
    823 
    824 class SPIRVPhi: public SPIRVInstruction {
    825 public:
    826   static const Op OC = OpPhi;
    827   static const SPIRVWord FixedWordCount = 3;
    828   SPIRVPhi(SPIRVType *TheType, SPIRVId TheId,
    829       const std::vector<SPIRVValue *> &ThePairs, SPIRVBasicBlock *BB)
    830     :SPIRVInstruction(ThePairs.size() + FixedWordCount, OC, TheType, TheId, BB){
    831     Pairs = getIds(ThePairs);
    832     validate();
    833     assert(BB && "Invalid BB");
    834   }
    835   SPIRVPhi():SPIRVInstruction(OC) {}
    836   std::vector<SPIRVValue *> getPairs() {
    837     return getValues(Pairs);
    838   }
    839   void addPair(SPIRVValue *Value, SPIRVBasicBlock *BB) {
    840     Pairs.push_back(Value->getId());
    841     Pairs.push_back(BB->getId());
    842     WordCount = Pairs.size() + FixedWordCount;
    843     validate();
    844   }
    845   void setPairs(const std::vector<SPIRVValue *> &ThePairs) {
    846     Pairs = getIds(ThePairs);
    847     WordCount = Pairs.size() + FixedWordCount;
    848     validate();
    849   }
    850   void foreachPair(std::function<void(SPIRVValue *, SPIRVBasicBlock *,
    851       size_t)> Func) {
    852     for (size_t I = 0, E = Pairs.size()/2; I != E; ++I) {
    853       SPIRVEntry *Value, *BB;
    854       if (!Module->exist(Pairs[2*I], &Value) ||
    855           !Module->exist(Pairs[2*I+1], &BB))
    856         continue;
    857       Func(static_cast<SPIRVValue *>(Value), static_cast<SPIRVBasicBlock *>(BB),
    858           I);
    859     }
    860   }
    861   void foreachPair(std::function<void(SPIRVValue *, SPIRVBasicBlock *)> Func)
    862     const {
    863     for (size_t I = 0, E = Pairs.size()/2; I != E; ++I) {
    864       SPIRVEntry *Value, *BB;
    865       if (!Module->exist(Pairs[2*I], &Value) ||
    866           !Module->exist(Pairs[2*I+1], &BB))
    867         continue;
    868       Func(static_cast<SPIRVValue *>(Value), static_cast<SPIRVBasicBlock *>(BB));
    869     }
    870   }
    871   void setWordCount(SPIRVWord TheWordCount) {
    872     SPIRVEntry::setWordCount(TheWordCount);
    873     Pairs.resize(TheWordCount - FixedWordCount);
    874   }
    875   _SPIRV_DEF_ENCDEC3(Type, Id, Pairs)
    876   void validate()const {
    877     assert(WordCount == Pairs.size() + FixedWordCount);
    878     assert(OpCode == OC);
    879     assert(Pairs.size() % 2 == 0);
    880     foreachPair([=](SPIRVValue *IncomingV, SPIRVBasicBlock *IncomingBB){
    881       assert(IncomingV->isForward() || IncomingV->getType() == Type);
    882       assert(IncomingBB->isBasicBlock() || IncomingBB->isForward());
    883     });
    884     SPIRVInstruction::validate();
    885   }
    886 protected:
    887   std::vector<SPIRVId> Pairs;
    888 };
    889 
    890 class SPIRVCompare:public SPIRVInstTemplateBase {
    891 protected:
    892   void validate()const {
    893     auto Op1 = Ops[0];
    894     auto Op2 = Ops[1];
    895     SPIRVType *op1Ty, *op2Ty, *resTy;
    896     SPIRVInstruction::validate();
    897     if (getValue(Op1)->isForward() || getValue(Op2)->isForward())
    898       return;
    899 
    900     if (getValueType(Op1)->isTypeVector()) {
    901       op1Ty = getValueType(Op1)->getVectorComponentType();
    902       op2Ty = getValueType(Op2)->getVectorComponentType();
    903       resTy = Type->getVectorComponentType();
    904       assert(getValueType(Op1)->getVectorComponentCount() ==
    905              getValueType(Op2)->getVectorComponentCount() &&
    906                "Inconsistent Vector component width");
    907     }
    908     else {
    909       op1Ty = getValueType(Op1);
    910       op2Ty = getValueType(Op2);
    911       resTy = Type;
    912     }
    913     assert(isCmpOpCode(OpCode) && "Invalid op code for cmp inst");
    914     assert((resTy->isTypeBool() || resTy->isTypeInt()) &&
    915         "Invalid type for compare instruction");
    916     assert(op1Ty == op2Ty && "Inconsistent types");
    917   }
    918 };
    919 
    920 template<Op OC>
    921 class SPIRVCmpInst:public SPIRVInstTemplate<SPIRVCompare, OC, true, 5, false> {
    922 };
    923 
    924 #define _SPIRV_OP(x) typedef SPIRVCmpInst<Op##x> SPIRV##x;
    925 _SPIRV_OP(IEqual)
    926 _SPIRV_OP(FOrdEqual)
    927 _SPIRV_OP(FUnordEqual)
    928 _SPIRV_OP(INotEqual)
    929 _SPIRV_OP(FOrdNotEqual)
    930 _SPIRV_OP(FUnordNotEqual)
    931 _SPIRV_OP(ULessThan)
    932 _SPIRV_OP(SLessThan)
    933 _SPIRV_OP(FOrdLessThan)
    934 _SPIRV_OP(FUnordLessThan)
    935 _SPIRV_OP(UGreaterThan)
    936 _SPIRV_OP(SGreaterThan)
    937 _SPIRV_OP(FOrdGreaterThan)
    938 _SPIRV_OP(FUnordGreaterThan)
    939 _SPIRV_OP(ULessThanEqual)
    940 _SPIRV_OP(SLessThanEqual)
    941 _SPIRV_OP(FOrdLessThanEqual)
    942 _SPIRV_OP(FUnordLessThanEqual)
    943 _SPIRV_OP(UGreaterThanEqual)
    944 _SPIRV_OP(SGreaterThanEqual)
    945 _SPIRV_OP(FOrdGreaterThanEqual)
    946 _SPIRV_OP(FUnordGreaterThanEqual)
    947 _SPIRV_OP(LessOrGreater)
    948 _SPIRV_OP(Ordered)
    949 _SPIRV_OP(Unordered)
    950 #undef _SPIRV_OP
    951 
    952 class SPIRVSelect:public SPIRVInstruction {
    953 public:
    954   // Complete constructor
    955   SPIRVSelect(SPIRVId TheId, SPIRVId TheCondition, SPIRVId TheOp1, SPIRVId TheOp2,
    956       SPIRVBasicBlock *TheBB)
    957     :SPIRVInstruction(6, OpSelect, TheBB->getValueType(TheOp1), TheId,
    958         TheBB), Condition(TheCondition), Op1(TheOp1), Op2(TheOp2){
    959     validate();
    960     assert(TheBB && "Invalid BB");
    961   }
    962   // Incomplete constructor
    963   SPIRVSelect():SPIRVInstruction(OpSelect), Condition(SPIRVID_INVALID),
    964       Op1(SPIRVID_INVALID), Op2(SPIRVID_INVALID){}
    965   SPIRVValue *getCondition() { return getValue(Condition);}
    966   SPIRVValue *getTrueValue() { return getValue(Op1);}
    967   SPIRVValue *getFalseValue() { return getValue(Op2);}
    968 protected:
    969   _SPIRV_DEF_ENCDEC5(Type, Id, Condition, Op1, Op2)
    970   void validate()const {
    971     SPIRVInstruction::validate();
    972     if (getValue(Condition)->isForward() ||
    973         getValue(Op1)->isForward() ||
    974         getValue(Op2)->isForward())
    975       return;
    976 
    977     SPIRVType *conTy = getValueType(Condition)->isTypeVector() ?
    978         getValueType(Condition)->getVectorComponentType() :
    979         getValueType(Condition);
    980     (void) conTy;
    981     assert(conTy->isTypeBool() && "Invalid type");
    982     assert(getType() == getValueType(Op1) && getType() == getValueType(Op2) &&
    983         "Inconsistent type");
    984   }
    985   SPIRVId Condition;
    986   SPIRVId Op1;
    987   SPIRVId Op2;
    988 };
    989 
    990 class SPIRVSwitch: public SPIRVInstruction {
    991 public:
    992   static const Op OC = OpSwitch;
    993   static const SPIRVWord FixedWordCount = 3;
    994   SPIRVSwitch(SPIRVValue *TheSelect, SPIRVBasicBlock *TheDefault,
    995       const std::vector<std::pair<SPIRVWord, SPIRVBasicBlock *>> &ThePairs,
    996       SPIRVBasicBlock *BB)
    997     :SPIRVInstruction(ThePairs.size() * 2 + FixedWordCount, OC, BB),
    998      Select(TheSelect->getId()), Default(TheDefault->getId()) {
    999     for (auto &I:ThePairs) {
   1000       Pairs.push_back(I.first);
   1001       Pairs.push_back(I.second->getId());
   1002     }
   1003     validate();
   1004     assert(BB && "Invalid BB");
   1005   }
   1006   SPIRVSwitch():SPIRVInstruction(OC), Select(SPIRVWORD_MAX),
   1007       Default(SPIRVWORD_MAX) {
   1008     setHasNoId();
   1009     setHasNoType();
   1010   }
   1011   std::vector<SPIRVValue *> getPairs() {
   1012     return getValues(Pairs);
   1013   }
   1014   SPIRVValue *getSelect() const { return getValue(Select);}
   1015   SPIRVBasicBlock *getDefault() const {
   1016     return static_cast<SPIRVBasicBlock *>(getValue(Default));
   1017   }
   1018   size_t getNumPairs() const { return Pairs.size()/2;}
   1019   void foreachPair(std::function<void(SPIRVWord, SPIRVBasicBlock *, size_t)> Func)
   1020     const {
   1021     for (size_t I = 0, E = Pairs.size()/2; I != E; ++I) {
   1022       SPIRVEntry *BB;
   1023       if (!Module->exist(Pairs[2*I+1], &BB))
   1024         continue;
   1025       Func(Pairs[2*I], static_cast<SPIRVBasicBlock *>(BB), I);
   1026     }
   1027   }
   1028   void setWordCount(SPIRVWord TheWordCount) {
   1029     SPIRVEntry::setWordCount(TheWordCount);
   1030     Pairs.resize(TheWordCount - FixedWordCount);
   1031   }
   1032   _SPIRV_DEF_ENCDEC3(Select, Default, Pairs)
   1033   void validate()const {
   1034     assert(WordCount == Pairs.size() + FixedWordCount);
   1035     assert(OpCode == OC);
   1036     assert(Pairs.size() % 2 == 0);
   1037     foreachPair([=](SPIRVWord Literal, SPIRVBasicBlock *BB, size_t Index){
   1038       assert(BB->isBasicBlock() || BB->isForward());
   1039     });
   1040     SPIRVInstruction::validate();
   1041   }
   1042 protected:
   1043   SPIRVId Select;
   1044   SPIRVId Default;
   1045   std::vector<SPIRVWord> Pairs;
   1046 };
   1047 
   1048 class SPIRVUnary:public SPIRVInstTemplateBase {
   1049 protected:
   1050   void validate()const {
   1051     auto Op = Ops[0];
   1052     SPIRVInstruction::validate();
   1053     if (getValue(Op)->isForward())
   1054       return;
   1055     if (isGenericNegateOpCode(OpCode)) {
   1056       SPIRVType *resTy = Type->isTypeVector() ?
   1057         Type->getVectorComponentType() : Type;
   1058       SPIRVType *opTy = Type->isTypeVector() ?
   1059         getValueType(Op)->getVectorComponentType() : getValueType(Op);
   1060 
   1061       assert(getType() == getValueType(Op)  &&
   1062         "Inconsistent type");
   1063       (void) resTy;
   1064       assert((resTy->isTypeInt() || resTy->isTypeFloat()) &&
   1065         "Invalid type for Generic Negate instruction");
   1066       (void) opTy;
   1067       assert((resTy->getBitWidth() == opTy->getBitWidth()) &&
   1068         "Invalid bitwidth for Generic Negate instruction");
   1069       assert((Type->isTypeVector() ? (Type->getVectorComponentCount() ==
   1070           getValueType(Op)->getVectorComponentCount()): 1) &&
   1071           "Invalid vector component Width for Generic Negate instruction");
   1072     }
   1073   }
   1074 };
   1075 
   1076 template<Op OC>
   1077 class SPIRVUnaryInst:public SPIRVInstTemplate<SPIRVUnary, OC, true, 4, false> {
   1078 };
   1079 
   1080 #define _SPIRV_OP(x) typedef SPIRVUnaryInst<Op##x> SPIRV##x;
   1081 _SPIRV_OP(ConvertFToU)
   1082 _SPIRV_OP(ConvertFToS)
   1083 _SPIRV_OP(ConvertSToF)
   1084 _SPIRV_OP(ConvertUToF)
   1085 _SPIRV_OP(UConvert)
   1086 _SPIRV_OP(SConvert)
   1087 _SPIRV_OP(FConvert)
   1088 _SPIRV_OP(SatConvertSToU)
   1089 _SPIRV_OP(SatConvertUToS)
   1090 _SPIRV_OP(ConvertPtrToU)
   1091 _SPIRV_OP(ConvertUToPtr)
   1092 _SPIRV_OP(PtrCastToGeneric)
   1093 _SPIRV_OP(GenericCastToPtr)
   1094 _SPIRV_OP(Bitcast)
   1095 _SPIRV_OP(SNegate)
   1096 _SPIRV_OP(FNegate)
   1097 _SPIRV_OP(Not)
   1098 _SPIRV_OP(LogicalNot)
   1099 _SPIRV_OP(IsNan)
   1100 _SPIRV_OP(IsInf)
   1101 _SPIRV_OP(IsFinite)
   1102 _SPIRV_OP(IsNormal)
   1103 _SPIRV_OP(SignBitSet)
   1104 _SPIRV_OP(Any)
   1105 _SPIRV_OP(All)
   1106 #undef _SPIRV_OP
   1107 
   1108 class SPIRVAccessChainBase :public SPIRVInstTemplateBase {
   1109 public:
   1110   SPIRVValue *getBase() { return this->getValue(this->Ops[0]);}
   1111   std::vector<SPIRVValue *> getIndices()const {
   1112     std::vector<SPIRVWord> IndexWords(this->Ops.begin() + 1, this->Ops.end());
   1113     return this->getValues(IndexWords);
   1114   }
   1115   bool isInBounds() {
   1116     return OpCode == OpInBoundsAccessChain ||
   1117         OpCode == OpInBoundsPtrAccessChain;
   1118   }
   1119   bool hasPtrIndex() {
   1120     return OpCode == OpPtrAccessChain ||
   1121         OpCode == OpInBoundsPtrAccessChain;
   1122   }
   1123 };
   1124 
   1125 template<Op OC, unsigned FixedWC>
   1126 class SPIRVAccessChainGeneric
   1127     :public SPIRVInstTemplate<SPIRVAccessChainBase, OC, true, FixedWC, true> {
   1128 };
   1129 
   1130 typedef SPIRVAccessChainGeneric<OpAccessChain, 4> SPIRVAccessChain;
   1131 typedef SPIRVAccessChainGeneric<OpInBoundsAccessChain, 4>
   1132   SPIRVInBoundsAccessChain;
   1133 typedef SPIRVAccessChainGeneric<OpPtrAccessChain, 5> SPIRVPtrAccessChain;
   1134 typedef SPIRVAccessChainGeneric<OpInBoundsPtrAccessChain, 5>
   1135   SPIRVInBoundsPtrAccessChain;
   1136 
   1137 template<Op OC, SPIRVWord FixedWordCount>
   1138 class SPIRVFunctionCallGeneric: public SPIRVInstruction {
   1139 public:
   1140   SPIRVFunctionCallGeneric(SPIRVType *TheType, SPIRVId TheId,
   1141       const std::vector<SPIRVWord> &TheArgs, SPIRVBasicBlock *BB)
   1142     :SPIRVInstruction(TheArgs.size() + FixedWordCount, OC, TheType, TheId, BB),
   1143      Args(TheArgs){
   1144     validate();
   1145     assert(BB && "Invalid BB");
   1146   }
   1147   SPIRVFunctionCallGeneric(SPIRVType *TheType, SPIRVId TheId,
   1148       const std::vector<SPIRVValue *> &TheArgs, SPIRVBasicBlock *BB)
   1149     :SPIRVInstruction(TheArgs.size() + FixedWordCount, OC, TheType, TheId, BB) {
   1150     Args = getIds(TheArgs);
   1151     validate();
   1152     assert(BB && "Invalid BB");
   1153   }
   1154   SPIRVFunctionCallGeneric():SPIRVInstruction(OC) {}
   1155   const std::vector<SPIRVWord> &getArguments() {
   1156     return Args;
   1157   }
   1158   std::vector<SPIRVValue *> getArgumentValues() {
   1159     return getValues(Args);
   1160   }
   1161   std::vector<SPIRVType *> getArgumentValueTypes()const {
   1162     std::vector<SPIRVType *> ArgTypes;
   1163     for (auto &I:Args)
   1164       ArgTypes.push_back(getValue(I)->getType());
   1165     return ArgTypes;
   1166   }
   1167   void setWordCount(SPIRVWord TheWordCount) {
   1168     SPIRVEntry::setWordCount(TheWordCount);
   1169     Args.resize(TheWordCount - FixedWordCount);
   1170   }
   1171   void validate()const {
   1172     SPIRVInstruction::validate();
   1173   }
   1174 protected:
   1175   std::vector<SPIRVWord> Args;
   1176 };
   1177 
   1178 class SPIRVFunctionCall:
   1179     public SPIRVFunctionCallGeneric<OpFunctionCall, 4> {
   1180 public:
   1181   SPIRVFunctionCall(SPIRVId TheId, SPIRVFunction *TheFunction,
   1182       const std::vector<SPIRVWord> &TheArgs, SPIRVBasicBlock *BB);
   1183   SPIRVFunctionCall():FunctionId(SPIRVID_INVALID) {}
   1184   SPIRVFunction *getFunction()const {
   1185     return get<SPIRVFunction>(FunctionId);
   1186   }
   1187   _SPIRV_DEF_ENCDEC4(Type, Id, FunctionId, Args)
   1188   void validate()const;
   1189   bool isOperandLiteral(unsigned Index) const { return false;}
   1190 protected:
   1191   SPIRVId FunctionId;
   1192 };
   1193 
   1194 class SPIRVExtInst: public SPIRVFunctionCallGeneric<OpExtInst, 5> {
   1195 public:
   1196   SPIRVExtInst(SPIRVType *TheType, SPIRVId TheId,
   1197       SPIRVId TheBuiltinSet, SPIRVWord TheEntryPoint,
   1198       const std::vector<SPIRVWord> &TheArgs, SPIRVBasicBlock *BB)
   1199     :SPIRVFunctionCallGeneric(TheType, TheId, TheArgs, BB),
   1200      ExtSetId(TheBuiltinSet),
   1201      ExtOp(TheEntryPoint) {
   1202     setExtSetKindById();
   1203     validate();
   1204   }
   1205   SPIRVExtInst(SPIRVType *TheType, SPIRVId TheId,
   1206       SPIRVId TheBuiltinSet, SPIRVWord TheEntryPoint,
   1207       const std::vector<SPIRVValue *> &TheArgs, SPIRVBasicBlock *BB)
   1208     :SPIRVFunctionCallGeneric(TheType, TheId, TheArgs, BB),
   1209      ExtSetId(TheBuiltinSet),
   1210      ExtOp(TheEntryPoint) {
   1211     setExtSetKindById();
   1212     validate();
   1213   }
   1214   SPIRVExtInst(SPIRVExtInstSetKind SetKind = SPIRVEIS_Count,
   1215       unsigned ExtOC = SPIRVWORD_MAX)
   1216     :ExtSetId(SPIRVWORD_MAX), ExtOp(ExtOC), ExtSetKind(SetKind) {}
   1217   void setExtSetId(unsigned Set) { ExtSetId = Set;}
   1218   void setExtOp(unsigned ExtOC) { ExtOp = ExtOC;}
   1219   SPIRVId getExtSetId()const {
   1220     return ExtSetId;
   1221   }
   1222   SPIRVWord getExtOp()const {
   1223     return ExtOp;
   1224   }
   1225   void setExtSetKindById() {
   1226     assert(Module && "Invalid module");
   1227     ExtSetKind = Module->getBuiltinSet(ExtSetId);
   1228     assert(ExtSetKind == SPIRVEIS_OpenCL && "not supported");
   1229   }
   1230   void encode(spv_ostream &O) const {
   1231     getEncoder(O) << Type << Id << ExtSetId;
   1232     switch(ExtSetKind) {
   1233     case SPIRVEIS_OpenCL:
   1234       getEncoder(O) << ExtOpOCL;
   1235       break;
   1236     default:
   1237       assert(0 && "not supported");
   1238       getEncoder(O) << ExtOp;
   1239     }
   1240     getEncoder(O) << Args;
   1241   }
   1242   void decode(std::istream &I) {
   1243     getDecoder(I) >> Type >> Id >> ExtSetId;
   1244     setExtSetKindById();
   1245     switch(ExtSetKind) {
   1246     case SPIRVEIS_OpenCL:
   1247       getDecoder(I) >> ExtOpOCL;
   1248       break;
   1249     default:
   1250       assert(0 && "not supported");
   1251       getDecoder(I) >> ExtOp;
   1252     }
   1253     getDecoder(I) >> Args;
   1254   }
   1255   void validate()const {
   1256     SPIRVFunctionCallGeneric::validate();
   1257     validateBuiltin(ExtSetId, ExtOp);
   1258   }
   1259   bool isOperandLiteral(unsigned Index) const {
   1260     assert(ExtSetKind == SPIRVEIS_OpenCL &&
   1261         "Unsupported extended instruction set");
   1262     auto EOC = static_cast<OCLExtOpKind>(ExtOp);
   1263     switch(EOC) {
   1264     default:
   1265       return false;
   1266     case OpenCLLIB::Vloadn:
   1267     case OpenCLLIB::Vload_halfn:
   1268     case OpenCLLIB::Vloada_halfn:
   1269       return Index == 2;
   1270     case OpenCLLIB::Vstore_half_r:
   1271     case OpenCLLIB::Vstore_halfn_r:
   1272     case OpenCLLIB::Vstorea_halfn_r:
   1273       return Index == 3;
   1274     }
   1275   }
   1276 protected:
   1277   SPIRVId ExtSetId;
   1278   union {
   1279     SPIRVWord ExtOp;
   1280     OCLExtOpKind ExtOpOCL;
   1281   };
   1282   SPIRVExtInstSetKind ExtSetKind;
   1283 };
   1284 
   1285 class SPIRVCompositeExtract:public SPIRVInstruction {
   1286 public:
   1287   const static Op OC = OpCompositeExtract;
   1288   // Complete constructor
   1289   SPIRVCompositeExtract(SPIRVType *TheType, SPIRVId TheId, SPIRVValue *TheComposite,
   1290       const std::vector<SPIRVWord>& TheIndices, SPIRVBasicBlock *TheBB):
   1291         SPIRVInstruction(TheIndices.size() + 4, OC, TheType, TheId, TheBB),
   1292         Composite(TheComposite->getId()), Indices(TheIndices){
   1293     validate();
   1294     assert(TheBB && "Invalid BB");
   1295   }
   1296   // Incomplete constructor
   1297   SPIRVCompositeExtract():SPIRVInstruction(OC), Composite(SPIRVID_INVALID){}
   1298 
   1299   SPIRVValue *getComposite() { return getValue(Composite);}
   1300   const std::vector<SPIRVWord>& getIndices()const { return Indices;}
   1301 protected:
   1302   void setWordCount(SPIRVWord TheWordCount) {
   1303     SPIRVEntry::setWordCount(TheWordCount);
   1304     Indices.resize(TheWordCount - 4);
   1305   }
   1306   _SPIRV_DEF_ENCDEC4(Type, Id, Composite, Indices)
   1307   // ToDo: validate the result type is consistent with the base type and indices
   1308   // need to trace through the base type for struct types
   1309   void validate()const {
   1310     SPIRVInstruction::validate();
   1311     assert(getValueType(Composite)->isTypeArray() ||
   1312         getValueType(Composite)->isTypeStruct() ||
   1313         getValueType(Composite)->isTypeVector());
   1314   }
   1315   SPIRVId Composite;
   1316   std::vector<SPIRVWord> Indices;
   1317 };
   1318 
   1319 class SPIRVCompositeInsert:public SPIRVInstruction {
   1320 public:
   1321   const static Op OC = OpCompositeInsert;
   1322   const static SPIRVWord FixedWordCount = 5;
   1323   // Complete constructor
   1324   SPIRVCompositeInsert(SPIRVId TheId, SPIRVValue *TheObject,
   1325       SPIRVValue *TheComposite, const std::vector<SPIRVWord>& TheIndices,
   1326       SPIRVBasicBlock *TheBB):
   1327         SPIRVInstruction(TheIndices.size() + FixedWordCount, OC,
   1328             TheComposite->getType(), TheId, TheBB),
   1329         Object(TheObject->getId()), Composite(TheComposite->getId()),
   1330         Indices(TheIndices){
   1331     validate();
   1332     assert(TheBB && "Invalid BB");
   1333   }
   1334   // Incomplete constructor
   1335   SPIRVCompositeInsert():SPIRVInstruction(OC), Object(SPIRVID_INVALID),
   1336       Composite(SPIRVID_INVALID){}
   1337 
   1338   SPIRVValue *getObject() { return getValue(Object);}
   1339   SPIRVValue *getComposite() { return getValue(Composite);}
   1340   const std::vector<SPIRVWord>& getIndices()const { return Indices;}
   1341 protected:
   1342   void setWordCount(SPIRVWord TheWordCount) {
   1343     SPIRVEntry::setWordCount(TheWordCount);
   1344     Indices.resize(TheWordCount - FixedWordCount);
   1345   }
   1346   _SPIRV_DEF_ENCDEC5(Type, Id, Object, Composite, Indices)
   1347   // ToDo: validate the object type is consistent with the base type and indices
   1348   // need to trace through the base type for struct types
   1349   void validate()const {
   1350     SPIRVInstruction::validate();
   1351     assert(OpCode == OC);
   1352     assert(WordCount == Indices.size() + FixedWordCount);
   1353     assert(getValueType(Composite)->isTypeArray() ||
   1354         getValueType(Composite)->isTypeStruct() ||
   1355         getValueType(Composite)->isTypeVector());
   1356     assert(Type == getValueType(Composite));
   1357   }
   1358   SPIRVId Object;
   1359   SPIRVId Composite;
   1360   std::vector<SPIRVWord> Indices;
   1361 };
   1362 
   1363 class SPIRVCopyObject :public SPIRVInstruction {
   1364 public:
   1365   const static Op OC = OpCopyObject;
   1366 
   1367   // Complete constructor
   1368   SPIRVCopyObject(SPIRVType *TheType, SPIRVId TheId, SPIRVValue *TheOperand,
   1369     SPIRVBasicBlock *TheBB) :
   1370     SPIRVInstruction(4, OC, TheType, TheId, TheBB),
   1371     Operand(TheOperand->getId()) {
   1372     validate();
   1373     assert(TheBB && "Invalid BB");
   1374   }
   1375   // Incomplete constructor
   1376   SPIRVCopyObject() :SPIRVInstruction(OC), Operand(SPIRVID_INVALID) {}
   1377 
   1378   SPIRVValue *getOperand() { return getValue(Operand); }
   1379 
   1380 protected:
   1381   _SPIRV_DEF_ENCDEC3(Type, Id, Operand)
   1382 
   1383     void validate()const {
   1384     SPIRVInstruction::validate();
   1385   }
   1386   SPIRVId Operand;
   1387 };
   1388 
   1389 
   1390 class SPIRVCopyMemory :public SPIRVInstruction, public SPIRVMemoryAccess {
   1391 public:
   1392   const static Op OC = OpCopyMemory;
   1393   const static SPIRVWord FixedWords = 3;
   1394   // Complete constructor
   1395   SPIRVCopyMemory(SPIRVValue *TheTarget, SPIRVValue *TheSource,
   1396       const std::vector<SPIRVWord> &TheMemoryAccess,
   1397     SPIRVBasicBlock *TheBB) :
   1398     SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OC, TheBB),
   1399     SPIRVMemoryAccess(TheMemoryAccess),
   1400     MemoryAccess(TheMemoryAccess),
   1401     Target(TheTarget->getId()),
   1402     Source(TheSource->getId()) {
   1403     validate();
   1404     assert(TheBB && "Invalid BB");
   1405   }
   1406 
   1407   // Incomplete constructor
   1408   SPIRVCopyMemory() :SPIRVInstruction(OC), SPIRVMemoryAccess(),
   1409       Target(SPIRVID_INVALID),
   1410     Source(SPIRVID_INVALID) {
   1411     setHasNoId();
   1412     setHasNoType();
   1413   }
   1414 
   1415   SPIRVValue *getSource() { return getValue(Source); }
   1416   SPIRVValue *getTarget() { return getValue(Target); }
   1417 
   1418 protected:
   1419   void setWordCount(SPIRVWord TheWordCount) {
   1420     SPIRVEntry::setWordCount(TheWordCount);
   1421     MemoryAccess.resize(TheWordCount - FixedWords);
   1422   }
   1423 
   1424   void encode(spv_ostream &O) const {
   1425     getEncoder(O) << Target << Source << MemoryAccess;
   1426   }
   1427 
   1428   void decode(std::istream &I) {
   1429     getDecoder(I) >> Target >> Source >> MemoryAccess;
   1430     MemoryAccessUpdate(MemoryAccess);
   1431   }
   1432 
   1433   void validate()const {
   1434     assert((getValueType(Id) == getValueType(Source)) && "Inconsistent type");
   1435     assert(getValueType(Id)->isTypePointer() && "Invalid type");
   1436     assert(!(getValueType(Id)->getPointerElementType()->isTypeVoid()) &&
   1437         "Invalid type");
   1438     SPIRVInstruction::validate();
   1439   }
   1440 
   1441   std::vector<SPIRVWord> MemoryAccess;
   1442   SPIRVId Target;
   1443   SPIRVId Source;
   1444 };
   1445 
   1446 class SPIRVCopyMemorySized :public SPIRVInstruction, public SPIRVMemoryAccess {
   1447 public:
   1448   const static Op OC = OpCopyMemorySized;
   1449   const static SPIRVWord FixedWords = 4;
   1450   // Complete constructor
   1451   SPIRVCopyMemorySized(SPIRVValue *TheTarget, SPIRVValue *TheSource,
   1452       SPIRVValue *TheSize, const std::vector<SPIRVWord> &TheMemoryAccess,
   1453       SPIRVBasicBlock *TheBB) :
   1454       SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OC, TheBB),
   1455       SPIRVMemoryAccess(TheMemoryAccess),
   1456       MemoryAccess(TheMemoryAccess),
   1457       Target(TheTarget->getId()),
   1458       Source(TheSource->getId()),
   1459       Size(TheSize->getId()) {
   1460     validate();
   1461     assert(TheBB && "Invalid BB");
   1462   }
   1463   // Incomplete constructor
   1464   SPIRVCopyMemorySized() :SPIRVInstruction(OC), SPIRVMemoryAccess(),
   1465       Target(SPIRVID_INVALID), Source(SPIRVID_INVALID), Size(0) {
   1466     setHasNoId();
   1467     setHasNoType();
   1468   }
   1469 
   1470   SPIRVValue *getSource() { return getValue(Source); }
   1471   SPIRVValue *getTarget() { return getValue(Target); }
   1472   SPIRVValue *getSize() { return getValue(Size); }
   1473 
   1474 protected:
   1475   void setWordCount(SPIRVWord TheWordCount) {
   1476     SPIRVEntry::setWordCount(TheWordCount);
   1477     MemoryAccess.resize(TheWordCount - FixedWords);
   1478   }
   1479 
   1480   void encode(spv_ostream &O) const {
   1481     getEncoder(O) << Target << Source << Size << MemoryAccess;
   1482   }
   1483 
   1484   void decode(std::istream &I) {
   1485     getDecoder(I) >> Target >> Source >> Size >> MemoryAccess;
   1486     MemoryAccessUpdate(MemoryAccess);
   1487   }
   1488 
   1489     void validate()const {
   1490     SPIRVInstruction::validate();
   1491   }
   1492 
   1493   std::vector<SPIRVWord> MemoryAccess;
   1494   SPIRVId Target;
   1495   SPIRVId Source;
   1496   SPIRVId Size;
   1497 };
   1498 
   1499 class SPIRVVectorExtractDynamic:public SPIRVInstruction {
   1500 public:
   1501   const static Op OC = OpVectorExtractDynamic;
   1502   // Complete constructor
   1503   SPIRVVectorExtractDynamic(SPIRVId TheId, SPIRVValue *TheVector,
   1504       SPIRVValue* TheIndex, SPIRVBasicBlock *TheBB)
   1505   :SPIRVInstruction(5, OC, TheVector->getType()->getVectorComponentType(),
   1506       TheId, TheBB), VectorId(TheVector->getId()),
   1507       IndexId(TheIndex->getId()){
   1508     validate();
   1509     assert(TheBB && "Invalid BB");
   1510   }
   1511   // Incomplete constructor
   1512   SPIRVVectorExtractDynamic():SPIRVInstruction(OC), VectorId(SPIRVID_INVALID),
   1513       IndexId(SPIRVID_INVALID){}
   1514 
   1515   SPIRVValue *getVector() { return getValue(VectorId);}
   1516   SPIRVValue *getIndex()const { return getValue(IndexId);}
   1517 protected:
   1518   _SPIRV_DEF_ENCDEC4(Type, Id, VectorId, IndexId)
   1519   void validate()const {
   1520     SPIRVInstruction::validate();
   1521     if (getValue(VectorId)->isForward())
   1522       return;
   1523     assert(getValueType(VectorId)->isTypeVector());
   1524   }
   1525   SPIRVId VectorId;
   1526   SPIRVId IndexId;
   1527 };
   1528 
   1529 class SPIRVVectorInsertDynamic :public SPIRVInstruction {
   1530 public:
   1531   const static Op OC = OpVectorInsertDynamic;
   1532   // Complete constructor
   1533   SPIRVVectorInsertDynamic(SPIRVId TheId, SPIRVValue *TheVector,
   1534       SPIRVValue* TheComponent, SPIRVValue* TheIndex, SPIRVBasicBlock *TheBB)
   1535     :SPIRVInstruction(6, OC, TheVector->getType()->getVectorComponentType(),
   1536     TheId, TheBB), VectorId(TheVector->getId()),
   1537     IndexId(TheIndex->getId()), ComponentId(TheComponent->getId()){
   1538     validate();
   1539     assert(TheBB && "Invalid BB");
   1540   }
   1541   // Incomplete constructor
   1542   SPIRVVectorInsertDynamic() :SPIRVInstruction(OC), VectorId(SPIRVID_INVALID),
   1543     IndexId(SPIRVID_INVALID), ComponentId(SPIRVID_INVALID){}
   1544 
   1545   SPIRVValue *getVector() { return getValue(VectorId); }
   1546   SPIRVValue *getIndex()const { return getValue(IndexId); }
   1547   SPIRVValue *getComponent() { return getValue(ComponentId); }
   1548 protected:
   1549   _SPIRV_DEF_ENCDEC5(Type, Id, VectorId, ComponentId, IndexId)
   1550     void validate()const {
   1551     SPIRVInstruction::validate();
   1552     if (getValue(VectorId)->isForward())
   1553       return;
   1554     assert(getValueType(VectorId)->isTypeVector());
   1555   }
   1556   SPIRVId VectorId;
   1557   SPIRVId IndexId;
   1558   SPIRVId ComponentId;
   1559 };
   1560 
   1561 class SPIRVVectorShuffle:public SPIRVInstruction {
   1562 public:
   1563   const static Op OC = OpVectorShuffle;
   1564   const static SPIRVWord FixedWordCount = 5;
   1565   // Complete constructor
   1566   SPIRVVectorShuffle(SPIRVId TheId, SPIRVType *TheType, SPIRVValue *TheVector1,
   1567       SPIRVValue *TheVector2, const std::vector<SPIRVWord>& TheComponents,
   1568       SPIRVBasicBlock *TheBB):
   1569         SPIRVInstruction(TheComponents.size() + FixedWordCount, OC, TheType,
   1570             TheId, TheBB),
   1571         Vector1(TheVector1->getId()), Vector2(TheVector2->getId()),
   1572         Components(TheComponents){
   1573     validate();
   1574     assert(TheBB && "Invalid BB");
   1575   }
   1576   // Incomplete constructor
   1577   SPIRVVectorShuffle():SPIRVInstruction(OC), Vector1(SPIRVID_INVALID),
   1578       Vector2(SPIRVID_INVALID){}
   1579 
   1580   SPIRVValue *getVector1() { return getValue(Vector1);}
   1581   SPIRVValue *getVector2() { return getValue(Vector2);}
   1582   const std::vector<SPIRVWord>& getComponents()const { return Components;}
   1583 protected:
   1584   void setWordCount(SPIRVWord TheWordCount) {
   1585     SPIRVEntry::setWordCount(TheWordCount);
   1586     Components.resize(TheWordCount - FixedWordCount);
   1587   }
   1588   _SPIRV_DEF_ENCDEC5(Type, Id, Vector1, Vector2, Components)
   1589   void validate()const {
   1590     SPIRVInstruction::validate();
   1591     assert(OpCode == OC);
   1592     assert(WordCount == Components.size() + FixedWordCount);
   1593     assert(Type->isTypeVector());
   1594     assert(Type->getVectorComponentType() ==
   1595         getValueType(Vector1)->getVectorComponentType());
   1596     if (getValue(Vector1)->isForward() ||
   1597         getValue(Vector2)->isForward())
   1598       return;
   1599     assert(getValueType(Vector1) == getValueType(Vector2));
   1600     size_t CompCount = Type->getVectorComponentCount();
   1601     (void) CompCount;
   1602     assert(Components.size() == CompCount);
   1603     assert(Components.size() > 1);
   1604   }
   1605   SPIRVId Vector1;
   1606   SPIRVId Vector2;
   1607   std::vector<SPIRVWord> Components;
   1608 };
   1609 
   1610 class SPIRVControlBarrier:public SPIRVInstruction {
   1611 public:
   1612   static const Op OC = OpControlBarrier;
   1613   // Complete constructor
   1614   SPIRVControlBarrier(SPIRVValue *TheScope,
   1615       SPIRVValue *TheMemScope, SPIRVValue *TheMemSema,
   1616       SPIRVBasicBlock *TheBB)
   1617     :SPIRVInstruction(4, OC, TheBB), ExecScope(TheScope->getId()),
   1618     MemScope(TheMemScope->getId()), MemSema(TheMemSema->getId()){
   1619     validate();
   1620     assert(TheBB && "Invalid BB");
   1621   }
   1622   // Incomplete constructor
   1623   SPIRVControlBarrier():SPIRVInstruction(OC), ExecScope(ScopeInvocation) {
   1624     setHasNoId();
   1625     setHasNoType();
   1626   }
   1627   void setWordCount(SPIRVWord TheWordCount) {
   1628     SPIRVEntry::setWordCount(TheWordCount);
   1629   }
   1630   SPIRVValue *getExecScope() const { return getValue(ExecScope); }
   1631   SPIRVValue *getMemScope() const { return getValue(MemScope); }
   1632   SPIRVValue *getMemSemantic() const { return getValue(MemSema); }
   1633   std::vector<SPIRVValue *> getOperands() {
   1634     std::vector<SPIRVId> Operands;
   1635     Operands.push_back(ExecScope);
   1636     Operands.push_back(MemScope);
   1637     Operands.push_back(MemSema);
   1638     return getValues(Operands);
   1639   }
   1640 protected:
   1641   _SPIRV_DEF_ENCDEC3(ExecScope, MemScope, MemSema)
   1642   void validate()const {
   1643     assert(OpCode == OC);
   1644     assert(WordCount == 4);
   1645     SPIRVInstruction::validate();
   1646   }
   1647   SPIRVId ExecScope;
   1648   SPIRVId MemScope;
   1649   SPIRVId MemSema;
   1650 };
   1651 
   1652 class SPIRVGroupAsyncCopy:public SPIRVInstruction {
   1653 public:
   1654   static const Op OC = OpGroupAsyncCopy;
   1655   static const SPIRVWord WC = 9;
   1656   // Complete constructor
   1657   SPIRVGroupAsyncCopy(SPIRVValue *TheScope, SPIRVId TheId,
   1658       SPIRVValue *TheDest, SPIRVValue *TheSrc, SPIRVValue *TheNumElems,
   1659       SPIRVValue *TheStride, SPIRVValue *TheEvent, SPIRVBasicBlock *TheBB)
   1660     :SPIRVInstruction(WC, OC, TheEvent->getType(), TheId, TheBB),
   1661     ExecScope(TheScope->getId()), Destination(TheDest->getId()),
   1662      Source(TheSrc->getId()), NumElements(TheNumElems->getId()),
   1663      Stride(TheStride->getId()), Event(TheEvent->getId()){
   1664     validate();
   1665     assert(TheBB && "Invalid BB");
   1666   }
   1667   // Incomplete constructor
   1668   SPIRVGroupAsyncCopy():SPIRVInstruction(OC), ExecScope(SPIRVID_INVALID),
   1669       Destination(SPIRVID_INVALID), Source(SPIRVID_INVALID),
   1670       NumElements(SPIRVID_INVALID), Stride(SPIRVID_INVALID),
   1671       Event(SPIRVID_INVALID){
   1672   }
   1673   SPIRVValue *getExecScope() const { return getValue(ExecScope); }
   1674   SPIRVValue *getDestination()const { return getValue(Destination);}
   1675   SPIRVValue *getSource()const { return getValue(Source);}
   1676   SPIRVValue *getNumElements()const { return getValue(NumElements);}
   1677   SPIRVValue *getStride()const { return getValue(Stride);}
   1678   SPIRVValue *getEvent()const { return getValue(Event);}
   1679   std::vector<SPIRVValue *> getOperands() {
   1680     std::vector<SPIRVId> Operands;
   1681     Operands.push_back(Destination);
   1682     Operands.push_back(Source);
   1683     Operands.push_back(NumElements);
   1684     Operands.push_back(Stride);
   1685     Operands.push_back(Event);
   1686     return getValues(Operands);
   1687   }
   1688 
   1689 protected:
   1690   _SPIRV_DEF_ENCDEC8(Type, Id, ExecScope, Destination, Source, NumElements,
   1691       Stride, Event)
   1692   void validate()const {
   1693     assert(OpCode == OC);
   1694     assert(WordCount == WC);
   1695     SPIRVInstruction::validate();
   1696   }
   1697   SPIRVId ExecScope;
   1698   SPIRVId Destination;
   1699   SPIRVId Source;
   1700   SPIRVId NumElements;
   1701   SPIRVId Stride;
   1702   SPIRVId Event;
   1703 };
   1704 
   1705 enum SPIRVOpKind {
   1706   SPIRVOPK_Id,
   1707   SPIRVOPK_Literal,
   1708   SPIRVOPK_Count
   1709 };
   1710 
   1711 class SPIRVDevEnqInstBase:public SPIRVInstTemplateBase {
   1712 public:
   1713   SPIRVCapVec getRequiriedCapability() const {
   1714     return getVec(CapabilityDeviceEnqueue);
   1715   }
   1716 };
   1717 
   1718 #define _SPIRV_OP(x, ...) \
   1719   typedef SPIRVInstTemplate<SPIRVDevEnqInstBase, Op##x, __VA_ARGS__> \
   1720       SPIRV##x;
   1721 // CL 2.0 enqueue kernel builtins
   1722 _SPIRV_OP(EnqueueMarker, true, 7)
   1723 _SPIRV_OP(EnqueueKernel, true, 13, true)
   1724 _SPIRV_OP(GetKernelNDrangeSubGroupCount, true, 8)
   1725 _SPIRV_OP(GetKernelNDrangeMaxSubGroupSize, true, 8)
   1726 _SPIRV_OP(GetKernelWorkGroupSize, true, 7)
   1727 _SPIRV_OP(GetKernelPreferredWorkGroupSizeMultiple, true, 7)
   1728 _SPIRV_OP(RetainEvent, false, 2)
   1729 _SPIRV_OP(ReleaseEvent, false, 2)
   1730 _SPIRV_OP(CreateUserEvent, true, 3)
   1731 _SPIRV_OP(IsValidEvent, true, 4)
   1732 _SPIRV_OP(SetUserEventStatus, false, 3)
   1733 _SPIRV_OP(CaptureEventProfilingInfo, false, 4)
   1734 _SPIRV_OP(GetDefaultQueue, true, 3)
   1735 _SPIRV_OP(BuildNDRange, true, 6)
   1736 #undef _SPIRV_OP
   1737 
   1738 class SPIRVPipeInstBase:public SPIRVInstTemplateBase {
   1739 public:
   1740   SPIRVCapVec getRequiriedCapability() const {
   1741     return getVec(CapabilityPipes);
   1742   }
   1743 };
   1744 
   1745 #define _SPIRV_OP(x, ...) \
   1746   typedef SPIRVInstTemplate<SPIRVPipeInstBase, Op##x, __VA_ARGS__> \
   1747       SPIRV##x;
   1748 // CL 2.0 pipe builtins
   1749 _SPIRV_OP(ReadPipe, true, 7)
   1750 _SPIRV_OP(WritePipe, true, 7)
   1751 _SPIRV_OP(ReservedReadPipe, true, 9)
   1752 _SPIRV_OP(ReservedWritePipe, true, 9)
   1753 _SPIRV_OP(ReserveReadPipePackets, true, 7)
   1754 _SPIRV_OP(ReserveWritePipePackets, true, 7)
   1755 _SPIRV_OP(CommitReadPipe, false, 5)
   1756 _SPIRV_OP(CommitWritePipe, false, 5)
   1757 _SPIRV_OP(IsValidReserveId, true, 4)
   1758 _SPIRV_OP(GetNumPipePackets, true, 6)
   1759 _SPIRV_OP(GetMaxPipePackets, true, 6)
   1760 #undef _SPIRV_OP
   1761 
   1762 class SPIRVPipeStorageInstBase :public SPIRVInstTemplateBase {
   1763 public:
   1764   SPIRVCapVec getRequiriedCapability() const {
   1765     return getVec(CapabilityPipeStorage, CapabilityPipes);
   1766   }
   1767 };
   1768 
   1769 #define _SPIRV_OP(x, ...) \
   1770   typedef SPIRVInstTemplate<SPIRVPipeStorageInstBase, Op##x, __VA_ARGS__> \
   1771   SPIRV##x;
   1772 
   1773 _SPIRV_OP(CreatePipeFromPipeStorage, true, 4)
   1774 #undef _SPIRV_OP
   1775 
   1776 class SPIRVGroupInstBase:public SPIRVInstTemplateBase {
   1777 public:
   1778   SPIRVCapVec getRequiriedCapability() const {
   1779     return getVec(CapabilityGroups);
   1780   }
   1781 };
   1782 
   1783 #define _SPIRV_OP(x, ...) \
   1784   typedef SPIRVInstTemplate<SPIRVGroupInstBase, Op##x, __VA_ARGS__> \
   1785       SPIRV##x;
   1786 // Group instructions
   1787 _SPIRV_OP(GroupWaitEvents, false, 4)
   1788 _SPIRV_OP(GroupAll, true, 5)
   1789 _SPIRV_OP(GroupAny, true, 5)
   1790 _SPIRV_OP(GroupBroadcast, true, 6)
   1791 _SPIRV_OP(GroupIAdd, true, 6, false, 1)
   1792 _SPIRV_OP(GroupFAdd, true, 6, false, 1)
   1793 _SPIRV_OP(GroupFMin, true, 6, false, 1)
   1794 _SPIRV_OP(GroupUMin, true, 6, false, 1)
   1795 _SPIRV_OP(GroupSMin, true, 6, false, 1)
   1796 _SPIRV_OP(GroupFMax, true, 6, false, 1)
   1797 _SPIRV_OP(GroupUMax, true, 6, false, 1)
   1798 _SPIRV_OP(GroupSMax, true, 6, false, 1)
   1799 _SPIRV_OP(GroupReserveReadPipePackets, true, 8)
   1800 _SPIRV_OP(GroupReserveWritePipePackets, true, 8)
   1801 _SPIRV_OP(GroupCommitReadPipe, false, 6)
   1802 _SPIRV_OP(GroupCommitWritePipe, false, 6)
   1803 #undef _SPIRV_OP
   1804 
   1805 class SPIRVAtomicInstBase:public SPIRVInstTemplateBase {
   1806 public:
   1807   SPIRVCapVec getRequiriedCapability() const {
   1808     return getVec(CapabilityInt64Atomics);
   1809   }
   1810 };
   1811 
   1812 #define _SPIRV_OP(x, ...) \
   1813   typedef SPIRVInstTemplate<SPIRVAtomicInstBase, Op##x, __VA_ARGS__> \
   1814       SPIRV##x;
   1815 // Atomic builtins
   1816 _SPIRV_OP(AtomicFlagTestAndSet, true, 6)
   1817 _SPIRV_OP(AtomicFlagClear, false, 4)
   1818 _SPIRV_OP(AtomicLoad, true, 6)
   1819 _SPIRV_OP(AtomicStore, false, 5)
   1820 _SPIRV_OP(AtomicExchange, true, 7)
   1821 _SPIRV_OP(AtomicCompareExchange, true, 9)
   1822 _SPIRV_OP(AtomicCompareExchangeWeak, true, 9)
   1823 _SPIRV_OP(AtomicIIncrement, true, 6)
   1824 _SPIRV_OP(AtomicIDecrement, true, 6)
   1825 _SPIRV_OP(AtomicIAdd, true, 7)
   1826 _SPIRV_OP(AtomicISub, true, 7)
   1827 _SPIRV_OP(AtomicUMin, true, 7)
   1828 _SPIRV_OP(AtomicUMax, true, 7)
   1829 _SPIRV_OP(AtomicSMin, true, 7)
   1830 _SPIRV_OP(AtomicSMax, true, 7)
   1831 _SPIRV_OP(AtomicAnd, true, 7)
   1832 _SPIRV_OP(AtomicOr, true, 7)
   1833 _SPIRV_OP(AtomicXor, true, 7)
   1834 _SPIRV_OP(MemoryBarrier, false, 3)
   1835 #undef _SPIRV_OP
   1836 
   1837 class SPIRVImageInstBase:public SPIRVInstTemplateBase {
   1838 public:
   1839   SPIRVCapVec getRequiriedCapability() const {
   1840     return getVec(CapabilityImageBasic);
   1841   }
   1842 };
   1843 
   1844 #define _SPIRV_OP(x, ...) \
   1845   typedef SPIRVInstTemplate<SPIRVImageInstBase, Op##x, __VA_ARGS__> \
   1846       SPIRV##x;
   1847 // Image instructions
   1848 _SPIRV_OP(SampledImage, true, 5)
   1849 _SPIRV_OP(ImageSampleImplicitLod, true, 5, true)
   1850 _SPIRV_OP(ImageSampleExplicitLod, true, 7, true, 2)
   1851 _SPIRV_OP(ImageRead, true, 5, true, 2)
   1852 _SPIRV_OP(ImageWrite, false, 4, true, 3)
   1853 _SPIRV_OP(ImageQueryFormat, true, 4)
   1854 _SPIRV_OP(ImageQueryOrder, true, 4)
   1855 _SPIRV_OP(ImageQuerySizeLod, true, 5)
   1856 _SPIRV_OP(ImageQuerySize, true, 4)
   1857 _SPIRV_OP(ImageQueryLod, true, 5)
   1858 _SPIRV_OP(ImageQueryLevels, true, 4)
   1859 _SPIRV_OP(ImageQuerySamples, true, 4)
   1860 #undef _SPIRV_OP
   1861 
   1862 #define _SPIRV_OP(x, ...) \
   1863   typedef SPIRVInstTemplate<SPIRVInstTemplateBase, Op##x, __VA_ARGS__> \
   1864       SPIRV##x;
   1865 // Other instructions
   1866 _SPIRV_OP(SpecConstantOp, true, 4, true, 0)
   1867 _SPIRV_OP(GenericPtrMemSemantics, true, 4, false)
   1868 _SPIRV_OP(GenericCastToPtrExplicit, true, 5, false, 1)
   1869 #undef _SPIRV_OP
   1870 
   1871 SPIRVSpecConstantOp *createSpecConstantOpInst(SPIRVInstruction *Inst);
   1872 SPIRVInstruction *createInstFromSpecConstantOp(SPIRVSpecConstantOp *C);
   1873 }
   1874 
   1875 #endif // SPIRVINSTRUCTION_HPP_
   1876