• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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):
ExecScope(TheScope)72     ExecScope(TheScope){}
73   Scope ExecScope;
74 };
75 
76 class SPIRVComponentMemorySemanticsMask {
77 public:
78   SPIRVComponentMemorySemanticsMask(SPIRVWord TheSema = SPIRVWORD_MAX):
MemSema(TheSema)79     MemSema(TheSema){}
80   SPIRVWord MemSema;
81 };
82 
83 class SPIRVComponentOperands {
84 public:
SPIRVComponentOperands()85   SPIRVComponentOperands(){};
SPIRVComponentOperands(const std::vector<SPIRVValue * > & TheOperands)86   SPIRVComponentOperands(const std::vector<SPIRVValue *> &TheOperands):
87     Operands(TheOperands){};
SPIRVComponentOperands(std::vector<SPIRVValue * > && TheOperands)88   SPIRVComponentOperands(std::vector<SPIRVValue *> &&TheOperands):
89     Operands(std::move(TheOperands)){};
getCompOperands()90   std::vector<SPIRVValue *> getCompOperands() {
91     return Operands;
92   }
getCompOperandTypes()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
SPIRVValue(TheOC)122   SPIRVInstruction(Op TheOC = OpNop):SPIRVValue(TheOC), BB(NULL){}
123 
isInst()124   virtual bool isInst() const { return true;}
getParent()125   SPIRVBasicBlock *getParent() const {return BB;}
getPrevious()126   SPIRVInstruction *getPrevious() const { return BB->getPrevious(this);}
getNext()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 *);
addFPRoundingMode(SPIRVFPRoundingModeKind Kind)135   void addFPRoundingMode(SPIRVFPRoundingModeKind Kind) {
136     addDecorate(DecorationFPRoundingMode, Kind);
137   }
eraseFPRoundingMode()138   void eraseFPRoundingMode() {
139     eraseDecorate(DecorationFPRoundingMode);
140   }
setSaturatedConversion(bool Enable)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   }
isSaturatedConversion()154   bool isSaturatedConversion() {
155     return hasDecorate(DecorationSaturatedConversion) ||
156         OpCode == OpSatConvertSToU ||
157         OpCode == OpSatConvertUToS;
158   }
159 
getBasicBlock()160   SPIRVBasicBlock* getBasicBlock() const {
161     return BB;
162   }
163 
setBasicBlock(SPIRVBasicBlock * TheBB)164   void setBasicBlock(SPIRVBasicBlock* TheBB) {
165     BB = TheBB;
166     if (TheBB)
167       setModule(TheBB->getModule());
168   }
169 
170 protected:
validate()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.
create(Op TheOC)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.
create(Op TheOC,SPIRVType * TheType,SPIRVId TheId,SPIRVBasicBlock * TheBB,SPIRVModule * TheModule)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.
create(Op TheOC,SPIRVType * TheType,SPIRVId TheId,const std::vector<SPIRVWord> & TheOps,SPIRVBasicBlock * TheBB,SPIRVModule * TheModule)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)
SPIRVInstruction(OC)207     :SPIRVInstruction(OC), HasVariWC(false){
208     init();
209   }
~SPIRVInstTemplateBase()210   virtual ~SPIRVInstTemplateBase(){}
init(SPIRVType * TheType,SPIRVId TheId,SPIRVBasicBlock * TheBB,SPIRVModule * TheModule)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   }
init()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   }
isOperandLiteral(unsigned I)240   virtual bool isOperandLiteral(unsigned I) const {
241     return Lit.count(I);
242   }
addLit(unsigned L)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.
getExpectedNumOperands()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   }
setOpWordsAndValidate(const std::vector<SPIRVWord> & TheOps)258   virtual void setOpWordsAndValidate(const std::vector<SPIRVWord> &TheOps) {
259     setOpWords(TheOps);
260     validate();
261   }
setOpWords(const std::vector<SPIRVWord> & TheOps)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   }
setWordCount(SPIRVWord TheWordCount)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 
getOpWords()289   std::vector<SPIRVWord> &getOpWords() {
290     return Ops;
291   }
292 
getOpWords()293   const std::vector<SPIRVWord> &getOpWords() const {
294     return Ops;
295   }
296 
getOpWord(int I)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.
getOpValue(int I)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.
getOperandOffset()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.
getOperands()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 
getNonLiteralOperands()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 
getOperand(unsigned I)335   virtual SPIRVValue *getOperand(unsigned I) {
336     return getOpValue(I + getOperandOffset());
337   }
338 
hasExecScope()339   bool hasExecScope() const {
340     return SPIRV::hasExecScope(OpCode);
341   }
342 
hasGroupOperation()343   bool hasGroupOperation() const {
344     return SPIRV::hasGroupOperation(OpCode);
345   }
346 
getSPIRVGroupOperation(SPIRVGroupOperationKind & GroupOp)347   bool getSPIRVGroupOperation(SPIRVGroupOperationKind &GroupOp) const {
348     if (!hasGroupOperation())
349       return false;
350     GroupOp = static_cast<SPIRVGroupOperationKind>(Ops[1]);
351     return true;
352   }
353 
getExecutionScope()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 
hasVariableWordCount()361   bool hasVariableWordCount() const {
362     return HasVariWC;
363   }
364 
setHasVariableWordCount(bool VariWC)365   void setHasVariableWordCount(bool VariWC) {
366     HasVariWC = VariWC;
367   }
368 
369 protected:
encode(spv_ostream & O)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   }
decode(std::istream & I)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;
SPIRVInstTemplate()402   SPIRVInstTemplate(){
403     init();
404   }
~SPIRVInstTemplate()405   virtual ~SPIRVInstTemplate(){}
init()406   virtual void init() {
407     this->initImpl(OC, HasId, WC, HasVariableWC, Literal1, Literal2, Literal3);
408   }
409 };
410 
411 class SPIRVMemoryAccess {
412 public:
SPIRVMemoryAccess(const std::vector<SPIRVWord> & TheMemoryAccess)413   SPIRVMemoryAccess(const std::vector<SPIRVWord> &TheMemoryAccess):
414     TheMemoryAccessMask(0), Alignment(0) {
415     MemoryAccessUpdate(TheMemoryAccess);
416   }
417 
SPIRVMemoryAccess()418   SPIRVMemoryAccess() : TheMemoryAccessMask(0), Alignment(0){}
419 
MemoryAccessUpdate(const std::vector<SPIRVWord> & MemoryAccess)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   }
isVolatile()430   SPIRVWord isVolatile() const { return getMemoryAccessMask() & MemoryAccessVolatileMask; }
isNonTemporal()431   SPIRVWord isNonTemporal() const { return getMemoryAccessMask() & MemoryAccessNontemporalMask; }
getMemoryAccessMask()432   SPIRVWord getMemoryAccessMask() const { return TheMemoryAccessMask; }
getAlignment()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
SPIRVVariable(SPIRVType * TheType,SPIRVId TheId,SPIRVValue * TheInitializer,const std::string & TheName,SPIRVStorageClassKind TheStorageClass,SPIRVBasicBlock * TheBB,SPIRVModule * TheM)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
SPIRVVariable()456   SPIRVVariable() :SPIRVInstruction(OpVariable),
457       StorageClass(StorageClassFunction){}
458 
getStorageClass()459   SPIRVStorageClassKind getStorageClass() const { return StorageClass; }
getInitializer()460   SPIRVValue *getInitializer() const {
461     if (Initializer.empty())
462       return nullptr;
463     assert(Initializer.size() == 1);
464     return getValue(Initializer[0]);
465   }
isConstant()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   }
setBuiltin(SPIRVBuiltinVariableKind Kind)478   void setBuiltin(SPIRVBuiltinVariableKind Kind) {
479     assert(isValid(Kind));
480     addDecorate(new SPIRVDecorate(DecorationBuiltIn, this, Kind));
481   }
setIsConstant(bool Is)482   void setIsConstant(bool Is) {
483     if (Is)
484       addDecorate(new SPIRVDecorate(DecorationConstant, this));
485     else
486       eraseDecorate(DecorationConstant);
487   }
getNonLiteralOperands()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:
validate()494   void validate() const {
495     SPIRVValue::validate();
496     assert(isValid(StorageClass));
497     assert(Initializer.size() == 1 || Initializer.empty());
498   }
setWordCount(SPIRVWord TheWordCount)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