10e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===- SPIRVInstruction.h - Class to represent SPIRV instruction -*- C++ -*-===//
20e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
30e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//                     The LLVM/SPIRV Translator
40e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
50e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// This file is distributed under the University of Illinois Open Source
60e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// License. See LICENSE.TXT for details.
70e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
80e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
90e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Permission is hereby granted, free of charge, to any person obtaining a
110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// copy of this software and associated documentation files (the "Software"),
120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// to deal with the Software without restriction, including without limitation
130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// the rights to use, copy, modify, merge, publish, distribute, sublicense,
140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// and/or sell copies of the Software, and to permit persons to whom the
150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Software is furnished to do so, subject to the following conditions:
160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Redistributions of source code must retain the above copyright notice,
180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// this list of conditions and the following disclaimers.
190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Redistributions in binary form must reproduce the above copyright notice,
200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// this list of conditions and the following disclaimers in the documentation
210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// and/or other materials provided with the distribution.
220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Neither the names of Advanced Micro Devices, Inc., nor the names of its
230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// contributors may be used to endorse or promote products derived from this
240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Software without specific prior written permission.
250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// THE SOFTWARE.
320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===----------------------------------------------------------------------===//
340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// \file
350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///
360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/// This file defines Instruction class for SPIR-V.
370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung///
380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===----------------------------------------------------------------------===//
390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#ifndef SPIRVINSTRUCTION_HPP_
410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define SPIRVINSTRUCTION_HPP_
420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVEnum.h"
440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVIsValidEnum.h"
450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVStream.h"
460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVValue.h"
470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVBasicBlock.h"
480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVOpCode.h"
490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <cassert>
510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <cstdint>
520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <functional>
530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <iostream>
540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <map>
550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <utility>
560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <vector>
570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <unordered_set>
580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungnamespace SPIRV{
600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef std::vector<SPIRVValue *> ValueVec;
620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef std::pair<ValueVec::iterator, ValueVec::iterator> ValueRange;
630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVBasicBlock;
650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVFunction;
660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungbool isSpecConstantOpAllowedOp(Op OC);
680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVComponentExecutionScope {
700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVComponentExecutionScope(Scope TheScope = ScopeInvocation):
720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    ExecScope(TheScope){}
730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  Scope ExecScope;
740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVComponentMemorySemanticsMask {
770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVComponentMemorySemanticsMask(SPIRVWord TheSema = SPIRVWORD_MAX):
790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemSema(TheSema){}
800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord MemSema;
810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVComponentOperands {
840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVComponentOperands(){};
860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVComponentOperands(const std::vector<SPIRVValue *> &TheOperands):
870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands(TheOperands){};
880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVComponentOperands(std::vector<SPIRVValue *> &&TheOperands):
890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands(std::move(TheOperands)){};
900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> getCompOperands() {
910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Operands;
920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVType *> getCompOperandTypes() {
940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    std::vector<SPIRVType *> Tys;
950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (auto &I:getCompOperands())
960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Tys.push_back(I->getType());
970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Tys;
980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
1000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> Operands;
1010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
1020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVInstruction: public SPIRVValue {
1040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
1050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor for instruction with type and id
1060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType,
1070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVId TheId, SPIRVBasicBlock *TheBB);
1080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor for instruction with module, type and id
1090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction(unsigned TheWordCount, Op TheOC,
1100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVType *TheType, SPIRVId TheId, SPIRVBasicBlock *TheBB,
1110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVModule *TheBM);
1120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor for instruction with id but no type
1130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVId TheId,
1140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB);
1150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor for instruction without type and id
1160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction(unsigned TheWordCount, Op TheOC,
1170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB);
1180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor for instruction with type but no id
1190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction(unsigned TheWordCount, Op TheOC, SPIRVType *TheType,
1200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB);
1210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
1220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction(Op TheOC = OpNop):SPIRVValue(TheOC), BB(NULL){}
1230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual bool isInst() const { return true;}
1250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBasicBlock *getParent() const {return BB;}
1260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction *getPrevious() const { return BB->getPrevious(this);}
1270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstruction *getNext() const { return BB->getNext(this);}
1280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual std::vector<SPIRVValue *> getOperands();
1290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVType*> getOperandTypes();
1300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static std::vector<SPIRVType*> getOperandTypes(
1310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVValue *> &Ops);
1320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setParent(SPIRVBasicBlock *);
1340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setScope(SPIRVEntry *);
1350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void addFPRoundingMode(SPIRVFPRoundingModeKind Kind) {
1360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    addDecorate(DecorationFPRoundingMode, Kind);
1370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void eraseFPRoundingMode() {
1390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    eraseDecorate(DecorationFPRoundingMode);
1400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setSaturatedConversion(bool Enable) {
1420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (Enable)
1430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      addDecorate(DecorationSaturatedConversion);
1440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    else
1450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      eraseDecorate(DecorationSaturatedConversion);
1460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool hasFPRoundingMode(SPIRVFPRoundingModeKind *Kind = nullptr) {
1480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVWord V;
1490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Found = hasDecorate(DecorationFPRoundingMode, 0, &V);
1500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (Found && Kind)
1510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      *Kind = static_cast<SPIRVFPRoundingModeKind>(V);
1520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Found;
1530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isSaturatedConversion() {
1550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return hasDecorate(DecorationSaturatedConversion) ||
1560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        OpCode == OpSatConvertSToU ||
1570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        OpCode == OpSatConvertUToS;
1580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBasicBlock* getBasicBlock() const {
1610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return BB;
1620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setBasicBlock(SPIRVBasicBlock* TheBB) {
1650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    BB = TheBB;
1660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (TheBB)
1670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      setModule(TheBB->getModule());
1680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
1710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
1720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVValue::validate();
1730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprivate:
1750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBasicBlock *BB;
1760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
1770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVInstTemplateBase:public SPIRVInstruction {
1790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
1800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Create an empty instruction. Mainly for getting format information,
1810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// e.g. whether an operand is literal.
1820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static SPIRVInstTemplateBase *create(Op TheOC){
1830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Inst = static_cast<SPIRVInstTemplateBase *>(SPIRVEntry::create(TheOC));
1840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Inst);
1850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Inst->init();
1860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Inst;
1870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Create a instruction without operands.
1890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static SPIRVInstTemplateBase *create(Op TheOC, SPIRVType *TheType,
1900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVId TheId, SPIRVBasicBlock *TheBB,
1910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVModule *TheModule){
1920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Inst = create(TheOC);
1930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Inst->init(TheType, TheId, TheBB, TheModule);
1940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Inst;
1950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Create a complete and valid instruction.
1970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static SPIRVInstTemplateBase *create(Op TheOC, SPIRVType *TheType,
1980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVId TheId, const std::vector<SPIRVWord> &TheOps, SPIRVBasicBlock *TheBB,
1990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVModule *TheModule){
2000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Inst = create(TheOC);
2010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Inst->init(TheType, TheId, TheBB, TheModule);
2020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Inst->setOpWords(TheOps);
2030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Inst->validate();
2040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Inst;
2050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstTemplateBase(Op OC = OpNop)
2070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(OC), HasVariWC(false){
2080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    init();
2090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual ~SPIRVInstTemplateBase(){}
2110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstTemplateBase *init(SPIRVType *TheType,
2120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVId TheId, SPIRVBasicBlock *TheBB,
2130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVModule *TheModule){
2140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert((TheBB || TheModule) && "Invalid BB or Module");
2150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (TheBB)
2160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      setBasicBlock(TheBB);
2170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    else {
2180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      setModule(TheModule);
2190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
2200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setId(hasId() ? TheId : SPIRVID_INVALID);
2210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setType(hasType() ? TheType : nullptr);
2220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return this;
2230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void init() {}
2250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void initImpl(Op OC, bool HasId = true, SPIRVWord WC = 0,
2260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      bool VariWC = false, unsigned Lit1 = ~0U,
2270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      unsigned Lit2 = ~0U, unsigned Lit3 = ~0U){
2280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    OpCode = OC;
2290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!HasId) {
2300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      setHasNoId();
2310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      setHasNoType();
2320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
2330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (WC)
2340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVEntry::setWordCount(WC);
2350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasVariableWordCount(VariWC);
2360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    addLit(Lit1);
2370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    addLit(Lit2);
2380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    addLit(Lit3);
2390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual bool isOperandLiteral(unsigned I) const {
2410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Lit.count(I);
2420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void addLit(unsigned L) {
2440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (L != ~0U)
2450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Lit.insert(L);
2460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// \return Expected number of operands. If the instruction has variable
2480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// number of words, return the minimum.
2490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord getExpectedNumOperands() const {
2500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount > 0 && "Word count not initialized");
2510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Exp = WordCount - 1;
2520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasId())
2530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      --Exp;
2540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasType())
2550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      --Exp;
2560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Exp;
2570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void setOpWordsAndValidate(const std::vector<SPIRVWord> &TheOps) {
2590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setOpWords(TheOps);
2600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
2610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void setOpWords(const std::vector<SPIRVWord> &TheOps) {
2630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVWord WC = TheOps.size() + 1;
2640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasId())
2650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      ++WC;
2660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasType())
2670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      ++WC;
2680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (WordCount) {
2690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (WordCount == WC) {
2700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        // do nothing
2710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      } else {
2720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        assert(HasVariWC && WC >= WordCount && "Invalid word count");
2730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        SPIRVEntry::setWordCount(WC);
2740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      }
2750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else
2760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVEntry::setWordCount(WC);
2770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Ops = TheOps;
2780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void setWordCount(SPIRVWord TheWordCount) {
2800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
2810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto NumOps = WordCount - 1;
2820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasId())
2830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      --NumOps;
2840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasType())
2850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      --NumOps;
2860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Ops.resize(NumOps);
2870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
2890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> &getOpWords() {
2900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Ops;
2910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
2930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const std::vector<SPIRVWord> &getOpWords() const {
2940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Ops;
2950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
2960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
2970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord getOpWord(int I) const {
2980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Ops[I];
2990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// Get operand as value.
3020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  /// If the operand is a literal, return it as a uint32 constant.
3030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getOpValue(int I) {
3040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return isOperandLiteral(I) ? Module->getLiteralAsConstant(Ops[I]) :
3050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValue(Ops[I]);
3060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Get the offset of operands.
3090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Some instructions skip literals when returning operands.
3100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  size_t getOperandOffset() const {
3110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasExecScope() && !isGroupOpCode(OpCode) && !isPipeOpCode(OpCode))
3120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return 1;
3130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return 0;
3140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Get operands which are values.
3170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Drop execution scope and group operation literals.
3180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Return other literals as uint32 constants.
3190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual std::vector<SPIRVValue *> getOperands() {
3200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    std::vector<SPIRVValue*> VOps;
3210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Offset = getOperandOffset();
3220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (size_t I = 0, E = Ops.size() - Offset; I != E; ++I)
3230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      VOps.push_back(getOperand(I));
3240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return VOps;
3250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
3280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    std::vector<SPIRVEntry*> Operands;
3290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (size_t I = getOperandOffset(), E = Ops.size(); I < E; ++I)
3300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (!isOperandLiteral(I))
3310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Operands.push_back(getEntry(Ops[I]));
3320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Operands;
3330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual SPIRVValue *getOperand(unsigned I) {
3360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getOpValue(I + getOperandOffset());
3370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool hasExecScope() const {
3400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return SPIRV::hasExecScope(OpCode);
3410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool hasGroupOperation() const {
3440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return SPIRV::hasGroupOperation(OpCode);
3450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool getSPIRVGroupOperation(SPIRVGroupOperationKind &GroupOp) const {
3480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!hasGroupOperation())
3490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return false;
3500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    GroupOp = static_cast<SPIRVGroupOperationKind>(Ops[1]);
3510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return true;
3520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  Scope getExecutionScope() const {
3550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if(!hasExecScope())
3560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return ScopeInvocation;
3570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return static_cast<Scope>(
3580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        static_cast<SPIRVConstant*>(getValue(Ops[0]))->getZExtIntValue());
3590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool hasVariableWordCount() const {
3620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return HasVariWC;
3630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setHasVariableWordCount(bool VariWC) {
3660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    HasVariWC = VariWC;
3670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
3700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void encode(spv_ostream &O) const {
3710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto E = getEncoder(O);
3720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasType())
3730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      E << Type;
3740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasId())
3750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      E << Id;
3760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    E << Ops;
3770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void decode(std::istream &I) {
3790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto D = getDecoder(I);
3800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasType())
3810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      D >> Type;
3820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasId())
3830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      D >> Id;
3840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    D >> Ops;
3850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
3860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> Ops;
3870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool HasVariWC;
3880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::unordered_set<unsigned> Lit; // Literal operand index
3890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
3900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
3910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtemplate<typename BT        = SPIRVInstTemplateBase,
3920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung         Op OC              = OpNop,
3930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung         bool HasId         = true,
3940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung         SPIRVWord WC        = 0,
3950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung         bool HasVariableWC = false,
3960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung         unsigned Literal1  = ~0U,
3970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung         unsigned Literal2  = ~0U,
3980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung         unsigned Literal3  = ~0U>
3990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVInstTemplate:public BT {
4000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
4010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef BT BaseTy;
4020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstTemplate(){
4030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    init();
4040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual ~SPIRVInstTemplate(){}
4060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual void init() {
4070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    this->initImpl(OC, HasId, WC, HasVariableWC, Literal1, Literal2, Literal3);
4080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
4100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVMemoryAccess {
4120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
4130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVMemoryAccess(const std::vector<SPIRVWord> &TheMemoryAccess):
4140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    TheMemoryAccessMask(0), Alignment(0) {
4150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccessUpdate(TheMemoryAccess);
4160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVMemoryAccess() : TheMemoryAccessMask(0), Alignment(0){}
4190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void MemoryAccessUpdate(const std::vector<SPIRVWord> &MemoryAccess) {
4210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!MemoryAccess.size())
4220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
4230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert((MemoryAccess.size() == 1 || MemoryAccess.size() == 2) && "Invalid memory access operand size");
4240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    TheMemoryAccessMask = MemoryAccess[0];
4250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (MemoryAccess[0] & MemoryAccessAlignedMask) {
4260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(MemoryAccess.size() == 2 && "Alignment operand is missing");
4270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Alignment = MemoryAccess[1];
4280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
4290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord isVolatile() const { return getMemoryAccessMask() & MemoryAccessVolatileMask; }
4310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord isNonTemporal() const { return getMemoryAccessMask() & MemoryAccessNontemporalMask; }
4320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord getMemoryAccessMask() const { return TheMemoryAccessMask; }
4330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord getAlignment() const { return Alignment; }
4340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
4360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord TheMemoryAccessMask;
4370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord Alignment;
4380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
4390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVVariable : public SPIRVInstruction {
4410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
4420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor for integer constant
4430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVariable(SPIRVType *TheType, SPIRVId TheId,
4440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVValue *TheInitializer, const std::string &TheName,
4450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVStorageClassKind TheStorageClass, SPIRVBasicBlock *TheBB,
4460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVModule *TheM)
4470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(TheInitializer ? 5 : 4, OpVariable, TheType,
4480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        TheId, TheBB, TheM),
4490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    StorageClass(TheStorageClass){
4500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (TheInitializer)
4510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Initializer.push_back(TheInitializer->getId());
4520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Name = TheName;
4530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
4540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
4560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVariable() :SPIRVInstruction(OpVariable),
4570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      StorageClass(StorageClassFunction){}
4580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
4590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVStorageClassKind getStorageClass() const { return StorageClass; }
4600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getInitializer() const {
4610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (Initializer.empty())
4620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return nullptr;
4630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Initializer.size() == 1);
4640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValue(Initializer[0]);
4650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isConstant() const {
4670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return hasDecorate(DecorationConstant);
4680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isBuiltin(SPIRVBuiltinVariableKind *BuiltinKind = nullptr) const {
4700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVWord Kind;
4710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    bool Found = hasDecorate(DecorationBuiltIn, 0, &Kind);
4720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (!Found)
4730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return false;
4740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (BuiltinKind)
4750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      *BuiltinKind = static_cast<SPIRVBuiltinVariableKind>(Kind);
4760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return true;
4770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setBuiltin(SPIRVBuiltinVariableKind Kind) {
4790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(isValid(Kind));
4800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    addDecorate(new SPIRVDecorate(DecorationBuiltIn, this, Kind));
4810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setIsConstant(bool Is) {
4830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (Is)
4840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      addDecorate(new SPIRVDecorate(DecorationConstant, this));
4850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    else
4860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      eraseDecorate(DecorationConstant);
4870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
4890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (SPIRVValue *V = getInitializer())
4900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return std::vector<SPIRVEntry*>(1, V);
4910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return std::vector<SPIRVEntry*>();
4920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
4940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate() const {
4950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVValue::validate();
4960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(isValid(StorageClass));
4970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Initializer.size() == 1 || Initializer.empty());
4980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
4990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
5000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
5010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Initializer.resize(WordCount - 4);
5020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC4(Type, Id, StorageClass, Initializer)
5040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVStorageClassKind StorageClass;
5060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVId> Initializer;
5070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
5080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVStore:public SPIRVInstruction, public SPIRVMemoryAccess {
5100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
5110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static SPIRVWord FixedWords = 3;
5120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
5130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVStore(SPIRVId PointerId, SPIRVId ValueId,
5140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *TheBB)
5150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OpStore,
5160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        TheBB),
5170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     SPIRVMemoryAccess(TheMemoryAccess),
5180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     MemoryAccess(TheMemoryAccess),
5190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     PtrId(PointerId),
5200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     ValId(ValueId){
5210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setAttr();
5220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
5230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
5240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
5260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVStore():SPIRVInstruction(OpStore), SPIRVMemoryAccess(),
5270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      PtrId(SPIRVID_INVALID), ValId(SPIRVID_INVALID){
5280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setAttr();
5290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getSrc() const { return getValue(ValId);}
5320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getDst() const { return getValue(PtrId);}
5330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
5340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setAttr() {
5350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
5360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
5370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
5400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
5410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccess.resize(TheWordCount - FixedWords);
5420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void encode(spv_ostream &O) const {
5440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getEncoder(O) << PtrId << ValId << MemoryAccess;
5450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void decode(std::istream &I) {
5480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getDecoder(I) >> PtrId >> ValId >> MemoryAccess;
5490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccessUpdate(MemoryAccess);
5500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
5530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
5540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getSrc()->isForward() || getDst()->isForward())
5550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
5560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getValueType(PtrId)->getPointerElementType() == getValueType(ValId)
5570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        && "Inconsistent operand types");
5580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprivate:
5600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> MemoryAccess;
5610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId PtrId;
5620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId ValId;
5630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
5640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVLoad:public SPIRVInstruction, public SPIRVMemoryAccess {
5660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
5670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static SPIRVWord FixedWords = 4;
5680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
5690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVLoad(SPIRVId TheId, SPIRVId PointerId,
5700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *TheBB)
5710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(FixedWords + TheMemoryAccess.size() , OpLoad,
5720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        TheBB->getValueType(PointerId)->getPointerElementType(), TheId, TheBB),
5730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        SPIRVMemoryAccess(TheMemoryAccess), PtrId(PointerId),
5740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        MemoryAccess(TheMemoryAccess) {
5750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      validate();
5760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(TheBB && "Invalid BB");
5770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
5780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
5790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVLoad():SPIRVInstruction(OpLoad), SPIRVMemoryAccess(),
5800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      PtrId(SPIRVID_INVALID){}
5810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getSrc() const { return Module->get<SPIRVValue>(PtrId);}
5830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
5850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
5860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
5870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccess.resize(TheWordCount - FixedWords);
5880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void encode(spv_ostream &O) const {
5910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getEncoder(O) << Type << Id << PtrId << MemoryAccess;
5920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void decode(std::istream &I) {
5950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getDecoder(I) >> Type >> Id >> PtrId >> MemoryAccess;
5960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccessUpdate(MemoryAccess);
5970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
5980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
5990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
6000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
6010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert((getValue(PtrId)->isForward() ||
6020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Type == getValueType(PtrId)->getPointerElementType()) &&
6030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Inconsistent types");
6040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
6050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprivate:
6060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId PtrId;
6070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> MemoryAccess;
6080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
6090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
6100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVBinary:public SPIRVInstTemplateBase {
6110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
6120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
6130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVId Op1 = Ops[0];
6140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVId Op2 = Ops[1];
6150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVType *op1Ty, *op2Ty;
6160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
6170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValue(Op1)->isForward() || getValue(Op2)->isForward())
6180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
6190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValueType(Op1)->isTypeVector()) {
6200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op1Ty = getValueType(Op1)->getVectorComponentType();
6210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op2Ty = getValueType(Op2)->getVectorComponentType();
6220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(getValueType(Op1)->getVectorComponentCount() ==
6230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung             getValueType(Op2)->getVectorComponentCount() &&
6240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung               "Inconsistent Vector component width");
6250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
6260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    else {
6270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op1Ty = getValueType(Op1);
6280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op2Ty = getValueType(Op2);
6290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
6300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
6310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (isBinaryOpCode(OpCode)) {
6320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(getValueType(Op1)== getValueType(Op2) &&
6330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung             "Invalid type for binary instruction");
6340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((op1Ty->isTypeInt() || op2Ty->isTypeFloat()) &&
6350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung               "Invalid type for Binary instruction");
6360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((op1Ty->getBitWidth() == op2Ty->getBitWidth()) &&
6370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung               "Inconsistent BitWidth");
6380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else if (isShiftOpCode(OpCode)) {
6390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((op1Ty->isTypeInt() || op2Ty->isTypeInt()) &&
6400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          "Invalid type for shift instruction");
6410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else if (isLogicalOpCode(OpCode)) {
6420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((op1Ty->isTypeBool() || op2Ty->isTypeBool()) &&
6430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          "Invalid type for logical instruction");
6440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else if (isBitwiseOpCode(OpCode)) {
6450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((op1Ty->isTypeInt() || op2Ty->isTypeInt()) &&
6460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          "Invalid type for bitwise instruction");
6470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((op1Ty->getIntegerBitWidth() == op2Ty->getIntegerBitWidth()) &&
6480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          "Inconsistent BitWidth");
6490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    } else {
6500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(0 && "Invalid op code!");
6510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
6520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
6530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
6540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
6550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtemplate<Op OC>
6560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVBinaryInst:public SPIRVInstTemplate<SPIRVBinary, OC, true, 5, false> {
6570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
6580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
6590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung/* ToDo: SMod and FMod to be added */
6600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x) typedef SPIRVBinaryInst<Op##x> SPIRV##x;
6610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IAdd)
6620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FAdd)
6630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ISub)
6640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FSub)
6650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IMul)
6660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FMul)
6670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(UDiv)
6680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SDiv)
6690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FDiv)
6700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SRem)
6710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FRem)
6720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(UMod)
6730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ShiftLeftLogical)
6740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ShiftRightLogical)
6750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ShiftRightArithmetic)
6760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(LogicalAnd)
6770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(LogicalOr)
6780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(LogicalEqual)
6790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(LogicalNotEqual)
6800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(BitwiseAnd)
6810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(BitwiseOr)
6820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(BitwiseXor)
6830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(Dot)
6840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
6850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
6860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtemplate<Op TheOpCode>
6870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVInstNoOperand:public SPIRVInstruction {
6880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
6890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
6900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstNoOperand(SPIRVBasicBlock *TheBB):SPIRVInstruction(1, TheOpCode,
6910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      TheBB){
6920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setAttr();
6930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
6940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
6950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
6960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInstNoOperand():SPIRVInstruction(TheOpCode){
6970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setAttr();
6980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
6990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
7000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setAttr() {
7010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
7020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
7030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC0
7050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
7060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
7070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef SPIRVInstNoOperand<OpReturn> SPIRVReturn;
7080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
7090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVReturnValue:public SPIRVInstruction {
7100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
7110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const Op OC = OpReturnValue;
7120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
7130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVReturnValue(SPIRVValue *TheReturnValue, SPIRVBasicBlock *TheBB)
7140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(2, OC, TheBB), ReturnValueId(TheReturnValue->getId()){
7150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setAttr();
7160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
7170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
7180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
7200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVReturnValue():SPIRVInstruction(OC), ReturnValueId(SPIRVID_INVALID) {
7210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setAttr();
7220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
7240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getReturnValue() const {
7250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValue(ReturnValueId);
7260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
7280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setAttr() {
7290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
7300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
7310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC1(ReturnValueId)
7330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
7340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
7350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId ReturnValueId;
7370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
7380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
7390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVBranch:public SPIRVInstruction {
7400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
7410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const Op OC = OpBranch;
7420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
7430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBranch(SPIRVLabel *TheTargetLabel,SPIRVBasicBlock *TheBB)
7440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(2, OC, TheBB), TargetLabelId(TheTargetLabel->getId()) {
7450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
7460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
7470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
7490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBranch():SPIRVInstruction(OC), TargetLabelId(SPIRVID_INVALID) {
7500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
7510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
7520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getTargetLabel() const {
7540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValue(TargetLabelId);
7550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
7570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC1(TargetLabelId)
7580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
7590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
7600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == 2);
7610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
7620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getTargetLabel()->isLabel() || getTargetLabel()->isForward());
7630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId TargetLabelId;
7650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
7660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
7670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVBranchConditional:public SPIRVInstruction {
7680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
7690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const Op OC = OpBranchConditional;
7700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
7710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBranchConditional(SPIRVValue *TheCondition, SPIRVLabel *TheTrueLabel,
7720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVLabel *TheFalseLabel, SPIRVBasicBlock *TheBB)
7730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(4, OC, TheBB), ConditionId(TheCondition->getId()),
7740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     TrueLabelId(TheTrueLabel->getId()), FalseLabelId(TheFalseLabel->getId()){
7750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
7760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBranchConditional(SPIRVValue *TheCondition, SPIRVLabel *TheTrueLabel,
7780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVLabel *TheFalseLabel, SPIRVBasicBlock *TheBB, SPIRVWord TrueWeight,
7790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVWord FalseWeight)
7800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(6, OC, TheBB), ConditionId(TheCondition->getId()),
7810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     TrueLabelId(TheTrueLabel->getId()), FalseLabelId(TheFalseLabel->getId()){
7820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    BranchWeights.push_back(TrueWeight);
7830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    BranchWeights.push_back(FalseWeight);
7840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
7850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
7860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
7880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBranchConditional():SPIRVInstruction(OC), ConditionId(SPIRVID_INVALID),
7890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      TrueLabelId(SPIRVID_INVALID), FalseLabelId(SPIRVID_INVALID) {
7900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
7910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
7920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getCondition() const {
7940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValue(ConditionId);
7950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVLabel *getTrueLabel() const {
7970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return get<SPIRVLabel>(TrueLabelId);
7980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
7990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVLabel *getFalseLabel() const {
8000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return get<SPIRVLabel>(FalseLabelId);
8010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
8030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
8040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
8050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    BranchWeights.resize(TheWordCount - 4);
8060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC4(ConditionId, TrueLabelId, FalseLabelId, BranchWeights)
8080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
8090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
8100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == 4 || WordCount == 6);
8110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == BranchWeights.size() + 4);
8120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
8130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getCondition()->isForward() ||
8140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getCondition()->getType()->isTypeBool());
8150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getTrueLabel()->isForward() || getTrueLabel()->isLabel());
8160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getFalseLabel()->isForward() || getFalseLabel()->isLabel());
8170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId ConditionId;
8190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId TrueLabelId;
8200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId FalseLabelId;
8210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> BranchWeights;
8220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
8230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
8240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVPhi: public SPIRVInstruction {
8250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
8260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const Op OC = OpPhi;
8270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const SPIRVWord FixedWordCount = 3;
8280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVPhi(SPIRVType *TheType, SPIRVId TheId,
8290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVValue *> &ThePairs, SPIRVBasicBlock *BB)
8300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(ThePairs.size() + FixedWordCount, OC, TheType, TheId, BB){
8310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Pairs = getIds(ThePairs);
8320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
8330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(BB && "Invalid BB");
8340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVPhi():SPIRVInstruction(OC) {}
8360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> getPairs() {
8370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValues(Pairs);
8380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void addPair(SPIRVValue *Value, SPIRVBasicBlock *BB) {
8400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Pairs.push_back(Value->getId());
8410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Pairs.push_back(BB->getId());
8420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    WordCount = Pairs.size() + FixedWordCount;
8430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
8440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setPairs(const std::vector<SPIRVValue *> &ThePairs) {
8460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Pairs = getIds(ThePairs);
8470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    WordCount = Pairs.size() + FixedWordCount;
8480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
8490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void foreachPair(std::function<void(SPIRVValue *, SPIRVBasicBlock *,
8510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      size_t)> Func) {
8520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (size_t I = 0, E = Pairs.size()/2; I != E; ++I) {
8530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVEntry *Value, *BB;
8540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (!Module->exist(Pairs[2*I], &Value) ||
8550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          !Module->exist(Pairs[2*I+1], &BB))
8560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        continue;
8570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Func(static_cast<SPIRVValue *>(Value), static_cast<SPIRVBasicBlock *>(BB),
8580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          I);
8590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
8600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void foreachPair(std::function<void(SPIRVValue *, SPIRVBasicBlock *)> Func)
8620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    const {
8630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (size_t I = 0, E = Pairs.size()/2; I != E; ++I) {
8640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVEntry *Value, *BB;
8650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (!Module->exist(Pairs[2*I], &Value) ||
8660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          !Module->exist(Pairs[2*I+1], &BB))
8670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        continue;
8680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Func(static_cast<SPIRVValue *>(Value), static_cast<SPIRVBasicBlock *>(BB));
8690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
8700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
8720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
8730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Pairs.resize(TheWordCount - FixedWordCount);
8740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC3(Type, Id, Pairs)
8760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
8770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == Pairs.size() + FixedWordCount);
8780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
8790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Pairs.size() % 2 == 0);
8800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    foreachPair([=](SPIRVValue *IncomingV, SPIRVBasicBlock *IncomingBB){
8810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(IncomingV->isForward() || IncomingV->getType() == Type);
8820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(IncomingBB->isBasicBlock() || IncomingBB->isForward());
8830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    });
8840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
8850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
8860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
8870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVId> Pairs;
8880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
8890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
8900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVCompare:public SPIRVInstTemplateBase {
8910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
8920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
8930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Op1 = Ops[0];
8940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Op2 = Ops[1];
8950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVType *op1Ty, *op2Ty, *resTy;
8960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
8970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValue(Op1)->isForward() || getValue(Op2)->isForward())
8980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
8990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
9000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValueType(Op1)->isTypeVector()) {
9010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op1Ty = getValueType(Op1)->getVectorComponentType();
9020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op2Ty = getValueType(Op2)->getVectorComponentType();
9030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      resTy = Type->getVectorComponentType();
9040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(getValueType(Op1)->getVectorComponentCount() ==
9050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung             getValueType(Op2)->getVectorComponentCount() &&
9060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung               "Inconsistent Vector component width");
9070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
9080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    else {
9090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op1Ty = getValueType(Op1);
9100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      op2Ty = getValueType(Op2);
9110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      resTy = Type;
9120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
9130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(isCmpOpCode(OpCode) && "Invalid op code for cmp inst");
9140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert((resTy->isTypeBool() || resTy->isTypeInt()) &&
9150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Invalid type for compare instruction");
9160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(op1Ty == op2Ty && "Inconsistent types");
9170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
9180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
9190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
9200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtemplate<Op OC>
9210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVCmpInst:public SPIRVInstTemplate<SPIRVCompare, OC, true, 5, false> {
9220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
9230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
9240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x) typedef SPIRVCmpInst<Op##x> SPIRV##x;
9250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IEqual)
9260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FOrdEqual)
9270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FUnordEqual)
9280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(INotEqual)
9290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FOrdNotEqual)
9300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FUnordNotEqual)
9310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ULessThan)
9320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SLessThan)
9330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FOrdLessThan)
9340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FUnordLessThan)
9350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(UGreaterThan)
9360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SGreaterThan)
9370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FOrdGreaterThan)
9380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FUnordGreaterThan)
9390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ULessThanEqual)
9400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SLessThanEqual)
9410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FOrdLessThanEqual)
9420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FUnordLessThanEqual)
9430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(UGreaterThanEqual)
9440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SGreaterThanEqual)
9450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FOrdGreaterThanEqual)
9460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FUnordGreaterThanEqual)
9470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(LessOrGreater)
9480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(Ordered)
9490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(Unordered)
9500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
9510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
9520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVSelect:public SPIRVInstruction {
9530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
9540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
9550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVSelect(SPIRVId TheId, SPIRVId TheCondition, SPIRVId TheOp1, SPIRVId TheOp2,
9560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB)
9570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(6, OpSelect, TheBB->getValueType(TheOp1), TheId,
9580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        TheBB), Condition(TheCondition), Op1(TheOp1), Op2(TheOp2){
9590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
9600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
9610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
9620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
9630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVSelect():SPIRVInstruction(OpSelect), Condition(SPIRVID_INVALID),
9640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Op1(SPIRVID_INVALID), Op2(SPIRVID_INVALID){}
9650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getCondition() { return getValue(Condition);}
9660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getTrueValue() { return getValue(Op1);}
9670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getFalseValue() { return getValue(Op2);}
9680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
9690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC5(Type, Id, Condition, Op1, Op2)
9700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
9710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
9720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValue(Condition)->isForward() ||
9730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValue(Op1)->isForward() ||
9740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValue(Op2)->isForward())
9750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
9760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
9770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVType *conTy = getValueType(Condition)->isTypeVector() ?
9780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Condition)->getVectorComponentType() :
9790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Condition);
9800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    (void) conTy;
9810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(conTy->isTypeBool() && "Invalid type");
9820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getType() == getValueType(Op1) && getType() == getValueType(Op2) &&
9830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Inconsistent type");
9840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
9850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Condition;
9860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Op1;
9870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Op2;
9880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
9890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
9900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVSwitch: public SPIRVInstruction {
9910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
9920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const Op OC = OpSwitch;
9930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const SPIRVWord FixedWordCount = 3;
9940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVSwitch(SPIRVValue *TheSelect, SPIRVBasicBlock *TheDefault,
9950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<std::pair<SPIRVWord, SPIRVBasicBlock *>> &ThePairs,
9960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *BB)
9970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(ThePairs.size() * 2 + FixedWordCount, OC, BB),
9980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     Select(TheSelect->getId()), Default(TheDefault->getId()) {
9990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (auto &I:ThePairs) {
10000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Pairs.push_back(I.first);
10010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Pairs.push_back(I.second->getId());
10020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
10030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
10040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(BB && "Invalid BB");
10050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVSwitch():SPIRVInstruction(OC), Select(SPIRVWORD_MAX),
10070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Default(SPIRVWORD_MAX) {
10080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
10090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
10100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> getPairs() {
10120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValues(Pairs);
10130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getSelect() const { return getValue(Select);}
10150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBasicBlock *getDefault() const {
10160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return static_cast<SPIRVBasicBlock *>(getValue(Default));
10170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  size_t getNumPairs() const { return Pairs.size()/2;}
10190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void foreachPair(std::function<void(SPIRVWord, SPIRVBasicBlock *, size_t)> Func)
10200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    const {
10210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (size_t I = 0, E = Pairs.size()/2; I != E; ++I) {
10220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVEntry *BB;
10230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      if (!Module->exist(Pairs[2*I+1], &BB))
10240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        continue;
10250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Func(Pairs[2*I], static_cast<SPIRVBasicBlock *>(BB), I);
10260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
10270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
10290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
10300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Pairs.resize(TheWordCount - FixedWordCount);
10310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC3(Select, Default, Pairs)
10330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
10340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == Pairs.size() + FixedWordCount);
10350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
10360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Pairs.size() % 2 == 0);
10370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    foreachPair([=](SPIRVWord Literal, SPIRVBasicBlock *BB, size_t Index){
10380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(BB->isBasicBlock() || BB->isForward());
10390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    });
10400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
10410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
10430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Select;
10440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Default;
10450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> Pairs;
10460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
10470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
10480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVUnary:public SPIRVInstTemplateBase {
10490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
10500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
10510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto Op = Ops[0];
10520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
10530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValue(Op)->isForward())
10540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
10550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (isGenericNegateOpCode(OpCode)) {
10560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVType *resTy = Type->isTypeVector() ?
10570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Type->getVectorComponentType() : Type;
10580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVType *opTy = Type->isTypeVector() ?
10590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Op)->getVectorComponentType() : getValueType(Op);
10600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
10610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(getType() == getValueType(Op)  &&
10620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Inconsistent type");
10630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      (void) resTy;
10640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((resTy->isTypeInt() || resTy->isTypeFloat()) &&
10650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Invalid type for Generic Negate instruction");
10660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      (void) opTy;
10670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((resTy->getBitWidth() == opTy->getBitWidth()) &&
10680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Invalid bitwidth for Generic Negate instruction");
10690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert((Type->isTypeVector() ? (Type->getVectorComponentCount() ==
10700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          getValueType(Op)->getVectorComponentCount()): 1) &&
10710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung          "Invalid vector component Width for Generic Negate instruction");
10720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
10730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
10740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
10750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
10760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtemplate<Op OC>
10770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVUnaryInst:public SPIRVInstTemplate<SPIRVUnary, OC, true, 4, false> {
10780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
10790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
10800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x) typedef SPIRVUnaryInst<Op##x> SPIRV##x;
10810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ConvertFToU)
10820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ConvertFToS)
10830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ConvertSToF)
10840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ConvertUToF)
10850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(UConvert)
10860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SConvert)
10870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FConvert)
10880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SatConvertSToU)
10890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SatConvertUToS)
10900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ConvertPtrToU)
10910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ConvertUToPtr)
10920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(PtrCastToGeneric)
10930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GenericCastToPtr)
10940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(Bitcast)
10950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SNegate)
10960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(FNegate)
10970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(Not)
10980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(LogicalNot)
10990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IsNan)
11000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IsInf)
11010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IsFinite)
11020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IsNormal)
11030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SignBitSet)
11040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(Any)
11050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(All)
11060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
11070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
11080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVAccessChainBase :public SPIRVInstTemplateBase {
11090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
11100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getBase() { return this->getValue(this->Ops[0]);}
11110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> getIndices()const {
11120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    std::vector<SPIRVWord> IndexWords(this->Ops.begin() + 1, this->Ops.end());
11130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return this->getValues(IndexWords);
11140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isInBounds() {
11160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return OpCode == OpInBoundsAccessChain ||
11170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        OpCode == OpInBoundsPtrAccessChain;
11180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool hasPtrIndex() {
11200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return OpCode == OpPtrAccessChain ||
11210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        OpCode == OpInBoundsPtrAccessChain;
11220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
11240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
11250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtemplate<Op OC, unsigned FixedWC>
11260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVAccessChainGeneric
11270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :public SPIRVInstTemplate<SPIRVAccessChainBase, OC, true, FixedWC, true> {
11280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
11290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
11300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef SPIRVAccessChainGeneric<OpAccessChain, 4> SPIRVAccessChain;
11310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef SPIRVAccessChainGeneric<OpInBoundsAccessChain, 4>
11320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInBoundsAccessChain;
11330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef SPIRVAccessChainGeneric<OpPtrAccessChain, 5> SPIRVPtrAccessChain;
11340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef SPIRVAccessChainGeneric<OpInBoundsPtrAccessChain, 5>
11350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVInBoundsPtrAccessChain;
11360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
11370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtemplate<Op OC, SPIRVWord FixedWordCount>
11380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVFunctionCallGeneric: public SPIRVInstruction {
11390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
11400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionCallGeneric(SPIRVType *TheType, SPIRVId TheId,
11410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVWord> &TheArgs, SPIRVBasicBlock *BB)
11420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(TheArgs.size() + FixedWordCount, OC, TheType, TheId, BB),
11430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     Args(TheArgs){
11440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
11450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(BB && "Invalid BB");
11460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionCallGeneric(SPIRVType *TheType, SPIRVId TheId,
11480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVValue *> &TheArgs, SPIRVBasicBlock *BB)
11490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(TheArgs.size() + FixedWordCount, OC, TheType, TheId, BB) {
11500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Args = getIds(TheArgs);
11510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
11520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(BB && "Invalid BB");
11530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionCallGeneric():SPIRVInstruction(OC) {}
11550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const std::vector<SPIRVWord> &getArguments() {
11560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Args;
11570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> getArgumentValues() {
11590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValues(Args);
11600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVType *> getArgumentValueTypes()const {
11620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    std::vector<SPIRVType *> ArgTypes;
11630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (auto &I:Args)
11640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      ArgTypes.push_back(getValue(I)->getType());
11650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return ArgTypes;
11660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
11680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
11690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Args.resize(TheWordCount - FixedWordCount);
11700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
11720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
11730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
11750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> Args;
11760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
11770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
11780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVFunctionCall:
11790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    public SPIRVFunctionCallGeneric<OpFunctionCall, 4> {
11800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
11810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionCall(SPIRVId TheId, SPIRVFunction *TheFunction,
11820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVWord> &TheArgs, SPIRVBasicBlock *BB);
11830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionCall():FunctionId(SPIRVID_INVALID) {}
11840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunction *getFunction()const {
11850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return get<SPIRVFunction>(FunctionId);
11860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
11870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC4(Type, Id, FunctionId, Args)
11880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const;
11890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isOperandLiteral(unsigned Index) const { return false;}
11900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
11910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId FunctionId;
11920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
11930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
11940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVExtInst: public SPIRVFunctionCallGeneric<OpExtInst, 5> {
11950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
11960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVExtInst(SPIRVType *TheType, SPIRVId TheId,
11970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVId TheBuiltinSet, SPIRVWord TheEntryPoint,
11980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVWord> &TheArgs, SPIRVBasicBlock *BB)
11990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVFunctionCallGeneric(TheType, TheId, TheArgs, BB),
12000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     ExtSetId(TheBuiltinSet),
12010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     ExtOp(TheEntryPoint) {
12020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setExtSetKindById();
12030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
12040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVExtInst(SPIRVType *TheType, SPIRVId TheId,
12060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVId TheBuiltinSet, SPIRVWord TheEntryPoint,
12070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVValue *> &TheArgs, SPIRVBasicBlock *BB)
12080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVFunctionCallGeneric(TheType, TheId, TheArgs, BB),
12090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     ExtSetId(TheBuiltinSet),
12100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     ExtOp(TheEntryPoint) {
12110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setExtSetKindById();
12120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
12130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVExtInst(SPIRVExtInstSetKind SetKind = SPIRVEIS_Count,
12150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      unsigned ExtOC = SPIRVWORD_MAX)
12160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :ExtSetId(SPIRVWORD_MAX), ExtOp(ExtOC), ExtSetKind(SetKind) {}
12170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setExtSetId(unsigned Set) { ExtSetId = Set;}
12180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setExtOp(unsigned ExtOC) { ExtOp = ExtOC;}
12190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId getExtSetId()const {
12200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return ExtSetId;
12210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord getExtOp()const {
12230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return ExtOp;
12240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setExtSetKindById() {
12260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Module && "Invalid module");
12270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    ExtSetKind = Module->getBuiltinSet(ExtSetId);
12280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(ExtSetKind == SPIRVEIS_OpenCL && "not supported");
12290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void encode(spv_ostream &O) const {
12310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getEncoder(O) << Type << Id << ExtSetId;
12320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    switch(ExtSetKind) {
12330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case SPIRVEIS_OpenCL:
12340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      getEncoder(O) << ExtOpOCL;
12350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      break;
12360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    default:
12370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(0 && "not supported");
12380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      getEncoder(O) << ExtOp;
12390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
12400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getEncoder(O) << Args;
12410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void decode(std::istream &I) {
12430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getDecoder(I) >> Type >> Id >> ExtSetId;
12440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setExtSetKindById();
12450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    switch(ExtSetKind) {
12460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case SPIRVEIS_OpenCL:
12470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      getDecoder(I) >> ExtOpOCL;
12480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      break;
12490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    default:
12500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      assert(0 && "not supported");
12510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      getDecoder(I) >> ExtOp;
12520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
12530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getDecoder(I) >> Args;
12540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
12560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVFunctionCallGeneric::validate();
12570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validateBuiltin(ExtSetId, ExtOp);
12580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isOperandLiteral(unsigned Index) const {
12600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(ExtSetKind == SPIRVEIS_OpenCL &&
12610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Unsupported extended instruction set");
12620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    auto EOC = static_cast<OCLExtOpKind>(ExtOp);
12630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    switch(EOC) {
12640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    default:
12650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return false;
12660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case OpenCLLIB::Vloadn:
12670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case OpenCLLIB::Vload_halfn:
12680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case OpenCLLIB::Vloada_halfn:
12690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return Index == 2;
12700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case OpenCLLIB::Vstore_half_r:
12710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case OpenCLLIB::Vstore_halfn_r:
12720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    case OpenCLLIB::Vstorea_halfn_r:
12730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return Index == 3;
12740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    }
12750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
12770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId ExtSetId;
12780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  union {
12790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVWord ExtOp;
12800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    OCLExtOpKind ExtOpOCL;
12810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  };
12820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVExtInstSetKind ExtSetKind;
12830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
12840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
12850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVCompositeExtract:public SPIRVInstruction {
12860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
12870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpCompositeExtract;
12880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
12890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCompositeExtract(SPIRVType *TheType, SPIRVId TheId, SPIRVValue *TheComposite,
12900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVWord>& TheIndices, SPIRVBasicBlock *TheBB):
12910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        SPIRVInstruction(TheIndices.size() + 4, OC, TheType, TheId, TheBB),
12920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Composite(TheComposite->getId()), Indices(TheIndices){
12930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
12940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
12950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
12960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
12970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCompositeExtract():SPIRVInstruction(OC), Composite(SPIRVID_INVALID){}
12980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
12990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getComposite() { return getValue(Composite);}
13000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const std::vector<SPIRVWord>& getIndices()const { return Indices;}
13010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
13020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
13030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
13040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Indices.resize(TheWordCount - 4);
13050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
13060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC4(Type, Id, Composite, Indices)
13070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // ToDo: validate the result type is consistent with the base type and indices
13080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // need to trace through the base type for struct types
13090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
13100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
13110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getValueType(Composite)->isTypeArray() ||
13120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Composite)->isTypeStruct() ||
13130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Composite)->isTypeVector());
13140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
13150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Composite;
13160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> Indices;
13170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
13180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVCompositeInsert:public SPIRVInstruction {
13200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
13210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpCompositeInsert;
13220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static SPIRVWord FixedWordCount = 5;
13230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
13240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCompositeInsert(SPIRVId TheId, SPIRVValue *TheObject,
13250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue *TheComposite, const std::vector<SPIRVWord>& TheIndices,
13260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB):
13270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        SPIRVInstruction(TheIndices.size() + FixedWordCount, OC,
13280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            TheComposite->getType(), TheId, TheBB),
13290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Object(TheObject->getId()), Composite(TheComposite->getId()),
13300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Indices(TheIndices){
13310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
13320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
13330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
13340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
13350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCompositeInsert():SPIRVInstruction(OC), Object(SPIRVID_INVALID),
13360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Composite(SPIRVID_INVALID){}
13370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getObject() { return getValue(Object);}
13390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getComposite() { return getValue(Composite);}
13400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const std::vector<SPIRVWord>& getIndices()const { return Indices;}
13410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
13420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
13430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
13440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Indices.resize(TheWordCount - FixedWordCount);
13450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
13460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC5(Type, Id, Object, Composite, Indices)
13470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // ToDo: validate the object type is consistent with the base type and indices
13480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // need to trace through the base type for struct types
13490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
13500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
13510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
13520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == Indices.size() + FixedWordCount);
13530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getValueType(Composite)->isTypeArray() ||
13540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Composite)->isTypeStruct() ||
13550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Composite)->isTypeVector());
13560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Type == getValueType(Composite));
13570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
13580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Object;
13590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Composite;
13600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> Indices;
13610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
13620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVCopyObject :public SPIRVInstruction {
13640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
13650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpCopyObject;
13660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
13680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCopyObject(SPIRVType *TheType, SPIRVId TheId, SPIRVValue *TheOperand,
13690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVBasicBlock *TheBB) :
13700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction(4, OC, TheType, TheId, TheBB),
13710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operand(TheOperand->getId()) {
13720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
13730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
13740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
13750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
13760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCopyObject() :SPIRVInstruction(OC), Operand(SPIRVID_INVALID) {}
13770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getOperand() { return getValue(Operand); }
13790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
13810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC3(Type, Id, Operand)
13820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    void validate()const {
13840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
13850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
13860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Operand;
13870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
13880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
13900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVCopyMemory :public SPIRVInstruction, public SPIRVMemoryAccess {
13910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
13920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpCopyMemory;
13930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static SPIRVWord FixedWords = 3;
13940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
13950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCopyMemory(SPIRVValue *TheTarget, SPIRVValue *TheSource,
13960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      const std::vector<SPIRVWord> &TheMemoryAccess,
13970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVBasicBlock *TheBB) :
13980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OC, TheBB),
13990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVMemoryAccess(TheMemoryAccess),
14000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccess(TheMemoryAccess),
14010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Target(TheTarget->getId()),
14020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Source(TheSource->getId()) {
14030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
14040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
14050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
14080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCopyMemory() :SPIRVInstruction(OC), SPIRVMemoryAccess(),
14090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Target(SPIRVID_INVALID),
14100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Source(SPIRVID_INVALID) {
14110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
14120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
14130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getSource() { return getValue(Source); }
14160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getTarget() { return getValue(Target); }
14170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
14190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
14200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
14210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccess.resize(TheWordCount - FixedWords);
14220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void encode(spv_ostream &O) const {
14250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getEncoder(O) << Target << Source << MemoryAccess;
14260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void decode(std::istream &I) {
14290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getDecoder(I) >> Target >> Source >> MemoryAccess;
14300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccessUpdate(MemoryAccess);
14310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
14340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert((getValueType(Id) == getValueType(Source)) && "Inconsistent type");
14350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getValueType(Id)->isTypePointer() && "Invalid type");
14360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(!(getValueType(Id)->getPointerElementType()->isTypeVoid()) &&
14370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        "Invalid type");
14380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
14390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> MemoryAccess;
14420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Target;
14430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Source;
14440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
14450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVCopyMemorySized :public SPIRVInstruction, public SPIRVMemoryAccess {
14470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
14480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpCopyMemorySized;
14490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static SPIRVWord FixedWords = 4;
14500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
14510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCopyMemorySized(SPIRVValue *TheTarget, SPIRVValue *TheSource,
14520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue *TheSize, const std::vector<SPIRVWord> &TheMemoryAccess,
14530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB) :
14540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVInstruction(FixedWords + TheMemoryAccess.size(), OC, TheBB),
14550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVMemoryAccess(TheMemoryAccess),
14560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      MemoryAccess(TheMemoryAccess),
14570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Target(TheTarget->getId()),
14580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Source(TheSource->getId()),
14590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Size(TheSize->getId()) {
14600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
14610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
14620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
14640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCopyMemorySized() :SPIRVInstruction(OC), SPIRVMemoryAccess(),
14650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Target(SPIRVID_INVALID), Source(SPIRVID_INVALID), Size(0) {
14660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
14670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
14680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getSource() { return getValue(Source); }
14710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getTarget() { return getValue(Target); }
14720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getSize() { return getValue(Size); }
14730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
14750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
14760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
14770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccess.resize(TheWordCount - FixedWords);
14780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void encode(spv_ostream &O) const {
14810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getEncoder(O) << Target << Source << Size << MemoryAccess;
14820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void decode(std::istream &I) {
14850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    getDecoder(I) >> Target >> Source >> Size >> MemoryAccess;
14860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemoryAccessUpdate(MemoryAccess);
14870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    void validate()const {
14900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
14910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
14920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> MemoryAccess;
14940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Target;
14950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Source;
14960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Size;
14970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
14980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
14990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVVectorExtractDynamic:public SPIRVInstruction {
15000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
15010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpVectorExtractDynamic;
15020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
15030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVectorExtractDynamic(SPIRVId TheId, SPIRVValue *TheVector,
15040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue* TheIndex, SPIRVBasicBlock *TheBB)
15050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  :SPIRVInstruction(5, OC, TheVector->getType()->getVectorComponentType(),
15060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      TheId, TheBB), VectorId(TheVector->getId()),
15070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      IndexId(TheIndex->getId()){
15080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
15090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
15100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
15110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
15120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVectorExtractDynamic():SPIRVInstruction(OC), VectorId(SPIRVID_INVALID),
15130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      IndexId(SPIRVID_INVALID){}
15140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
15150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getVector() { return getValue(VectorId);}
15160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getIndex()const { return getValue(IndexId);}
15170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
15180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC4(Type, Id, VectorId, IndexId)
15190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
15200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
15210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValue(VectorId)->isForward())
15220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
15230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getValueType(VectorId)->isTypeVector());
15240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
15250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId VectorId;
15260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId IndexId;
15270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
15280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
15290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVVectorInsertDynamic :public SPIRVInstruction {
15300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
15310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpVectorInsertDynamic;
15320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
15330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVectorInsertDynamic(SPIRVId TheId, SPIRVValue *TheVector,
15340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue* TheComponent, SPIRVValue* TheIndex, SPIRVBasicBlock *TheBB)
15350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(6, OC, TheVector->getType()->getVectorComponentType(),
15360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    TheId, TheBB), VectorId(TheVector->getId()),
15370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    IndexId(TheIndex->getId()), ComponentId(TheComponent->getId()){
15380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
15390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
15400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
15410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
15420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVectorInsertDynamic() :SPIRVInstruction(OC), VectorId(SPIRVID_INVALID),
15430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    IndexId(SPIRVID_INVALID), ComponentId(SPIRVID_INVALID){}
15440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
15450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getVector() { return getValue(VectorId); }
15460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getIndex()const { return getValue(IndexId); }
15470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getComponent() { return getValue(ComponentId); }
15480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
15490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC5(Type, Id, VectorId, ComponentId, IndexId)
15500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    void validate()const {
15510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
15520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValue(VectorId)->isForward())
15530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
15540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getValueType(VectorId)->isTypeVector());
15550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
15560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId VectorId;
15570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId IndexId;
15580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId ComponentId;
15590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
15600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
15610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVVectorShuffle:public SPIRVInstruction {
15620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
15630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static Op OC = OpVectorShuffle;
15640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const static SPIRVWord FixedWordCount = 5;
15650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
15660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVectorShuffle(SPIRVId TheId, SPIRVType *TheType, SPIRVValue *TheVector1,
15670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue *TheVector2, const std::vector<SPIRVWord>& TheComponents,
15680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB):
15690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        SPIRVInstruction(TheComponents.size() + FixedWordCount, OC, TheType,
15700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung            TheId, TheBB),
15710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Vector1(TheVector1->getId()), Vector2(TheVector2->getId()),
15720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        Components(TheComponents){
15730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
15740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
15750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
15760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
15770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVVectorShuffle():SPIRVInstruction(OC), Vector1(SPIRVID_INVALID),
15780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Vector2(SPIRVID_INVALID){}
15790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
15800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getVector1() { return getValue(Vector1);}
15810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getVector2() { return getValue(Vector2);}
15820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  const std::vector<SPIRVWord>& getComponents()const { return Components;}
15830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
15840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
15850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
15860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Components.resize(TheWordCount - FixedWordCount);
15870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
15880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC5(Type, Id, Vector1, Vector2, Components)
15890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
15900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
15910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
15920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == Components.size() + FixedWordCount);
15930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Type->isTypeVector());
15940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Type->getVectorComponentType() ==
15950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValueType(Vector1)->getVectorComponentType());
15960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (getValue(Vector1)->isForward() ||
15970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getValue(Vector2)->isForward())
15980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return;
15990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(getValueType(Vector1) == getValueType(Vector2));
16000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    size_t CompCount = Type->getVectorComponentCount();
16010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    (void) CompCount;
16020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Components.size() == CompCount);
16030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(Components.size() > 1);
16040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Vector1;
16060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Vector2;
16070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVWord> Components;
16080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
16090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
16100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVControlBarrier:public SPIRVInstruction {
16110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
16120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const Op OC = OpControlBarrier;
16130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
16140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVControlBarrier(SPIRVValue *TheScope,
16150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue *TheMemScope, SPIRVValue *TheMemSema,
16160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVBasicBlock *TheBB)
16170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(4, OC, TheBB), ExecScope(TheScope->getId()),
16180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    MemScope(TheMemScope->getId()), MemSema(TheMemSema->getId()){
16190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
16200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
16210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
16230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVControlBarrier():SPIRVInstruction(OC), ExecScope(ScopeInvocation) {
16240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoId();
16250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    setHasNoType();
16260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setWordCount(SPIRVWord TheWordCount) {
16280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVEntry::setWordCount(TheWordCount);
16290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getExecScope() const { return getValue(ExecScope); }
16310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getMemScope() const { return getValue(MemScope); }
16320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getMemSemantic() const { return getValue(MemSema); }
16330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> getOperands() {
16340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    std::vector<SPIRVId> Operands;
16350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(ExecScope);
16360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(MemScope);
16370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(MemSema);
16380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValues(Operands);
16390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
16410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC3(ExecScope, MemScope, MemSema)
16420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
16430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
16440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == 4);
16450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
16460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId ExecScope;
16480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId MemScope;
16490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId MemSema;
16500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
16510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
16520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVGroupAsyncCopy:public SPIRVInstruction {
16530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
16540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const Op OC = OpGroupAsyncCopy;
16550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  static const SPIRVWord WC = 9;
16560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor
16570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVGroupAsyncCopy(SPIRVValue *TheScope, SPIRVId TheId,
16580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue *TheDest, SPIRVValue *TheSrc, SPIRVValue *TheNumElems,
16590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVValue *TheStride, SPIRVValue *TheEvent, SPIRVBasicBlock *TheBB)
16600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVInstruction(WC, OC, TheEvent->getType(), TheId, TheBB),
16610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    ExecScope(TheScope->getId()), Destination(TheDest->getId()),
16620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     Source(TheSrc->getId()), NumElements(TheNumElems->getId()),
16630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     Stride(TheStride->getId()), Event(TheEvent->getId()){
16640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
16650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(TheBB && "Invalid BB");
16660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
16680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVGroupAsyncCopy():SPIRVInstruction(OC), ExecScope(SPIRVID_INVALID),
16690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Destination(SPIRVID_INVALID), Source(SPIRVID_INVALID),
16700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      NumElements(SPIRVID_INVALID), Stride(SPIRVID_INVALID),
16710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Event(SPIRVID_INVALID){
16720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getExecScope() const { return getValue(ExecScope); }
16740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getDestination()const { return getValue(Destination);}
16750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getSource()const { return getValue(Source);}
16760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getNumElements()const { return getValue(NumElements);}
16770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getStride()const { return getValue(Stride);}
16780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVValue *getEvent()const { return getValue(Event);}
16790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVValue *> getOperands() {
16800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    std::vector<SPIRVId> Operands;
16810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(Destination);
16820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(Source);
16830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(NumElements);
16840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(Stride);
16850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Operands.push_back(Event);
16860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getValues(Operands);
16870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
16890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
16900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC8(Type, Id, ExecScope, Destination, Source, NumElements,
16910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Stride, Event)
16920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
16930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(OpCode == OC);
16940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(WordCount == WC);
16950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVInstruction::validate();
16960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
16970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId ExecScope;
16980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Destination;
16990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Source;
17000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId NumElements;
17010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Stride;
17020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId Event;
17030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
17040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungenum SPIRVOpKind {
17060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVOPK_Id,
17070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVOPK_Literal,
17080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVOPK_Count
17090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
17100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVDevEnqInstBase:public SPIRVInstTemplateBase {
17120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
17130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCapVec getRequiriedCapability() const {
17140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getVec(CapabilityDeviceEnqueue);
17150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
17160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
17170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x, ...) \
17190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef SPIRVInstTemplate<SPIRVDevEnqInstBase, Op##x, __VA_ARGS__> \
17200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRV##x;
17210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// CL 2.0 enqueue kernel builtins
17220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(EnqueueMarker, true, 7)
17230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(EnqueueKernel, true, 13, true)
17240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GetKernelNDrangeSubGroupCount, true, 8)
17250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GetKernelNDrangeMaxSubGroupSize, true, 8)
17260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GetKernelWorkGroupSize, true, 7)
17270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GetKernelPreferredWorkGroupSizeMultiple, true, 7)
17280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(RetainEvent, false, 2)
17290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ReleaseEvent, false, 2)
17300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(CreateUserEvent, true, 3)
17310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IsValidEvent, true, 4)
17320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SetUserEventStatus, false, 3)
17330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(CaptureEventProfilingInfo, false, 4)
17340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GetDefaultQueue, true, 3)
17350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(BuildNDRange, true, 6)
17360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
17370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVPipeInstBase:public SPIRVInstTemplateBase {
17390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
17400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCapVec getRequiriedCapability() const {
17410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getVec(CapabilityPipes);
17420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
17430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
17440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x, ...) \
17460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef SPIRVInstTemplate<SPIRVPipeInstBase, Op##x, __VA_ARGS__> \
17470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRV##x;
17480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// CL 2.0 pipe builtins
17490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ReadPipe, true, 7)
17500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(WritePipe, true, 7)
17510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ReservedReadPipe, true, 9)
17520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ReservedWritePipe, true, 9)
17530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ReserveReadPipePackets, true, 7)
17540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ReserveWritePipePackets, true, 7)
17550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(CommitReadPipe, false, 5)
17560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(CommitWritePipe, false, 5)
17570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(IsValidReserveId, true, 4)
17580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GetNumPipePackets, true, 6)
17590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GetMaxPipePackets, true, 6)
17600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
17610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVPipeStorageInstBase :public SPIRVInstTemplateBase {
17630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
17640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCapVec getRequiriedCapability() const {
17650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getVec(CapabilityPipeStorage, CapabilityPipes);
17660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
17670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
17680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x, ...) \
17700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef SPIRVInstTemplate<SPIRVPipeStorageInstBase, Op##x, __VA_ARGS__> \
17710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRV##x;
17720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(CreatePipeFromPipeStorage, true, 4)
17740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
17750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVGroupInstBase:public SPIRVInstTemplateBase {
17770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
17780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCapVec getRequiriedCapability() const {
17790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getVec(CapabilityGroups);
17800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
17810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
17820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
17830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x, ...) \
17840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef SPIRVInstTemplate<SPIRVGroupInstBase, Op##x, __VA_ARGS__> \
17850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRV##x;
17860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Group instructions
17870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupWaitEvents, false, 4)
17880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupAll, true, 5)
17890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupAny, true, 5)
17900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupBroadcast, true, 6)
17910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupIAdd, true, 6, false, 1)
17920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupFAdd, true, 6, false, 1)
17930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupFMin, true, 6, false, 1)
17940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupUMin, true, 6, false, 1)
17950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupSMin, true, 6, false, 1)
17960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupFMax, true, 6, false, 1)
17970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupUMax, true, 6, false, 1)
17980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupSMax, true, 6, false, 1)
17990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupReserveReadPipePackets, true, 8)
18000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupReserveWritePipePackets, true, 8)
18010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupCommitReadPipe, false, 6)
18020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GroupCommitWritePipe, false, 6)
18030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
18040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
18050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVAtomicInstBase:public SPIRVInstTemplateBase {
18060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
18070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCapVec getRequiriedCapability() const {
18080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getVec(CapabilityInt64Atomics);
18090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
18100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
18110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
18120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x, ...) \
18130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef SPIRVInstTemplate<SPIRVAtomicInstBase, Op##x, __VA_ARGS__> \
18140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRV##x;
18150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Atomic builtins
18160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicFlagTestAndSet, true, 6)
18170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicFlagClear, false, 4)
18180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicLoad, true, 6)
18190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicStore, false, 5)
18200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicExchange, true, 7)
18210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicCompareExchange, true, 9)
18220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicCompareExchangeWeak, true, 9)
18230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicIIncrement, true, 6)
18240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicIDecrement, true, 6)
18250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicIAdd, true, 7)
18260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicISub, true, 7)
18270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicUMin, true, 7)
18280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicUMax, true, 7)
18290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicSMin, true, 7)
18300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicSMax, true, 7)
18310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicAnd, true, 7)
18320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicOr, true, 7)
18330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(AtomicXor, true, 7)
18340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(MemoryBarrier, false, 3)
18350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
18360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
18370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVImageInstBase:public SPIRVInstTemplateBase {
18380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
18390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCapVec getRequiriedCapability() const {
18400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getVec(CapabilityImageBasic);
18410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
18420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
18430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
18440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x, ...) \
18450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef SPIRVInstTemplate<SPIRVImageInstBase, Op##x, __VA_ARGS__> \
18460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRV##x;
18470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Image instructions
18480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SampledImage, true, 5)
18490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageSampleImplicitLod, true, 5, true)
18500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageSampleExplicitLod, true, 7, true, 2)
18510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageRead, true, 5, true, 2)
18520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageWrite, false, 4, true, 3)
18530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageQueryFormat, true, 4)
18540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageQueryOrder, true, 4)
18550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageQuerySizeLod, true, 5)
18560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageQuerySize, true, 4)
18570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageQueryLod, true, 5)
18580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageQueryLevels, true, 4)
18590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(ImageQuerySamples, true, 4)
18600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
18610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
18620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define _SPIRV_OP(x, ...) \
18630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef SPIRVInstTemplate<SPIRVInstTemplateBase, Op##x, __VA_ARGS__> \
18640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRV##x;
18650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Other instructions
18660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(SpecConstantOp, true, 4, true, 0)
18670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GenericPtrMemSemantics, true, 4, false)
18680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung_SPIRV_OP(GenericCastToPtrExplicit, true, 5, false, 1)
18690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#undef _SPIRV_OP
18700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
18710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) SungSPIRVSpecConstantOp *createSpecConstantOpInst(SPIRVInstruction *Inst);
18720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) SungSPIRVInstruction *createInstFromSpecConstantOp(SPIRVSpecConstantOp *C);
18730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung}
18740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
18750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#endif // SPIRVINSTRUCTION_HPP_
1876