summaryrefslogtreecommitdiff
path: root/lib/SPIRV/libSPIRV/SPIRVModule.cpp
diff options
context:
space:
mode:
authorPierre Moreau <dev@pmoreau.org>2018-04-13 17:38:55 +0200
committerAlexey Sotkin <alexey.sotkin@intel.com>2018-04-24 12:21:49 +0300
commitd1c02b3954cfdeaca99c0b5d17ce55f02c94e792 (patch)
tree86ce820fb95b32701222cee65924f2cb1e72c67f /lib/SPIRV/libSPIRV/SPIRVModule.cpp
parent01dddd07c475bcbb24a11931c649384c904e82d8 (diff)
Change all line endings to UNIX-style
The code was currently using a mix of DOS-style and UNIX-style; LLVM itself uses UNIX-style. Commands used: * dos2unix `find include -iname "*"` * dos2unix `find lib -iname "*"` * dos2unix `find test -iname "*"` * dos2unix `find tools -iname "*"`
Diffstat (limited to 'lib/SPIRV/libSPIRV/SPIRVModule.cpp')
-rw-r--r--lib/SPIRV/libSPIRV/SPIRVModule.cpp3342
1 files changed, 1671 insertions, 1671 deletions
diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.cpp b/lib/SPIRV/libSPIRV/SPIRVModule.cpp
index 33dfeb4..7e3db72 100644
--- a/lib/SPIRV/libSPIRV/SPIRVModule.cpp
+++ b/lib/SPIRV/libSPIRV/SPIRVModule.cpp
@@ -1,1673 +1,1673 @@
-//===- SPIRVModule.cpp - Class to represent SPIR-V module --------*- C++ -*-===//
-//
-// The LLVM/SPIRV Translator
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal with the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimers.
-// Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimers in the documentation
-// and/or other materials provided with the distribution.
-// Neither the names of Advanced Micro Devices, Inc., nor the names of its
-// contributors may be used to endorse or promote products derived from this
-// Software without specific prior written permission.
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
-// THE SOFTWARE.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-///
-/// This file implements Module class for SPIR-V.
-///
-//===----------------------------------------------------------------------===//
-
-#include "SPIRVModule.h"
-#include "SPIRVDebug.h"
-#include "SPIRVEntry.h"
-#include "SPIRVType.h"
-#include "SPIRVValue.h"
-#include "SPIRVExtInst.h"
-#include "SPIRVFunction.h"
-#include "SPIRVInstruction.h"
-#include "SPIRVStream.h"
-
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-
-namespace SPIRV{
-
-SPIRVModule::SPIRVModule():AutoAddCapability(true), ValidateCapability(false)
-{}
-
-SPIRVModule::~SPIRVModule()
-{}
-
-class SPIRVModuleImpl : public SPIRVModule {
-public:
- SPIRVModuleImpl():SPIRVModule(), NextId(1), BoolType(NULL),
- SPIRVVersion(SPIRV_1_0),
- GeneratorId(SPIRVGEN_KhronosLLVMSPIRVTranslator),
- GeneratorVer(0),
- InstSchema(SPIRVISCH_Default),
- SrcLang(SourceLanguageOpenCL_C),
- SrcLangVer(102000) {
- AddrModel = sizeof(size_t) == 32 ? AddressingModelPhysical32
- : AddressingModelPhysical64;
- // OpenCL memory model requires Kernel capability
- setMemoryModel(MemoryModelOpenCL);
- }
- virtual ~SPIRVModuleImpl();
-
- // Object query functions
- bool exist(SPIRVId) const;
- bool exist(SPIRVId, SPIRVEntry **) const;
- SPIRVId getId(SPIRVId Id = SPIRVID_INVALID, unsigned Increment = 1);
- virtual SPIRVEntry *getEntry(SPIRVId Id) const;
- bool hasDebugInfo() const { return !StringVec.empty();}
-
- // Error handling functions
- SPIRVErrorLog &getErrorLog() { return ErrLog;}
- SPIRVErrorCode getError(std::string &ErrMsg) { return ErrLog.getError(ErrMsg);}
-
- // Module query functions
- SPIRVAddressingModelKind getAddressingModel() { return AddrModel;}
- SPIRVExtInstSetKind getBuiltinSet(SPIRVId SetId) const;
- const SPIRVCapMap &getCapability() const { return CapMap; }
- bool hasCapability(SPIRVCapabilityKind Cap) const {
- return CapMap.find(Cap) != CapMap.end();
- }
- std::set<std::string> &getExtension() { return SPIRVExt;}
- SPIRVFunction *getFunction(unsigned I) const { return FuncVec[I];}
- SPIRVVariable *getVariable(unsigned I) const { return VariableVec[I];}
- virtual SPIRVValue *getValue(SPIRVId TheId) const;
- virtual std::vector<SPIRVValue *> getValues(const std::vector<SPIRVId>&)const;
- virtual std::vector<SPIRVId> getIds(const std::vector<SPIRVEntry *>&)const;
- virtual std::vector<SPIRVId> getIds(const std::vector<SPIRVValue *>&)const;
- virtual SPIRVType *getValueType(SPIRVId TheId)const;
- virtual std::vector<SPIRVType *> getValueTypes(const std::vector<SPIRVId>&)
- const;
- SPIRVMemoryModelKind getMemoryModel() const { return MemoryModel;}
- virtual SPIRVConstant* getLiteralAsConstant(unsigned Literal);
- unsigned getNumEntryPoints(SPIRVExecutionModelKind EM) const {
- auto Loc = EntryPointVec.find(EM);
- if (Loc == EntryPointVec.end())
- return 0;
- return Loc->second.size();
- }
- SPIRVFunction *getEntryPoint(SPIRVExecutionModelKind EM, unsigned I) const {
- auto Loc = EntryPointVec.find(EM);
- if (Loc == EntryPointVec.end())
- return nullptr;
- assert(I < Loc->second.size());
- return get<SPIRVFunction>(Loc->second[I]);
- }
- unsigned getNumFunctions() const { return FuncVec.size();}
- unsigned getNumVariables() const { return VariableVec.size();}
- SourceLanguage getSourceLanguage(SPIRVWord * Ver = nullptr) const {
- if (Ver)
- *Ver = SrcLangVer;
- return SrcLang;
- }
- std::set<std::string> &getSourceExtension() { return SrcExtension;}
- bool isEntryPoint(SPIRVExecutionModelKind, SPIRVId EP) const;
- unsigned short getGeneratorId() const { return GeneratorId; }
- unsigned short getGeneratorVer() const { return GeneratorVer; }
- SPIRVWord getSPIRVVersion() const { return SPIRVVersion; }
-
- // Module changing functions
- bool importBuiltinSet(const std::string &, SPIRVId *);
- bool importBuiltinSetWithId(const std::string &, SPIRVId);
- void optimizeDecorates();
- void setAddressingModel(SPIRVAddressingModelKind AM) { AddrModel = AM;}
- void setAlignment(SPIRVValue *, SPIRVWord);
- void setMemoryModel(SPIRVMemoryModelKind MM) {
- MemoryModel = MM;
- if (MemoryModel == spv::MemoryModelOpenCL)
- addCapability(CapabilityKernel);
- }
- void setName(SPIRVEntry *E, const std::string &Name);
- void setSourceLanguage(SourceLanguage Lang, SPIRVWord Ver) {
- SrcLang = Lang;
- SrcLangVer = Ver;
- }
- void setGeneratorId(unsigned short Id) { GeneratorId = Id; }
- void setGeneratorVer(unsigned short Ver) { GeneratorVer = Ver; }
- void resolveUnknownStructFields();
-
- void setSPIRVVersion(SPIRVWord Ver) override { SPIRVVersion = Ver; }
-
- // Object creation functions
- template<class T> void addTo(std::vector<T *> &V, SPIRVEntry *E);
- virtual SPIRVEntry *addEntry(SPIRVEntry *E);
- virtual SPIRVBasicBlock *addBasicBlock(SPIRVFunction *, SPIRVId);
- virtual SPIRVString *getString(const std::string &Str);
- virtual SPIRVMemberName *addMemberName(SPIRVTypeStruct *ST,
- SPIRVWord MemberNumber, const std::string &Name);
- virtual void addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
- SPIRVId ID);
- virtual void addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line,
- SPIRVWord Column);
- virtual const std::shared_ptr<const SPIRVLine>& getCurrentLine() const;
- virtual void setCurrentLine(const std::shared_ptr<const SPIRVLine> &Line);
- virtual void addCapability(SPIRVCapabilityKind);
- virtual void addCapabilityInternal(SPIRVCapabilityKind);
- virtual const SPIRVDecorateGeneric *addDecorate(SPIRVDecorateGeneric *);
- virtual SPIRVDecorationGroup *addDecorationGroup();
- virtual SPIRVDecorationGroup *addDecorationGroup(SPIRVDecorationGroup *Group);
- virtual SPIRVGroupDecorate *addGroupDecorate(SPIRVDecorationGroup *Group,
- const std::vector<SPIRVEntry *> &Targets);
- virtual SPIRVGroupDecorateGeneric *addGroupDecorateGeneric(
- SPIRVGroupDecorateGeneric *GDec);
- virtual SPIRVGroupMemberDecorate *addGroupMemberDecorate(
- SPIRVDecorationGroup *Group, const std::vector<SPIRVEntry *> &Targets);
- virtual void addEntryPoint(SPIRVExecutionModelKind ExecModel,
- SPIRVId EntryPoint);
- virtual SPIRVForward *addForward(SPIRVType *Ty);
- virtual SPIRVForward *addForward(SPIRVId, SPIRVType *Ty);
- virtual SPIRVFunction *addFunction(SPIRVFunction *);
- virtual SPIRVFunction *addFunction(SPIRVTypeFunction *, SPIRVId);
- virtual SPIRVEntry *replaceForward(SPIRVForward *, SPIRVEntry *);
- virtual void eraseInstruction(SPIRVInstruction *, SPIRVBasicBlock *);
-
- // Type creation functions
- template<class T> T * addType(T *Ty);
- virtual SPIRVTypeArray *addArrayType(SPIRVType *, SPIRVConstant *);
- virtual SPIRVTypeBool *addBoolType();
- virtual SPIRVTypeFloat *addFloatType(unsigned BitWidth);
- virtual SPIRVTypeFunction *addFunctionType(SPIRVType *,
- const std::vector<SPIRVType *> &);
- virtual SPIRVTypeInt *addIntegerType(unsigned BitWidth);
- virtual SPIRVTypeOpaque *addOpaqueType(const std::string &);
- virtual SPIRVTypePointer *addPointerType(SPIRVStorageClassKind, SPIRVType *);
- virtual SPIRVTypeImage *addImageType(SPIRVType *,
- const SPIRVTypeImageDescriptor &);
- virtual SPIRVTypeImage *addImageType(SPIRVType *,
- const SPIRVTypeImageDescriptor &, SPIRVAccessQualifierKind);
- virtual SPIRVTypeSampler *addSamplerType();
- virtual SPIRVTypePipeStorage *addPipeStorageType();
- virtual SPIRVTypeSampledImage *addSampledImageType(SPIRVTypeImage *T);
- virtual SPIRVTypeStruct *openStructType(unsigned, const std::string &);
- virtual void closeStructType(SPIRVTypeStruct *T, bool);
- virtual SPIRVTypeVector *addVectorType(SPIRVType *, SPIRVWord);
- virtual SPIRVType *addOpaqueGenericType(Op);
- virtual SPIRVTypeDeviceEvent *addDeviceEventType();
- virtual SPIRVTypeQueue *addQueueType();
- virtual SPIRVTypePipe *addPipeType();
- virtual SPIRVTypeVoid *addVoidType();
- virtual void createForwardPointers();
-
- // Constant creation functions
- virtual SPIRVInstruction *addBranchInst(SPIRVLabel *, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addBranchConditionalInst(SPIRVValue *, SPIRVLabel *,
- SPIRVLabel *, SPIRVBasicBlock *);
- virtual SPIRVValue *addCompositeConstant(SPIRVType *,
- const std::vector<SPIRVValue*>&);
- virtual SPIRVValue *addConstant(SPIRVValue *);
- virtual SPIRVValue *addConstant(SPIRVType *, uint64_t);
- virtual SPIRVValue *addDoubleConstant(SPIRVTypeFloat *, double);
- virtual SPIRVValue *addFloatConstant(SPIRVTypeFloat *, float);
- virtual SPIRVValue *addIntegerConstant(SPIRVTypeInt *, uint64_t);
- virtual SPIRVValue *addNullConstant(SPIRVType *);
- virtual SPIRVValue *addUndef(SPIRVType *TheType);
- virtual SPIRVValue *addSamplerConstant(SPIRVType *TheType, SPIRVWord AddrMode,
- SPIRVWord ParametricMode, SPIRVWord FilterMode);
- virtual SPIRVValue* addPipeStorageConstant(SPIRVType* TheType,
- SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity);
-
- // Instruction creation functions
- virtual SPIRVInstruction *addPtrAccessChainInst(SPIRVType *, SPIRVValue *,
- std::vector<SPIRVValue *>, SPIRVBasicBlock *, bool);
- virtual SPIRVInstruction *addAsyncGroupCopy(SPIRVValue *Scope,
- SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride,
- SPIRVValue *Event, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addExtInst(SPIRVType *,
- SPIRVWord, SPIRVWord, const std::vector<SPIRVWord> &,
- SPIRVBasicBlock *);
- virtual SPIRVInstruction *addExtInst(SPIRVType *,
- SPIRVWord, SPIRVWord, const std::vector<SPIRVValue *> &,
- SPIRVBasicBlock *);
- virtual SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *,
- SPIRVValue *, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addCallInst(SPIRVFunction*,
- const std::vector<SPIRVWord> &, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addCmpInst(Op, SPIRVType *, SPIRVValue *,
- SPIRVValue *, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addLoadInst(SPIRVValue *,
- const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addPhiInst(SPIRVType *, std::vector<SPIRVValue *>,
- SPIRVBasicBlock *);
- virtual SPIRVInstruction *addCompositeConstructInst(SPIRVType *,
- const std::vector<SPIRVId>&, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addCompositeExtractInst(SPIRVType *, SPIRVValue *,
- const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addCompositeInsertInst(SPIRVValue *Object,
- SPIRVValue *Composite, const std::vector<SPIRVWord>& Indices,
- SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addCopyObjectInst(SPIRVType *TheType,
- SPIRVValue *Operand, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addCopyMemoryInst(SPIRVValue *, SPIRVValue *,
- const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addCopyMemorySizedInst(SPIRVValue *, SPIRVValue *,
- SPIRVValue *, const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addControlBarrierInst(
- SPIRVValue *ExecKind, SPIRVValue *MemKind,
- SPIRVValue *MemSema, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addGroupInst(Op OpCode, SPIRVType *Type,
- Scope Scope, const std::vector<SPIRVValue *> &Ops,
- SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addInstruction(SPIRVInstruction *Inst,
- SPIRVBasicBlock *BB);
- virtual SPIRVInstTemplateBase *addInstTemplate(Op OC,
- SPIRVBasicBlock* BB, SPIRVType *Ty);
- virtual SPIRVInstTemplateBase *addInstTemplate(Op OC,
- const std::vector<SPIRVWord>& Ops, SPIRVBasicBlock* BB, SPIRVType *Ty);
- virtual SPIRVInstruction *addLifetimeInst(Op OC, SPIRVValue *Object,
- SPIRVWord Size, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addMemoryBarrierInst(
- Scope ScopeKind, SPIRVWord MemFlag, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addUnreachableInst(SPIRVBasicBlock *);
- virtual SPIRVInstruction *addReturnInst(SPIRVBasicBlock *);
- virtual SPIRVInstruction *addReturnValueInst(SPIRVValue *, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addSelectInst(SPIRVValue *, SPIRVValue *, SPIRVValue *,
- SPIRVBasicBlock *);
- virtual SPIRVInstruction *addLoopMergeInst(SPIRVId MergeBlock,
- SPIRVId ContinueTarget, SPIRVWord LoopControl, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addSelectionMergeInst(SPIRVId MergeBlock,
- SPIRVWord SelectionControl, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addStoreInst(SPIRVValue *, SPIRVValue *,
- const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addSwitchInst(SPIRVValue *, SPIRVBasicBlock *,
- const std::vector<std::pair<std::vector<SPIRVWord>, SPIRVBasicBlock *>>&,
- SPIRVBasicBlock *);
- virtual SPIRVInstruction *addFModInst(SPIRVType *TheType, SPIRVId TheDividend,
- SPIRVId TheDivisor, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addVectorTimesScalarInst(SPIRVType *TheType,
- SPIRVId TheVector, SPIRVId TheScalar, SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addUnaryInst(Op, SPIRVType *, SPIRVValue *,
- SPIRVBasicBlock *);
- virtual SPIRVInstruction *addVariable(SPIRVType *, bool, SPIRVLinkageTypeKind,
- SPIRVValue *, const std::string &, SPIRVStorageClassKind, SPIRVBasicBlock *);
- virtual SPIRVValue *addVectorShuffleInst(SPIRVType *Type, SPIRVValue *Vec1,
- SPIRVValue *Vec2, const std::vector<SPIRVWord> &Components,
- SPIRVBasicBlock *BB);
- virtual SPIRVInstruction *addVectorExtractDynamicInst(SPIRVValue *,
- SPIRVValue *, SPIRVBasicBlock *);
- virtual SPIRVInstruction *addVectorInsertDynamicInst(SPIRVValue *,
- SPIRVValue *, SPIRVValue*, SPIRVBasicBlock *);
-
- // I/O functions
- friend spv_ostream & operator<<(spv_ostream &O, SPIRVModule& M);
- friend std::istream & operator>>(std::istream &I, SPIRVModule& M);
-
-private:
- SPIRVErrorLog ErrLog;
- SPIRVId NextId;
- SPIRVTypeInt *BoolType;
- SPIRVWord SPIRVVersion;
- unsigned short GeneratorId;
- unsigned short GeneratorVer;
- SPIRVInstructionSchemaKind InstSchema;
- SourceLanguage SrcLang;
- SPIRVWord SrcLangVer;
- std::set<std::string> SrcExtension;
- std::set<std::string> SPIRVExt;
- SPIRVAddressingModelKind AddrModel;
- SPIRVMemoryModelKind MemoryModel;
-
- typedef std::map<SPIRVId, SPIRVEntry *> SPIRVIdToEntryMap;
- typedef std::set<SPIRVEntry *> SPIRVEntrySet;
- typedef std::set<SPIRVId> SPIRVIdSet;
- typedef std::vector<SPIRVId> SPIRVIdVec;
- typedef std::vector<SPIRVFunction *> SPIRVFunctionVector;
- typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
- typedef std::vector<SPIRVType *> SPIRVTypeVec;
- typedef std::vector<SPIRVValue *> SPIRVConstantVector;
- typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
- typedef std::vector<SPIRVString *> SPIRVStringVec;
- typedef std::vector<SPIRVMemberName *> SPIRVMemberNameVec;
- typedef std::vector<SPIRVDecorationGroup *> SPIRVDecGroupVec;
- typedef std::vector<SPIRVGroupDecorateGeneric *> SPIRVGroupDecVec;
- typedef std::map<SPIRVId, SPIRVExtInstSetKind> SPIRVIdToBuiltinSetMap;
- typedef std::map<SPIRVExecutionModelKind, SPIRVIdSet> SPIRVExecModelIdSetMap;
- typedef std::map<SPIRVExecutionModelKind, SPIRVIdVec> SPIRVExecModelIdVecMap;
- typedef std::unordered_map<std::string, SPIRVString*> SPIRVStringMap;
- typedef std::map<SPIRVTypeStruct *, std::vector<std::pair<unsigned, SPIRVId>>>
- SPIRVUnknownStructFieldMap;
-
- SPIRVForwardPointerVec ForwardPointerVec;
- SPIRVTypeVec TypeVec;
- SPIRVIdToEntryMap IdEntryMap;
- SPIRVFunctionVector FuncVec;
- SPIRVConstantVector ConstVec;
- SPIRVVariableVec VariableVec;
- SPIRVEntrySet EntryNoId; // Entries without id
- SPIRVIdToBuiltinSetMap IdBuiltinMap;
- SPIRVIdSet NamedId;
- SPIRVStringVec StringVec;
- SPIRVMemberNameVec MemberNameVec;
- std::shared_ptr<const SPIRVLine> CurrentLine;
- SPIRVDecorateSet DecorateSet;
- SPIRVDecGroupVec DecGroupVec;
- SPIRVGroupDecVec GroupDecVec;
- SPIRVExecModelIdSetMap EntryPointSet;
- SPIRVExecModelIdVecMap EntryPointVec;
- SPIRVStringMap StrMap;
- SPIRVCapMap CapMap;
- SPIRVUnknownStructFieldMap UnknownStructFieldMap;
- std::map<unsigned, SPIRVTypeInt*> IntTypeMap;
- std::map<unsigned, SPIRVConstant*> LiteralMap;
-
- void layoutEntry(SPIRVEntry* Entry);
-};
-
-SPIRVModuleImpl::~SPIRVModuleImpl() {
- for (auto I : EntryNoId)
- delete I;
-
- for (auto I : IdEntryMap)
- delete I.second;
-
- for (auto C : CapMap)
- delete C.second;
-}
-
-const std::shared_ptr<const SPIRVLine>&
-SPIRVModuleImpl::getCurrentLine() const {
- return CurrentLine;
-}
-
-void
-SPIRVModuleImpl::setCurrentLine(const std::shared_ptr<const SPIRVLine>& Line) {
- CurrentLine = Line;
-}
-
-void
-SPIRVModuleImpl::addLine(SPIRVEntry* E, SPIRVId FileNameId,
- SPIRVWord Line, SPIRVWord Column) {
- if (!(CurrentLine && CurrentLine->equals(FileNameId, Line, Column)))
- CurrentLine.reset(new SPIRVLine(this, FileNameId, Line, Column));
- assert(E && "invalid entry");
- E->setLine(CurrentLine);
-}
-
-// Creates decoration group and group decorates from decorates shared by
-// multiple targets.
-void
-SPIRVModuleImpl::optimizeDecorates() {
- SPIRVDBG(spvdbgs() << "[optimizeDecorates] begin\n");
- for (auto I = DecorateSet.begin(), E = DecorateSet.end(); I != E;) {
- auto D = *I;
- SPIRVDBG(spvdbgs() << " check " << *D << '\n');
- if (D->getOpCode() == OpMemberDecorate) {
- ++I;
- continue;
- }
- auto ER = DecorateSet.equal_range(D);
- SPIRVDBG(spvdbgs() << " equal range " << **ER.first
- << " to ";
- if (ER.second != DecorateSet.end())
- spvdbgs() << **ER.second;
- else
- spvdbgs() << "end";
- spvdbgs() << '\n');
- if (std::distance(ER.first, ER.second) < 2) {
- I = ER.second;
- SPIRVDBG(spvdbgs() << " skip equal range \n");
- continue;
- }
- SPIRVDBG(spvdbgs() << " add deco group. erase equal range\n");
- auto G = add(new SPIRVDecorationGroup(this, getId()));
- std::vector<SPIRVId> Targets;
- Targets.push_back(D->getTargetId());
- const_cast<SPIRVDecorateGeneric*>(D)->setTargetId(G->getId());
- G->getDecorations().insert(D);
- for (I = ER.first; I != ER.second; ++I) {
- auto E = *I;
- if (*E == *D)
- continue;
- Targets.push_back(E->getTargetId());
- }
-
- // WordCount is only 16 bits. We can only have 65535 - FixedWC targtets per
- // group.
- // For now, just skip using a group if the number of targets to too big
- if (Targets.size() < 65530) {
- DecorateSet.erase(ER.first, ER.second);
- auto GD = add(new SPIRVGroupDecorate(G, Targets));
- DecGroupVec.push_back(G);
- GroupDecVec.push_back(GD);
- }
- }
-}
-
-SPIRVValue*
-SPIRVModuleImpl::addSamplerConstant(SPIRVType* TheType,
- SPIRVWord AddrMode, SPIRVWord ParametricMode, SPIRVWord FilterMode) {
- return addConstant(new SPIRVConstantSampler(this, TheType, getId(), AddrMode,
- ParametricMode, FilterMode));
-}
-
-SPIRVValue*
-SPIRVModuleImpl::addPipeStorageConstant(SPIRVType* TheType,
- SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity) {
- return addConstant(new SPIRVConstantPipeStorage(this, TheType, getId(),
- PacketSize, PacketAlign, Capacity));
-}
-
-void
-SPIRVModuleImpl::addCapability(SPIRVCapabilityKind Cap) {
- addCapabilities(SPIRV::getCapability(Cap));
- SPIRVDBG(spvdbgs() << "addCapability: " << Cap << '\n');
- if (hasCapability(Cap))
- return;
-
- CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap)));
-}
-
-void
-SPIRVModuleImpl::addCapabilityInternal(SPIRVCapabilityKind Cap) {
- if (AutoAddCapability) {
- if (hasCapability(Cap))
- return;
-
- CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap)));
- }
-}
-
-SPIRVConstant*
-SPIRVModuleImpl::getLiteralAsConstant(unsigned Literal) {
- auto Loc = LiteralMap.find(Literal);
- if (Loc != LiteralMap.end())
- return Loc->second;
- auto Ty = addIntegerType(32);
- auto V = new SPIRVConstant(this, Ty, getId(), static_cast<uint64_t>(Literal));
- LiteralMap[Literal] = V;
- addConstant(V);
- return V;
-}
-
-void
-SPIRVModuleImpl::layoutEntry(SPIRVEntry* E) {
- auto OC = E->getOpCode();
- switch (OC) {
- case OpString:
- addTo(StringVec, E);
- break;
- case OpMemberName:
- addTo(MemberNameVec, E);
- break;
- case OpVariable: {
- auto BV = static_cast<SPIRVVariable*>(E);
- if (!BV->getParent())
- addTo(VariableVec, E);
- }
- break;
- default:
- if (isTypeOpCode(OC))
- TypeVec.push_back(static_cast<SPIRVType*>(E));
- else if (isConstantOpCode(OC))
- ConstVec.push_back(static_cast<SPIRVConstant*>(E));
- break;
- }
-}
-
-// Add an entry to the id to entry map.
-// Assert if the id is mapped to a different entry.
-// Certain entries need to be add to specific collectors to maintain
-// logic layout of SPIRV.
-SPIRVEntry *
-SPIRVModuleImpl::addEntry(SPIRVEntry *Entry) {
- assert(Entry && "Invalid entry");
- if (Entry->hasId()) {
- SPIRVId Id = Entry->getId();
- assert(Entry->getId() != SPIRVID_INVALID && "Invalid id");
- SPIRVEntry *Mapped = nullptr;
- if (exist(Id, &Mapped)) {
- if (Mapped->getOpCode() == OpForward) {
- replaceForward(static_cast<SPIRVForward *>(Mapped), Entry);
- } else {
- assert(Mapped == Entry && "Id used twice");
- }
- } else
- IdEntryMap[Id] = Entry;
- } else {
- // Entry of OpLine will be deleted by std::shared_ptr automatically.
- if (Entry->getOpCode() != OpLine)
- EntryNoId.insert(Entry);
- }
-
- Entry->setModule(this);
-
- layoutEntry(Entry);
- if (AutoAddCapability) {
- for (auto &I:Entry->getRequiredCapability()) {
- addCapability(I);
- }
- }
- if (ValidateCapability) {
- assert(none_of(
- Entry->getRequiredCapability().begin(),
- Entry->getRequiredCapability().end(),
- [this](SPIRVCapabilityKind &val) { return !CapMap.count(val); }));
- }
- return Entry;
-}
-
-bool
-SPIRVModuleImpl::exist(SPIRVId Id) const {
- return exist(Id, nullptr);
-}
-
-bool
-SPIRVModuleImpl::exist(SPIRVId Id, SPIRVEntry **Entry) const {
- assert (Id != SPIRVID_INVALID && "Invalid Id");
- SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
- if (Loc == IdEntryMap.end())
- return false;
- if (Entry)
- *Entry = Loc->second;
- return true;
-}
-
-// If Id is invalid, returns the next available id.
-// Otherwise returns the given id and adjust the next available id by increment.
-SPIRVId
-SPIRVModuleImpl::getId(SPIRVId Id, unsigned increment) {
- if (!isValidId(Id))
- Id = NextId;
- else
- NextId = std::max(Id, NextId);
- NextId += increment;
- return Id;
-}
-
-SPIRVEntry *
-SPIRVModuleImpl::getEntry(SPIRVId Id) const {
- assert (Id != SPIRVID_INVALID && "Invalid Id");
- SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
- assert (Loc != IdEntryMap.end() && "Id is not in map");
- return Loc->second;
-}
-
-SPIRVExtInstSetKind
-SPIRVModuleImpl::getBuiltinSet(SPIRVId SetId) const {
- auto Loc = IdBuiltinMap.find(SetId);
- assert(Loc != IdBuiltinMap.end() && "Invalid builtin set id");
- return Loc->second;
-}
-
-bool
-SPIRVModuleImpl::isEntryPoint(SPIRVExecutionModelKind ExecModel, SPIRVId EP)
- const {
- assert(isValid(ExecModel) && "Invalid execution model");
- assert(EP != SPIRVID_INVALID && "Invalid function id");
- auto Loc = EntryPointSet.find(ExecModel);
- if (Loc == EntryPointSet.end())
- return false;
- return Loc->second.count(EP);
-}
-
-// Module change functions
-bool
-SPIRVModuleImpl::importBuiltinSet(const std::string& BuiltinSetName,
- SPIRVId *BuiltinSetId) {
- SPIRVId TmpBuiltinSetId = getId();
- if (!importBuiltinSetWithId(BuiltinSetName, TmpBuiltinSetId))
- return false;
- if (BuiltinSetId)
- *BuiltinSetId = TmpBuiltinSetId;
- return true;
-}
-
-bool
-SPIRVModuleImpl::importBuiltinSetWithId(const std::string& BuiltinSetName,
- SPIRVId BuiltinSetId) {
- SPIRVExtInstSetKind BuiltinSet = SPIRVEIS_Count;
- SPIRVCKRT(SPIRVBuiltinSetNameMap::rfind(BuiltinSetName, &BuiltinSet),
- InvalidBuiltinSetName, "Actual is " + BuiltinSetName);
- IdBuiltinMap[BuiltinSetId] = BuiltinSet;
- return true;
-}
-
-void
-SPIRVModuleImpl::setAlignment(SPIRVValue *V, SPIRVWord A) {
- V->setAlignment(A);
-}
-
-void
-SPIRVModuleImpl::setName(SPIRVEntry *E, const std::string &Name) {
- E->setName(Name);
- if (!E->hasId())
- return;
- if (!Name.empty())
- NamedId.insert(E->getId());
- else
- NamedId.erase(E->getId());
-}
-
-void SPIRVModuleImpl::resolveUnknownStructFields() {
- for (auto &KV : UnknownStructFieldMap) {
- auto *Struct = KV.first;
- for (auto &Indices : KV.second) {
- unsigned I = Indices.first;
- SPIRVId ID = Indices.second;
-
- auto Ty = static_cast<SPIRVType *>(getEntry(ID));
- Struct->setMemberType(I, Ty);
- }
- }
-}
-
-// Type creation functions
-template<class T>
-T *
-SPIRVModuleImpl::addType(T *Ty) {
- add(Ty);
- if (!Ty->getName().empty())
- setName(Ty, Ty->getName());
- return Ty;
-}
-
-SPIRVTypeVoid *
-SPIRVModuleImpl::addVoidType() {
- return addType(new SPIRVTypeVoid(this, getId()));
-}
-
-SPIRVTypeArray *
-SPIRVModuleImpl::addArrayType(SPIRVType *ElementType, SPIRVConstant *Length) {
- return addType(new SPIRVTypeArray(this, getId(), ElementType, Length));
-}
-
-SPIRVTypeBool *
-SPIRVModuleImpl::addBoolType() {
- return addType(new SPIRVTypeBool(this, getId()));
-}
-
-SPIRVTypeInt *
-SPIRVModuleImpl::addIntegerType(unsigned BitWidth) {
- auto Loc = IntTypeMap.find(BitWidth);
- if (Loc != IntTypeMap.end())
- return Loc->second;
- auto Ty = new SPIRVTypeInt(this, getId(), BitWidth, false);
- IntTypeMap[BitWidth] = Ty;
- return addType(Ty);
-}
-
-SPIRVTypeFloat *
-SPIRVModuleImpl::addFloatType(unsigned BitWidth) {
- SPIRVTypeFloat *T = addType(new SPIRVTypeFloat(this, getId(), BitWidth));
- return T;
-}
-
-SPIRVTypePointer *
-SPIRVModuleImpl::addPointerType(SPIRVStorageClassKind StorageClass,
- SPIRVType *ElementType) {
- return addType(new SPIRVTypePointer(this, getId(), StorageClass,
- ElementType));
-}
-
-SPIRVTypeFunction *
-SPIRVModuleImpl::addFunctionType(SPIRVType *ReturnType,
- const std::vector<SPIRVType *>& ParameterTypes) {
- return addType(new SPIRVTypeFunction(this, getId(), ReturnType,
- ParameterTypes));
-}
-
-SPIRVTypeOpaque*
-SPIRVModuleImpl::addOpaqueType(const std::string& Name) {
- return addType(new SPIRVTypeOpaque(this, getId(), Name));
-}
-
-SPIRVTypeStruct *SPIRVModuleImpl::openStructType(unsigned NumMembers,
- const std::string &Name) {
- auto T = new SPIRVTypeStruct(this, getId(), NumMembers, Name);
- return T;
-}
-
-void SPIRVModuleImpl::closeStructType(SPIRVTypeStruct *T, bool Packed) {
- addType(T);
- T->setPacked(Packed);
-}
-
-SPIRVTypeVector*
-SPIRVModuleImpl::addVectorType(SPIRVType* CompType, SPIRVWord CompCount) {
- return addType(new SPIRVTypeVector(this, getId(), CompType, CompCount));
-}
-SPIRVType *
-SPIRVModuleImpl::addOpaqueGenericType(Op TheOpCode) {
- return addType(new SPIRVTypeOpaqueGeneric(TheOpCode, this, getId()));
-}
-
-SPIRVTypeDeviceEvent *
-SPIRVModuleImpl::addDeviceEventType() {
- return addType(new SPIRVTypeDeviceEvent(this, getId()));
-}
-
-SPIRVTypeQueue *
-SPIRVModuleImpl::addQueueType() {
- return addType(new SPIRVTypeQueue(this, getId()));
-}
-
-SPIRVTypePipe*
-SPIRVModuleImpl::addPipeType() {
- return addType(new SPIRVTypePipe(this, getId()));
-}
-
-SPIRVTypeImage *
-SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
- const SPIRVTypeImageDescriptor &Desc) {
- return addType(new SPIRVTypeImage(this, getId(),
- SampledType ? SampledType->getId() : 0, Desc));
-}
-
-SPIRVTypeImage *
-SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
- const SPIRVTypeImageDescriptor &Desc, SPIRVAccessQualifierKind Acc) {
- return addType(new SPIRVTypeImage(this, getId(),
- SampledType ? SampledType->getId() : 0, Desc, Acc));
-}
-
-SPIRVTypeSampler *
-SPIRVModuleImpl::addSamplerType() {
- return addType(new SPIRVTypeSampler(this, getId()));
-}
-
-SPIRVTypePipeStorage*
-SPIRVModuleImpl::addPipeStorageType() {
- return addType(new SPIRVTypePipeStorage(this, getId()));
-}
-
-SPIRVTypeSampledImage *
-SPIRVModuleImpl::addSampledImageType(SPIRVTypeImage *T) {
- return addType(new SPIRVTypeSampledImage(this, getId(), T));
-}
-
-void SPIRVModuleImpl::createForwardPointers() {
- std::unordered_set<SPIRVId> Seen;
-
- for (auto *T : TypeVec) {
- if (T->hasId())
- Seen.insert(T->getId());
-
- if (!T->isTypeStruct())
- continue;
-
- auto ST = static_cast<SPIRVTypeStruct *>(T);
-
- for (unsigned i = 0; i < ST->getStructMemberCount(); ++i) {
- auto MemberTy = ST->getStructMemberType(i);
- if (!MemberTy->isTypePointer()) continue;
- auto Ptr = static_cast<SPIRVTypePointer *>(MemberTy);
-
- if (Seen.find(Ptr->getId()) == Seen.end()) {
- ForwardPointerVec.push_back(new SPIRVTypeForwardPointer(
- this, Ptr, Ptr->getPointerStorageClass()));
- }
- }
- }
-}
-
-SPIRVFunction *
-SPIRVModuleImpl::addFunction(SPIRVFunction *Func) {
- FuncVec.push_back(add(Func));
- return Func;
-}
-
-SPIRVFunction *
-SPIRVModuleImpl::addFunction(SPIRVTypeFunction *FuncType, SPIRVId Id) {
- return addFunction(new SPIRVFunction(this, FuncType,
- getId(Id, FuncType->getNumParameters() + 1)));
-}
-
-SPIRVBasicBlock *
-SPIRVModuleImpl::addBasicBlock(SPIRVFunction *Func, SPIRVId Id) {
- return Func->addBasicBlock(new SPIRVBasicBlock(getId(Id), Func));
-}
-
-const SPIRVDecorateGeneric *
-SPIRVModuleImpl::addDecorate(SPIRVDecorateGeneric *Dec) {
- add(Dec);
- SPIRVId Id = Dec->getTargetId();
- bool Found = exist(Id);
+//===- SPIRVModule.cpp - Class to represent SPIR-V module --------*- C++ -*-===//
+//
+// The LLVM/SPIRV Translator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal with the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimers.
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimers in the documentation
+// and/or other materials provided with the distribution.
+// Neither the names of Advanced Micro Devices, Inc., nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// Software without specific prior written permission.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
+// THE SOFTWARE.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements Module class for SPIR-V.
+///
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVModule.h"
+#include "SPIRVDebug.h"
+#include "SPIRVEntry.h"
+#include "SPIRVType.h"
+#include "SPIRVValue.h"
+#include "SPIRVExtInst.h"
+#include "SPIRVFunction.h"
+#include "SPIRVInstruction.h"
+#include "SPIRVStream.h"
+
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+
+namespace SPIRV{
+
+SPIRVModule::SPIRVModule():AutoAddCapability(true), ValidateCapability(false)
+{}
+
+SPIRVModule::~SPIRVModule()
+{}
+
+class SPIRVModuleImpl : public SPIRVModule {
+public:
+ SPIRVModuleImpl():SPIRVModule(), NextId(1), BoolType(NULL),
+ SPIRVVersion(SPIRV_1_0),
+ GeneratorId(SPIRVGEN_KhronosLLVMSPIRVTranslator),
+ GeneratorVer(0),
+ InstSchema(SPIRVISCH_Default),
+ SrcLang(SourceLanguageOpenCL_C),
+ SrcLangVer(102000) {
+ AddrModel = sizeof(size_t) == 32 ? AddressingModelPhysical32
+ : AddressingModelPhysical64;
+ // OpenCL memory model requires Kernel capability
+ setMemoryModel(MemoryModelOpenCL);
+ }
+ virtual ~SPIRVModuleImpl();
+
+ // Object query functions
+ bool exist(SPIRVId) const;
+ bool exist(SPIRVId, SPIRVEntry **) const;
+ SPIRVId getId(SPIRVId Id = SPIRVID_INVALID, unsigned Increment = 1);
+ virtual SPIRVEntry *getEntry(SPIRVId Id) const;
+ bool hasDebugInfo() const { return !StringVec.empty();}
+
+ // Error handling functions
+ SPIRVErrorLog &getErrorLog() { return ErrLog;}
+ SPIRVErrorCode getError(std::string &ErrMsg) { return ErrLog.getError(ErrMsg);}
+
+ // Module query functions
+ SPIRVAddressingModelKind getAddressingModel() { return AddrModel;}
+ SPIRVExtInstSetKind getBuiltinSet(SPIRVId SetId) const;
+ const SPIRVCapMap &getCapability() const { return CapMap; }
+ bool hasCapability(SPIRVCapabilityKind Cap) const {
+ return CapMap.find(Cap) != CapMap.end();
+ }
+ std::set<std::string> &getExtension() { return SPIRVExt;}
+ SPIRVFunction *getFunction(unsigned I) const { return FuncVec[I];}
+ SPIRVVariable *getVariable(unsigned I) const { return VariableVec[I];}
+ virtual SPIRVValue *getValue(SPIRVId TheId) const;
+ virtual std::vector<SPIRVValue *> getValues(const std::vector<SPIRVId>&)const;
+ virtual std::vector<SPIRVId> getIds(const std::vector<SPIRVEntry *>&)const;
+ virtual std::vector<SPIRVId> getIds(const std::vector<SPIRVValue *>&)const;
+ virtual SPIRVType *getValueType(SPIRVId TheId)const;
+ virtual std::vector<SPIRVType *> getValueTypes(const std::vector<SPIRVId>&)
+ const;
+ SPIRVMemoryModelKind getMemoryModel() const { return MemoryModel;}
+ virtual SPIRVConstant* getLiteralAsConstant(unsigned Literal);
+ unsigned getNumEntryPoints(SPIRVExecutionModelKind EM) const {
+ auto Loc = EntryPointVec.find(EM);
+ if (Loc == EntryPointVec.end())
+ return 0;
+ return Loc->second.size();
+ }
+ SPIRVFunction *getEntryPoint(SPIRVExecutionModelKind EM, unsigned I) const {
+ auto Loc = EntryPointVec.find(EM);
+ if (Loc == EntryPointVec.end())
+ return nullptr;
+ assert(I < Loc->second.size());
+ return get<SPIRVFunction>(Loc->second[I]);
+ }
+ unsigned getNumFunctions() const { return FuncVec.size();}
+ unsigned getNumVariables() const { return VariableVec.size();}
+ SourceLanguage getSourceLanguage(SPIRVWord * Ver = nullptr) const {
+ if (Ver)
+ *Ver = SrcLangVer;
+ return SrcLang;
+ }
+ std::set<std::string> &getSourceExtension() { return SrcExtension;}
+ bool isEntryPoint(SPIRVExecutionModelKind, SPIRVId EP) const;
+ unsigned short getGeneratorId() const { return GeneratorId; }
+ unsigned short getGeneratorVer() const { return GeneratorVer; }
+ SPIRVWord getSPIRVVersion() const { return SPIRVVersion; }
+
+ // Module changing functions
+ bool importBuiltinSet(const std::string &, SPIRVId *);
+ bool importBuiltinSetWithId(const std::string &, SPIRVId);
+ void optimizeDecorates();
+ void setAddressingModel(SPIRVAddressingModelKind AM) { AddrModel = AM;}
+ void setAlignment(SPIRVValue *, SPIRVWord);
+ void setMemoryModel(SPIRVMemoryModelKind MM) {
+ MemoryModel = MM;
+ if (MemoryModel == spv::MemoryModelOpenCL)
+ addCapability(CapabilityKernel);
+ }
+ void setName(SPIRVEntry *E, const std::string &Name);
+ void setSourceLanguage(SourceLanguage Lang, SPIRVWord Ver) {
+ SrcLang = Lang;
+ SrcLangVer = Ver;
+ }
+ void setGeneratorId(unsigned short Id) { GeneratorId = Id; }
+ void setGeneratorVer(unsigned short Ver) { GeneratorVer = Ver; }
+ void resolveUnknownStructFields();
+
+ void setSPIRVVersion(SPIRVWord Ver) override { SPIRVVersion = Ver; }
+
+ // Object creation functions
+ template<class T> void addTo(std::vector<T *> &V, SPIRVEntry *E);
+ virtual SPIRVEntry *addEntry(SPIRVEntry *E);
+ virtual SPIRVBasicBlock *addBasicBlock(SPIRVFunction *, SPIRVId);
+ virtual SPIRVString *getString(const std::string &Str);
+ virtual SPIRVMemberName *addMemberName(SPIRVTypeStruct *ST,
+ SPIRVWord MemberNumber, const std::string &Name);
+ virtual void addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
+ SPIRVId ID);
+ virtual void addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line,
+ SPIRVWord Column);
+ virtual const std::shared_ptr<const SPIRVLine>& getCurrentLine() const;
+ virtual void setCurrentLine(const std::shared_ptr<const SPIRVLine> &Line);
+ virtual void addCapability(SPIRVCapabilityKind);
+ virtual void addCapabilityInternal(SPIRVCapabilityKind);
+ virtual const SPIRVDecorateGeneric *addDecorate(SPIRVDecorateGeneric *);
+ virtual SPIRVDecorationGroup *addDecorationGroup();
+ virtual SPIRVDecorationGroup *addDecorationGroup(SPIRVDecorationGroup *Group);
+ virtual SPIRVGroupDecorate *addGroupDecorate(SPIRVDecorationGroup *Group,
+ const std::vector<SPIRVEntry *> &Targets);
+ virtual SPIRVGroupDecorateGeneric *addGroupDecorateGeneric(
+ SPIRVGroupDecorateGeneric *GDec);
+ virtual SPIRVGroupMemberDecorate *addGroupMemberDecorate(
+ SPIRVDecorationGroup *Group, const std::vector<SPIRVEntry *> &Targets);
+ virtual void addEntryPoint(SPIRVExecutionModelKind ExecModel,
+ SPIRVId EntryPoint);
+ virtual SPIRVForward *addForward(SPIRVType *Ty);
+ virtual SPIRVForward *addForward(SPIRVId, SPIRVType *Ty);
+ virtual SPIRVFunction *addFunction(SPIRVFunction *);
+ virtual SPIRVFunction *addFunction(SPIRVTypeFunction *, SPIRVId);
+ virtual SPIRVEntry *replaceForward(SPIRVForward *, SPIRVEntry *);
+ virtual void eraseInstruction(SPIRVInstruction *, SPIRVBasicBlock *);
+
+ // Type creation functions
+ template<class T> T * addType(T *Ty);
+ virtual SPIRVTypeArray *addArrayType(SPIRVType *, SPIRVConstant *);
+ virtual SPIRVTypeBool *addBoolType();
+ virtual SPIRVTypeFloat *addFloatType(unsigned BitWidth);
+ virtual SPIRVTypeFunction *addFunctionType(SPIRVType *,
+ const std::vector<SPIRVType *> &);
+ virtual SPIRVTypeInt *addIntegerType(unsigned BitWidth);
+ virtual SPIRVTypeOpaque *addOpaqueType(const std::string &);
+ virtual SPIRVTypePointer *addPointerType(SPIRVStorageClassKind, SPIRVType *);
+ virtual SPIRVTypeImage *addImageType(SPIRVType *,
+ const SPIRVTypeImageDescriptor &);
+ virtual SPIRVTypeImage *addImageType(SPIRVType *,
+ const SPIRVTypeImageDescriptor &, SPIRVAccessQualifierKind);
+ virtual SPIRVTypeSampler *addSamplerType();
+ virtual SPIRVTypePipeStorage *addPipeStorageType();
+ virtual SPIRVTypeSampledImage *addSampledImageType(SPIRVTypeImage *T);
+ virtual SPIRVTypeStruct *openStructType(unsigned, const std::string &);
+ virtual void closeStructType(SPIRVTypeStruct *T, bool);
+ virtual SPIRVTypeVector *addVectorType(SPIRVType *, SPIRVWord);
+ virtual SPIRVType *addOpaqueGenericType(Op);
+ virtual SPIRVTypeDeviceEvent *addDeviceEventType();
+ virtual SPIRVTypeQueue *addQueueType();
+ virtual SPIRVTypePipe *addPipeType();
+ virtual SPIRVTypeVoid *addVoidType();
+ virtual void createForwardPointers();
+
+ // Constant creation functions
+ virtual SPIRVInstruction *addBranchInst(SPIRVLabel *, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addBranchConditionalInst(SPIRVValue *, SPIRVLabel *,
+ SPIRVLabel *, SPIRVBasicBlock *);
+ virtual SPIRVValue *addCompositeConstant(SPIRVType *,
+ const std::vector<SPIRVValue*>&);
+ virtual SPIRVValue *addConstant(SPIRVValue *);
+ virtual SPIRVValue *addConstant(SPIRVType *, uint64_t);
+ virtual SPIRVValue *addDoubleConstant(SPIRVTypeFloat *, double);
+ virtual SPIRVValue *addFloatConstant(SPIRVTypeFloat *, float);
+ virtual SPIRVValue *addIntegerConstant(SPIRVTypeInt *, uint64_t);
+ virtual SPIRVValue *addNullConstant(SPIRVType *);
+ virtual SPIRVValue *addUndef(SPIRVType *TheType);
+ virtual SPIRVValue *addSamplerConstant(SPIRVType *TheType, SPIRVWord AddrMode,
+ SPIRVWord ParametricMode, SPIRVWord FilterMode);
+ virtual SPIRVValue* addPipeStorageConstant(SPIRVType* TheType,
+ SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity);
+
+ // Instruction creation functions
+ virtual SPIRVInstruction *addPtrAccessChainInst(SPIRVType *, SPIRVValue *,
+ std::vector<SPIRVValue *>, SPIRVBasicBlock *, bool);
+ virtual SPIRVInstruction *addAsyncGroupCopy(SPIRVValue *Scope,
+ SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride,
+ SPIRVValue *Event, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addExtInst(SPIRVType *,
+ SPIRVWord, SPIRVWord, const std::vector<SPIRVWord> &,
+ SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addExtInst(SPIRVType *,
+ SPIRVWord, SPIRVWord, const std::vector<SPIRVValue *> &,
+ SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *,
+ SPIRVValue *, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addCallInst(SPIRVFunction*,
+ const std::vector<SPIRVWord> &, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addCmpInst(Op, SPIRVType *, SPIRVValue *,
+ SPIRVValue *, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addLoadInst(SPIRVValue *,
+ const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addPhiInst(SPIRVType *, std::vector<SPIRVValue *>,
+ SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addCompositeConstructInst(SPIRVType *,
+ const std::vector<SPIRVId>&, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addCompositeExtractInst(SPIRVType *, SPIRVValue *,
+ const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addCompositeInsertInst(SPIRVValue *Object,
+ SPIRVValue *Composite, const std::vector<SPIRVWord>& Indices,
+ SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addCopyObjectInst(SPIRVType *TheType,
+ SPIRVValue *Operand, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addCopyMemoryInst(SPIRVValue *, SPIRVValue *,
+ const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addCopyMemorySizedInst(SPIRVValue *, SPIRVValue *,
+ SPIRVValue *, const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addControlBarrierInst(
+ SPIRVValue *ExecKind, SPIRVValue *MemKind,
+ SPIRVValue *MemSema, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addGroupInst(Op OpCode, SPIRVType *Type,
+ Scope Scope, const std::vector<SPIRVValue *> &Ops,
+ SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addInstruction(SPIRVInstruction *Inst,
+ SPIRVBasicBlock *BB);
+ virtual SPIRVInstTemplateBase *addInstTemplate(Op OC,
+ SPIRVBasicBlock* BB, SPIRVType *Ty);
+ virtual SPIRVInstTemplateBase *addInstTemplate(Op OC,
+ const std::vector<SPIRVWord>& Ops, SPIRVBasicBlock* BB, SPIRVType *Ty);
+ virtual SPIRVInstruction *addLifetimeInst(Op OC, SPIRVValue *Object,
+ SPIRVWord Size, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addMemoryBarrierInst(
+ Scope ScopeKind, SPIRVWord MemFlag, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addUnreachableInst(SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addReturnInst(SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addReturnValueInst(SPIRVValue *, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addSelectInst(SPIRVValue *, SPIRVValue *, SPIRVValue *,
+ SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addLoopMergeInst(SPIRVId MergeBlock,
+ SPIRVId ContinueTarget, SPIRVWord LoopControl, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addSelectionMergeInst(SPIRVId MergeBlock,
+ SPIRVWord SelectionControl, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addStoreInst(SPIRVValue *, SPIRVValue *,
+ const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addSwitchInst(SPIRVValue *, SPIRVBasicBlock *,
+ const std::vector<std::pair<std::vector<SPIRVWord>, SPIRVBasicBlock *>>&,
+ SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addFModInst(SPIRVType *TheType, SPIRVId TheDividend,
+ SPIRVId TheDivisor, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addVectorTimesScalarInst(SPIRVType *TheType,
+ SPIRVId TheVector, SPIRVId TheScalar, SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addUnaryInst(Op, SPIRVType *, SPIRVValue *,
+ SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addVariable(SPIRVType *, bool, SPIRVLinkageTypeKind,
+ SPIRVValue *, const std::string &, SPIRVStorageClassKind, SPIRVBasicBlock *);
+ virtual SPIRVValue *addVectorShuffleInst(SPIRVType *Type, SPIRVValue *Vec1,
+ SPIRVValue *Vec2, const std::vector<SPIRVWord> &Components,
+ SPIRVBasicBlock *BB);
+ virtual SPIRVInstruction *addVectorExtractDynamicInst(SPIRVValue *,
+ SPIRVValue *, SPIRVBasicBlock *);
+ virtual SPIRVInstruction *addVectorInsertDynamicInst(SPIRVValue *,
+ SPIRVValue *, SPIRVValue*, SPIRVBasicBlock *);
+
+ // I/O functions
+ friend spv_ostream & operator<<(spv_ostream &O, SPIRVModule& M);
+ friend std::istream & operator>>(std::istream &I, SPIRVModule& M);
+
+private:
+ SPIRVErrorLog ErrLog;
+ SPIRVId NextId;
+ SPIRVTypeInt *BoolType;
+ SPIRVWord SPIRVVersion;
+ unsigned short GeneratorId;
+ unsigned short GeneratorVer;
+ SPIRVInstructionSchemaKind InstSchema;
+ SourceLanguage SrcLang;
+ SPIRVWord SrcLangVer;
+ std::set<std::string> SrcExtension;
+ std::set<std::string> SPIRVExt;
+ SPIRVAddressingModelKind AddrModel;
+ SPIRVMemoryModelKind MemoryModel;
+
+ typedef std::map<SPIRVId, SPIRVEntry *> SPIRVIdToEntryMap;
+ typedef std::set<SPIRVEntry *> SPIRVEntrySet;
+ typedef std::set<SPIRVId> SPIRVIdSet;
+ typedef std::vector<SPIRVId> SPIRVIdVec;
+ typedef std::vector<SPIRVFunction *> SPIRVFunctionVector;
+ typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
+ typedef std::vector<SPIRVType *> SPIRVTypeVec;
+ typedef std::vector<SPIRVValue *> SPIRVConstantVector;
+ typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
+ typedef std::vector<SPIRVString *> SPIRVStringVec;
+ typedef std::vector<SPIRVMemberName *> SPIRVMemberNameVec;
+ typedef std::vector<SPIRVDecorationGroup *> SPIRVDecGroupVec;
+ typedef std::vector<SPIRVGroupDecorateGeneric *> SPIRVGroupDecVec;
+ typedef std::map<SPIRVId, SPIRVExtInstSetKind> SPIRVIdToBuiltinSetMap;
+ typedef std::map<SPIRVExecutionModelKind, SPIRVIdSet> SPIRVExecModelIdSetMap;
+ typedef std::map<SPIRVExecutionModelKind, SPIRVIdVec> SPIRVExecModelIdVecMap;
+ typedef std::unordered_map<std::string, SPIRVString*> SPIRVStringMap;
+ typedef std::map<SPIRVTypeStruct *, std::vector<std::pair<unsigned, SPIRVId>>>
+ SPIRVUnknownStructFieldMap;
+
+ SPIRVForwardPointerVec ForwardPointerVec;
+ SPIRVTypeVec TypeVec;
+ SPIRVIdToEntryMap IdEntryMap;
+ SPIRVFunctionVector FuncVec;
+ SPIRVConstantVector ConstVec;
+ SPIRVVariableVec VariableVec;
+ SPIRVEntrySet EntryNoId; // Entries without id
+ SPIRVIdToBuiltinSetMap IdBuiltinMap;
+ SPIRVIdSet NamedId;
+ SPIRVStringVec StringVec;
+ SPIRVMemberNameVec MemberNameVec;
+ std::shared_ptr<const SPIRVLine> CurrentLine;
+ SPIRVDecorateSet DecorateSet;
+ SPIRVDecGroupVec DecGroupVec;
+ SPIRVGroupDecVec GroupDecVec;
+ SPIRVExecModelIdSetMap EntryPointSet;
+ SPIRVExecModelIdVecMap EntryPointVec;
+ SPIRVStringMap StrMap;
+ SPIRVCapMap CapMap;
+ SPIRVUnknownStructFieldMap UnknownStructFieldMap;
+ std::map<unsigned, SPIRVTypeInt*> IntTypeMap;
+ std::map<unsigned, SPIRVConstant*> LiteralMap;
+
+ void layoutEntry(SPIRVEntry* Entry);
+};
+
+SPIRVModuleImpl::~SPIRVModuleImpl() {
+ for (auto I : EntryNoId)
+ delete I;
+
+ for (auto I : IdEntryMap)
+ delete I.second;
+
+ for (auto C : CapMap)
+ delete C.second;
+}
+
+const std::shared_ptr<const SPIRVLine>&
+SPIRVModuleImpl::getCurrentLine() const {
+ return CurrentLine;
+}
+
+void
+SPIRVModuleImpl::setCurrentLine(const std::shared_ptr<const SPIRVLine>& Line) {
+ CurrentLine = Line;
+}
+
+void
+SPIRVModuleImpl::addLine(SPIRVEntry* E, SPIRVId FileNameId,
+ SPIRVWord Line, SPIRVWord Column) {
+ if (!(CurrentLine && CurrentLine->equals(FileNameId, Line, Column)))
+ CurrentLine.reset(new SPIRVLine(this, FileNameId, Line, Column));
+ assert(E && "invalid entry");
+ E->setLine(CurrentLine);
+}
+
+// Creates decoration group and group decorates from decorates shared by
+// multiple targets.
+void
+SPIRVModuleImpl::optimizeDecorates() {
+ SPIRVDBG(spvdbgs() << "[optimizeDecorates] begin\n");
+ for (auto I = DecorateSet.begin(), E = DecorateSet.end(); I != E;) {
+ auto D = *I;
+ SPIRVDBG(spvdbgs() << " check " << *D << '\n');
+ if (D->getOpCode() == OpMemberDecorate) {
+ ++I;
+ continue;
+ }
+ auto ER = DecorateSet.equal_range(D);
+ SPIRVDBG(spvdbgs() << " equal range " << **ER.first
+ << " to ";
+ if (ER.second != DecorateSet.end())
+ spvdbgs() << **ER.second;
+ else
+ spvdbgs() << "end";
+ spvdbgs() << '\n');
+ if (std::distance(ER.first, ER.second) < 2) {
+ I = ER.second;
+ SPIRVDBG(spvdbgs() << " skip equal range \n");
+ continue;
+ }
+ SPIRVDBG(spvdbgs() << " add deco group. erase equal range\n");
+ auto G = add(new SPIRVDecorationGroup(this, getId()));
+ std::vector<SPIRVId> Targets;
+ Targets.push_back(D->getTargetId());
+ const_cast<SPIRVDecorateGeneric*>(D)->setTargetId(G->getId());
+ G->getDecorations().insert(D);
+ for (I = ER.first; I != ER.second; ++I) {
+ auto E = *I;
+ if (*E == *D)
+ continue;
+ Targets.push_back(E->getTargetId());
+ }
+
+ // WordCount is only 16 bits. We can only have 65535 - FixedWC targtets per
+ // group.
+ // For now, just skip using a group if the number of targets to too big
+ if (Targets.size() < 65530) {
+ DecorateSet.erase(ER.first, ER.second);
+ auto GD = add(new SPIRVGroupDecorate(G, Targets));
+ DecGroupVec.push_back(G);
+ GroupDecVec.push_back(GD);
+ }
+ }
+}
+
+SPIRVValue*
+SPIRVModuleImpl::addSamplerConstant(SPIRVType* TheType,
+ SPIRVWord AddrMode, SPIRVWord ParametricMode, SPIRVWord FilterMode) {
+ return addConstant(new SPIRVConstantSampler(this, TheType, getId(), AddrMode,
+ ParametricMode, FilterMode));
+}
+
+SPIRVValue*
+SPIRVModuleImpl::addPipeStorageConstant(SPIRVType* TheType,
+ SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity) {
+ return addConstant(new SPIRVConstantPipeStorage(this, TheType, getId(),
+ PacketSize, PacketAlign, Capacity));
+}
+
+void
+SPIRVModuleImpl::addCapability(SPIRVCapabilityKind Cap) {
+ addCapabilities(SPIRV::getCapability(Cap));
+ SPIRVDBG(spvdbgs() << "addCapability: " << Cap << '\n');
+ if (hasCapability(Cap))
+ return;
+
+ CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap)));
+}
+
+void
+SPIRVModuleImpl::addCapabilityInternal(SPIRVCapabilityKind Cap) {
+ if (AutoAddCapability) {
+ if (hasCapability(Cap))
+ return;
+
+ CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap)));
+ }
+}
+
+SPIRVConstant*
+SPIRVModuleImpl::getLiteralAsConstant(unsigned Literal) {
+ auto Loc = LiteralMap.find(Literal);
+ if (Loc != LiteralMap.end())
+ return Loc->second;
+ auto Ty = addIntegerType(32);
+ auto V = new SPIRVConstant(this, Ty, getId(), static_cast<uint64_t>(Literal));
+ LiteralMap[Literal] = V;
+ addConstant(V);
+ return V;
+}
+
+void
+SPIRVModuleImpl::layoutEntry(SPIRVEntry* E) {
+ auto OC = E->getOpCode();
+ switch (OC) {
+ case OpString:
+ addTo(StringVec, E);
+ break;
+ case OpMemberName:
+ addTo(MemberNameVec, E);
+ break;
+ case OpVariable: {
+ auto BV = static_cast<SPIRVVariable*>(E);
+ if (!BV->getParent())
+ addTo(VariableVec, E);
+ }
+ break;
+ default:
+ if (isTypeOpCode(OC))
+ TypeVec.push_back(static_cast<SPIRVType*>(E));
+ else if (isConstantOpCode(OC))
+ ConstVec.push_back(static_cast<SPIRVConstant*>(E));
+ break;
+ }
+}
+
+// Add an entry to the id to entry map.
+// Assert if the id is mapped to a different entry.
+// Certain entries need to be add to specific collectors to maintain
+// logic layout of SPIRV.
+SPIRVEntry *
+SPIRVModuleImpl::addEntry(SPIRVEntry *Entry) {
+ assert(Entry && "Invalid entry");
+ if (Entry->hasId()) {
+ SPIRVId Id = Entry->getId();
+ assert(Entry->getId() != SPIRVID_INVALID && "Invalid id");
+ SPIRVEntry *Mapped = nullptr;
+ if (exist(Id, &Mapped)) {
+ if (Mapped->getOpCode() == OpForward) {
+ replaceForward(static_cast<SPIRVForward *>(Mapped), Entry);
+ } else {
+ assert(Mapped == Entry && "Id used twice");
+ }
+ } else
+ IdEntryMap[Id] = Entry;
+ } else {
+ // Entry of OpLine will be deleted by std::shared_ptr automatically.
+ if (Entry->getOpCode() != OpLine)
+ EntryNoId.insert(Entry);
+ }
+
+ Entry->setModule(this);
+
+ layoutEntry(Entry);
+ if (AutoAddCapability) {
+ for (auto &I:Entry->getRequiredCapability()) {
+ addCapability(I);
+ }
+ }
+ if (ValidateCapability) {
+ assert(none_of(
+ Entry->getRequiredCapability().begin(),
+ Entry->getRequiredCapability().end(),
+ [this](SPIRVCapabilityKind &val) { return !CapMap.count(val); }));
+ }
+ return Entry;
+}
+
+bool
+SPIRVModuleImpl::exist(SPIRVId Id) const {
+ return exist(Id, nullptr);
+}
+
+bool
+SPIRVModuleImpl::exist(SPIRVId Id, SPIRVEntry **Entry) const {
+ assert (Id != SPIRVID_INVALID && "Invalid Id");
+ SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
+ if (Loc == IdEntryMap.end())
+ return false;
+ if (Entry)
+ *Entry = Loc->second;
+ return true;
+}
+
+// If Id is invalid, returns the next available id.
+// Otherwise returns the given id and adjust the next available id by increment.
+SPIRVId
+SPIRVModuleImpl::getId(SPIRVId Id, unsigned increment) {
+ if (!isValidId(Id))
+ Id = NextId;
+ else
+ NextId = std::max(Id, NextId);
+ NextId += increment;
+ return Id;
+}
+
+SPIRVEntry *
+SPIRVModuleImpl::getEntry(SPIRVId Id) const {
+ assert (Id != SPIRVID_INVALID && "Invalid Id");
+ SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
+ assert (Loc != IdEntryMap.end() && "Id is not in map");
+ return Loc->second;
+}
+
+SPIRVExtInstSetKind
+SPIRVModuleImpl::getBuiltinSet(SPIRVId SetId) const {
+ auto Loc = IdBuiltinMap.find(SetId);
+ assert(Loc != IdBuiltinMap.end() && "Invalid builtin set id");
+ return Loc->second;
+}
+
+bool
+SPIRVModuleImpl::isEntryPoint(SPIRVExecutionModelKind ExecModel, SPIRVId EP)
+ const {
+ assert(isValid(ExecModel) && "Invalid execution model");
+ assert(EP != SPIRVID_INVALID && "Invalid function id");
+ auto Loc = EntryPointSet.find(ExecModel);
+ if (Loc == EntryPointSet.end())
+ return false;
+ return Loc->second.count(EP);
+}
+
+// Module change functions
+bool
+SPIRVModuleImpl::importBuiltinSet(const std::string& BuiltinSetName,
+ SPIRVId *BuiltinSetId) {
+ SPIRVId TmpBuiltinSetId = getId();
+ if (!importBuiltinSetWithId(BuiltinSetName, TmpBuiltinSetId))
+ return false;
+ if (BuiltinSetId)
+ *BuiltinSetId = TmpBuiltinSetId;
+ return true;
+}
+
+bool
+SPIRVModuleImpl::importBuiltinSetWithId(const std::string& BuiltinSetName,
+ SPIRVId BuiltinSetId) {
+ SPIRVExtInstSetKind BuiltinSet = SPIRVEIS_Count;
+ SPIRVCKRT(SPIRVBuiltinSetNameMap::rfind(BuiltinSetName, &BuiltinSet),
+ InvalidBuiltinSetName, "Actual is " + BuiltinSetName);
+ IdBuiltinMap[BuiltinSetId] = BuiltinSet;
+ return true;
+}
+
+void
+SPIRVModuleImpl::setAlignment(SPIRVValue *V, SPIRVWord A) {
+ V->setAlignment(A);
+}
+
+void
+SPIRVModuleImpl::setName(SPIRVEntry *E, const std::string &Name) {
+ E->setName(Name);
+ if (!E->hasId())
+ return;
+ if (!Name.empty())
+ NamedId.insert(E->getId());
+ else
+ NamedId.erase(E->getId());
+}
+
+void SPIRVModuleImpl::resolveUnknownStructFields() {
+ for (auto &KV : UnknownStructFieldMap) {
+ auto *Struct = KV.first;
+ for (auto &Indices : KV.second) {
+ unsigned I = Indices.first;
+ SPIRVId ID = Indices.second;
+
+ auto Ty = static_cast<SPIRVType *>(getEntry(ID));
+ Struct->setMemberType(I, Ty);
+ }
+ }
+}
+
+// Type creation functions
+template<class T>
+T *
+SPIRVModuleImpl::addType(T *Ty) {
+ add(Ty);
+ if (!Ty->getName().empty())
+ setName(Ty, Ty->getName());
+ return Ty;
+}
+
+SPIRVTypeVoid *
+SPIRVModuleImpl::addVoidType() {
+ return addType(new SPIRVTypeVoid(this, getId()));
+}
+
+SPIRVTypeArray *
+SPIRVModuleImpl::addArrayType(SPIRVType *ElementType, SPIRVConstant *Length) {
+ return addType(new SPIRVTypeArray(this, getId(), ElementType, Length));
+}
+
+SPIRVTypeBool *
+SPIRVModuleImpl::addBoolType() {
+ return addType(new SPIRVTypeBool(this, getId()));
+}
+
+SPIRVTypeInt *
+SPIRVModuleImpl::addIntegerType(unsigned BitWidth) {
+ auto Loc = IntTypeMap.find(BitWidth);
+ if (Loc != IntTypeMap.end())
+ return Loc->second;
+ auto Ty = new SPIRVTypeInt(this, getId(), BitWidth, false);
+ IntTypeMap[BitWidth] = Ty;
+ return addType(Ty);
+}
+
+SPIRVTypeFloat *
+SPIRVModuleImpl::addFloatType(unsigned BitWidth) {
+ SPIRVTypeFloat *T = addType(new SPIRVTypeFloat(this, getId(), BitWidth));
+ return T;
+}
+
+SPIRVTypePointer *
+SPIRVModuleImpl::addPointerType(SPIRVStorageClassKind StorageClass,
+ SPIRVType *ElementType) {
+ return addType(new SPIRVTypePointer(this, getId(), StorageClass,
+ ElementType));
+}
+
+SPIRVTypeFunction *
+SPIRVModuleImpl::addFunctionType(SPIRVType *ReturnType,
+ const std::vector<SPIRVType *>& ParameterTypes) {
+ return addType(new SPIRVTypeFunction(this, getId(), ReturnType,
+ ParameterTypes));
+}
+
+SPIRVTypeOpaque*
+SPIRVModuleImpl::addOpaqueType(const std::string& Name) {
+ return addType(new SPIRVTypeOpaque(this, getId(), Name));
+}
+
+SPIRVTypeStruct *SPIRVModuleImpl::openStructType(unsigned NumMembers,
+ const std::string &Name) {
+ auto T = new SPIRVTypeStruct(this, getId(), NumMembers, Name);
+ return T;
+}
+
+void SPIRVModuleImpl::closeStructType(SPIRVTypeStruct *T, bool Packed) {
+ addType(T);
+ T->setPacked(Packed);
+}
+
+SPIRVTypeVector*
+SPIRVModuleImpl::addVectorType(SPIRVType* CompType, SPIRVWord CompCount) {
+ return addType(new SPIRVTypeVector(this, getId(), CompType, CompCount));
+}
+SPIRVType *
+SPIRVModuleImpl::addOpaqueGenericType(Op TheOpCode) {
+ return addType(new SPIRVTypeOpaqueGeneric(TheOpCode, this, getId()));
+}
+
+SPIRVTypeDeviceEvent *
+SPIRVModuleImpl::addDeviceEventType() {
+ return addType(new SPIRVTypeDeviceEvent(this, getId()));
+}
+
+SPIRVTypeQueue *
+SPIRVModuleImpl::addQueueType() {
+ return addType(new SPIRVTypeQueue(this, getId()));
+}
+
+SPIRVTypePipe*
+SPIRVModuleImpl::addPipeType() {
+ return addType(new SPIRVTypePipe(this, getId()));
+}
+
+SPIRVTypeImage *
+SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
+ const SPIRVTypeImageDescriptor &Desc) {
+ return addType(new SPIRVTypeImage(this, getId(),
+ SampledType ? SampledType->getId() : 0, Desc));
+}
+
+SPIRVTypeImage *
+SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
+ const SPIRVTypeImageDescriptor &Desc, SPIRVAccessQualifierKind Acc) {
+ return addType(new SPIRVTypeImage(this, getId(),
+ SampledType ? SampledType->getId() : 0, Desc, Acc));
+}
+
+SPIRVTypeSampler *
+SPIRVModuleImpl::addSamplerType() {
+ return addType(new SPIRVTypeSampler(this, getId()));
+}
+
+SPIRVTypePipeStorage*
+SPIRVModuleImpl::addPipeStorageType() {
+ return addType(new SPIRVTypePipeStorage(this, getId()));
+}
+
+SPIRVTypeSampledImage *
+SPIRVModuleImpl::addSampledImageType(SPIRVTypeImage *T) {
+ return addType(new SPIRVTypeSampledImage(this, getId(), T));
+}
+
+void SPIRVModuleImpl::createForwardPointers() {
+ std::unordered_set<SPIRVId> Seen;
+
+ for (auto *T : TypeVec) {
+ if (T->hasId())
+ Seen.insert(T->getId());
+
+ if (!T->isTypeStruct())
+ continue;
+
+ auto ST = static_cast<SPIRVTypeStruct *>(T);
+
+ for (unsigned i = 0; i < ST->getStructMemberCount(); ++i) {
+ auto MemberTy = ST->getStructMemberType(i);
+ if (!MemberTy->isTypePointer()) continue;
+ auto Ptr = static_cast<SPIRVTypePointer *>(MemberTy);
+
+ if (Seen.find(Ptr->getId()) == Seen.end()) {
+ ForwardPointerVec.push_back(new SPIRVTypeForwardPointer(
+ this, Ptr, Ptr->getPointerStorageClass()));
+ }
+ }
+ }
+}
+
+SPIRVFunction *
+SPIRVModuleImpl::addFunction(SPIRVFunction *Func) {
+ FuncVec.push_back(add(Func));
+ return Func;
+}
+
+SPIRVFunction *
+SPIRVModuleImpl::addFunction(SPIRVTypeFunction *FuncType, SPIRVId Id) {
+ return addFunction(new SPIRVFunction(this, FuncType,
+ getId(Id, FuncType->getNumParameters() + 1)));
+}
+
+SPIRVBasicBlock *
+SPIRVModuleImpl::addBasicBlock(SPIRVFunction *Func, SPIRVId Id) {
+ return Func->addBasicBlock(new SPIRVBasicBlock(getId(Id), Func));
+}
+
+const SPIRVDecorateGeneric *
+SPIRVModuleImpl::addDecorate(SPIRVDecorateGeneric *Dec) {
+ add(Dec);
+ SPIRVId Id = Dec->getTargetId();
+ bool Found = exist(Id);
(void)Found;
- assert (Found && "Decorate target does not exist");
- if (!Dec->getOwner())
- DecorateSet.insert(Dec);
- addCapabilities(Dec->getRequiredCapability());
- return Dec;
-}
-
-void
-SPIRVModuleImpl::addEntryPoint(SPIRVExecutionModelKind ExecModel,
- SPIRVId EntryPoint){
- assert(isValid(ExecModel) && "Invalid execution model");
- assert(EntryPoint != SPIRVID_INVALID && "Invalid entry point");
- EntryPointSet[ExecModel].insert(EntryPoint);
- EntryPointVec[ExecModel].push_back(EntryPoint);
- addCapabilities(SPIRV::getCapability(ExecModel));
-}
-
-SPIRVForward *
-SPIRVModuleImpl::addForward(SPIRVType *Ty) {
- return add(new SPIRVForward(this, Ty, getId()));
-}
-
-SPIRVForward *
-SPIRVModuleImpl::addForward(SPIRVId Id, SPIRVType *Ty) {
- return add(new SPIRVForward(this, Ty, Id));
-}
-
-SPIRVEntry *
-SPIRVModuleImpl::replaceForward(SPIRVForward *Forward, SPIRVEntry *Entry) {
- SPIRVId Id = Entry->getId();
- SPIRVId ForwardId = Forward->getId();
- if (ForwardId == Id)
- IdEntryMap[Id] = Entry;
- else {
- auto Loc = IdEntryMap.find(Id);
- assert(Loc != IdEntryMap.end());
- IdEntryMap.erase(Loc);
- Entry->setId(ForwardId);
- IdEntryMap[ForwardId] = Entry;
- }
- // Annotations include name, decorations, execution modes
- Entry->takeAnnotations(Forward);
- delete Forward;
- return Entry;
-}
-
-void
-SPIRVModuleImpl::eraseInstruction(SPIRVInstruction *I, SPIRVBasicBlock *BB) {
- SPIRVId Id = I->getId();
- BB->eraseInstruction(I);
- auto Loc = IdEntryMap.find(Id);
- assert(Loc != IdEntryMap.end());
- IdEntryMap.erase(Loc);
- delete I;
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addConstant(SPIRVValue *C) {
- return add(C);
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addConstant(SPIRVType *Ty, uint64_t V) {
- if (Ty->isTypeBool()) {
- if (V)
- return addConstant(new SPIRVConstantTrue(this, Ty, getId()));
- else
- return addConstant(new SPIRVConstantFalse(this, Ty, getId()));
- }
- if (Ty->isTypeInt())
- return addIntegerConstant(static_cast<SPIRVTypeInt*>(Ty), V);
- return addConstant(new SPIRVConstant(this, Ty, getId(), V));
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addIntegerConstant(SPIRVTypeInt *Ty, uint64_t V) {
- if (Ty->getBitWidth() == 32) {
+ assert (Found && "Decorate target does not exist");
+ if (!Dec->getOwner())
+ DecorateSet.insert(Dec);
+ addCapabilities(Dec->getRequiredCapability());
+ return Dec;
+}
+
+void
+SPIRVModuleImpl::addEntryPoint(SPIRVExecutionModelKind ExecModel,
+ SPIRVId EntryPoint){
+ assert(isValid(ExecModel) && "Invalid execution model");
+ assert(EntryPoint != SPIRVID_INVALID && "Invalid entry point");
+ EntryPointSet[ExecModel].insert(EntryPoint);
+ EntryPointVec[ExecModel].push_back(EntryPoint);
+ addCapabilities(SPIRV::getCapability(ExecModel));
+}
+
+SPIRVForward *
+SPIRVModuleImpl::addForward(SPIRVType *Ty) {
+ return add(new SPIRVForward(this, Ty, getId()));
+}
+
+SPIRVForward *
+SPIRVModuleImpl::addForward(SPIRVId Id, SPIRVType *Ty) {
+ return add(new SPIRVForward(this, Ty, Id));
+}
+
+SPIRVEntry *
+SPIRVModuleImpl::replaceForward(SPIRVForward *Forward, SPIRVEntry *Entry) {
+ SPIRVId Id = Entry->getId();
+ SPIRVId ForwardId = Forward->getId();
+ if (ForwardId == Id)
+ IdEntryMap[Id] = Entry;
+ else {
+ auto Loc = IdEntryMap.find(Id);
+ assert(Loc != IdEntryMap.end());
+ IdEntryMap.erase(Loc);
+ Entry->setId(ForwardId);
+ IdEntryMap[ForwardId] = Entry;
+ }
+ // Annotations include name, decorations, execution modes
+ Entry->takeAnnotations(Forward);
+ delete Forward;
+ return Entry;
+}
+
+void
+SPIRVModuleImpl::eraseInstruction(SPIRVInstruction *I, SPIRVBasicBlock *BB) {
+ SPIRVId Id = I->getId();
+ BB->eraseInstruction(I);
+ auto Loc = IdEntryMap.find(Id);
+ assert(Loc != IdEntryMap.end());
+ IdEntryMap.erase(Loc);
+ delete I;
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addConstant(SPIRVValue *C) {
+ return add(C);
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addConstant(SPIRVType *Ty, uint64_t V) {
+ if (Ty->isTypeBool()) {
+ if (V)
+ return addConstant(new SPIRVConstantTrue(this, Ty, getId()));
+ else
+ return addConstant(new SPIRVConstantFalse(this, Ty, getId()));
+ }
+ if (Ty->isTypeInt())
+ return addIntegerConstant(static_cast<SPIRVTypeInt*>(Ty), V);
+ return addConstant(new SPIRVConstant(this, Ty, getId(), V));
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addIntegerConstant(SPIRVTypeInt *Ty, uint64_t V) {
+ if (Ty->getBitWidth() == 32) {
unsigned I32 = static_cast<unsigned>(V);
- assert(I32 == V && "Integer value truncated");
- return getLiteralAsConstant(I32);
- }
- return addConstant(new SPIRVConstant(this, Ty, getId(), V));
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addFloatConstant(SPIRVTypeFloat *Ty, float V) {
- return addConstant(new SPIRVConstant(this, Ty, getId(), V));
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addDoubleConstant(SPIRVTypeFloat *Ty, double V) {
- return addConstant(new SPIRVConstant(this, Ty, getId(), V));
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addNullConstant(SPIRVType *Ty) {
- return addConstant(new SPIRVConstantNull(this, Ty, getId()));
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addCompositeConstant(SPIRVType *Ty,
- const std::vector<SPIRVValue*>& Elements) {
- return addConstant(new SPIRVConstantComposite(this, Ty, getId(), Elements));
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addUndef(SPIRVType *TheType) {
- return addConstant(new SPIRVUndef(this, TheType, getId()));
-}
-
-// Instruction creation functions
-
-SPIRVInstruction *
-SPIRVModuleImpl::addStoreInst(SPIRVValue *Target, SPIRVValue *Source,
- const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
- return BB->addInstruction(new SPIRVStore(Target->getId(),
- Source->getId(), TheMemoryAccess, BB));
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addSwitchInst(SPIRVValue *Select, SPIRVBasicBlock *Default,
- const std::vector<std::pair<std::vector<SPIRVWord>, SPIRVBasicBlock *>>& Pairs,
- SPIRVBasicBlock *BB) {
- return BB->addInstruction(new SPIRVSwitch(Select, Default, Pairs, BB));
-}
-SPIRVInstruction *
-SPIRVModuleImpl::addFModInst(SPIRVType *TheType, SPIRVId TheDividend,
- SPIRVId TheDivisor, SPIRVBasicBlock *BB) {
- return BB->addInstruction(new SPIRVFMod(TheType, getId(), TheDividend,
- TheDivisor, BB));
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addVectorTimesScalarInst(SPIRVType *TheType, SPIRVId TheVector,
- SPIRVId TheScalar, SPIRVBasicBlock *BB) {
- return BB->addInstruction(new SPIRVVectorTimesScalar(TheType, getId(),
- TheVector, TheScalar, BB));
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addGroupInst(Op OpCode, SPIRVType *Type,
- Scope Scope, const std::vector<SPIRVValue *> &Ops,
- SPIRVBasicBlock *BB) {
- assert(!Type || !Type->isTypeVoid());
- auto WordOps = getIds(Ops);
- WordOps.insert(WordOps.begin(), Scope);
- return addInstTemplate(OpCode, WordOps, BB, Type);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB) {
- if (BB)
- return BB->addInstruction(Inst);
- if (Inst->getOpCode() != OpSpecConstantOp)
- Inst = createSpecConstantOpInst(Inst);
- return static_cast<SPIRVInstruction *>(addConstant(Inst));
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addLoadInst(SPIRVValue *Source,
- const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVLoad(getId(), Source->getId(),
- TheMemoryAccess, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addPhiInst(SPIRVType *Type,
- std::vector<SPIRVValue *> IncomingPairs, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVPhi(Type, getId(), IncomingPairs, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addExtInst(SPIRVType *TheType, SPIRVWord BuiltinSet,
- SPIRVWord EntryPoint, const std::vector<SPIRVWord> &Args,
- SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVExtInst(TheType, getId(),
- BuiltinSet, EntryPoint, Args, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addExtInst(SPIRVType *TheType, SPIRVWord BuiltinSet,
- SPIRVWord EntryPoint, const std::vector<SPIRVValue *> &Args,
- SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVExtInst(TheType, getId(),
- BuiltinSet, EntryPoint, Args, BB), BB);
-}
-
-SPIRVInstruction*
-SPIRVModuleImpl::addCallInst(SPIRVFunction* TheFunction,
- const std::vector<SPIRVWord> &TheArguments, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVFunctionCall(getId(), TheFunction,
- TheArguments, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addBinaryInst(Op TheOpCode, SPIRVType *Type,
- SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB){
- return addInstruction(SPIRVInstTemplateBase::create(TheOpCode, Type, getId(),
- getVec(Op1->getId(), Op2->getId()), BB, this), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addUnreachableInst(SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVUnreachable(BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addReturnInst(SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVReturn(BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addReturnValueInst(SPIRVValue *ReturnValue, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVReturnValue(ReturnValue, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addUnaryInst(Op TheOpCode, SPIRVType *TheType,
- SPIRVValue *Op, SPIRVBasicBlock *BB) {
- return addInstruction(SPIRVInstTemplateBase::create(TheOpCode,
- TheType, getId(), getVec(Op->getId()), BB, this), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addVectorExtractDynamicInst(SPIRVValue *TheVector,
- SPIRVValue *Index, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVVectorExtractDynamic(getId(), TheVector,
- Index, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addVectorInsertDynamicInst(SPIRVValue *TheVector,
-SPIRVValue *TheComponent, SPIRVValue*Index, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVVectorInsertDynamic(getId(), TheVector,
- TheComponent, Index, BB), BB);
-}
-
-SPIRVValue *
-SPIRVModuleImpl::addVectorShuffleInst(SPIRVType * Type, SPIRVValue *Vec1,
- SPIRVValue *Vec2, const std::vector<SPIRVWord> &Components,
- SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVVectorShuffle(getId(), Type, Vec1, Vec2,
- Components, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addBranchInst(SPIRVLabel *TargetLabel, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVBranch(TargetLabel, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addBranchConditionalInst(SPIRVValue *Condition,
- SPIRVLabel *TrueLabel, SPIRVLabel *FalseLabel, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVBranchConditional(Condition, TrueLabel,
- FalseLabel, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addCmpInst(Op TheOpCode, SPIRVType *TheType,
- SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB) {
- return addInstruction(SPIRVInstTemplateBase::create(TheOpCode,
- TheType, getId(), getVec(Op1->getId(), Op2->getId()), BB, this), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addControlBarrierInst(SPIRVValue *ExecKind,
- SPIRVValue *MemKind, SPIRVValue *MemSema, SPIRVBasicBlock *BB) {
- return addInstruction(
- new SPIRVControlBarrier(ExecKind, MemKind, MemSema, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addLifetimeInst(Op OC, SPIRVValue *Object, SPIRVWord Size,
- SPIRVBasicBlock *BB) {
- if(OC == OpLifetimeStart)
- return BB->addInstruction(new SPIRVLifetimeStart(Object->getId(),
- Size, BB));
- else
- return BB->addInstruction(new SPIRVLifetimeStop(Object->getId(),
- Size, BB));
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addMemoryBarrierInst(Scope ScopeKind,
- SPIRVWord MemFlag, SPIRVBasicBlock *BB) {
- return addInstruction(SPIRVInstTemplateBase::create(OpMemoryBarrier,
- nullptr, SPIRVID_INVALID,
- getVec(static_cast<SPIRVWord>(ScopeKind), MemFlag), BB, this), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addSelectInst(SPIRVValue *Condition, SPIRVValue *Op1,
- SPIRVValue *Op2, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVSelect(getId(), Condition->getId(),
- Op1->getId(), Op2->getId(), BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addSelectionMergeInst(SPIRVId MergeBlock,
- SPIRVWord SelectionControl, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVSelectionMerge(MergeBlock, SelectionControl, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addLoopMergeInst(SPIRVId MergeBlock, SPIRVId ContinueTarget,
- SPIRVWord LoopControl, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVLoopMerge(MergeBlock, ContinueTarget,
- LoopControl, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addPtrAccessChainInst(SPIRVType *Type, SPIRVValue *Base,
- std::vector<SPIRVValue *> Indices, SPIRVBasicBlock *BB, bool IsInBounds){
- return addInstruction(SPIRVInstTemplateBase::create(
- IsInBounds?OpInBoundsPtrAccessChain:OpPtrAccessChain,
- Type, getId(), getVec(Base->getId(), Base->getIds(Indices)),
- BB, this), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addAsyncGroupCopy(SPIRVValue *Scope,
- SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride,
- SPIRVValue *Event, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVGroupAsyncCopy(Scope, getId(), Dest, Src,
- NumElems, Stride, Event, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addCompositeConstructInst(SPIRVType *Type,
- const std::vector<SPIRVId>& Constituents, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVCompositeConstruct(Type, getId(),
- Constituents, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addCompositeExtractInst(SPIRVType *Type, SPIRVValue *TheVector,
- const std::vector<SPIRVWord>& Indices, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVCompositeExtract(Type, getId(), TheVector,
- Indices, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addCompositeInsertInst(SPIRVValue *Object,
- SPIRVValue *Composite, const std::vector<SPIRVWord>& Indices,
- SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVCompositeInsert(getId(), Object, Composite,
- Indices, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addCopyObjectInst(SPIRVType *TheType, SPIRVValue *Operand,
- SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVCopyObject(TheType, getId(), Operand, BB), BB);
-
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addCopyMemoryInst(SPIRVValue *TheTarget, SPIRVValue *TheSource,
- const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVCopyMemory(TheTarget, TheSource,
- TheMemoryAccess, BB), BB);
-}
-
-SPIRVInstruction *
-SPIRVModuleImpl::addCopyMemorySizedInst(SPIRVValue *TheTarget,
- SPIRVValue *TheSource, SPIRVValue *TheSize,
- const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
- return addInstruction(new SPIRVCopyMemorySized(TheTarget, TheSource, TheSize,
- TheMemoryAccess, BB), BB);
-}
-
-SPIRVInstruction*
-SPIRVModuleImpl::addVariable(SPIRVType *Type, bool IsConstant,
- SPIRVLinkageTypeKind LinkageType, SPIRVValue *Initializer,
- const std::string &Name, SPIRVStorageClassKind StorageClass,
- SPIRVBasicBlock *BB) {
- SPIRVVariable *Variable = new SPIRVVariable(Type, getId(), Initializer,
- Name, StorageClass, BB, this);
- if (BB)
- return addInstruction(Variable, BB);
-
- add(Variable);
- if (LinkageType != LinkageTypeInternal)
- Variable->setLinkageType(LinkageType);
- Variable->setIsConstant(IsConstant);
- return Variable;
-}
-
-template<class T>
-spv_ostream &
-operator<< (spv_ostream &O, const std::vector<T *>& V) {
- for (auto &I: V)
- O << *I;
- return O;
-}
-
-template<class T, class B>
-spv_ostream &
-operator<< (spv_ostream &O, const std::multiset<T *, B>& V) {
- for (auto &I: V)
- O << *I;
- return O;
-}
-
-// To satisfy SPIR-V spec requirement:
-// "All operands must be declared before being used",
-// we do DFS based topological sort
-// https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
-class TopologicalSort {
- enum DFSState : char {
- Unvisited,
- Discovered,
- Visited
- };
- typedef std::vector<SPIRVType *> SPIRVTypeVec;
- typedef std::vector<SPIRVValue *> SPIRVConstantVector;
- typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
- typedef std::vector<SPIRVEntry *> SPIRVConstAndVarVec;
- typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
- typedef std::function<bool(SPIRVEntry*, SPIRVEntry*)> IdComp;
- typedef std::map<SPIRVEntry*, DFSState, IdComp> EntryStateMapTy;
-
- SPIRVTypeVec TypeIntVec;
- SPIRVConstantVector ConstIntVec;
- SPIRVTypeVec TypeVec;
- SPIRVConstAndVarVec ConstAndVarVec;
- const SPIRVForwardPointerVec& ForwardPointerVec;
- EntryStateMapTy EntryStateMap;
-
- friend spv_ostream & operator<<(spv_ostream &O, const TopologicalSort &S);
-
-// This method implements recursive depth-first search among all Entries in
-// EntryStateMap. Traversing entries and adding them to corresponding container
-// after visiting all dependent entries(post-order traversal) guarantees that
-// the entry's operands will appear in the container before the entry itslef.
- void visit(SPIRVEntry* E) {
- DFSState& State = EntryStateMap[E];
- assert(State != Discovered && "Cyclic dependency detected");
- if (State == Visited)
- return;
- State = Discovered;
- for (SPIRVEntry *Op : E->getNonLiteralOperands()) {
- auto Comp = [&Op](SPIRVTypeForwardPointer *FwdPtr) {
- return FwdPtr->getPointer() == Op;
- };
- // Skip forward referenced pointers
- if (Op->getOpCode() == OpTypePointer &&
- find_if(ForwardPointerVec.begin(), ForwardPointerVec.end(), Comp) !=
- ForwardPointerVec.end())
- continue;
- visit(Op);
- }
- State = Visited;
- Op OC = E->getOpCode();
- if (OC == OpTypeInt)
- TypeIntVec.push_back(static_cast<SPIRVType*>(E));
- else if (isConstantOpCode(OC)) {
- SPIRVConstant *C = static_cast<SPIRVConstant*>(E);
- if (C->getType()->isTypeInt())
- ConstIntVec.push_back(C);
- else
- ConstAndVarVec.push_back(E);
- } else if (isTypeOpCode(OC))
- TypeVec.push_back(static_cast<SPIRVType*>(E));
- else
- ConstAndVarVec.push_back(E);
- }
-public:
- TopologicalSort(const SPIRVTypeVec &_TypeVec,
- const SPIRVConstantVector &_ConstVec,
- const SPIRVVariableVec &_VariableVec,
- const SPIRVForwardPointerVec &_ForwardPointerVec) :
- ForwardPointerVec(_ForwardPointerVec),
- EntryStateMap([](SPIRVEntry* a, SPIRVEntry* b) -> bool {
- return a->getId() < b->getId();
- })
- {
- // Collect entries for sorting
- for (auto *T : _TypeVec)
- EntryStateMap[T] = DFSState::Unvisited;
- for (auto *C : _ConstVec)
- EntryStateMap[C] = DFSState::Unvisited;
- for (auto *V : _VariableVec)
- EntryStateMap[V] = DFSState::Unvisited;
- // Run topoligical sort
- for (auto ES : EntryStateMap)
- visit(ES.first);
- }
-};
-
-spv_ostream &
-operator<< (spv_ostream &O, const TopologicalSort &S) {
- O << S.TypeIntVec
- << S.ConstIntVec
- << S.TypeVec
- << S.ConstAndVarVec;
- return O;
-}
-
-spv_ostream &
-operator<< (spv_ostream &O, SPIRVModule &M) {
- SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl*>(&M);
-
- SPIRVEncoder Encoder(O);
- Encoder << MagicNumber
- << MI.SPIRVVersion
- << (((SPIRVWord)MI.GeneratorId << 16) | MI.GeneratorVer)
- << MI.NextId /* Bound for Id */
- << MI.InstSchema;
- O << SPIRVNL();
-
- for (auto &I:MI.CapMap)
- O << *I.second;
-
- for (auto &I:M.getExtension()) {
- assert(!I.empty() && "Invalid extension");
- O << SPIRVExtension(&M, I);
- }
-
- for (auto &I:MI.IdBuiltinMap)
- O << SPIRVExtInstImport(&M, I.first, SPIRVBuiltinSetNameMap::map(I.second));
-
- O << SPIRVMemoryModel(&M);
-
- for (auto &I:MI.EntryPointVec)
- for (auto &II:I.second)
- O << SPIRVEntryPoint(&M, I.first, II,
- M.get<SPIRVFunction>(II)->getName());
-
- for (auto &I:MI.EntryPointVec)
- for (auto &II:I.second)
- MI.get<SPIRVFunction>(II)->encodeExecutionModes(O);
-
- O << MI.StringVec;
-
- for (auto &I:M.getSourceExtension()) {
- assert(!I.empty() && "Invalid source extension");
- O << SPIRVSourceExtension(&M, I);
- }
-
- O << SPIRVSource(&M);
-
- for (auto &I:MI.NamedId) {
- // Don't output name for entry point since it is redundant
- bool IsEntryPoint = false;
- for (auto &EPS:MI.EntryPointSet)
- if (EPS.second.count(I)) {
- IsEntryPoint = true;
- break;
- }
- if (!IsEntryPoint)
- M.getEntry(I)->encodeName(O);
- }
-
- O << MI.MemberNameVec
- << MI.DecGroupVec
- << MI.DecorateSet
- << MI.GroupDecVec
- << MI.ForwardPointerVec
- << TopologicalSort(MI.TypeVec, MI.ConstVec, MI.VariableVec,
- MI.ForwardPointerVec)
- << SPIRVNL()
- << MI.FuncVec;
- return O;
-}
-
-template<class T>
-void SPIRVModuleImpl::addTo(std::vector<T*>& V, SPIRVEntry* E) {
- V.push_back(static_cast<T *>(E));
-}
-
-// The first decoration group includes all the previously defined decorates.
-// The second decoration group includes all the decorates defined between the
-// first and second decoration group. So long so forth.
-SPIRVDecorationGroup*
-SPIRVModuleImpl::addDecorationGroup() {
- return addDecorationGroup(new SPIRVDecorationGroup(this, getId()));
-}
-
-SPIRVDecorationGroup*
-SPIRVModuleImpl::addDecorationGroup(SPIRVDecorationGroup* Group) {
- add(Group);
- Group->takeDecorates(DecorateSet);
- DecGroupVec.push_back(Group);
- SPIRVDBG(spvdbgs() << "[addDecorationGroup] {" << *Group << "}\n";
- spvdbgs() << " Remaining DecorateSet: {" << DecorateSet << "}\n");
- assert(DecorateSet.empty());
- return Group;
-}
-
-SPIRVGroupDecorateGeneric*
-SPIRVModuleImpl::addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) {
- add(GDec);
- GDec->decorateTargets();
- GroupDecVec.push_back(GDec);
- return GDec;
-}
-SPIRVGroupDecorate*
-SPIRVModuleImpl::addGroupDecorate(
- SPIRVDecorationGroup* Group, const std::vector<SPIRVEntry*>& Targets) {
- auto GD = new SPIRVGroupDecorate(Group, getIds(Targets));
- addGroupDecorateGeneric(GD);
- return GD;
-}
-
-SPIRVGroupMemberDecorate*
-SPIRVModuleImpl::addGroupMemberDecorate(
- SPIRVDecorationGroup* Group, const std::vector<SPIRVEntry*>& Targets) {
- auto GMD = new SPIRVGroupMemberDecorate(Group, getIds(Targets));
- addGroupDecorateGeneric(GMD);
- return GMD;
-}
-
-SPIRVString*
-SPIRVModuleImpl::getString(const std::string& Str) {
- auto Loc = StrMap.find(Str);
- if (Loc != StrMap.end())
- return Loc->second;
- auto S = add(new SPIRVString(this, getId(), Str));
- StrMap[Str] = S;
- return S;
-}
-
-SPIRVMemberName*
-SPIRVModuleImpl::addMemberName(SPIRVTypeStruct* ST,
- SPIRVWord MemberNumber, const std::string& Name) {
- return add(new SPIRVMemberName(ST, MemberNumber, Name));
-}
-
-void SPIRVModuleImpl::addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
- SPIRVId ID) {
- UnknownStructFieldMap[Struct].push_back(std::make_pair(I, ID));
-}
-
-std::istream &
-operator>> (std::istream &I, SPIRVModule &M) {
- SPIRVDecoder Decoder(I, M);
- SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl*>(&M);
- // Disable automatic capability filling.
- MI.setAutoAddCapability(false);
-
- SPIRVWord Magic;
- Decoder >> Magic;
- assert(Magic == MagicNumber && "Invalid magic number");
-
- Decoder >> MI.SPIRVVersion;
- assert(MI.SPIRVVersion <= SPV_VERSION && "Unsupported SPIRV version number");
-
- SPIRVWord Generator = 0;
- Decoder >> Generator;
- MI.GeneratorId = Generator >> 16;
- MI.GeneratorVer = Generator & 0xFFFF;
-
- // Bound for Id
- Decoder >> MI.NextId;
-
- Decoder >> MI.InstSchema;
- assert(MI.InstSchema == SPIRVISCH_Default && "Unsupported instruction schema");
-
- while (Decoder.getWordCountAndOpCode()) {
- SPIRVEntry *Entry = Decoder.getEntry();
- if (Entry != nullptr)
- M.add(Entry);
- }
-
- MI.optimizeDecorates();
- MI.resolveUnknownStructFields();
- MI.createForwardPointers();
- return I;
-}
-
-SPIRVModule *
-SPIRVModule::createSPIRVModule() {
- return new SPIRVModuleImpl;
-}
-
-SPIRVValue *
-SPIRVModuleImpl::getValue(SPIRVId TheId)const {
- return get<SPIRVValue>(TheId);
-}
-
-SPIRVType *
-SPIRVModuleImpl::getValueType(SPIRVId TheId)const {
- return get<SPIRVValue>(TheId)->getType();
-}
-
-std::vector<SPIRVValue *>
-SPIRVModuleImpl::getValues(const std::vector<SPIRVId>& IdVec)const {
- std::vector<SPIRVValue *> ValueVec;
- for (auto i:IdVec)
- ValueVec.push_back(getValue(i));
- return ValueVec;
-}
-
-std::vector<SPIRVType *>
-SPIRVModuleImpl::getValueTypes(const std::vector<SPIRVId>& IdVec)const {
- std::vector<SPIRVType *> TypeVec;
- for (auto i:IdVec)
- TypeVec.push_back(getValue(i)->getType());
- return TypeVec;
-}
-
-std::vector<SPIRVId>
-SPIRVModuleImpl::getIds(const std::vector<SPIRVEntry *> &ValueVec)const {
- std::vector<SPIRVId> IdVec;
- for (auto i:ValueVec)
- IdVec.push_back(i->getId());
- return IdVec;
-}
-
-std::vector<SPIRVId>
-SPIRVModuleImpl::getIds(const std::vector<SPIRVValue *> &ValueVec)const {
- std::vector<SPIRVId> IdVec;
- for (auto i:ValueVec)
- IdVec.push_back(i->getId());
- return IdVec;
-}
-
-SPIRVInstTemplateBase*
-SPIRVModuleImpl::addInstTemplate(Op OC,
- SPIRVBasicBlock* BB, SPIRVType *Ty) {
- assert (!Ty || !Ty->isTypeVoid());
- SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
- auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, BB, this);
- BB->addInstruction(Ins);
- return Ins;
-}
-
-SPIRVInstTemplateBase*
-SPIRVModuleImpl::addInstTemplate(Op OC,
- const std::vector<SPIRVWord>& Ops, SPIRVBasicBlock* BB, SPIRVType *Ty) {
- assert (!Ty || !Ty->isTypeVoid());
- SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
- auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, Ops, BB, this);
- BB->addInstruction(Ins);
- return Ins;
-}
-
-SPIRVDbgInfo::SPIRVDbgInfo(SPIRVModule *TM)
-:M(TM){
-}
-
-std::string
-SPIRVDbgInfo::getEntryPointFileStr(SPIRVExecutionModelKind EM, unsigned I) {
- if (M->getNumEntryPoints(EM) == 0)
- return "";
- return getFunctionFileStr(M->getEntryPoint(EM, I));
-}
-
-std::string
-SPIRVDbgInfo::getFunctionFileStr(SPIRVFunction *F) {
- if (F->hasLine())
- return F->getLine()->getFileNameStr();
- return "";
-}
-
-unsigned
-SPIRVDbgInfo::getFunctionLineNo(SPIRVFunction *F) {
- if (F->hasLine())
- return F->getLine()->getLine();
- return 0;
-}
-
-bool IsSPIRVBinary(const std::string &Img) {
- if (Img.size() < sizeof(unsigned))
- return false;
- auto Magic = reinterpret_cast<const unsigned*>(Img.data());
- return *Magic == MagicNumber;
-}
-
-#ifdef _SPIRV_SUPPORT_TEXT_FMT
-
-bool ConvertSPIRV(std::istream &IS, spv_ostream &OS,
- std::string &ErrMsg, bool FromText, bool ToText) {
- auto SaveOpt = SPIRVUseTextFormat;
- SPIRVUseTextFormat = FromText;
- SPIRVModuleImpl M;
- IS >> M;
- if (M.getError(ErrMsg) != SPIRVEC_Success) {
- SPIRVUseTextFormat = SaveOpt;
- return false;
- }
- SPIRVUseTextFormat = ToText;
- OS << M;
- if (M.getError(ErrMsg) != SPIRVEC_Success) {
- SPIRVUseTextFormat = SaveOpt;
- return false;
- }
- SPIRVUseTextFormat = SaveOpt;
- return true;
-}
-
-bool IsSPIRVText(const std::string &Img) {
- std::istringstream SS(Img);
- unsigned Magic = 0;
- SS >> Magic;
- if (SS.bad())
- return false;
- return Magic == MagicNumber;
-}
-
-bool ConvertSPIRV(std::string &Input, std::string &Out,
- std::string &ErrMsg, bool ToText) {
- auto FromText = IsSPIRVText(Input);
- if (ToText == FromText) {
- Out = Input;
- return true;
- }
- std::istringstream IS(Input);
-#ifdef _SPIRV_LLVM_API
- llvm::raw_string_ostream OS(Out);
-#else
- std::ostringstream OS;
-#endif
- if (!ConvertSPIRV(IS, OS, ErrMsg, FromText, ToText))
- return false;
- Out = OS.str();
- return true;
-}
-
-#endif // _SPIRV_SUPPORT_TEXT_FMT
-
-}
-
+ assert(I32 == V && "Integer value truncated");
+ return getLiteralAsConstant(I32);
+ }
+ return addConstant(new SPIRVConstant(this, Ty, getId(), V));
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addFloatConstant(SPIRVTypeFloat *Ty, float V) {
+ return addConstant(new SPIRVConstant(this, Ty, getId(), V));
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addDoubleConstant(SPIRVTypeFloat *Ty, double V) {
+ return addConstant(new SPIRVConstant(this, Ty, getId(), V));
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addNullConstant(SPIRVType *Ty) {
+ return addConstant(new SPIRVConstantNull(this, Ty, getId()));
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addCompositeConstant(SPIRVType *Ty,
+ const std::vector<SPIRVValue*>& Elements) {
+ return addConstant(new SPIRVConstantComposite(this, Ty, getId(), Elements));
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addUndef(SPIRVType *TheType) {
+ return addConstant(new SPIRVUndef(this, TheType, getId()));
+}
+
+// Instruction creation functions
+
+SPIRVInstruction *
+SPIRVModuleImpl::addStoreInst(SPIRVValue *Target, SPIRVValue *Source,
+ const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
+ return BB->addInstruction(new SPIRVStore(Target->getId(),
+ Source->getId(), TheMemoryAccess, BB));
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addSwitchInst(SPIRVValue *Select, SPIRVBasicBlock *Default,
+ const std::vector<std::pair<std::vector<SPIRVWord>, SPIRVBasicBlock *>>& Pairs,
+ SPIRVBasicBlock *BB) {
+ return BB->addInstruction(new SPIRVSwitch(Select, Default, Pairs, BB));
+}
+SPIRVInstruction *
+SPIRVModuleImpl::addFModInst(SPIRVType *TheType, SPIRVId TheDividend,
+ SPIRVId TheDivisor, SPIRVBasicBlock *BB) {
+ return BB->addInstruction(new SPIRVFMod(TheType, getId(), TheDividend,
+ TheDivisor, BB));
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addVectorTimesScalarInst(SPIRVType *TheType, SPIRVId TheVector,
+ SPIRVId TheScalar, SPIRVBasicBlock *BB) {
+ return BB->addInstruction(new SPIRVVectorTimesScalar(TheType, getId(),
+ TheVector, TheScalar, BB));
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addGroupInst(Op OpCode, SPIRVType *Type,
+ Scope Scope, const std::vector<SPIRVValue *> &Ops,
+ SPIRVBasicBlock *BB) {
+ assert(!Type || !Type->isTypeVoid());
+ auto WordOps = getIds(Ops);
+ WordOps.insert(WordOps.begin(), Scope);
+ return addInstTemplate(OpCode, WordOps, BB, Type);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB) {
+ if (BB)
+ return BB->addInstruction(Inst);
+ if (Inst->getOpCode() != OpSpecConstantOp)
+ Inst = createSpecConstantOpInst(Inst);
+ return static_cast<SPIRVInstruction *>(addConstant(Inst));
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addLoadInst(SPIRVValue *Source,
+ const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVLoad(getId(), Source->getId(),
+ TheMemoryAccess, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addPhiInst(SPIRVType *Type,
+ std::vector<SPIRVValue *> IncomingPairs, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVPhi(Type, getId(), IncomingPairs, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addExtInst(SPIRVType *TheType, SPIRVWord BuiltinSet,
+ SPIRVWord EntryPoint, const std::vector<SPIRVWord> &Args,
+ SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVExtInst(TheType, getId(),
+ BuiltinSet, EntryPoint, Args, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addExtInst(SPIRVType *TheType, SPIRVWord BuiltinSet,
+ SPIRVWord EntryPoint, const std::vector<SPIRVValue *> &Args,
+ SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVExtInst(TheType, getId(),
+ BuiltinSet, EntryPoint, Args, BB), BB);
+}
+
+SPIRVInstruction*
+SPIRVModuleImpl::addCallInst(SPIRVFunction* TheFunction,
+ const std::vector<SPIRVWord> &TheArguments, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVFunctionCall(getId(), TheFunction,
+ TheArguments, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addBinaryInst(Op TheOpCode, SPIRVType *Type,
+ SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB){
+ return addInstruction(SPIRVInstTemplateBase::create(TheOpCode, Type, getId(),
+ getVec(Op1->getId(), Op2->getId()), BB, this), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addUnreachableInst(SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVUnreachable(BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addReturnInst(SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVReturn(BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addReturnValueInst(SPIRVValue *ReturnValue, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVReturnValue(ReturnValue, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addUnaryInst(Op TheOpCode, SPIRVType *TheType,
+ SPIRVValue *Op, SPIRVBasicBlock *BB) {
+ return addInstruction(SPIRVInstTemplateBase::create(TheOpCode,
+ TheType, getId(), getVec(Op->getId()), BB, this), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addVectorExtractDynamicInst(SPIRVValue *TheVector,
+ SPIRVValue *Index, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVVectorExtractDynamic(getId(), TheVector,
+ Index, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addVectorInsertDynamicInst(SPIRVValue *TheVector,
+SPIRVValue *TheComponent, SPIRVValue*Index, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVVectorInsertDynamic(getId(), TheVector,
+ TheComponent, Index, BB), BB);
+}
+
+SPIRVValue *
+SPIRVModuleImpl::addVectorShuffleInst(SPIRVType * Type, SPIRVValue *Vec1,
+ SPIRVValue *Vec2, const std::vector<SPIRVWord> &Components,
+ SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVVectorShuffle(getId(), Type, Vec1, Vec2,
+ Components, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addBranchInst(SPIRVLabel *TargetLabel, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVBranch(TargetLabel, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addBranchConditionalInst(SPIRVValue *Condition,
+ SPIRVLabel *TrueLabel, SPIRVLabel *FalseLabel, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVBranchConditional(Condition, TrueLabel,
+ FalseLabel, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addCmpInst(Op TheOpCode, SPIRVType *TheType,
+ SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB) {
+ return addInstruction(SPIRVInstTemplateBase::create(TheOpCode,
+ TheType, getId(), getVec(Op1->getId(), Op2->getId()), BB, this), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addControlBarrierInst(SPIRVValue *ExecKind,
+ SPIRVValue *MemKind, SPIRVValue *MemSema, SPIRVBasicBlock *BB) {
+ return addInstruction(
+ new SPIRVControlBarrier(ExecKind, MemKind, MemSema, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addLifetimeInst(Op OC, SPIRVValue *Object, SPIRVWord Size,
+ SPIRVBasicBlock *BB) {
+ if(OC == OpLifetimeStart)
+ return BB->addInstruction(new SPIRVLifetimeStart(Object->getId(),
+ Size, BB));
+ else
+ return BB->addInstruction(new SPIRVLifetimeStop(Object->getId(),
+ Size, BB));
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addMemoryBarrierInst(Scope ScopeKind,
+ SPIRVWord MemFlag, SPIRVBasicBlock *BB) {
+ return addInstruction(SPIRVInstTemplateBase::create(OpMemoryBarrier,
+ nullptr, SPIRVID_INVALID,
+ getVec(static_cast<SPIRVWord>(ScopeKind), MemFlag), BB, this), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addSelectInst(SPIRVValue *Condition, SPIRVValue *Op1,
+ SPIRVValue *Op2, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVSelect(getId(), Condition->getId(),
+ Op1->getId(), Op2->getId(), BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addSelectionMergeInst(SPIRVId MergeBlock,
+ SPIRVWord SelectionControl, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVSelectionMerge(MergeBlock, SelectionControl, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addLoopMergeInst(SPIRVId MergeBlock, SPIRVId ContinueTarget,
+ SPIRVWord LoopControl, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVLoopMerge(MergeBlock, ContinueTarget,
+ LoopControl, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addPtrAccessChainInst(SPIRVType *Type, SPIRVValue *Base,
+ std::vector<SPIRVValue *> Indices, SPIRVBasicBlock *BB, bool IsInBounds){
+ return addInstruction(SPIRVInstTemplateBase::create(
+ IsInBounds?OpInBoundsPtrAccessChain:OpPtrAccessChain,
+ Type, getId(), getVec(Base->getId(), Base->getIds(Indices)),
+ BB, this), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addAsyncGroupCopy(SPIRVValue *Scope,
+ SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride,
+ SPIRVValue *Event, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVGroupAsyncCopy(Scope, getId(), Dest, Src,
+ NumElems, Stride, Event, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addCompositeConstructInst(SPIRVType *Type,
+ const std::vector<SPIRVId>& Constituents, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVCompositeConstruct(Type, getId(),
+ Constituents, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addCompositeExtractInst(SPIRVType *Type, SPIRVValue *TheVector,
+ const std::vector<SPIRVWord>& Indices, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVCompositeExtract(Type, getId(), TheVector,
+ Indices, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addCompositeInsertInst(SPIRVValue *Object,
+ SPIRVValue *Composite, const std::vector<SPIRVWord>& Indices,
+ SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVCompositeInsert(getId(), Object, Composite,
+ Indices, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addCopyObjectInst(SPIRVType *TheType, SPIRVValue *Operand,
+ SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVCopyObject(TheType, getId(), Operand, BB), BB);
+
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addCopyMemoryInst(SPIRVValue *TheTarget, SPIRVValue *TheSource,
+ const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVCopyMemory(TheTarget, TheSource,
+ TheMemoryAccess, BB), BB);
+}
+
+SPIRVInstruction *
+SPIRVModuleImpl::addCopyMemorySizedInst(SPIRVValue *TheTarget,
+ SPIRVValue *TheSource, SPIRVValue *TheSize,
+ const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
+ return addInstruction(new SPIRVCopyMemorySized(TheTarget, TheSource, TheSize,
+ TheMemoryAccess, BB), BB);
+}
+
+SPIRVInstruction*
+SPIRVModuleImpl::addVariable(SPIRVType *Type, bool IsConstant,
+ SPIRVLinkageTypeKind LinkageType, SPIRVValue *Initializer,
+ const std::string &Name, SPIRVStorageClassKind StorageClass,
+ SPIRVBasicBlock *BB) {
+ SPIRVVariable *Variable = new SPIRVVariable(Type, getId(), Initializer,
+ Name, StorageClass, BB, this);
+ if (BB)
+ return addInstruction(Variable, BB);
+
+ add(Variable);
+ if (LinkageType != LinkageTypeInternal)
+ Variable->setLinkageType(LinkageType);
+ Variable->setIsConstant(IsConstant);
+ return Variable;
+}
+
+template<class T>
+spv_ostream &
+operator<< (spv_ostream &O, const std::vector<T *>& V) {
+ for (auto &I: V)
+ O << *I;
+ return O;
+}
+
+template<class T, class B>
+spv_ostream &
+operator<< (spv_ostream &O, const std::multiset<T *, B>& V) {
+ for (auto &I: V)
+ O << *I;
+ return O;
+}
+
+// To satisfy SPIR-V spec requirement:
+// "All operands must be declared before being used",
+// we do DFS based topological sort
+// https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
+class TopologicalSort {
+ enum DFSState : char {
+ Unvisited,
+ Discovered,
+ Visited
+ };
+ typedef std::vector<SPIRVType *> SPIRVTypeVec;
+ typedef std::vector<SPIRVValue *> SPIRVConstantVector;
+ typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
+ typedef std::vector<SPIRVEntry *> SPIRVConstAndVarVec;
+ typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
+ typedef std::function<bool(SPIRVEntry*, SPIRVEntry*)> IdComp;
+ typedef std::map<SPIRVEntry*, DFSState, IdComp> EntryStateMapTy;
+
+ SPIRVTypeVec TypeIntVec;
+ SPIRVConstantVector ConstIntVec;
+ SPIRVTypeVec TypeVec;
+ SPIRVConstAndVarVec ConstAndVarVec;
+ const SPIRVForwardPointerVec& ForwardPointerVec;
+ EntryStateMapTy EntryStateMap;
+
+ friend spv_ostream & operator<<(spv_ostream &O, const TopologicalSort &S);
+
+// This method implements recursive depth-first search among all Entries in
+// EntryStateMap. Traversing entries and adding them to corresponding container
+// after visiting all dependent entries(post-order traversal) guarantees that
+// the entry's operands will appear in the container before the entry itslef.
+ void visit(SPIRVEntry* E) {
+ DFSState& State = EntryStateMap[E];
+ assert(State != Discovered && "Cyclic dependency detected");
+ if (State == Visited)
+ return;
+ State = Discovered;
+ for (SPIRVEntry *Op : E->getNonLiteralOperands()) {
+ auto Comp = [&Op](SPIRVTypeForwardPointer *FwdPtr) {
+ return FwdPtr->getPointer() == Op;
+ };
+ // Skip forward referenced pointers
+ if (Op->getOpCode() == OpTypePointer &&
+ find_if(ForwardPointerVec.begin(), ForwardPointerVec.end(), Comp) !=
+ ForwardPointerVec.end())
+ continue;
+ visit(Op);
+ }
+ State = Visited;
+ Op OC = E->getOpCode();
+ if (OC == OpTypeInt)
+ TypeIntVec.push_back(static_cast<SPIRVType*>(E));
+ else if (isConstantOpCode(OC)) {
+ SPIRVConstant *C = static_cast<SPIRVConstant*>(E);
+ if (C->getType()->isTypeInt())
+ ConstIntVec.push_back(C);
+ else
+ ConstAndVarVec.push_back(E);
+ } else if (isTypeOpCode(OC))
+ TypeVec.push_back(static_cast<SPIRVType*>(E));
+ else
+ ConstAndVarVec.push_back(E);
+ }
+public:
+ TopologicalSort(const SPIRVTypeVec &_TypeVec,
+ const SPIRVConstantVector &_ConstVec,
+ const SPIRVVariableVec &_VariableVec,
+ const SPIRVForwardPointerVec &_ForwardPointerVec) :
+ ForwardPointerVec(_ForwardPointerVec),
+ EntryStateMap([](SPIRVEntry* a, SPIRVEntry* b) -> bool {
+ return a->getId() < b->getId();
+ })
+ {
+ // Collect entries for sorting
+ for (auto *T : _TypeVec)
+ EntryStateMap[T] = DFSState::Unvisited;
+ for (auto *C : _ConstVec)
+ EntryStateMap[C] = DFSState::Unvisited;
+ for (auto *V : _VariableVec)
+ EntryStateMap[V] = DFSState::Unvisited;
+ // Run topoligical sort
+ for (auto ES : EntryStateMap)
+ visit(ES.first);
+ }
+};
+
+spv_ostream &
+operator<< (spv_ostream &O, const TopologicalSort &S) {
+ O << S.TypeIntVec
+ << S.ConstIntVec
+ << S.TypeVec
+ << S.ConstAndVarVec;
+ return O;
+}
+
+spv_ostream &
+operator<< (spv_ostream &O, SPIRVModule &M) {
+ SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl*>(&M);
+
+ SPIRVEncoder Encoder(O);
+ Encoder << MagicNumber
+ << MI.SPIRVVersion
+ << (((SPIRVWord)MI.GeneratorId << 16) | MI.GeneratorVer)
+ << MI.NextId /* Bound for Id */
+ << MI.InstSchema;
+ O << SPIRVNL();
+
+ for (auto &I:MI.CapMap)
+ O << *I.second;
+
+ for (auto &I:M.getExtension()) {
+ assert(!I.empty() && "Invalid extension");
+ O << SPIRVExtension(&M, I);
+ }
+
+ for (auto &I:MI.IdBuiltinMap)
+ O << SPIRVExtInstImport(&M, I.first, SPIRVBuiltinSetNameMap::map(I.second));
+
+ O << SPIRVMemoryModel(&M);
+
+ for (auto &I:MI.EntryPointVec)
+ for (auto &II:I.second)
+ O << SPIRVEntryPoint(&M, I.first, II,
+ M.get<SPIRVFunction>(II)->getName());
+
+ for (auto &I:MI.EntryPointVec)
+ for (auto &II:I.second)
+ MI.get<SPIRVFunction>(II)->encodeExecutionModes(O);
+
+ O << MI.StringVec;
+
+ for (auto &I:M.getSourceExtension()) {
+ assert(!I.empty() && "Invalid source extension");
+ O << SPIRVSourceExtension(&M, I);
+ }
+
+ O << SPIRVSource(&M);
+
+ for (auto &I:MI.NamedId) {
+ // Don't output name for entry point since it is redundant
+ bool IsEntryPoint = false;
+ for (auto &EPS:MI.EntryPointSet)
+ if (EPS.second.count(I)) {
+ IsEntryPoint = true;
+ break;
+ }
+ if (!IsEntryPoint)
+ M.getEntry(I)->encodeName(O);
+ }
+
+ O << MI.MemberNameVec
+ << MI.DecGroupVec
+ << MI.DecorateSet
+ << MI.GroupDecVec
+ << MI.ForwardPointerVec
+ << TopologicalSort(MI.TypeVec, MI.ConstVec, MI.VariableVec,
+ MI.ForwardPointerVec)
+ << SPIRVNL()
+ << MI.FuncVec;
+ return O;
+}
+
+template<class T>
+void SPIRVModuleImpl::addTo(std::vector<T*>& V, SPIRVEntry* E) {
+ V.push_back(static_cast<T *>(E));
+}
+
+// The first decoration group includes all the previously defined decorates.
+// The second decoration group includes all the decorates defined between the
+// first and second decoration group. So long so forth.
+SPIRVDecorationGroup*
+SPIRVModuleImpl::addDecorationGroup() {
+ return addDecorationGroup(new SPIRVDecorationGroup(this, getId()));
+}
+
+SPIRVDecorationGroup*
+SPIRVModuleImpl::addDecorationGroup(SPIRVDecorationGroup* Group) {
+ add(Group);
+ Group->takeDecorates(DecorateSet);
+ DecGroupVec.push_back(Group);
+ SPIRVDBG(spvdbgs() << "[addDecorationGroup] {" << *Group << "}\n";
+ spvdbgs() << " Remaining DecorateSet: {" << DecorateSet << "}\n");
+ assert(DecorateSet.empty());
+ return Group;
+}
+
+SPIRVGroupDecorateGeneric*
+SPIRVModuleImpl::addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) {
+ add(GDec);
+ GDec->decorateTargets();
+ GroupDecVec.push_back(GDec);
+ return GDec;
+}
+SPIRVGroupDecorate*
+SPIRVModuleImpl::addGroupDecorate(
+ SPIRVDecorationGroup* Group, const std::vector<SPIRVEntry*>& Targets) {
+ auto GD = new SPIRVGroupDecorate(Group, getIds(Targets));
+ addGroupDecorateGeneric(GD);
+ return GD;
+}
+
+SPIRVGroupMemberDecorate*
+SPIRVModuleImpl::addGroupMemberDecorate(
+ SPIRVDecorationGroup* Group, const std::vector<SPIRVEntry*>& Targets) {
+ auto GMD = new SPIRVGroupMemberDecorate(Group, getIds(Targets));
+ addGroupDecorateGeneric(GMD);
+ return GMD;
+}
+
+SPIRVString*
+SPIRVModuleImpl::getString(const std::string& Str) {
+ auto Loc = StrMap.find(Str);
+ if (Loc != StrMap.end())
+ return Loc->second;
+ auto S = add(new SPIRVString(this, getId(), Str));
+ StrMap[Str] = S;
+ return S;
+}
+
+SPIRVMemberName*
+SPIRVModuleImpl::addMemberName(SPIRVTypeStruct* ST,
+ SPIRVWord MemberNumber, const std::string& Name) {
+ return add(new SPIRVMemberName(ST, MemberNumber, Name));
+}
+
+void SPIRVModuleImpl::addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
+ SPIRVId ID) {
+ UnknownStructFieldMap[Struct].push_back(std::make_pair(I, ID));
+}
+
+std::istream &
+operator>> (std::istream &I, SPIRVModule &M) {
+ SPIRVDecoder Decoder(I, M);
+ SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl*>(&M);
+ // Disable automatic capability filling.
+ MI.setAutoAddCapability(false);
+
+ SPIRVWord Magic;
+ Decoder >> Magic;
+ assert(Magic == MagicNumber && "Invalid magic number");
+
+ Decoder >> MI.SPIRVVersion;
+ assert(MI.SPIRVVersion <= SPV_VERSION && "Unsupported SPIRV version number");
+
+ SPIRVWord Generator = 0;
+ Decoder >> Generator;
+ MI.GeneratorId = Generator >> 16;
+ MI.GeneratorVer = Generator & 0xFFFF;
+
+ // Bound for Id
+ Decoder >> MI.NextId;
+
+ Decoder >> MI.InstSchema;
+ assert(MI.InstSchema == SPIRVISCH_Default && "Unsupported instruction schema");
+
+ while (Decoder.getWordCountAndOpCode()) {
+ SPIRVEntry *Entry = Decoder.getEntry();
+ if (Entry != nullptr)
+ M.add(Entry);
+ }
+
+ MI.optimizeDecorates();
+ MI.resolveUnknownStructFields();
+ MI.createForwardPointers();
+ return I;
+}
+
+SPIRVModule *
+SPIRVModule::createSPIRVModule() {
+ return new SPIRVModuleImpl;
+}
+
+SPIRVValue *
+SPIRVModuleImpl::getValue(SPIRVId TheId)const {
+ return get<SPIRVValue>(TheId);
+}
+
+SPIRVType *
+SPIRVModuleImpl::getValueType(SPIRVId TheId)const {
+ return get<SPIRVValue>(TheId)->getType();
+}
+
+std::vector<SPIRVValue *>
+SPIRVModuleImpl::getValues(const std::vector<SPIRVId>& IdVec)const {
+ std::vector<SPIRVValue *> ValueVec;
+ for (auto i:IdVec)
+ ValueVec.push_back(getValue(i));
+ return ValueVec;
+}
+
+std::vector<SPIRVType *>
+SPIRVModuleImpl::getValueTypes(const std::vector<SPIRVId>& IdVec)const {
+ std::vector<SPIRVType *> TypeVec;
+ for (auto i:IdVec)
+ TypeVec.push_back(getValue(i)->getType());
+ return TypeVec;
+}
+
+std::vector<SPIRVId>
+SPIRVModuleImpl::getIds(const std::vector<SPIRVEntry *> &ValueVec)const {
+ std::vector<SPIRVId> IdVec;
+ for (auto i:ValueVec)
+ IdVec.push_back(i->getId());
+ return IdVec;
+}
+
+std::vector<SPIRVId>
+SPIRVModuleImpl::getIds(const std::vector<SPIRVValue *> &ValueVec)const {
+ std::vector<SPIRVId> IdVec;
+ for (auto i:ValueVec)
+ IdVec.push_back(i->getId());
+ return IdVec;
+}
+
+SPIRVInstTemplateBase*
+SPIRVModuleImpl::addInstTemplate(Op OC,
+ SPIRVBasicBlock* BB, SPIRVType *Ty) {
+ assert (!Ty || !Ty->isTypeVoid());
+ SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
+ auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, BB, this);
+ BB->addInstruction(Ins);
+ return Ins;
+}
+
+SPIRVInstTemplateBase*
+SPIRVModuleImpl::addInstTemplate(Op OC,
+ const std::vector<SPIRVWord>& Ops, SPIRVBasicBlock* BB, SPIRVType *Ty) {
+ assert (!Ty || !Ty->isTypeVoid());
+ SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
+ auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, Ops, BB, this);
+ BB->addInstruction(Ins);
+ return Ins;
+}
+
+SPIRVDbgInfo::SPIRVDbgInfo(SPIRVModule *TM)
+:M(TM){
+}
+
+std::string
+SPIRVDbgInfo::getEntryPointFileStr(SPIRVExecutionModelKind EM, unsigned I) {
+ if (M->getNumEntryPoints(EM) == 0)
+ return "";
+ return getFunctionFileStr(M->getEntryPoint(EM, I));
+}
+
+std::string
+SPIRVDbgInfo::getFunctionFileStr(SPIRVFunction *F) {
+ if (F->hasLine())
+ return F->getLine()->getFileNameStr();
+ return "";
+}
+
+unsigned
+SPIRVDbgInfo::getFunctionLineNo(SPIRVFunction *F) {
+ if (F->hasLine())
+ return F->getLine()->getLine();
+ return 0;
+}
+
+bool IsSPIRVBinary(const std::string &Img) {
+ if (Img.size() < sizeof(unsigned))
+ return false;
+ auto Magic = reinterpret_cast<const unsigned*>(Img.data());
+ return *Magic == MagicNumber;
+}
+
+#ifdef _SPIRV_SUPPORT_TEXT_FMT
+
+bool ConvertSPIRV(std::istream &IS, spv_ostream &OS,
+ std::string &ErrMsg, bool FromText, bool ToText) {
+ auto SaveOpt = SPIRVUseTextFormat;
+ SPIRVUseTextFormat = FromText;
+ SPIRVModuleImpl M;
+ IS >> M;
+ if (M.getError(ErrMsg) != SPIRVEC_Success) {
+ SPIRVUseTextFormat = SaveOpt;
+ return false;
+ }
+ SPIRVUseTextFormat = ToText;
+ OS << M;
+ if (M.getError(ErrMsg) != SPIRVEC_Success) {
+ SPIRVUseTextFormat = SaveOpt;
+ return false;
+ }
+ SPIRVUseTextFormat = SaveOpt;
+ return true;
+}
+
+bool IsSPIRVText(const std::string &Img) {
+ std::istringstream SS(Img);
+ unsigned Magic = 0;
+ SS >> Magic;
+ if (SS.bad())
+ return false;
+ return Magic == MagicNumber;
+}
+
+bool ConvertSPIRV(std::string &Input, std::string &Out,
+ std::string &ErrMsg, bool ToText) {
+ auto FromText = IsSPIRVText(Input);
+ if (ToText == FromText) {
+ Out = Input;
+ return true;
+ }
+ std::istringstream IS(Input);
+#ifdef _SPIRV_LLVM_API
+ llvm::raw_string_ostream OS(Out);
+#else
+ std::ostringstream OS;
+#endif
+ if (!ConvertSPIRV(IS, OS, ErrMsg, FromText, ToText))
+ return false;
+ Out = OS.str();
+ return true;
+}
+
+#endif // _SPIRV_SUPPORT_TEXT_FMT
+
+}
+