1 //===- SPIRVModule.cpp - Class to represent SPIR-V module -------*- C++ -*-===//
2 //
3 //                     The LLVM/SPIRV Translator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal with the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // Redistributions of source code must retain the above copyright notice,
18 // this list of conditions and the following disclaimers.
19 // Redistributions in binary form must reproduce the above copyright notice,
20 // this list of conditions and the following disclaimers in the documentation
21 // and/or other materials provided with the distribution.
22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its
23 // contributors may be used to endorse or promote products derived from this
24 // Software without specific prior written permission.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
31 // THE SOFTWARE.
32 //
33 //===----------------------------------------------------------------------===//
34 /// \file
35 ///
36 /// This file implements Module class for SPIR-V.
37 ///
38 //===----------------------------------------------------------------------===//
39 
40 #include "SPIRVModule.h"
41 #include "SPIRVAsm.h"
42 #include "SPIRVDebug.h"
43 #include "SPIRVEntry.h"
44 #include "SPIRVExtInst.h"
45 #include "SPIRVFunction.h"
46 #include "SPIRVInstruction.h"
47 #include "SPIRVMemAliasingINTEL.h"
48 #include "SPIRVNameMapEnum.h"
49 #include "SPIRVStream.h"
50 #include "SPIRVType.h"
51 #include "SPIRVValue.h"
52 
53 #include "llvm/ADT/APInt.h"
54 
55 #include <set>
56 #include <unordered_map>
57 #include <unordered_set>
58 
59 namespace SPIRV {
60 
SPIRVModule()61 SPIRVModule::SPIRVModule()
62     : AutoAddCapability(true), ValidateCapability(false), IsValid(true) {}
63 
~SPIRVModule()64 SPIRVModule::~SPIRVModule() {}
65 
66 class SPIRVModuleImpl : public SPIRVModule {
67 public:
SPIRVModuleImpl()68   SPIRVModuleImpl()
69       : SPIRVModule(), NextId(1),
70         SPIRVVersion(static_cast<SPIRVWord>(VersionNumber::SPIRV_1_0)),
71         GeneratorId(SPIRVGEN_KhronosLLVMSPIRVTranslator), GeneratorVer(0),
72         InstSchema(SPIRVISCH_Default), SrcLang(SourceLanguageOpenCL_C),
73         SrcLangVer(102000) {
74     AddrModel = sizeof(size_t) == 32 ? AddressingModelPhysical32
75                                      : AddressingModelPhysical64;
76     // OpenCL memory model requires Kernel capability
77     setMemoryModel(MemoryModelOpenCL);
78   }
79 
SPIRVModuleImpl(const SPIRV::TranslatorOpts & Opts)80   SPIRVModuleImpl(const SPIRV::TranslatorOpts &Opts) : SPIRVModuleImpl() {
81     TranslationOpts = Opts;
82   }
83 
84   ~SPIRVModuleImpl() override;
85 
86   // Object query functions
87   bool exist(SPIRVId) const override;
88   bool exist(SPIRVId, SPIRVEntry **) const override;
89   SPIRVId getId(SPIRVId Id = SPIRVID_INVALID, unsigned Increment = 1);
90   SPIRVEntry *getEntry(SPIRVId Id) const override;
91   // If we have at least on OpLine in the module the CurrentLine is non-empty
hasDebugInfo() const92   bool hasDebugInfo() const override {
93     return CurrentLine.get() || !DebugInstVec.empty();
94   }
95 
96   // Error handling functions
getErrorLog()97   SPIRVErrorLog &getErrorLog() override { return ErrLog; }
getError(std::string & ErrMsg)98   SPIRVErrorCode getError(std::string &ErrMsg) override {
99     return ErrLog.getError(ErrMsg);
100   }
checkExtension(ExtensionID Ext,SPIRVErrorCode ErrCode,const std::string & Msg)101   bool checkExtension(ExtensionID Ext, SPIRVErrorCode ErrCode,
102                       const std::string &Msg) override {
103     if (ErrLog.checkError(isAllowedToUseExtension(Ext), ErrCode, Msg))
104       return true;
105     setInvalid();
106     return false;
107   }
108 
109   // Module query functions
getAddressingModel()110   SPIRVAddressingModelKind getAddressingModel() override { return AddrModel; }
111   SPIRVExtInstSetKind getBuiltinSet(SPIRVId SetId) const override;
getCapability() const112   const SPIRVCapMap &getCapability() const override { return CapMap; }
hasCapability(SPIRVCapabilityKind Cap) const113   bool hasCapability(SPIRVCapabilityKind Cap) const override {
114     return CapMap.find(Cap) != CapMap.end();
115   }
getExtension()116   std::set<std::string> &getExtension() override { return SPIRVExt; }
getFunction(unsigned I) const117   SPIRVFunction *getFunction(unsigned I) const override { return FuncVec[I]; }
getVariable(unsigned I) const118   SPIRVVariable *getVariable(unsigned I) const override {
119     return VariableVec[I];
120   }
121   SPIRVValue *getValue(SPIRVId TheId) const override;
122   std::vector<SPIRVValue *>
123   getValues(const std::vector<SPIRVId> &) const override;
124   std::vector<SPIRVId> getIds(const std::vector<SPIRVEntry *> &) const override;
125   std::vector<SPIRVId> getIds(const std::vector<SPIRVValue *> &) const override;
126   SPIRVType *getValueType(SPIRVId TheId) const override;
127   std::vector<SPIRVType *>
128   getValueTypes(const std::vector<SPIRVId> &) const override;
getMemoryModel() const129   SPIRVMemoryModelKind getMemoryModel() const override { return MemoryModel; }
130   SPIRVConstant *getLiteralAsConstant(unsigned Literal) override;
getNumEntryPoints(SPIRVExecutionModelKind EM) const131   unsigned getNumEntryPoints(SPIRVExecutionModelKind EM) const override {
132     auto Loc = EntryPointVec.find(EM);
133     if (Loc == EntryPointVec.end())
134       return 0;
135     return Loc->second.size();
136   }
getEntryPoint(SPIRVExecutionModelKind EM,unsigned I) const137   SPIRVFunction *getEntryPoint(SPIRVExecutionModelKind EM,
138                                unsigned I) const override {
139     auto Loc = EntryPointVec.find(EM);
140     if (Loc == EntryPointVec.end())
141       return nullptr;
142     assert(I < Loc->second.size());
143     return get<SPIRVFunction>(Loc->second[I]);
144   }
getNumFunctions() const145   unsigned getNumFunctions() const override { return FuncVec.size(); }
getNumVariables() const146   unsigned getNumVariables() const override { return VariableVec.size(); }
getSourceLanguage(SPIRVWord * Ver=nullptr) const147   SourceLanguage getSourceLanguage(SPIRVWord *Ver = nullptr) const override {
148     if (Ver)
149       *Ver = SrcLangVer;
150     return SrcLang;
151   }
getSourceExtension()152   std::set<std::string> &getSourceExtension() override { return SrcExtension; }
153   bool isEntryPoint(SPIRVExecutionModelKind, SPIRVId EP) const override;
getGeneratorId() const154   unsigned short getGeneratorId() const override { return GeneratorId; }
getGeneratorVer() const155   unsigned short getGeneratorVer() const override { return GeneratorVer; }
getSPIRVVersion() const156   SPIRVWord getSPIRVVersion() const override { return SPIRVVersion; }
getDebugInstVec() const157   const std::vector<SPIRVExtInst *> &getDebugInstVec() const override {
158     return DebugInstVec;
159   }
getStringVec() const160   const std::vector<SPIRVString *> &getStringVec() const override {
161     return StringVec;
162   }
163   // Module changing functions
164   bool importBuiltinSet(const std::string &, SPIRVId *) override;
165   bool importBuiltinSetWithId(const std::string &, SPIRVId) override;
setAddressingModel(SPIRVAddressingModelKind AM)166   void setAddressingModel(SPIRVAddressingModelKind AM) override {
167     AddrModel = AM;
168   }
169   void setAlignment(SPIRVValue *, SPIRVWord) override;
setMemoryModel(SPIRVMemoryModelKind MM)170   void setMemoryModel(SPIRVMemoryModelKind MM) override {
171     MemoryModel = MM;
172     if (MemoryModel == spv::MemoryModelOpenCL)
173       addCapability(CapabilityKernel);
174   }
175   void setName(SPIRVEntry *E, const std::string &Name) override;
setSourceLanguage(SourceLanguage Lang,SPIRVWord Ver)176   void setSourceLanguage(SourceLanguage Lang, SPIRVWord Ver) override {
177     SrcLang = Lang;
178     SrcLangVer = Ver;
179   }
setGeneratorId(unsigned short Id)180   void setGeneratorId(unsigned short Id) override { GeneratorId = Id; }
setGeneratorVer(unsigned short Ver)181   void setGeneratorVer(unsigned short Ver) override { GeneratorVer = Ver; }
182   void resolveUnknownStructFields() override;
183 
setSPIRVVersion(SPIRVWord Ver)184   void setSPIRVVersion(SPIRVWord Ver) override {
185     assert(this->isAllowedToUseVersion(static_cast<VersionNumber>(Ver)));
186     SPIRVVersion = Ver;
187   }
188 
189   // Object creation functions
190   template <class T> void addTo(std::vector<T *> &V, SPIRVEntry *E);
191   SPIRVEntry *addEntry(SPIRVEntry *E) override;
192   SPIRVBasicBlock *addBasicBlock(SPIRVFunction *, SPIRVId) override;
193   SPIRVString *getString(const std::string &Str) override;
194   SPIRVMemberName *addMemberName(SPIRVTypeStruct *ST, SPIRVWord MemberNumber,
195                                  const std::string &Name) override;
196   void addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
197                              SPIRVId ID) override;
198   void addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line,
199                SPIRVWord Column) override;
200   const std::shared_ptr<const SPIRVLine> &getCurrentLine() const override;
201   void setCurrentLine(const std::shared_ptr<const SPIRVLine> &Line) override;
202   void addCapability(SPIRVCapabilityKind) override;
203   void addCapabilityInternal(SPIRVCapabilityKind) override;
204   void addExtension(ExtensionID) override;
205   const SPIRVDecorateGeneric *addDecorate(SPIRVDecorateGeneric *) override;
206   SPIRVDecorationGroup *addDecorationGroup() override;
207   SPIRVDecorationGroup *
208   addDecorationGroup(SPIRVDecorationGroup *Group) override;
209   SPIRVGroupDecorate *
210   addGroupDecorate(SPIRVDecorationGroup *Group,
211                    const std::vector<SPIRVEntry *> &Targets) override;
212   SPIRVGroupDecorateGeneric *
213   addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) override;
214   SPIRVGroupMemberDecorate *
215   addGroupMemberDecorate(SPIRVDecorationGroup *Group,
216                          const std::vector<SPIRVEntry *> &Targets) override;
217   void addEntryPoint(SPIRVExecutionModelKind ExecModel,
218                      SPIRVId EntryPoint) override;
219   SPIRVForward *addForward(SPIRVType *Ty) override;
220   SPIRVForward *addForward(SPIRVId, SPIRVType *Ty) override;
221   SPIRVFunction *addFunction(SPIRVFunction *) override;
222   SPIRVFunction *addFunction(SPIRVTypeFunction *, SPIRVId) override;
223   SPIRVEntry *replaceForward(SPIRVForward *, SPIRVEntry *) override;
224   void eraseInstruction(SPIRVInstruction *, SPIRVBasicBlock *) override;
225 
226   // Type creation functions
227   template <class T> T *addType(T *Ty);
228   SPIRVTypeArray *addArrayType(SPIRVType *, SPIRVConstant *) override;
229   SPIRVTypeBool *addBoolType() override;
230   SPIRVTypeFloat *addFloatType(unsigned BitWidth) override;
231   SPIRVTypeFunction *addFunctionType(SPIRVType *,
232                                      const std::vector<SPIRVType *> &) override;
233   SPIRVTypeInt *addIntegerType(unsigned BitWidth) override;
234   SPIRVTypeOpaque *addOpaqueType(const std::string &) override;
235   SPIRVTypePointer *addPointerType(SPIRVStorageClassKind, SPIRVType *) override;
236   SPIRVTypeImage *addImageType(SPIRVType *,
237                                const SPIRVTypeImageDescriptor &) override;
238   SPIRVTypeImage *addImageType(SPIRVType *, const SPIRVTypeImageDescriptor &,
239                                SPIRVAccessQualifierKind) override;
240   SPIRVTypeSampler *addSamplerType() override;
241   SPIRVTypePipeStorage *addPipeStorageType() override;
242   SPIRVTypeSampledImage *addSampledImageType(SPIRVTypeImage *T) override;
243   SPIRVTypeStruct *openStructType(unsigned, const std::string &) override;
244   SPIRVEntry *addTypeStructContinuedINTEL(unsigned NumMembers) override;
245   void closeStructType(SPIRVTypeStruct *T, bool) override;
246   SPIRVTypeVector *addVectorType(SPIRVType *, SPIRVWord) override;
247   SPIRVType *addOpaqueGenericType(Op) override;
248   SPIRVTypeDeviceEvent *addDeviceEventType() override;
249   SPIRVTypeQueue *addQueueType() override;
250   SPIRVTypePipe *addPipeType() override;
251   SPIRVTypeVoid *addVoidType() override;
252   SPIRVType *addSubgroupAvcINTELType(Op) override;
253   SPIRVTypeVmeImageINTEL *addVmeImageINTELType(SPIRVTypeImage *T) override;
254   SPIRVTypeBufferSurfaceINTEL *
255   addBufferSurfaceINTELType(SPIRVAccessQualifierKind Access) override;
256   SPIRVTypeTokenINTEL *addTokenTypeINTEL() override;
257 
258   // Constant creation functions
259   SPIRVInstruction *addBranchInst(SPIRVLabel *, SPIRVBasicBlock *) override;
260   SPIRVInstruction *addBranchConditionalInst(SPIRVValue *, SPIRVLabel *,
261                                              SPIRVLabel *,
262                                              SPIRVBasicBlock *) override;
263   SPIRVValue *addCompositeConstant(SPIRVType *,
264                                    const std::vector<SPIRVValue *> &) override;
265   SPIRVEntry *addCompositeConstantContinuedINTEL(
266       const std::vector<SPIRVValue *> &) override;
267   SPIRVValue *
268   addSpecConstantComposite(SPIRVType *Ty,
269                            const std::vector<SPIRVValue *> &Elements) override;
270   SPIRVEntry *addSpecConstantCompositeContinuedINTEL(
271       const std::vector<SPIRVValue *> &) override;
272   SPIRVValue *addConstFunctionPointerINTEL(SPIRVType *Ty,
273                                            SPIRVFunction *F) override;
274   SPIRVValue *addConstant(SPIRVValue *) override;
275   SPIRVValue *addConstant(SPIRVType *, uint64_t) override;
276   SPIRVValue *addConstant(SPIRVType *, llvm::APInt) override;
277   SPIRVValue *addSpecConstant(SPIRVType *, uint64_t) override;
278   SPIRVValue *addDoubleConstant(SPIRVTypeFloat *, double) override;
279   SPIRVValue *addFloatConstant(SPIRVTypeFloat *, float) override;
280   SPIRVValue *addIntegerConstant(SPIRVTypeInt *, uint64_t) override;
281   SPIRVValue *addNullConstant(SPIRVType *) override;
282   SPIRVValue *addUndef(SPIRVType *TheType) override;
283   SPIRVValue *addSamplerConstant(SPIRVType *TheType, SPIRVWord AddrMode,
284                                  SPIRVWord ParametricMode,
285                                  SPIRVWord FilterMode) override;
286   SPIRVValue *addPipeStorageConstant(SPIRVType *TheType, SPIRVWord PacketSize,
287                                      SPIRVWord PacketAlign,
288                                      SPIRVWord Capacity) override;
289 
290   // Instruction creation functions
291   SPIRVInstruction *addPtrAccessChainInst(SPIRVType *, SPIRVValue *,
292                                           std::vector<SPIRVValue *>,
293                                           SPIRVBasicBlock *, bool) override;
294   SPIRVInstruction *addAsyncGroupCopy(SPIRVValue *Scope, SPIRVValue *Dest,
295                                       SPIRVValue *Src, SPIRVValue *NumElems,
296                                       SPIRVValue *Stride, SPIRVValue *Event,
297                                       SPIRVBasicBlock *BB) override;
298   SPIRVInstruction *addExtInst(SPIRVType *, SPIRVWord, SPIRVWord,
299                                const std::vector<SPIRVWord> &,
300                                SPIRVBasicBlock *,
301                                SPIRVInstruction * = nullptr) override;
302   SPIRVInstruction *addExtInst(SPIRVType *, SPIRVWord, SPIRVWord,
303                                const std::vector<SPIRVValue *> &,
304                                SPIRVBasicBlock *,
305                                SPIRVInstruction * = nullptr) override;
306   SPIRVEntry *addDebugInfo(SPIRVWord, SPIRVType *TheType,
307                            const std::vector<SPIRVWord> &) override;
308   SPIRVEntry *addModuleProcessed(const std::string &) override;
309   std::vector<SPIRVModuleProcessed *> getModuleProcessedVec() override;
310   SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *,
311                                   SPIRVBasicBlock *) override;
312   SPIRVInstruction *addCallInst(SPIRVFunction *, const std::vector<SPIRVWord> &,
313                                 SPIRVBasicBlock *) override;
314   SPIRVInstruction *addIndirectCallInst(SPIRVValue *, SPIRVType *,
315                                         const std::vector<SPIRVWord> &,
316                                         SPIRVBasicBlock *) override;
317   SPIRVEntry *getOrAddAsmTargetINTEL(const std::string &) override;
318   SPIRVValue *addAsmINTEL(SPIRVTypeFunction *, SPIRVAsmTargetINTEL *,
319                           const std::string &, const std::string &) override;
320   SPIRVInstruction *addAsmCallINTELInst(SPIRVAsmINTEL *,
321                                         const std::vector<SPIRVWord> &,
322                                         SPIRVBasicBlock *) override;
323   SPIRVInstruction *addCmpInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *,
324                                SPIRVBasicBlock *) override;
325   SPIRVInstruction *addLoadInst(SPIRVValue *, const std::vector<SPIRVWord> &,
326                                 SPIRVBasicBlock *) override;
327   SPIRVInstruction *addPhiInst(SPIRVType *, std::vector<SPIRVValue *>,
328                                SPIRVBasicBlock *) override;
329   SPIRVInstruction *addCompositeConstructInst(SPIRVType *,
330                                               const std::vector<SPIRVId> &,
331                                               SPIRVBasicBlock *) override;
332   SPIRVInstruction *addCompositeExtractInst(SPIRVType *, SPIRVValue *,
333                                             const std::vector<SPIRVWord> &,
334                                             SPIRVBasicBlock *) override;
335   SPIRVInstruction *
336   addCompositeInsertInst(SPIRVValue *Object, SPIRVValue *Composite,
337                          const std::vector<SPIRVWord> &Indices,
338                          SPIRVBasicBlock *BB) override;
339   SPIRVInstruction *addCopyObjectInst(SPIRVType *TheType, SPIRVValue *Operand,
340                                       SPIRVBasicBlock *BB) override;
341   SPIRVInstruction *addCopyMemoryInst(SPIRVValue *, SPIRVValue *,
342                                       const std::vector<SPIRVWord> &,
343                                       SPIRVBasicBlock *) override;
344   SPIRVInstruction *addCopyMemorySizedInst(SPIRVValue *, SPIRVValue *,
345                                            SPIRVValue *,
346                                            const std::vector<SPIRVWord> &,
347                                            SPIRVBasicBlock *) override;
348   SPIRVInstruction *addControlBarrierInst(SPIRVValue *ExecKind,
349                                           SPIRVValue *MemKind,
350                                           SPIRVValue *MemSema,
351                                           SPIRVBasicBlock *BB) override;
352   SPIRVInstruction *addGroupInst(Op OpCode, SPIRVType *Type, Scope Scope,
353                                  const std::vector<SPIRVValue *> &Ops,
354                                  SPIRVBasicBlock *BB) override;
355   virtual SPIRVInstruction *
356   addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB,
357                  SPIRVInstruction *InsertBefore = nullptr);
358   SPIRVInstTemplateBase *addInstTemplate(Op OC, SPIRVBasicBlock *BB,
359                                          SPIRVType *Ty) override;
360   SPIRVInstTemplateBase *addInstTemplate(Op OC,
361                                          const std::vector<SPIRVWord> &Ops,
362                                          SPIRVBasicBlock *BB,
363                                          SPIRVType *Ty) override;
364   void addInstTemplate(SPIRVInstTemplateBase *Ins,
365                        const std::vector<SPIRVWord> &Ops, SPIRVBasicBlock *BB,
366                        SPIRVType *Ty) override;
367   SPIRVInstruction *addLifetimeInst(Op OC, SPIRVValue *Object, SPIRVWord Size,
368                                     SPIRVBasicBlock *BB) override;
369   SPIRVInstruction *addMemoryBarrierInst(Scope ScopeKind, SPIRVWord MemFlag,
370                                          SPIRVBasicBlock *BB) override;
371   SPIRVInstruction *addUnreachableInst(SPIRVBasicBlock *) override;
372   SPIRVInstruction *addReturnInst(SPIRVBasicBlock *) override;
373   SPIRVInstruction *addReturnValueInst(SPIRVValue *,
374                                        SPIRVBasicBlock *) override;
375   SPIRVInstruction *addSelectInst(SPIRVValue *, SPIRVValue *, SPIRVValue *,
376                                   SPIRVBasicBlock *) override;
377   SPIRVInstruction *
378   addLoopMergeInst(SPIRVId MergeBlock, SPIRVId ContinueTarget,
379                    SPIRVWord LoopControl,
380                    std::vector<SPIRVWord> LoopControlParameters,
381                    SPIRVBasicBlock *BB) override;
382   SPIRVInstruction *
383   addLoopControlINTELInst(SPIRVWord LoopControl,
384                           std::vector<SPIRVWord> LoopControlParameters,
385                           SPIRVBasicBlock *BB) override;
386   SPIRVInstruction *addFixedPointIntelInst(Op OC, SPIRVType *ResTy,
387                                            SPIRVValue *Input,
388                                            const std::vector<SPIRVWord> &Ops,
389                                            SPIRVBasicBlock *BB) override;
390   SPIRVInstruction *addArbFloatPointIntelInst(Op OC, SPIRVType *ResTy,
391                                               SPIRVValue *InA, SPIRVValue *InB,
392                                               const std::vector<SPIRVWord> &Ops,
393                                               SPIRVBasicBlock *BB) override;
394   SPIRVInstruction *addSelectionMergeInst(SPIRVId MergeBlock,
395                                           SPIRVWord SelectionControl,
396                                           SPIRVBasicBlock *BB) override;
397   SPIRVInstruction *addStoreInst(SPIRVValue *, SPIRVValue *,
398                                  const std::vector<SPIRVWord> &,
399                                  SPIRVBasicBlock *) override;
400   SPIRVInstruction *addSwitchInst(
401       SPIRVValue *, SPIRVBasicBlock *,
402       const std::vector<std::pair<std::vector<SPIRVWord>, SPIRVBasicBlock *>> &,
403       SPIRVBasicBlock *) override;
404   SPIRVInstruction *addVectorTimesScalarInst(SPIRVType *TheType,
405                                              SPIRVId TheVector,
406                                              SPIRVId TheScalar,
407                                              SPIRVBasicBlock *BB) override;
408   SPIRVInstruction *addVectorTimesMatrixInst(SPIRVType *TheType,
409                                              SPIRVId TheVector,
410                                              SPIRVId TheScalar,
411                                              SPIRVBasicBlock *BB) override;
412   SPIRVInstruction *addMatrixTimesScalarInst(SPIRVType *TheType,
413                                              SPIRVId TheMatrix,
414                                              SPIRVId TheScalar,
415                                              SPIRVBasicBlock *BB) override;
416   SPIRVInstruction *addMatrixTimesVectorInst(SPIRVType *TheType,
417                                              SPIRVId TheMatrix,
418                                              SPIRVId TheVector,
419                                              SPIRVBasicBlock *BB) override;
420   SPIRVInstruction *addMatrixTimesMatrixInst(SPIRVType *TheType, SPIRVId M1,
421                                              SPIRVId M2,
422                                              SPIRVBasicBlock *BB) override;
423   SPIRVInstruction *addTransposeInst(SPIRVType *TheType, SPIRVId TheMatrix,
424                                      SPIRVBasicBlock *BB) override;
425   SPIRVInstruction *addUnaryInst(Op, SPIRVType *, SPIRVValue *,
426                                  SPIRVBasicBlock *) override;
427   SPIRVInstruction *addVariable(SPIRVType *, bool, SPIRVLinkageTypeKind,
428                                 SPIRVValue *, const std::string &,
429                                 SPIRVStorageClassKind,
430                                 SPIRVBasicBlock *) override;
431   SPIRVValue *addVectorShuffleInst(SPIRVType *Type, SPIRVValue *Vec1,
432                                    SPIRVValue *Vec2,
433                                    const std::vector<SPIRVWord> &Components,
434                                    SPIRVBasicBlock *BB) override;
435   SPIRVInstruction *addVectorExtractDynamicInst(SPIRVValue *, SPIRVValue *,
436                                                 SPIRVBasicBlock *) override;
437   SPIRVInstruction *addVectorInsertDynamicInst(SPIRVValue *, SPIRVValue *,
438                                                SPIRVValue *,
439                                                SPIRVBasicBlock *) override;
440   SPIRVInstruction *addFPGARegINTELInst(SPIRVType *, SPIRVValue *,
441                                         SPIRVBasicBlock *) override;
442   SPIRVInstruction *addSampledImageInst(SPIRVType *, SPIRVValue *, SPIRVValue *,
443                                         SPIRVBasicBlock *) override;
444   template <typename AliasingInstType>
445   SPIRVEntry *getOrAddMemAliasingINTELInst(std::vector<SPIRVId> Args,
446                                            llvm::MDNode *MD);
447   SPIRVEntry *getOrAddAliasDomainDeclINTELInst(std::vector<SPIRVId> Args,
448                                                llvm::MDNode *MD) override;
449   SPIRVEntry *getOrAddAliasScopeDeclINTELInst(std::vector<SPIRVId> Args,
450                                               llvm::MDNode *MD) override;
451   SPIRVEntry *getOrAddAliasScopeListDeclINTELInst(std::vector<SPIRVId> Args,
452                                                   llvm::MDNode *MD) override;
453   SPIRVInstruction *addAssumeTrueKHRInst(SPIRVValue *Condition,
454                                          SPIRVBasicBlock *BB) override;
455   SPIRVInstruction *addExpectKHRInst(SPIRVType *ResultTy, SPIRVValue *Value,
456                                      SPIRVValue *ExpectedValue,
457                                      SPIRVBasicBlock *BB) override;
458 
459   virtual SPIRVId getExtInstSetId(SPIRVExtInstSetKind Kind) const override;
460 
461   // I/O functions
462   friend spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M);
463   friend std::istream &operator>>(std::istream &I, SPIRVModule &M);
464 
465 private:
466   SPIRVErrorLog ErrLog;
467   SPIRVId NextId;
468   SPIRVWord SPIRVVersion;
469   unsigned short GeneratorId;
470   unsigned short GeneratorVer;
471   SPIRVInstructionSchemaKind InstSchema;
472   SourceLanguage SrcLang;
473   SPIRVWord SrcLangVer;
474   std::set<std::string> SrcExtension;
475   std::set<std::string> SPIRVExt;
476   SPIRVAddressingModelKind AddrModel;
477   SPIRVMemoryModelKind MemoryModel;
478 
479   typedef std::map<SPIRVId, SPIRVEntry *> SPIRVIdToEntryMap;
480   typedef std::set<SPIRVEntry *> SPIRVEntrySet;
481   typedef std::set<SPIRVId> SPIRVIdSet;
482   typedef std::vector<SPIRVId> SPIRVIdVec;
483   typedef std::vector<SPIRVFunction *> SPIRVFunctionVector;
484   typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
485   typedef std::vector<SPIRVType *> SPIRVTypeVec;
486   typedef std::vector<SPIRVValue *> SPIRVConstantVector;
487   typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
488   typedef std::vector<SPIRVString *> SPIRVStringVec;
489   typedef std::vector<SPIRVMemberName *> SPIRVMemberNameVec;
490   typedef std::vector<SPIRVDecorationGroup *> SPIRVDecGroupVec;
491   typedef std::vector<SPIRVGroupDecorateGeneric *> SPIRVGroupDecVec;
492   typedef std::vector<SPIRVAsmTargetINTEL *> SPIRVAsmTargetVector;
493   typedef std::vector<SPIRVAsmINTEL *> SPIRVAsmVector;
494   typedef std::map<SPIRVId, SPIRVExtInstSetKind> SPIRVIdToInstructionSetMap;
495   std::map<SPIRVExtInstSetKind, SPIRVId> ExtInstSetIds;
496   typedef std::map<SPIRVId, SPIRVExtInstSetKind> SPIRVIdToBuiltinSetMap;
497   typedef std::map<SPIRVExecutionModelKind, SPIRVIdSet> SPIRVExecModelIdSetMap;
498   typedef std::map<SPIRVExecutionModelKind, SPIRVIdVec> SPIRVExecModelIdVecMap;
499   typedef std::unordered_map<std::string, SPIRVString *> SPIRVStringMap;
500   typedef std::map<SPIRVTypeStruct *, std::vector<std::pair<unsigned, SPIRVId>>>
501       SPIRVUnknownStructFieldMap;
502   typedef std::vector<SPIRVEntry *> SPIRVAliasInstMDVec;
503   typedef std::unordered_map<llvm::MDNode *, SPIRVEntry *> SPIRVAliasInstMDMap;
504 
505   SPIRVForwardPointerVec ForwardPointerVec;
506   SPIRVTypeVec TypeVec;
507   SPIRVIdToEntryMap IdEntryMap;
508   SPIRVFunctionVector FuncVec;
509   SPIRVConstantVector ConstVec;
510   SPIRVVariableVec VariableVec;
511   SPIRVEntrySet EntryNoId; // Entries without id
512   SPIRVIdToInstructionSetMap IdToInstSetMap;
513   SPIRVIdToBuiltinSetMap IdBuiltinMap;
514   SPIRVIdSet NamedId;
515   SPIRVStringVec StringVec;
516   SPIRVMemberNameVec MemberNameVec;
517   std::shared_ptr<const SPIRVLine> CurrentLine;
518   SPIRVDecorateSet DecorateSet;
519   SPIRVDecGroupVec DecGroupVec;
520   SPIRVGroupDecVec GroupDecVec;
521   SPIRVAsmTargetVector AsmTargetVec;
522   SPIRVAsmVector AsmVec;
523   SPIRVExecModelIdSetMap EntryPointSet;
524   SPIRVExecModelIdVecMap EntryPointVec;
525   SPIRVStringMap StrMap;
526   SPIRVCapMap CapMap;
527   SPIRVUnknownStructFieldMap UnknownStructFieldMap;
528   std::map<unsigned, SPIRVTypeInt *> IntTypeMap;
529   std::map<unsigned, SPIRVConstant *> LiteralMap;
530   std::vector<SPIRVExtInst *> DebugInstVec;
531   std::vector<SPIRVModuleProcessed *> ModuleProcessedVec;
532   SPIRVAliasInstMDVec AliasInstMDVec;
533   SPIRVAliasInstMDMap AliasInstMDMap;
534 
535   void layoutEntry(SPIRVEntry *Entry);
536 };
537 
~SPIRVModuleImpl()538 SPIRVModuleImpl::~SPIRVModuleImpl() {
539   for (auto I : EntryNoId)
540     delete I;
541 
542   for (auto I : IdEntryMap)
543     delete I.second;
544 
545   for (auto C : CapMap)
546     delete C.second;
547 
548   for (auto *M : ModuleProcessedVec)
549     delete M;
550 }
551 
552 const std::shared_ptr<const SPIRVLine> &
getCurrentLine() const553 SPIRVModuleImpl::getCurrentLine() const {
554   return CurrentLine;
555 }
556 
setCurrentLine(const std::shared_ptr<const SPIRVLine> & Line)557 void SPIRVModuleImpl::setCurrentLine(
558     const std::shared_ptr<const SPIRVLine> &Line) {
559   CurrentLine = Line;
560 }
561 
addLine(SPIRVEntry * E,SPIRVId FileNameId,SPIRVWord Line,SPIRVWord Column)562 void SPIRVModuleImpl::addLine(SPIRVEntry *E, SPIRVId FileNameId, SPIRVWord Line,
563                               SPIRVWord Column) {
564   if (!(CurrentLine && CurrentLine->equals(FileNameId, Line, Column)))
565     CurrentLine.reset(new SPIRVLine(this, FileNameId, Line, Column));
566   assert(E && "invalid entry");
567   E->setLine(CurrentLine);
568 }
569 
addSamplerConstant(SPIRVType * TheType,SPIRVWord AddrMode,SPIRVWord ParametricMode,SPIRVWord FilterMode)570 SPIRVValue *SPIRVModuleImpl::addSamplerConstant(SPIRVType *TheType,
571                                                 SPIRVWord AddrMode,
572                                                 SPIRVWord ParametricMode,
573                                                 SPIRVWord FilterMode) {
574   return addConstant(new SPIRVConstantSampler(this, TheType, getId(), AddrMode,
575                                               ParametricMode, FilterMode));
576 }
577 
addPipeStorageConstant(SPIRVType * TheType,SPIRVWord PacketSize,SPIRVWord PacketAlign,SPIRVWord Capacity)578 SPIRVValue *SPIRVModuleImpl::addPipeStorageConstant(SPIRVType *TheType,
579                                                     SPIRVWord PacketSize,
580                                                     SPIRVWord PacketAlign,
581                                                     SPIRVWord Capacity) {
582   return addConstant(new SPIRVConstantPipeStorage(
583       this, TheType, getId(), PacketSize, PacketAlign, Capacity));
584 }
585 
addExtension(ExtensionID Ext)586 void SPIRVModuleImpl::addExtension(ExtensionID Ext) {
587   std::string ExtName;
588   SPIRVMap<ExtensionID, std::string>::find(Ext, &ExtName);
589   if (!getErrorLog().checkError(isAllowedToUseExtension(Ext),
590                                 SPIRVEC_RequiresExtension, ExtName)) {
591     setInvalid();
592     return;
593   }
594   SPIRVExt.insert(ExtName);
595 }
596 
addCapability(SPIRVCapabilityKind Cap)597 void SPIRVModuleImpl::addCapability(SPIRVCapabilityKind Cap) {
598   addCapabilities(SPIRV::getCapability(Cap));
599   SPIRVDBG(spvdbgs() << "addCapability: " << SPIRVCapabilityNameMap::map(Cap)
600                      << '\n');
601   if (hasCapability(Cap))
602     return;
603 
604   auto *CapObj = new SPIRVCapability(this, Cap);
605   if (AutoAddExtensions) {
606     // While we are reading existing SPIR-V we need to read it as-is and don't
607     // add required extensions for each entry automatically
608     auto Ext = CapObj->getRequiredExtension();
609     if (Ext.hasValue())
610       addExtension(Ext.getValue());
611   }
612 
613   CapMap.insert(std::make_pair(Cap, CapObj));
614 }
615 
addCapabilityInternal(SPIRVCapabilityKind Cap)616 void SPIRVModuleImpl::addCapabilityInternal(SPIRVCapabilityKind Cap) {
617   if (AutoAddCapability) {
618     if (hasCapability(Cap))
619       return;
620 
621     CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap)));
622   }
623 }
624 
getLiteralAsConstant(unsigned Literal)625 SPIRVConstant *SPIRVModuleImpl::getLiteralAsConstant(unsigned Literal) {
626   auto Loc = LiteralMap.find(Literal);
627   if (Loc != LiteralMap.end())
628     return Loc->second;
629   auto Ty = addIntegerType(32);
630   auto V = new SPIRVConstant(this, Ty, getId(), static_cast<uint64_t>(Literal));
631   LiteralMap[Literal] = V;
632   addConstant(V);
633   return V;
634 }
635 
layoutEntry(SPIRVEntry * E)636 void SPIRVModuleImpl::layoutEntry(SPIRVEntry *E) {
637   auto OC = E->getOpCode();
638   int IntOC = static_cast<int>(OC);
639   switch (IntOC) {
640   case OpString:
641     addTo(StringVec, E);
642     break;
643   case OpMemberName:
644     addTo(MemberNameVec, E);
645     break;
646   case OpVariable: {
647     auto BV = static_cast<SPIRVVariable *>(E);
648     if (!BV->getParent())
649       addTo(VariableVec, E);
650   } break;
651   case OpExtInst: {
652     SPIRVExtInst *EI = static_cast<SPIRVExtInst *>(E);
653     if ((EI->getExtSetKind() == SPIRVEIS_Debug ||
654          EI->getExtSetKind() == SPIRVEIS_OpenCL_DebugInfo_100) &&
655         EI->getExtOp() != SPIRVDebug::Declare &&
656         EI->getExtOp() != SPIRVDebug::Value &&
657         EI->getExtOp() != SPIRVDebug::Scope &&
658         EI->getExtOp() != SPIRVDebug::NoScope) {
659       DebugInstVec.push_back(EI);
660     }
661     break;
662   }
663   case OpAsmTargetINTEL: {
664     addTo(AsmTargetVec, E);
665     break;
666   }
667   case internal::OpAliasDomainDeclINTEL:
668   case internal::OpAliasScopeDeclINTEL:
669   case internal::OpAliasScopeListDeclINTEL: {
670     addTo(AliasInstMDVec, E);
671     break;
672   }
673   case OpAsmINTEL: {
674     addTo(AsmVec, E);
675     break;
676   }
677   default:
678     if (isTypeOpCode(OC))
679       TypeVec.push_back(static_cast<SPIRVType *>(E));
680     else if (isConstantOpCode(OC))
681       ConstVec.push_back(static_cast<SPIRVConstant *>(E));
682     break;
683   }
684 }
685 
686 // Add an entry to the id to entry map.
687 // Assert if the id is mapped to a different entry.
688 // Certain entries need to be add to specific collectors to maintain
689 // logic layout of SPIRV.
addEntry(SPIRVEntry * Entry)690 SPIRVEntry *SPIRVModuleImpl::addEntry(SPIRVEntry *Entry) {
691   assert(Entry && "Invalid entry");
692   if (Entry->hasId()) {
693     SPIRVId Id = Entry->getId();
694     assert(Entry->getId() != SPIRVID_INVALID && "Invalid id");
695     SPIRVEntry *Mapped = nullptr;
696     if (exist(Id, &Mapped)) {
697       if (Mapped->getOpCode() == internal::OpForward) {
698         replaceForward(static_cast<SPIRVForward *>(Mapped), Entry);
699       } else {
700         assert(Mapped == Entry && "Id used twice");
701       }
702     } else
703       IdEntryMap[Id] = Entry;
704   } else {
705     // Entry of OpLine will be deleted by std::shared_ptr automatically.
706     if (Entry->getOpCode() != OpLine)
707       EntryNoId.insert(Entry);
708   }
709 
710   Entry->setModule(this);
711 
712   layoutEntry(Entry);
713   if (AutoAddCapability) {
714     for (auto &I : Entry->getRequiredCapability()) {
715       addCapability(I);
716     }
717   }
718   if (ValidateCapability) {
719     assert(none_of(
720         Entry->getRequiredCapability().begin(),
721         Entry->getRequiredCapability().end(),
722         [this](SPIRVCapabilityKind &val) { return !CapMap.count(val); }));
723   }
724   if (AutoAddExtensions) {
725     // While we are reading existing SPIR-V we need to read it as-is and don't
726     // add required extensions for each entry automatically
727     auto Ext = Entry->getRequiredExtension();
728     if (Ext.hasValue())
729       addExtension(Ext.getValue());
730   }
731 
732   return Entry;
733 }
734 
exist(SPIRVId Id) const735 bool SPIRVModuleImpl::exist(SPIRVId Id) const { return exist(Id, nullptr); }
736 
exist(SPIRVId Id,SPIRVEntry ** Entry) const737 bool SPIRVModuleImpl::exist(SPIRVId Id, SPIRVEntry **Entry) const {
738   assert(Id != SPIRVID_INVALID && "Invalid Id");
739   SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
740   if (Loc == IdEntryMap.end())
741     return false;
742   if (Entry)
743     *Entry = Loc->second;
744   return true;
745 }
746 
747 // If Id is invalid, returns the next available id.
748 // Otherwise returns the given id and adjust the next available id by increment.
getId(SPIRVId Id,unsigned Increment)749 SPIRVId SPIRVModuleImpl::getId(SPIRVId Id, unsigned Increment) {
750   if (!isValidId(Id))
751     Id = NextId;
752   else
753     NextId = std::max(Id, NextId);
754   NextId += Increment;
755   return Id;
756 }
757 
getEntry(SPIRVId Id) const758 SPIRVEntry *SPIRVModuleImpl::getEntry(SPIRVId Id) const {
759   assert(Id != SPIRVID_INVALID && "Invalid Id");
760   SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
761   assert(Loc != IdEntryMap.end() && "Id is not in map");
762   return Loc->second;
763 }
764 
getBuiltinSet(SPIRVId SetId) const765 SPIRVExtInstSetKind SPIRVModuleImpl::getBuiltinSet(SPIRVId SetId) const {
766   auto Loc = IdToInstSetMap.find(SetId);
767   assert(Loc != IdToInstSetMap.end() && "Invalid builtin set id");
768   return Loc->second;
769 }
770 
isEntryPoint(SPIRVExecutionModelKind ExecModel,SPIRVId EP) const771 bool SPIRVModuleImpl::isEntryPoint(SPIRVExecutionModelKind ExecModel,
772                                    SPIRVId EP) const {
773   assert(isValid(ExecModel) && "Invalid execution model");
774   assert(EP != SPIRVID_INVALID && "Invalid function id");
775   auto Loc = EntryPointSet.find(ExecModel);
776   if (Loc == EntryPointSet.end())
777     return false;
778   return Loc->second.count(EP);
779 }
780 
781 // Module change functions
importBuiltinSet(const std::string & BuiltinSetName,SPIRVId * BuiltinSetId)782 bool SPIRVModuleImpl::importBuiltinSet(const std::string &BuiltinSetName,
783                                        SPIRVId *BuiltinSetId) {
784   SPIRVId TmpBuiltinSetId = getId();
785   if (!importBuiltinSetWithId(BuiltinSetName, TmpBuiltinSetId))
786     return false;
787   if (BuiltinSetId)
788     *BuiltinSetId = TmpBuiltinSetId;
789   return true;
790 }
791 
importBuiltinSetWithId(const std::string & BuiltinSetName,SPIRVId BuiltinSetId)792 bool SPIRVModuleImpl::importBuiltinSetWithId(const std::string &BuiltinSetName,
793                                              SPIRVId BuiltinSetId) {
794   SPIRVExtInstSetKind BuiltinSet = SPIRVEIS_Count;
795   SPIRVCKRT(SPIRVBuiltinSetNameMap::rfind(BuiltinSetName, &BuiltinSet),
796             InvalidBuiltinSetName, "Actual is " + BuiltinSetName);
797   IdToInstSetMap[BuiltinSetId] = BuiltinSet;
798   ExtInstSetIds[BuiltinSet] = BuiltinSetId;
799   return true;
800 }
801 
setAlignment(SPIRVValue * V,SPIRVWord A)802 void SPIRVModuleImpl::setAlignment(SPIRVValue *V, SPIRVWord A) {
803   V->setAlignment(A);
804 }
805 
setName(SPIRVEntry * E,const std::string & Name)806 void SPIRVModuleImpl::setName(SPIRVEntry *E, const std::string &Name) {
807   E->setName(Name);
808   if (!E->hasId())
809     return;
810   if (!Name.empty())
811     NamedId.insert(E->getId());
812   else
813     NamedId.erase(E->getId());
814 }
815 
resolveUnknownStructFields()816 void SPIRVModuleImpl::resolveUnknownStructFields() {
817   for (auto &KV : UnknownStructFieldMap) {
818     auto *Struct = KV.first;
819     for (auto &Indices : KV.second) {
820       unsigned I = Indices.first;
821       SPIRVId ID = Indices.second;
822 
823       auto Ty = static_cast<SPIRVType *>(getEntry(ID));
824       Struct->setMemberType(I, Ty);
825     }
826   }
827 }
828 
829 // Type creation functions
addType(T * Ty)830 template <class T> T *SPIRVModuleImpl::addType(T *Ty) {
831   add(Ty);
832   if (!Ty->getName().empty())
833     setName(Ty, Ty->getName());
834   return Ty;
835 }
836 
addVoidType()837 SPIRVTypeVoid *SPIRVModuleImpl::addVoidType() {
838   return addType(new SPIRVTypeVoid(this, getId()));
839 }
840 
addArrayType(SPIRVType * ElementType,SPIRVConstant * Length)841 SPIRVTypeArray *SPIRVModuleImpl::addArrayType(SPIRVType *ElementType,
842                                               SPIRVConstant *Length) {
843   return addType(new SPIRVTypeArray(this, getId(), ElementType, Length));
844 }
845 
addBoolType()846 SPIRVTypeBool *SPIRVModuleImpl::addBoolType() {
847   return addType(new SPIRVTypeBool(this, getId()));
848 }
849 
addIntegerType(unsigned BitWidth)850 SPIRVTypeInt *SPIRVModuleImpl::addIntegerType(unsigned BitWidth) {
851   auto Loc = IntTypeMap.find(BitWidth);
852   if (Loc != IntTypeMap.end())
853     return Loc->second;
854   auto Ty = new SPIRVTypeInt(this, getId(), BitWidth, false);
855   IntTypeMap[BitWidth] = Ty;
856   return addType(Ty);
857 }
858 
addFloatType(unsigned BitWidth)859 SPIRVTypeFloat *SPIRVModuleImpl::addFloatType(unsigned BitWidth) {
860   SPIRVTypeFloat *T = addType(new SPIRVTypeFloat(this, getId(), BitWidth));
861   return T;
862 }
863 
864 SPIRVTypePointer *
addPointerType(SPIRVStorageClassKind StorageClass,SPIRVType * ElementType)865 SPIRVModuleImpl::addPointerType(SPIRVStorageClassKind StorageClass,
866                                 SPIRVType *ElementType) {
867   return addType(
868       new SPIRVTypePointer(this, getId(), StorageClass, ElementType));
869 }
870 
addFunctionType(SPIRVType * ReturnType,const std::vector<SPIRVType * > & ParameterTypes)871 SPIRVTypeFunction *SPIRVModuleImpl::addFunctionType(
872     SPIRVType *ReturnType, const std::vector<SPIRVType *> &ParameterTypes) {
873   return addType(
874       new SPIRVTypeFunction(this, getId(), ReturnType, ParameterTypes));
875 }
876 
addOpaqueType(const std::string & Name)877 SPIRVTypeOpaque *SPIRVModuleImpl::addOpaqueType(const std::string &Name) {
878   return addType(new SPIRVTypeOpaque(this, getId(), Name));
879 }
880 
openStructType(unsigned NumMembers,const std::string & Name)881 SPIRVTypeStruct *SPIRVModuleImpl::openStructType(unsigned NumMembers,
882                                                  const std::string &Name) {
883   auto T = new SPIRVTypeStruct(this, getId(), NumMembers, Name);
884   return T;
885 }
886 
addTypeStructContinuedINTEL(unsigned NumMembers)887 SPIRVEntry *SPIRVModuleImpl::addTypeStructContinuedINTEL(unsigned NumMembers) {
888   return add(new SPIRVTypeStructContinuedINTEL(this, NumMembers));
889 }
890 
closeStructType(SPIRVTypeStruct * T,bool Packed)891 void SPIRVModuleImpl::closeStructType(SPIRVTypeStruct *T, bool Packed) {
892   addType(T);
893   T->setPacked(Packed);
894 }
895 
addVectorType(SPIRVType * CompType,SPIRVWord CompCount)896 SPIRVTypeVector *SPIRVModuleImpl::addVectorType(SPIRVType *CompType,
897                                                 SPIRVWord CompCount) {
898   return addType(new SPIRVTypeVector(this, getId(), CompType, CompCount));
899 }
addOpaqueGenericType(Op TheOpCode)900 SPIRVType *SPIRVModuleImpl::addOpaqueGenericType(Op TheOpCode) {
901   return addType(new SPIRVTypeOpaqueGeneric(TheOpCode, this, getId()));
902 }
903 
addDeviceEventType()904 SPIRVTypeDeviceEvent *SPIRVModuleImpl::addDeviceEventType() {
905   return addType(new SPIRVTypeDeviceEvent(this, getId()));
906 }
907 
addQueueType()908 SPIRVTypeQueue *SPIRVModuleImpl::addQueueType() {
909   return addType(new SPIRVTypeQueue(this, getId()));
910 }
911 
addPipeType()912 SPIRVTypePipe *SPIRVModuleImpl::addPipeType() {
913   return addType(new SPIRVTypePipe(this, getId()));
914 }
915 
916 SPIRVTypeImage *
addImageType(SPIRVType * SampledType,const SPIRVTypeImageDescriptor & Desc)917 SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
918                               const SPIRVTypeImageDescriptor &Desc) {
919   return addType(new SPIRVTypeImage(
920       this, getId(), SampledType ? SampledType->getId() : 0, Desc));
921 }
922 
923 SPIRVTypeImage *
addImageType(SPIRVType * SampledType,const SPIRVTypeImageDescriptor & Desc,SPIRVAccessQualifierKind Acc)924 SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
925                               const SPIRVTypeImageDescriptor &Desc,
926                               SPIRVAccessQualifierKind Acc) {
927   return addType(new SPIRVTypeImage(
928       this, getId(), SampledType ? SampledType->getId() : 0, Desc, Acc));
929 }
930 
addSamplerType()931 SPIRVTypeSampler *SPIRVModuleImpl::addSamplerType() {
932   return addType(new SPIRVTypeSampler(this, getId()));
933 }
934 
addPipeStorageType()935 SPIRVTypePipeStorage *SPIRVModuleImpl::addPipeStorageType() {
936   return addType(new SPIRVTypePipeStorage(this, getId()));
937 }
938 
addSampledImageType(SPIRVTypeImage * T)939 SPIRVTypeSampledImage *SPIRVModuleImpl::addSampledImageType(SPIRVTypeImage *T) {
940   return addType(new SPIRVTypeSampledImage(this, getId(), T));
941 }
942 
943 SPIRVTypeVmeImageINTEL *
addVmeImageINTELType(SPIRVTypeImage * T)944 SPIRVModuleImpl::addVmeImageINTELType(SPIRVTypeImage *T) {
945   return addType(new SPIRVTypeVmeImageINTEL(this, getId(), T));
946 }
947 
948 SPIRVTypeBufferSurfaceINTEL *
addBufferSurfaceINTELType(SPIRVAccessQualifierKind Access)949 SPIRVModuleImpl::addBufferSurfaceINTELType(SPIRVAccessQualifierKind Access) {
950   return addType(new SPIRVTypeBufferSurfaceINTEL(this, getId(), Access));
951 }
952 
addSubgroupAvcINTELType(Op TheOpCode)953 SPIRVType *SPIRVModuleImpl::addSubgroupAvcINTELType(Op TheOpCode) {
954   return addType(new SPIRVTypeSubgroupAvcINTEL(TheOpCode, this, getId()));
955 }
956 
addTokenTypeINTEL()957 SPIRVTypeTokenINTEL *SPIRVModuleImpl::addTokenTypeINTEL() {
958   return addType(new SPIRVTypeTokenINTEL(this, getId()));
959 }
960 
addFunction(SPIRVFunction * Func)961 SPIRVFunction *SPIRVModuleImpl::addFunction(SPIRVFunction *Func) {
962   FuncVec.push_back(add(Func));
963   return Func;
964 }
965 
addFunction(SPIRVTypeFunction * FuncType,SPIRVId Id)966 SPIRVFunction *SPIRVModuleImpl::addFunction(SPIRVTypeFunction *FuncType,
967                                             SPIRVId Id) {
968   return addFunction(new SPIRVFunction(
969       this, FuncType, getId(Id, FuncType->getNumParameters() + 1)));
970 }
971 
addBasicBlock(SPIRVFunction * Func,SPIRVId Id)972 SPIRVBasicBlock *SPIRVModuleImpl::addBasicBlock(SPIRVFunction *Func,
973                                                 SPIRVId Id) {
974   return Func->addBasicBlock(new SPIRVBasicBlock(getId(Id), Func));
975 }
976 
977 const SPIRVDecorateGeneric *
addDecorate(SPIRVDecorateGeneric * Dec)978 SPIRVModuleImpl::addDecorate(SPIRVDecorateGeneric *Dec) {
979   add(Dec);
980   SPIRVId Id = Dec->getTargetId();
981   bool Found = exist(Id);
982   (void)Found;
983   assert(Found && "Decorate target does not exist");
984   if (!Dec->getOwner())
985     DecorateSet.insert(Dec);
986   addCapabilities(Dec->getRequiredCapability());
987   return Dec;
988 }
989 
addEntryPoint(SPIRVExecutionModelKind ExecModel,SPIRVId EntryPoint)990 void SPIRVModuleImpl::addEntryPoint(SPIRVExecutionModelKind ExecModel,
991                                     SPIRVId EntryPoint) {
992   assert(isValid(ExecModel) && "Invalid execution model");
993   assert(EntryPoint != SPIRVID_INVALID && "Invalid entry point");
994   EntryPointSet[ExecModel].insert(EntryPoint);
995   EntryPointVec[ExecModel].push_back(EntryPoint);
996   addCapabilities(SPIRV::getCapability(ExecModel));
997 }
998 
addForward(SPIRVType * Ty)999 SPIRVForward *SPIRVModuleImpl::addForward(SPIRVType *Ty) {
1000   return add(new SPIRVForward(this, Ty, getId()));
1001 }
1002 
addForward(SPIRVId Id,SPIRVType * Ty)1003 SPIRVForward *SPIRVModuleImpl::addForward(SPIRVId Id, SPIRVType *Ty) {
1004   return add(new SPIRVForward(this, Ty, Id));
1005 }
1006 
replaceForward(SPIRVForward * Forward,SPIRVEntry * Entry)1007 SPIRVEntry *SPIRVModuleImpl::replaceForward(SPIRVForward *Forward,
1008                                             SPIRVEntry *Entry) {
1009   SPIRVId Id = Entry->getId();
1010   SPIRVId ForwardId = Forward->getId();
1011   if (ForwardId == Id)
1012     IdEntryMap[Id] = Entry;
1013   else {
1014     auto Loc = IdEntryMap.find(Id);
1015     assert(Loc != IdEntryMap.end());
1016     IdEntryMap.erase(Loc);
1017     Entry->setId(ForwardId);
1018     IdEntryMap[ForwardId] = Entry;
1019   }
1020   // Annotations include name, decorations, execution modes
1021   Entry->takeAnnotations(Forward);
1022   delete Forward;
1023   return Entry;
1024 }
1025 
eraseInstruction(SPIRVInstruction * I,SPIRVBasicBlock * BB)1026 void SPIRVModuleImpl::eraseInstruction(SPIRVInstruction *I,
1027                                        SPIRVBasicBlock *BB) {
1028   SPIRVId Id = I->getId();
1029   BB->eraseInstruction(I);
1030   auto Loc = IdEntryMap.find(Id);
1031   assert(Loc != IdEntryMap.end());
1032   IdEntryMap.erase(Loc);
1033   delete I;
1034 }
1035 
addConstant(SPIRVValue * C)1036 SPIRVValue *SPIRVModuleImpl::addConstant(SPIRVValue *C) { return add(C); }
1037 
addConstant(SPIRVType * Ty,uint64_t V)1038 SPIRVValue *SPIRVModuleImpl::addConstant(SPIRVType *Ty, uint64_t V) {
1039   if (Ty->isTypeBool()) {
1040     if (V)
1041       return addConstant(new SPIRVConstantTrue(this, Ty, getId()));
1042     else
1043       return addConstant(new SPIRVConstantFalse(this, Ty, getId()));
1044   }
1045   if (Ty->isTypeInt())
1046     return addIntegerConstant(static_cast<SPIRVTypeInt *>(Ty), V);
1047   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
1048 }
1049 
addConstant(SPIRVType * Ty,llvm::APInt V)1050 SPIRVValue *SPIRVModuleImpl::addConstant(SPIRVType *Ty, llvm::APInt V) {
1051   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
1052 }
1053 
addIntegerConstant(SPIRVTypeInt * Ty,uint64_t V)1054 SPIRVValue *SPIRVModuleImpl::addIntegerConstant(SPIRVTypeInt *Ty, uint64_t V) {
1055   if (Ty->getBitWidth() == 32) {
1056     unsigned I32 = static_cast<unsigned>(V);
1057     assert(I32 == V && "Integer value truncated");
1058     return getLiteralAsConstant(I32);
1059   }
1060   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
1061 }
1062 
addFloatConstant(SPIRVTypeFloat * Ty,float V)1063 SPIRVValue *SPIRVModuleImpl::addFloatConstant(SPIRVTypeFloat *Ty, float V) {
1064   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
1065 }
1066 
addDoubleConstant(SPIRVTypeFloat * Ty,double V)1067 SPIRVValue *SPIRVModuleImpl::addDoubleConstant(SPIRVTypeFloat *Ty, double V) {
1068   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
1069 }
1070 
addNullConstant(SPIRVType * Ty)1071 SPIRVValue *SPIRVModuleImpl::addNullConstant(SPIRVType *Ty) {
1072   return addConstant(new SPIRVConstantNull(this, Ty, getId()));
1073 }
1074 
addCompositeConstant(SPIRVType * Ty,const std::vector<SPIRVValue * > & Elements)1075 SPIRVValue *SPIRVModuleImpl::addCompositeConstant(
1076     SPIRVType *Ty, const std::vector<SPIRVValue *> &Elements) {
1077   constexpr int MaxNumElements = MaxWordCount - SPIRVConstantComposite::FixedWC;
1078   const int NumElements = Elements.size();
1079 
1080   // In case number of elements is greater than maximum WordCount and
1081   // SPV_INTEL_long_constant_composite is not enabled, the error will be emitted
1082   // by validate functionality of SPIRVCompositeConstant class.
1083   if (NumElements <= MaxNumElements ||
1084       !isAllowedToUseExtension(ExtensionID::SPV_INTEL_long_constant_composite))
1085     return addConstant(new SPIRVConstantComposite(this, Ty, getId(), Elements));
1086 
1087   auto Start = Elements.begin();
1088   auto End = Start + MaxNumElements;
1089   std::vector<SPIRVValue *> Slice(Start, End);
1090   auto *Res =
1091       static_cast<SPIRVConstantComposite *>(addCompositeConstant(Ty, Slice));
1092   for (; End != Elements.end();) {
1093     Start = End;
1094     End = ((Elements.end() - End) > MaxNumElements) ? End + MaxNumElements
1095                                                     : Elements.end();
1096     Slice.assign(Start, End);
1097     auto Continued = static_cast<SPIRVConstantComposite::ContinuedInstType>(
1098         addCompositeConstantContinuedINTEL(Slice));
1099     Res->addContinuedInstruction(Continued);
1100   }
1101   return Res;
1102 }
1103 
addCompositeConstantContinuedINTEL(const std::vector<SPIRVValue * > & Elements)1104 SPIRVEntry *SPIRVModuleImpl::addCompositeConstantContinuedINTEL(
1105     const std::vector<SPIRVValue *> &Elements) {
1106   return add(new SPIRVConstantCompositeContinuedINTEL(this, Elements));
1107 }
1108 
addSpecConstantComposite(SPIRVType * Ty,const std::vector<SPIRVValue * > & Elements)1109 SPIRVValue *SPIRVModuleImpl::addSpecConstantComposite(
1110     SPIRVType *Ty, const std::vector<SPIRVValue *> &Elements) {
1111   constexpr int MaxNumElements =
1112       MaxWordCount - SPIRVSpecConstantComposite::FixedWC;
1113   const int NumElements = Elements.size();
1114 
1115   // In case number of elements is greater than maximum WordCount and
1116   // SPV_INTEL_long_constant_composite is not enabled, the error will be emitted
1117   // by validate functionality of SPIRVSpecConstantComposite class.
1118   if (NumElements <= MaxNumElements ||
1119       !isAllowedToUseExtension(ExtensionID::SPV_INTEL_long_constant_composite))
1120     return addConstant(
1121         new SPIRVSpecConstantComposite(this, Ty, getId(), Elements));
1122 
1123   auto Start = Elements.begin();
1124   auto End = Start + MaxNumElements;
1125   std::vector<SPIRVValue *> Slice(Start, End);
1126   auto *Res = static_cast<SPIRVSpecConstantComposite *>(
1127       addSpecConstantComposite(Ty, Slice));
1128   for (; End != Elements.end();) {
1129     Start = End;
1130     End = ((Elements.end() - End) > MaxNumElements) ? End + MaxNumElements
1131                                                     : Elements.end();
1132     Slice.assign(Start, End);
1133     auto Continued = static_cast<SPIRVSpecConstantComposite::ContinuedInstType>(
1134         addSpecConstantCompositeContinuedINTEL(Slice));
1135     Res->addContinuedInstruction(Continued);
1136   }
1137   return Res;
1138 }
1139 
addSpecConstantCompositeContinuedINTEL(const std::vector<SPIRVValue * > & Elements)1140 SPIRVEntry *SPIRVModuleImpl::addSpecConstantCompositeContinuedINTEL(
1141     const std::vector<SPIRVValue *> &Elements) {
1142   return add(new SPIRVSpecConstantCompositeContinuedINTEL(this, Elements));
1143 }
1144 
addConstFunctionPointerINTEL(SPIRVType * Ty,SPIRVFunction * F)1145 SPIRVValue *SPIRVModuleImpl::addConstFunctionPointerINTEL(SPIRVType *Ty,
1146                                                           SPIRVFunction *F) {
1147   return addConstant(new SPIRVConstFunctionPointerINTEL(getId(), Ty, F, this));
1148 }
1149 
addUndef(SPIRVType * TheType)1150 SPIRVValue *SPIRVModuleImpl::addUndef(SPIRVType *TheType) {
1151   return addConstant(new SPIRVUndef(this, TheType, getId()));
1152 }
1153 
addSpecConstant(SPIRVType * Ty,uint64_t V)1154 SPIRVValue *SPIRVModuleImpl::addSpecConstant(SPIRVType *Ty, uint64_t V) {
1155   if (Ty->isTypeBool()) {
1156     if (V)
1157       return add(new SPIRVSpecConstantTrue(this, Ty, getId()));
1158     else
1159       return add(new SPIRVSpecConstantFalse(this, Ty, getId()));
1160   }
1161   return add(new SPIRVSpecConstant(this, Ty, getId(), V));
1162 }
1163 
1164 // Instruction creation functions
1165 
1166 SPIRVInstruction *
addStoreInst(SPIRVValue * Target,SPIRVValue * Source,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)1167 SPIRVModuleImpl::addStoreInst(SPIRVValue *Target, SPIRVValue *Source,
1168                               const std::vector<SPIRVWord> &TheMemoryAccess,
1169                               SPIRVBasicBlock *BB) {
1170   return BB->addInstruction(
1171       new SPIRVStore(Target->getId(), Source->getId(), TheMemoryAccess, BB));
1172 }
1173 
addSwitchInst(SPIRVValue * Select,SPIRVBasicBlock * Default,const std::vector<std::pair<std::vector<SPIRVWord>,SPIRVBasicBlock * >> & Pairs,SPIRVBasicBlock * BB)1174 SPIRVInstruction *SPIRVModuleImpl::addSwitchInst(
1175     SPIRVValue *Select, SPIRVBasicBlock *Default,
1176     const std::vector<std::pair<std::vector<SPIRVWord>, SPIRVBasicBlock *>>
1177         &Pairs,
1178     SPIRVBasicBlock *BB) {
1179   return BB->addInstruction(new SPIRVSwitch(Select, Default, Pairs, BB));
1180 }
1181 
1182 SPIRVInstruction *
addVectorTimesScalarInst(SPIRVType * TheType,SPIRVId TheVector,SPIRVId TheScalar,SPIRVBasicBlock * BB)1183 SPIRVModuleImpl::addVectorTimesScalarInst(SPIRVType *TheType, SPIRVId TheVector,
1184                                           SPIRVId TheScalar,
1185                                           SPIRVBasicBlock *BB) {
1186   return BB->addInstruction(
1187       new SPIRVVectorTimesScalar(TheType, getId(), TheVector, TheScalar, BB));
1188 }
1189 
1190 SPIRVInstruction *
addVectorTimesMatrixInst(SPIRVType * TheType,SPIRVId TheVector,SPIRVId TheMatrix,SPIRVBasicBlock * BB)1191 SPIRVModuleImpl::addVectorTimesMatrixInst(SPIRVType *TheType, SPIRVId TheVector,
1192                                           SPIRVId TheMatrix,
1193                                           SPIRVBasicBlock *BB) {
1194   return BB->addInstruction(
1195       new SPIRVVectorTimesMatrix(TheType, getId(), TheVector, TheMatrix, BB));
1196 }
1197 
1198 SPIRVInstruction *
addMatrixTimesScalarInst(SPIRVType * TheType,SPIRVId TheMatrix,SPIRVId TheScalar,SPIRVBasicBlock * BB)1199 SPIRVModuleImpl::addMatrixTimesScalarInst(SPIRVType *TheType, SPIRVId TheMatrix,
1200                                           SPIRVId TheScalar,
1201                                           SPIRVBasicBlock *BB) {
1202   return BB->addInstruction(
1203       new SPIRVMatrixTimesScalar(TheType, getId(), TheMatrix, TheScalar, BB));
1204 }
1205 
1206 SPIRVInstruction *
addMatrixTimesVectorInst(SPIRVType * TheType,SPIRVId TheMatrix,SPIRVId TheVector,SPIRVBasicBlock * BB)1207 SPIRVModuleImpl::addMatrixTimesVectorInst(SPIRVType *TheType, SPIRVId TheMatrix,
1208                                           SPIRVId TheVector,
1209                                           SPIRVBasicBlock *BB) {
1210   return BB->addInstruction(
1211       new SPIRVMatrixTimesVector(TheType, getId(), TheMatrix, TheVector, BB));
1212 }
1213 
1214 SPIRVInstruction *
addMatrixTimesMatrixInst(SPIRVType * TheType,SPIRVId M1,SPIRVId M2,SPIRVBasicBlock * BB)1215 SPIRVModuleImpl::addMatrixTimesMatrixInst(SPIRVType *TheType, SPIRVId M1,
1216                                           SPIRVId M2, SPIRVBasicBlock *BB) {
1217   return BB->addInstruction(
1218       new SPIRVMatrixTimesMatrix(TheType, getId(), M1, M2, BB));
1219 }
1220 
addTransposeInst(SPIRVType * TheType,SPIRVId TheMatrix,SPIRVBasicBlock * BB)1221 SPIRVInstruction *SPIRVModuleImpl::addTransposeInst(SPIRVType *TheType,
1222                                                     SPIRVId TheMatrix,
1223                                                     SPIRVBasicBlock *BB) {
1224   return BB->addInstruction(
1225       new SPIRVTranspose(TheType, getId(), TheMatrix, BB));
1226 }
1227 
1228 SPIRVInstruction *
addGroupInst(Op OpCode,SPIRVType * Type,Scope Scope,const std::vector<SPIRVValue * > & Ops,SPIRVBasicBlock * BB)1229 SPIRVModuleImpl::addGroupInst(Op OpCode, SPIRVType *Type, Scope Scope,
1230                               const std::vector<SPIRVValue *> &Ops,
1231                               SPIRVBasicBlock *BB) {
1232   assert(!Type || !Type->isTypeVoid());
1233   auto WordOps = getIds(Ops);
1234   WordOps.insert(WordOps.begin(), Scope);
1235   return addInstTemplate(OpCode, WordOps, BB, Type);
1236 }
1237 
1238 SPIRVInstruction *
addInstruction(SPIRVInstruction * Inst,SPIRVBasicBlock * BB,SPIRVInstruction * InsertBefore)1239 SPIRVModuleImpl::addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB,
1240                                 SPIRVInstruction *InsertBefore) {
1241   if (BB)
1242     return BB->addInstruction(Inst, InsertBefore);
1243   if (Inst->getOpCode() != OpSpecConstantOp) {
1244     SPIRVInstruction *Res = createSpecConstantOpInst(Inst);
1245     delete Inst;
1246     Inst = Res;
1247   }
1248   return static_cast<SPIRVInstruction *>(addConstant(Inst));
1249 }
1250 
1251 SPIRVInstruction *
addLoadInst(SPIRVValue * Source,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)1252 SPIRVModuleImpl::addLoadInst(SPIRVValue *Source,
1253                              const std::vector<SPIRVWord> &TheMemoryAccess,
1254                              SPIRVBasicBlock *BB) {
1255   return addInstruction(
1256       new SPIRVLoad(getId(), Source->getId(), TheMemoryAccess, BB), BB);
1257 }
1258 
1259 SPIRVInstruction *
addPhiInst(SPIRVType * Type,std::vector<SPIRVValue * > IncomingPairs,SPIRVBasicBlock * BB)1260 SPIRVModuleImpl::addPhiInst(SPIRVType *Type,
1261                             std::vector<SPIRVValue *> IncomingPairs,
1262                             SPIRVBasicBlock *BB) {
1263   return addInstruction(new SPIRVPhi(Type, getId(), IncomingPairs, BB), BB);
1264 }
1265 
addExtInst(SPIRVType * TheType,SPIRVWord BuiltinSet,SPIRVWord EntryPoint,const std::vector<SPIRVWord> & Args,SPIRVBasicBlock * BB,SPIRVInstruction * InsertBefore)1266 SPIRVInstruction *SPIRVModuleImpl::addExtInst(
1267     SPIRVType *TheType, SPIRVWord BuiltinSet, SPIRVWord EntryPoint,
1268     const std::vector<SPIRVWord> &Args, SPIRVBasicBlock *BB,
1269     SPIRVInstruction *InsertBefore) {
1270   return addInstruction(
1271       new SPIRVExtInst(TheType, getId(), BuiltinSet, EntryPoint, Args, BB), BB,
1272       InsertBefore);
1273 }
1274 
addExtInst(SPIRVType * TheType,SPIRVWord BuiltinSet,SPIRVWord EntryPoint,const std::vector<SPIRVValue * > & Args,SPIRVBasicBlock * BB,SPIRVInstruction * InsertBefore)1275 SPIRVInstruction *SPIRVModuleImpl::addExtInst(
1276     SPIRVType *TheType, SPIRVWord BuiltinSet, SPIRVWord EntryPoint,
1277     const std::vector<SPIRVValue *> &Args, SPIRVBasicBlock *BB,
1278     SPIRVInstruction *InsertBefore) {
1279   return addInstruction(
1280       new SPIRVExtInst(TheType, getId(), BuiltinSet, EntryPoint, Args, BB), BB,
1281       InsertBefore);
1282 }
1283 
addDebugInfo(SPIRVWord InstId,SPIRVType * TheType,const std::vector<SPIRVWord> & Args)1284 SPIRVEntry *SPIRVModuleImpl::addDebugInfo(SPIRVWord InstId, SPIRVType *TheType,
1285                                           const std::vector<SPIRVWord> &Args) {
1286   return addEntry(
1287       new SPIRVExtInst(this, getId(), TheType, SPIRVEIS_OpenCL_DebugInfo_100,
1288                        ExtInstSetIds[getDebugInfoEIS()], InstId, Args));
1289 }
1290 
addModuleProcessed(const std::string & Process)1291 SPIRVEntry *SPIRVModuleImpl::addModuleProcessed(const std::string &Process) {
1292   ModuleProcessedVec.push_back(new SPIRVModuleProcessed(this, Process));
1293   return ModuleProcessedVec.back();
1294 }
1295 
getModuleProcessedVec()1296 std::vector<SPIRVModuleProcessed *> SPIRVModuleImpl::getModuleProcessedVec() {
1297   return ModuleProcessedVec;
1298 }
1299 
1300 SPIRVInstruction *
addCallInst(SPIRVFunction * TheFunction,const std::vector<SPIRVWord> & TheArguments,SPIRVBasicBlock * BB)1301 SPIRVModuleImpl::addCallInst(SPIRVFunction *TheFunction,
1302                              const std::vector<SPIRVWord> &TheArguments,
1303                              SPIRVBasicBlock *BB) {
1304   return addInstruction(
1305       new SPIRVFunctionCall(getId(), TheFunction, TheArguments, BB), BB);
1306 }
1307 
addIndirectCallInst(SPIRVValue * TheCalledValue,SPIRVType * TheReturnType,const std::vector<SPIRVWord> & TheArguments,SPIRVBasicBlock * BB)1308 SPIRVInstruction *SPIRVModuleImpl::addIndirectCallInst(
1309     SPIRVValue *TheCalledValue, SPIRVType *TheReturnType,
1310     const std::vector<SPIRVWord> &TheArguments, SPIRVBasicBlock *BB) {
1311   return addInstruction(
1312       new SPIRVFunctionPointerCallINTEL(getId(), TheCalledValue, TheReturnType,
1313                                         TheArguments, BB),
1314       BB);
1315 }
1316 
1317 SPIRVEntry *
getOrAddAsmTargetINTEL(const std::string & TheTarget)1318 SPIRVModuleImpl::getOrAddAsmTargetINTEL(const std::string &TheTarget) {
1319   auto TargetIt = std::find_if(AsmTargetVec.begin(), AsmTargetVec.end(),
1320                                [&TheTarget](const SPIRVAsmTargetINTEL *Target) {
1321                                  return Target->getTarget() == TheTarget;
1322                                });
1323   if (TargetIt == AsmTargetVec.end())
1324     return add(new SPIRVAsmTargetINTEL(this, getId(), TheTarget));
1325   return *TargetIt;
1326 }
1327 
addAsmINTEL(SPIRVTypeFunction * TheType,SPIRVAsmTargetINTEL * TheTarget,const std::string & TheInstructions,const std::string & TheConstraints)1328 SPIRVValue *SPIRVModuleImpl::addAsmINTEL(SPIRVTypeFunction *TheType,
1329                                          SPIRVAsmTargetINTEL *TheTarget,
1330                                          const std::string &TheInstructions,
1331                                          const std::string &TheConstraints) {
1332   auto Asm = new SPIRVAsmINTEL(this, TheType, getId(), TheTarget,
1333                                TheInstructions, TheConstraints);
1334   return add(Asm);
1335 }
1336 
1337 SPIRVInstruction *
addAsmCallINTELInst(SPIRVAsmINTEL * TheAsm,const std::vector<SPIRVWord> & TheArguments,SPIRVBasicBlock * BB)1338 SPIRVModuleImpl::addAsmCallINTELInst(SPIRVAsmINTEL *TheAsm,
1339                                      const std::vector<SPIRVWord> &TheArguments,
1340                                      SPIRVBasicBlock *BB) {
1341   return addInstruction(
1342       new SPIRVAsmCallINTEL(getId(), TheAsm, TheArguments, BB), BB);
1343 }
1344 
addBinaryInst(Op TheOpCode,SPIRVType * Type,SPIRVValue * Op1,SPIRVValue * Op2,SPIRVBasicBlock * BB)1345 SPIRVInstruction *SPIRVModuleImpl::addBinaryInst(Op TheOpCode, SPIRVType *Type,
1346                                                  SPIRVValue *Op1,
1347                                                  SPIRVValue *Op2,
1348                                                  SPIRVBasicBlock *BB) {
1349   return addInstruction(SPIRVInstTemplateBase::create(
1350                             TheOpCode, Type, getId(),
1351                             getVec(Op1->getId(), Op2->getId()), BB, this),
1352                         BB);
1353 }
1354 
addUnreachableInst(SPIRVBasicBlock * BB)1355 SPIRVInstruction *SPIRVModuleImpl::addUnreachableInst(SPIRVBasicBlock *BB) {
1356   return addInstruction(new SPIRVUnreachable(BB), BB);
1357 }
1358 
addReturnInst(SPIRVBasicBlock * BB)1359 SPIRVInstruction *SPIRVModuleImpl::addReturnInst(SPIRVBasicBlock *BB) {
1360   return addInstruction(new SPIRVReturn(BB), BB);
1361 }
1362 
addReturnValueInst(SPIRVValue * ReturnValue,SPIRVBasicBlock * BB)1363 SPIRVInstruction *SPIRVModuleImpl::addReturnValueInst(SPIRVValue *ReturnValue,
1364                                                       SPIRVBasicBlock *BB) {
1365   return addInstruction(new SPIRVReturnValue(ReturnValue, BB), BB);
1366 }
1367 
addUnaryInst(Op TheOpCode,SPIRVType * TheType,SPIRVValue * Op,SPIRVBasicBlock * BB)1368 SPIRVInstruction *SPIRVModuleImpl::addUnaryInst(Op TheOpCode,
1369                                                 SPIRVType *TheType,
1370                                                 SPIRVValue *Op,
1371                                                 SPIRVBasicBlock *BB) {
1372   return addInstruction(
1373       SPIRVInstTemplateBase::create(TheOpCode, TheType, getId(),
1374                                     getVec(Op->getId()), BB, this),
1375       BB);
1376 }
1377 
addVectorExtractDynamicInst(SPIRVValue * TheVector,SPIRVValue * Index,SPIRVBasicBlock * BB)1378 SPIRVInstruction *SPIRVModuleImpl::addVectorExtractDynamicInst(
1379     SPIRVValue *TheVector, SPIRVValue *Index, SPIRVBasicBlock *BB) {
1380   return addInstruction(
1381       new SPIRVVectorExtractDynamic(getId(), TheVector, Index, BB), BB);
1382 }
1383 
addVectorInsertDynamicInst(SPIRVValue * TheVector,SPIRVValue * TheComponent,SPIRVValue * Index,SPIRVBasicBlock * BB)1384 SPIRVInstruction *SPIRVModuleImpl::addVectorInsertDynamicInst(
1385     SPIRVValue *TheVector, SPIRVValue *TheComponent, SPIRVValue *Index,
1386     SPIRVBasicBlock *BB) {
1387   return addInstruction(
1388       new SPIRVVectorInsertDynamic(getId(), TheVector, TheComponent, Index, BB),
1389       BB);
1390 }
1391 
addVectorShuffleInst(SPIRVType * Type,SPIRVValue * Vec1,SPIRVValue * Vec2,const std::vector<SPIRVWord> & Components,SPIRVBasicBlock * BB)1392 SPIRVValue *SPIRVModuleImpl::addVectorShuffleInst(
1393     SPIRVType *Type, SPIRVValue *Vec1, SPIRVValue *Vec2,
1394     const std::vector<SPIRVWord> &Components, SPIRVBasicBlock *BB) {
1395   std::vector<SPIRVId> Ops{Vec1->getId(), Vec2->getId()};
1396   Ops.insert(Ops.end(), Components.begin(), Components.end());
1397 
1398   return addInstruction(SPIRVInstTemplateBase::create(OpVectorShuffle, Type,
1399                                                       getId(), Ops, BB, this),
1400                         BB);
1401 }
1402 
addBranchInst(SPIRVLabel * TargetLabel,SPIRVBasicBlock * BB)1403 SPIRVInstruction *SPIRVModuleImpl::addBranchInst(SPIRVLabel *TargetLabel,
1404                                                  SPIRVBasicBlock *BB) {
1405   return addInstruction(new SPIRVBranch(TargetLabel, BB), BB);
1406 }
1407 
addBranchConditionalInst(SPIRVValue * Condition,SPIRVLabel * TrueLabel,SPIRVLabel * FalseLabel,SPIRVBasicBlock * BB)1408 SPIRVInstruction *SPIRVModuleImpl::addBranchConditionalInst(
1409     SPIRVValue *Condition, SPIRVLabel *TrueLabel, SPIRVLabel *FalseLabel,
1410     SPIRVBasicBlock *BB) {
1411   return addInstruction(
1412       new SPIRVBranchConditional(Condition, TrueLabel, FalseLabel, BB), BB);
1413 }
1414 
addCmpInst(Op TheOpCode,SPIRVType * TheType,SPIRVValue * Op1,SPIRVValue * Op2,SPIRVBasicBlock * BB)1415 SPIRVInstruction *SPIRVModuleImpl::addCmpInst(Op TheOpCode, SPIRVType *TheType,
1416                                               SPIRVValue *Op1, SPIRVValue *Op2,
1417                                               SPIRVBasicBlock *BB) {
1418   return addInstruction(SPIRVInstTemplateBase::create(
1419                             TheOpCode, TheType, getId(),
1420                             getVec(Op1->getId(), Op2->getId()), BB, this),
1421                         BB);
1422 }
1423 
addControlBarrierInst(SPIRVValue * ExecKind,SPIRVValue * MemKind,SPIRVValue * MemSema,SPIRVBasicBlock * BB)1424 SPIRVInstruction *SPIRVModuleImpl::addControlBarrierInst(SPIRVValue *ExecKind,
1425                                                          SPIRVValue *MemKind,
1426                                                          SPIRVValue *MemSema,
1427                                                          SPIRVBasicBlock *BB) {
1428   return addInstruction(new SPIRVControlBarrier(ExecKind, MemKind, MemSema, BB),
1429                         BB);
1430 }
1431 
addLifetimeInst(Op OC,SPIRVValue * Object,SPIRVWord Size,SPIRVBasicBlock * BB)1432 SPIRVInstruction *SPIRVModuleImpl::addLifetimeInst(Op OC, SPIRVValue *Object,
1433                                                    SPIRVWord Size,
1434                                                    SPIRVBasicBlock *BB) {
1435   if (OC == OpLifetimeStart)
1436     return BB->addInstruction(
1437         new SPIRVLifetimeStart(Object->getId(), Size, BB));
1438   else
1439     return BB->addInstruction(new SPIRVLifetimeStop(Object->getId(), Size, BB));
1440 }
1441 
addMemoryBarrierInst(Scope ScopeKind,SPIRVWord MemFlag,SPIRVBasicBlock * BB)1442 SPIRVInstruction *SPIRVModuleImpl::addMemoryBarrierInst(Scope ScopeKind,
1443                                                         SPIRVWord MemFlag,
1444                                                         SPIRVBasicBlock *BB) {
1445   return addInstruction(SPIRVInstTemplateBase::create(
1446                             OpMemoryBarrier, nullptr, SPIRVID_INVALID,
1447                             getVec(static_cast<SPIRVWord>(ScopeKind), MemFlag),
1448                             BB, this),
1449                         BB);
1450 }
1451 
addSelectInst(SPIRVValue * Condition,SPIRVValue * Op1,SPIRVValue * Op2,SPIRVBasicBlock * BB)1452 SPIRVInstruction *SPIRVModuleImpl::addSelectInst(SPIRVValue *Condition,
1453                                                  SPIRVValue *Op1,
1454                                                  SPIRVValue *Op2,
1455                                                  SPIRVBasicBlock *BB) {
1456   return addInstruction(
1457       SPIRVInstTemplateBase::create(
1458           OpSelect, Op1->getType(), getId(),
1459           getVec(Condition->getId(), Op1->getId(), Op2->getId()), BB, this),
1460       BB);
1461 }
1462 
addSelectionMergeInst(SPIRVId MergeBlock,SPIRVWord SelectionControl,SPIRVBasicBlock * BB)1463 SPIRVInstruction *SPIRVModuleImpl::addSelectionMergeInst(
1464     SPIRVId MergeBlock, SPIRVWord SelectionControl, SPIRVBasicBlock *BB) {
1465   return addInstruction(
1466       new SPIRVSelectionMerge(MergeBlock, SelectionControl, BB), BB);
1467 }
1468 
addLoopMergeInst(SPIRVId MergeBlock,SPIRVId ContinueTarget,SPIRVWord LoopControl,std::vector<SPIRVWord> LoopControlParameters,SPIRVBasicBlock * BB)1469 SPIRVInstruction *SPIRVModuleImpl::addLoopMergeInst(
1470     SPIRVId MergeBlock, SPIRVId ContinueTarget, SPIRVWord LoopControl,
1471     std::vector<SPIRVWord> LoopControlParameters, SPIRVBasicBlock *BB) {
1472   return addInstruction(
1473       new SPIRVLoopMerge(MergeBlock, ContinueTarget, LoopControl,
1474                          LoopControlParameters, BB),
1475       BB, const_cast<SPIRVInstruction *>(BB->getTerminateInstr()));
1476 }
1477 
addLoopControlINTELInst(SPIRVWord LoopControl,std::vector<SPIRVWord> LoopControlParameters,SPIRVBasicBlock * BB)1478 SPIRVInstruction *SPIRVModuleImpl::addLoopControlINTELInst(
1479     SPIRVWord LoopControl, std::vector<SPIRVWord> LoopControlParameters,
1480     SPIRVBasicBlock *BB) {
1481   addCapability(CapabilityUnstructuredLoopControlsINTEL);
1482   addExtension(ExtensionID::SPV_INTEL_unstructured_loop_controls);
1483   return addInstruction(
1484       new SPIRVLoopControlINTEL(LoopControl, LoopControlParameters, BB), BB,
1485       const_cast<SPIRVInstruction *>(BB->getTerminateInstr()));
1486 }
1487 
addFixedPointIntelInst(Op OC,SPIRVType * ResTy,SPIRVValue * Input,const std::vector<SPIRVWord> & Ops,SPIRVBasicBlock * BB)1488 SPIRVInstruction *SPIRVModuleImpl::addFixedPointIntelInst(
1489     Op OC, SPIRVType *ResTy, SPIRVValue *Input,
1490     const std::vector<SPIRVWord> &Ops, SPIRVBasicBlock *BB) {
1491   std::vector<SPIRVWord> TheOps = getVec(Input->getId(), Ops);
1492   return addInstruction(
1493       SPIRVInstTemplateBase::create(OC, ResTy, getId(), TheOps, BB, this), BB);
1494 }
1495 
addArbFloatPointIntelInst(Op OC,SPIRVType * ResTy,SPIRVValue * InA,SPIRVValue * InB,const std::vector<SPIRVWord> & Ops,SPIRVBasicBlock * BB)1496 SPIRVInstruction *SPIRVModuleImpl::addArbFloatPointIntelInst(
1497     Op OC, SPIRVType *ResTy, SPIRVValue *InA, SPIRVValue *InB,
1498     const std::vector<SPIRVWord> &Ops, SPIRVBasicBlock *BB) {
1499   // SPIR-V format:
1500   //   A<id> [Literal MA] [B<id>] [Literal MB] [Literal Mout] [Literal Sign]
1501   //   [Literal EnableSubnormals Literal RoundingMode Literal RoundingAccuracy]
1502   auto OpsItr = Ops.begin();
1503   std::vector<SPIRVWord> TheOps = getVec(InA->getId(), *OpsItr++);
1504   if (InB)
1505     TheOps.push_back(InB->getId());
1506   TheOps.insert(TheOps.end(), OpsItr, Ops.end());
1507 
1508   return addInstruction(
1509       SPIRVInstTemplateBase::create(OC, ResTy, getId(), TheOps, BB, this), BB);
1510 }
1511 
1512 SPIRVInstruction *
addPtrAccessChainInst(SPIRVType * Type,SPIRVValue * Base,std::vector<SPIRVValue * > Indices,SPIRVBasicBlock * BB,bool IsInBounds)1513 SPIRVModuleImpl::addPtrAccessChainInst(SPIRVType *Type, SPIRVValue *Base,
1514                                        std::vector<SPIRVValue *> Indices,
1515                                        SPIRVBasicBlock *BB, bool IsInBounds) {
1516   return addInstruction(
1517       SPIRVInstTemplateBase::create(
1518           IsInBounds ? OpInBoundsPtrAccessChain : OpPtrAccessChain, Type,
1519           getId(), getVec(Base->getId(), Base->getIds(Indices)), BB, this),
1520       BB);
1521 }
1522 
addAsyncGroupCopy(SPIRVValue * Scope,SPIRVValue * Dest,SPIRVValue * Src,SPIRVValue * NumElems,SPIRVValue * Stride,SPIRVValue * Event,SPIRVBasicBlock * BB)1523 SPIRVInstruction *SPIRVModuleImpl::addAsyncGroupCopy(
1524     SPIRVValue *Scope, SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems,
1525     SPIRVValue *Stride, SPIRVValue *Event, SPIRVBasicBlock *BB) {
1526   return addInstruction(new SPIRVGroupAsyncCopy(Scope, getId(), Dest, Src,
1527                                                 NumElems, Stride, Event, BB),
1528                         BB);
1529 }
1530 
addCompositeConstructInst(SPIRVType * Type,const std::vector<SPIRVId> & Constituents,SPIRVBasicBlock * BB)1531 SPIRVInstruction *SPIRVModuleImpl::addCompositeConstructInst(
1532     SPIRVType *Type, const std::vector<SPIRVId> &Constituents,
1533     SPIRVBasicBlock *BB) {
1534   return addInstruction(
1535       new SPIRVCompositeConstruct(Type, getId(), Constituents, BB), BB);
1536 }
1537 
1538 SPIRVInstruction *
addCompositeExtractInst(SPIRVType * Type,SPIRVValue * TheVector,const std::vector<SPIRVWord> & Indices,SPIRVBasicBlock * BB)1539 SPIRVModuleImpl::addCompositeExtractInst(SPIRVType *Type, SPIRVValue *TheVector,
1540                                          const std::vector<SPIRVWord> &Indices,
1541                                          SPIRVBasicBlock *BB) {
1542   return addInstruction(SPIRVInstTemplateBase::create(
1543                             OpCompositeExtract, Type, getId(),
1544                             getVec(TheVector->getId(), Indices), BB, this),
1545                         BB);
1546 }
1547 
addCompositeInsertInst(SPIRVValue * Object,SPIRVValue * Composite,const std::vector<SPIRVWord> & Indices,SPIRVBasicBlock * BB)1548 SPIRVInstruction *SPIRVModuleImpl::addCompositeInsertInst(
1549     SPIRVValue *Object, SPIRVValue *Composite,
1550     const std::vector<SPIRVWord> &Indices, SPIRVBasicBlock *BB) {
1551   std::vector<SPIRVId> Ops{Object->getId(), Composite->getId()};
1552   Ops.insert(Ops.end(), Indices.begin(), Indices.end());
1553   return addInstruction(SPIRVInstTemplateBase::create(OpCompositeInsert,
1554                                                       Composite->getType(),
1555                                                       getId(), Ops, BB, this),
1556                         BB);
1557 }
1558 
addCopyObjectInst(SPIRVType * TheType,SPIRVValue * Operand,SPIRVBasicBlock * BB)1559 SPIRVInstruction *SPIRVModuleImpl::addCopyObjectInst(SPIRVType *TheType,
1560                                                      SPIRVValue *Operand,
1561                                                      SPIRVBasicBlock *BB) {
1562   return addInstruction(new SPIRVCopyObject(TheType, getId(), Operand, BB), BB);
1563 }
1564 
addCopyMemoryInst(SPIRVValue * TheTarget,SPIRVValue * TheSource,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)1565 SPIRVInstruction *SPIRVModuleImpl::addCopyMemoryInst(
1566     SPIRVValue *TheTarget, SPIRVValue *TheSource,
1567     const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
1568   return addInstruction(
1569       new SPIRVCopyMemory(TheTarget, TheSource, TheMemoryAccess, BB), BB);
1570 }
1571 
addCopyMemorySizedInst(SPIRVValue * TheTarget,SPIRVValue * TheSource,SPIRVValue * TheSize,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)1572 SPIRVInstruction *SPIRVModuleImpl::addCopyMemorySizedInst(
1573     SPIRVValue *TheTarget, SPIRVValue *TheSource, SPIRVValue *TheSize,
1574     const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
1575   return addInstruction(new SPIRVCopyMemorySized(TheTarget, TheSource, TheSize,
1576                                                  TheMemoryAccess, BB),
1577                         BB);
1578 }
1579 
addFPGARegINTELInst(SPIRVType * Type,SPIRVValue * V,SPIRVBasicBlock * BB)1580 SPIRVInstruction *SPIRVModuleImpl::addFPGARegINTELInst(SPIRVType *Type,
1581                                                        SPIRVValue *V,
1582                                                        SPIRVBasicBlock *BB) {
1583   return addInstruction(
1584       SPIRVInstTemplateBase::create(OpFPGARegINTEL, Type, getId(),
1585                                     getVec(V->getId()), BB, this),
1586       BB);
1587 }
1588 
addSampledImageInst(SPIRVType * ResultTy,SPIRVValue * Image,SPIRVValue * Sampler,SPIRVBasicBlock * BB)1589 SPIRVInstruction *SPIRVModuleImpl::addSampledImageInst(SPIRVType *ResultTy,
1590                                                        SPIRVValue *Image,
1591                                                        SPIRVValue *Sampler,
1592                                                        SPIRVBasicBlock *BB) {
1593   return addInstruction(SPIRVInstTemplateBase::create(
1594                             OpSampledImage, ResultTy, getId(),
1595                             getVec(Image->getId(), Sampler->getId()), BB, this),
1596                         BB);
1597 }
1598 
addAssumeTrueKHRInst(SPIRVValue * Condition,SPIRVBasicBlock * BB)1599 SPIRVInstruction *SPIRVModuleImpl::addAssumeTrueKHRInst(SPIRVValue *Condition,
1600                                                         SPIRVBasicBlock *BB) {
1601   return addInstruction(new SPIRVAssumeTrueKHR(Condition->getId(), BB), BB);
1602 }
1603 
addExpectKHRInst(SPIRVType * ResultTy,SPIRVValue * Value,SPIRVValue * ExpectedValue,SPIRVBasicBlock * BB)1604 SPIRVInstruction *SPIRVModuleImpl::addExpectKHRInst(SPIRVType *ResultTy,
1605                                                     SPIRVValue *Value,
1606                                                     SPIRVValue *ExpectedValue,
1607                                                     SPIRVBasicBlock *BB) {
1608   return addInstruction(SPIRVInstTemplateBase::create(
1609                             OpExpectKHR, ResultTy, getId(),
1610                             getVec(Value->getId(), ExpectedValue->getId()), BB,
1611                             this),
1612                         BB);
1613 }
1614 
1615 // Create AliasDomainDeclINTEL/AliasScopeDeclINTEL/AliasScopeListDeclINTEL
1616 // instructions
1617 template <typename AliasingInstType>
getOrAddMemAliasingINTELInst(std::vector<SPIRVId> Args,llvm::MDNode * MD)1618 SPIRVEntry *SPIRVModuleImpl::getOrAddMemAliasingINTELInst(
1619     std::vector<SPIRVId> Args, llvm::MDNode *MD) {
1620   assert(MD && "noalias/alias.scope metadata can't be null");
1621   // Don't duplicate aliasing instruction. For that use a map with a MDNode key
1622   if (AliasInstMDMap.find(MD) != AliasInstMDMap.end())
1623     return AliasInstMDMap[MD];
1624   SPIRVEntry *AliasInst = add(new AliasingInstType(this, getId(), Args));
1625   AliasInstMDMap.emplace(std::make_pair(MD, AliasInst));
1626   return AliasInst;
1627 }
1628 
1629 // Create AliasDomainDeclINTEL instruction
getOrAddAliasDomainDeclINTELInst(std::vector<SPIRVId> Args,llvm::MDNode * MD)1630 SPIRVEntry *SPIRVModuleImpl::getOrAddAliasDomainDeclINTELInst(
1631     std::vector<SPIRVId> Args, llvm::MDNode *MD) {
1632   return getOrAddMemAliasingINTELInst<SPIRVAliasDomainDeclINTEL>(Args, MD);
1633 }
1634 
1635 // Create AliasScopeDeclINTEL instruction
getOrAddAliasScopeDeclINTELInst(std::vector<SPIRVId> Args,llvm::MDNode * MD)1636 SPIRVEntry *SPIRVModuleImpl::getOrAddAliasScopeDeclINTELInst(
1637     std::vector<SPIRVId> Args, llvm::MDNode *MD) {
1638   return getOrAddMemAliasingINTELInst<SPIRVAliasScopeDeclINTEL>(Args, MD);
1639 }
1640 
1641 // Create AliasScopeListDeclINTEL instruction
getOrAddAliasScopeListDeclINTELInst(std::vector<SPIRVId> Args,llvm::MDNode * MD)1642 SPIRVEntry *SPIRVModuleImpl::getOrAddAliasScopeListDeclINTELInst(
1643     std::vector<SPIRVId> Args, llvm::MDNode *MD) {
1644   return getOrAddMemAliasingINTELInst<SPIRVAliasScopeListDeclINTEL>(Args, MD);
1645 }
1646 
addVariable(SPIRVType * Type,bool IsConstant,SPIRVLinkageTypeKind LinkageTy,SPIRVValue * Initializer,const std::string & Name,SPIRVStorageClassKind StorageClass,SPIRVBasicBlock * BB)1647 SPIRVInstruction *SPIRVModuleImpl::addVariable(
1648     SPIRVType *Type, bool IsConstant, SPIRVLinkageTypeKind LinkageTy,
1649     SPIRVValue *Initializer, const std::string &Name,
1650     SPIRVStorageClassKind StorageClass, SPIRVBasicBlock *BB) {
1651   SPIRVVariable *Variable = new SPIRVVariable(Type, getId(), Initializer, Name,
1652                                               StorageClass, BB, this);
1653   if (BB)
1654     return addInstruction(Variable, BB);
1655 
1656   add(Variable);
1657   if (LinkageTy != internal::LinkageTypeInternal)
1658     Variable->setLinkageType(LinkageTy);
1659   Variable->setIsConstant(IsConstant);
1660   return Variable;
1661 }
1662 
1663 template <class T>
operator <<(spv_ostream & O,const std::vector<T * > & V)1664 spv_ostream &operator<<(spv_ostream &O, const std::vector<T *> &V) {
1665   for (auto &I : V)
1666     O << *I;
1667   return O;
1668 }
1669 
1670 template <class T, class B>
operator <<(spv_ostream & O,const std::multiset<T *,B> & V)1671 spv_ostream &operator<<(spv_ostream &O, const std::multiset<T *, B> &V) {
1672   for (auto &I : V)
1673     O << *I;
1674   return O;
1675 }
1676 
1677 // To satisfy SPIR-V spec requirement:
1678 // "All operands must be declared before being used",
1679 // we do DFS based topological sort
1680 // https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
1681 class TopologicalSort {
1682   enum DFSState : char { Unvisited, Discovered, Visited };
1683   typedef std::vector<SPIRVType *> SPIRVTypeVec;
1684   typedef std::vector<SPIRVValue *> SPIRVConstantVector;
1685   typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
1686   typedef std::vector<SPIRVEntry *> SPIRVConstAndVarVec;
1687   typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
1688   typedef std::function<bool(SPIRVEntry *, SPIRVEntry *)> Comp;
1689   typedef std::map<SPIRVEntry *, DFSState, Comp> EntryStateMapTy;
1690   typedef std::function<bool(const SPIRVTypeForwardPointer *,
1691                              const SPIRVTypeForwardPointer *)>
1692       Equal;
1693   typedef std::function<size_t(const SPIRVTypeForwardPointer *)> Hash;
1694   // We may create forward pointers as we go through the types. We use
1695   // unordered set to avoid duplicates.
1696   typedef std::unordered_set<SPIRVTypeForwardPointer *, Hash, Equal>
1697       SPIRVForwardPointerSet;
1698 
1699   SPIRVTypeVec TypeIntVec;
1700   SPIRVConstantVector ConstIntVec;
1701   SPIRVTypeVec TypeVec;
1702   SPIRVConstAndVarVec ConstAndVarVec;
1703   SPIRVForwardPointerSet ForwardPointerSet;
1704   EntryStateMapTy EntryStateMap;
1705 
1706   friend spv_ostream &operator<<(spv_ostream &O, const TopologicalSort &S);
1707 
1708   // This method implements recursive depth-first search among all Entries in
1709   // EntryStateMap. Traversing entries and adding them to corresponding
1710   // container after visiting all dependent entries(post-order traversal)
1711   // guarantees that the entry's operands will appear in the container before
1712   // the entry itslef.
1713   // Returns true if cyclic dependency detected.
visit(SPIRVEntry * E)1714   bool visit(SPIRVEntry *E) {
1715     DFSState &State = EntryStateMap[E];
1716     if (State == Visited)
1717       return false;
1718     if (State == Discovered) // Cyclic dependency detected
1719       return true;
1720     State = Discovered;
1721     for (SPIRVEntry *Op : E->getNonLiteralOperands()) {
1722       if (EntryStateMap[Op] == Visited)
1723         continue;
1724       if (visit(Op)) {
1725         // We've found a recursive data type, e.g. a structure having a member
1726         // which is a pointer to the same structure.
1727         State = Unvisited; // Forget about it
1728         if (E->getOpCode() == OpTypePointer) {
1729           // If we have a pointer in the recursive chain, we can break the
1730           // cyclic dependency by inserting a forward declaration of that
1731           // pointer.
1732           SPIRVTypePointer *Ptr = static_cast<SPIRVTypePointer *>(E);
1733           SPIRVModule *BM = E->getModule();
1734           ForwardPointerSet.insert(BM->add(new SPIRVTypeForwardPointer(
1735               BM, Ptr, Ptr->getPointerStorageClass())));
1736           return false;
1737         }
1738         return true;
1739       }
1740     }
1741     Op OC = E->getOpCode();
1742     if (OC == OpTypeInt)
1743       TypeIntVec.push_back(static_cast<SPIRVType *>(E));
1744     else if (isConstantOpCode(OC)) {
1745       SPIRVConstant *C = static_cast<SPIRVConstant *>(E);
1746       if (C->getType()->isTypeInt())
1747         ConstIntVec.push_back(C);
1748       else
1749         ConstAndVarVec.push_back(E);
1750     } else if (isTypeOpCode(OC))
1751       TypeVec.push_back(static_cast<SPIRVType *>(E));
1752     else
1753       ConstAndVarVec.push_back(E);
1754     State = Visited;
1755     return false;
1756   }
1757 
1758 public:
TopologicalSort(const SPIRVTypeVec & TypeVec,const SPIRVConstantVector & ConstVec,const SPIRVVariableVec & VariableVec,SPIRVForwardPointerVec & ForwardPointerVec)1759   TopologicalSort(const SPIRVTypeVec &TypeVec,
1760                   const SPIRVConstantVector &ConstVec,
1761                   const SPIRVVariableVec &VariableVec,
1762                   SPIRVForwardPointerVec &ForwardPointerVec)
1763       : ForwardPointerSet(
1764             16, // bucket count
1765             [](const SPIRVTypeForwardPointer *Ptr) {
1766               return std::hash<SPIRVId>()(Ptr->getPointer()->getId());
1767             },
1768             [](const SPIRVTypeForwardPointer *Ptr1,
__anonc4ffec280402(const SPIRVTypeForwardPointer *Ptr1, const SPIRVTypeForwardPointer *Ptr2) 1769                const SPIRVTypeForwardPointer *Ptr2) {
1770               return Ptr1->getPointer()->getId() == Ptr2->getPointer()->getId();
1771             }),
__anonc4ffec280502(SPIRVEntry *A, SPIRVEntry *B) 1772         EntryStateMap([](SPIRVEntry *A, SPIRVEntry *B) -> bool {
1773           return A->getId() < B->getId();
1774         }) {
1775     // Collect entries for sorting
1776     for (auto *T : TypeVec)
1777       EntryStateMap[T] = DFSState::Unvisited;
1778     for (auto *C : ConstVec)
1779       EntryStateMap[C] = DFSState::Unvisited;
1780     for (auto *V : VariableVec)
1781       EntryStateMap[V] = DFSState::Unvisited;
1782     // Run topoligical sort
1783     for (auto ES : EntryStateMap) {
1784       if (visit(ES.first))
1785         llvm_unreachable("Cyclic dependency for types detected");
1786     }
1787     // Append forward pointers vector
1788     ForwardPointerVec.insert(ForwardPointerVec.end(), ForwardPointerSet.begin(),
1789                              ForwardPointerSet.end());
1790   }
1791 };
1792 
operator <<(spv_ostream & O,const TopologicalSort & S)1793 spv_ostream &operator<<(spv_ostream &O, const TopologicalSort &S) {
1794   O << S.TypeIntVec << S.ConstIntVec << S.TypeVec << S.ConstAndVarVec;
1795   return O;
1796 }
1797 
operator <<(spv_ostream & O,SPIRVModule & M)1798 spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M) {
1799   SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl *>(&M);
1800   // Start tracking of the current line with no line
1801   MI.CurrentLine.reset();
1802 
1803   SPIRVEncoder Encoder(O);
1804   Encoder << MagicNumber << MI.SPIRVVersion
1805           << (((SPIRVWord)MI.GeneratorId << 16) | MI.GeneratorVer)
1806           << MI.NextId /* Bound for Id */
1807           << MI.InstSchema;
1808   O << SPIRVNL();
1809 
1810   for (auto &I : MI.CapMap)
1811     O << *I.second;
1812 
1813   for (auto &I : M.getExtension()) {
1814     assert(!I.empty() && "Invalid extension");
1815     O << SPIRVExtension(&M, I);
1816   }
1817 
1818   for (auto &I : MI.IdToInstSetMap)
1819     O << SPIRVExtInstImport(&M, I.first, SPIRVBuiltinSetNameMap::map(I.second));
1820 
1821   O << SPIRVMemoryModel(&M);
1822 
1823   for (auto &I : MI.EntryPointVec)
1824     for (auto &II : I.second)
1825       O << SPIRVEntryPoint(&M, I.first, II, M.get<SPIRVFunction>(II)->getName(),
1826                            M.get<SPIRVFunction>(II)->getVariables());
1827 
1828   for (auto &I : MI.EntryPointVec)
1829     for (auto &II : I.second)
1830       MI.get<SPIRVFunction>(II)->encodeExecutionModes(O);
1831 
1832   O << MI.StringVec;
1833 
1834   for (auto &I : M.getSourceExtension()) {
1835     assert(!I.empty() && "Invalid source extension");
1836     O << SPIRVSourceExtension(&M, I);
1837   }
1838 
1839   O << SPIRVSource(&M);
1840 
1841   for (auto &I : MI.NamedId) {
1842     // Don't output name for entry point since it is redundant
1843     bool IsEntryPoint = false;
1844     for (auto &EPS : MI.EntryPointSet)
1845       if (EPS.second.count(I)) {
1846         IsEntryPoint = true;
1847         break;
1848       }
1849     if (!IsEntryPoint)
1850       M.getEntry(I)->encodeName(O);
1851   }
1852 
1853   if (M.isAllowedToUseExtension(
1854         ExtensionID::SPV_INTEL_memory_access_aliasing)) {
1855     O << SPIRVNL() << MI.AliasInstMDVec;
1856   }
1857 
1858   TopologicalSort TS(MI.TypeVec, MI.ConstVec, MI.VariableVec,
1859                      MI.ForwardPointerVec);
1860 
1861   O << MI.MemberNameVec << MI.ModuleProcessedVec << MI.DecGroupVec
1862     << MI.DecorateSet << MI.GroupDecVec << MI.ForwardPointerVec << TS;
1863 
1864   if (M.isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly)) {
1865     O << SPIRVNL() << MI.AsmTargetVec << MI.AsmVec;
1866   }
1867 
1868   O << SPIRVNL() << MI.DebugInstVec << SPIRVNL() << MI.FuncVec;
1869   return O;
1870 }
1871 
1872 template <class T>
addTo(std::vector<T * > & V,SPIRVEntry * E)1873 void SPIRVModuleImpl::addTo(std::vector<T *> &V, SPIRVEntry *E) {
1874   V.push_back(static_cast<T *>(E));
1875 }
1876 
1877 // The first decoration group includes all the previously defined decorates.
1878 // The second decoration group includes all the decorates defined between the
1879 // first and second decoration group. So long so forth.
addDecorationGroup()1880 SPIRVDecorationGroup *SPIRVModuleImpl::addDecorationGroup() {
1881   return addDecorationGroup(new SPIRVDecorationGroup(this, getId()));
1882 }
1883 
1884 SPIRVDecorationGroup *
addDecorationGroup(SPIRVDecorationGroup * Group)1885 SPIRVModuleImpl::addDecorationGroup(SPIRVDecorationGroup *Group) {
1886   add(Group);
1887   Group->takeDecorates(DecorateSet);
1888   DecGroupVec.push_back(Group);
1889   SPIRVDBG(spvdbgs() << "[addDecorationGroup] {" << *Group << "}\n";
1890            spvdbgs() << "  Remaining DecorateSet: {" << DecorateSet << "}\n");
1891   assert(DecorateSet.empty());
1892   return Group;
1893 }
1894 
1895 SPIRVGroupDecorateGeneric *
addGroupDecorateGeneric(SPIRVGroupDecorateGeneric * GDec)1896 SPIRVModuleImpl::addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) {
1897   add(GDec);
1898   GDec->decorateTargets();
1899   GroupDecVec.push_back(GDec);
1900   return GDec;
1901 }
1902 SPIRVGroupDecorate *
addGroupDecorate(SPIRVDecorationGroup * Group,const std::vector<SPIRVEntry * > & Targets)1903 SPIRVModuleImpl::addGroupDecorate(SPIRVDecorationGroup *Group,
1904                                   const std::vector<SPIRVEntry *> &Targets) {
1905   auto GD = new SPIRVGroupDecorate(Group, getIds(Targets));
1906   addGroupDecorateGeneric(GD);
1907   return GD;
1908 }
1909 
addGroupMemberDecorate(SPIRVDecorationGroup * Group,const std::vector<SPIRVEntry * > & Targets)1910 SPIRVGroupMemberDecorate *SPIRVModuleImpl::addGroupMemberDecorate(
1911     SPIRVDecorationGroup *Group, const std::vector<SPIRVEntry *> &Targets) {
1912   auto GMD = new SPIRVGroupMemberDecorate(Group, getIds(Targets));
1913   addGroupDecorateGeneric(GMD);
1914   return GMD;
1915 }
1916 
getString(const std::string & Str)1917 SPIRVString *SPIRVModuleImpl::getString(const std::string &Str) {
1918   auto Loc = StrMap.find(Str);
1919   if (Loc != StrMap.end())
1920     return Loc->second;
1921   auto S = add(new SPIRVString(this, getId(), Str));
1922   StrMap[Str] = S;
1923   return S;
1924 }
1925 
addMemberName(SPIRVTypeStruct * ST,SPIRVWord MemberNumber,const std::string & Name)1926 SPIRVMemberName *SPIRVModuleImpl::addMemberName(SPIRVTypeStruct *ST,
1927                                                 SPIRVWord MemberNumber,
1928                                                 const std::string &Name) {
1929   return add(new SPIRVMemberName(ST, MemberNumber, Name));
1930 }
1931 
addUnknownStructField(SPIRVTypeStruct * Struct,unsigned I,SPIRVId ID)1932 void SPIRVModuleImpl::addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
1933                                             SPIRVId ID) {
1934   UnknownStructFieldMap[Struct].push_back(std::make_pair(I, ID));
1935 }
1936 
to_string(uint32_t Version)1937 static std::string to_string(uint32_t Version) {
1938   std::string Res;
1939   switch (Version) {
1940   case static_cast<uint32_t>(VersionNumber::SPIRV_1_0):
1941     Res = "1.0";
1942     break;
1943   case static_cast<uint32_t>(VersionNumber::SPIRV_1_1):
1944     Res = "1.1";
1945     break;
1946   case static_cast<uint32_t>(VersionNumber::SPIRV_1_2):
1947     Res = "1.2";
1948     break;
1949   case static_cast<uint32_t>(VersionNumber::SPIRV_1_3):
1950     Res = "1.3";
1951     break;
1952   case static_cast<uint32_t>(VersionNumber::SPIRV_1_4):
1953     Res = "1.4";
1954     break;
1955   default:
1956     Res = "unknown";
1957   }
1958 
1959   Res += " (" + std::to_string(Version) + ")";
1960   return Res;
1961 }
1962 
to_string(VersionNumber Version)1963 static std::string to_string(VersionNumber Version) {
1964   return to_string(static_cast<uint32_t>(Version));
1965 }
1966 
operator >>(std::istream & I,SPIRVModule & M)1967 std::istream &operator>>(std::istream &I, SPIRVModule &M) {
1968   SPIRVDecoder Decoder(I, M);
1969   SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl *>(&M);
1970   // Disable automatic capability filling.
1971   MI.setAutoAddCapability(false);
1972   MI.setAutoAddExtensions(false);
1973 
1974   SPIRVWord Magic;
1975   Decoder >> Magic;
1976   if (!M.getErrorLog().checkError(Magic == MagicNumber, SPIRVEC_InvalidModule,
1977                                   "invalid magic number")) {
1978     M.setInvalid();
1979     return I;
1980   }
1981 
1982   Decoder >> MI.SPIRVVersion;
1983   bool SPIRVVersionIsKnown =
1984       static_cast<uint32_t>(VersionNumber::MinimumVersion) <= MI.SPIRVVersion &&
1985       MI.SPIRVVersion <= static_cast<uint32_t>(VersionNumber::MaximumVersion);
1986   if (!M.getErrorLog().checkError(
1987           SPIRVVersionIsKnown, SPIRVEC_InvalidModule,
1988           "unsupported SPIR-V version number '" + to_string(MI.SPIRVVersion) +
1989               "'. Range of supported/known SPIR-V "
1990               "versions is " +
1991               to_string(VersionNumber::MinimumVersion) + " - " +
1992               to_string(VersionNumber::MaximumVersion))) {
1993     M.setInvalid();
1994     return I;
1995   }
1996 
1997   bool SPIRVVersionIsAllowed = M.isAllowedToUseVersion(MI.SPIRVVersion);
1998   if (!M.getErrorLog().checkError(
1999           SPIRVVersionIsAllowed, SPIRVEC_InvalidModule,
2000           "incorrect SPIR-V version number " + to_string(MI.SPIRVVersion) +
2001               " - it conflicts with --spirv-max-version which is set to " +
2002               to_string(M.getMaximumAllowedSPIRVVersion()))) {
2003     M.setInvalid();
2004     return I;
2005   }
2006 
2007   SPIRVWord Generator = 0;
2008   Decoder >> Generator;
2009   MI.GeneratorId = Generator >> 16;
2010   MI.GeneratorVer = Generator & 0xFFFF;
2011 
2012   // Bound for Id
2013   Decoder >> MI.NextId;
2014 
2015   Decoder >> MI.InstSchema;
2016   if (!M.getErrorLog().checkError(MI.InstSchema == SPIRVISCH_Default,
2017                                   SPIRVEC_InvalidModule,
2018                                   "unsupported instruction schema")) {
2019     M.setInvalid();
2020     return I;
2021   }
2022 
2023   while (Decoder.getWordCountAndOpCode() && M.isModuleValid()) {
2024     SPIRVEntry *Entry = Decoder.getEntry();
2025     if (Entry != nullptr)
2026       M.add(Entry);
2027   }
2028 
2029   MI.resolveUnknownStructFields();
2030   return I;
2031 }
2032 
createSPIRVModule()2033 SPIRVModule *SPIRVModule::createSPIRVModule() { return new SPIRVModuleImpl(); }
2034 
createSPIRVModule(const SPIRV::TranslatorOpts & Opts)2035 SPIRVModule *SPIRVModule::createSPIRVModule(const SPIRV::TranslatorOpts &Opts) {
2036   return new SPIRVModuleImpl(Opts);
2037 }
2038 
getValue(SPIRVId TheId) const2039 SPIRVValue *SPIRVModuleImpl::getValue(SPIRVId TheId) const {
2040   return get<SPIRVValue>(TheId);
2041 }
2042 
getValueType(SPIRVId TheId) const2043 SPIRVType *SPIRVModuleImpl::getValueType(SPIRVId TheId) const {
2044   return get<SPIRVValue>(TheId)->getType();
2045 }
2046 
2047 std::vector<SPIRVValue *>
getValues(const std::vector<SPIRVId> & IdVec) const2048 SPIRVModuleImpl::getValues(const std::vector<SPIRVId> &IdVec) const {
2049   std::vector<SPIRVValue *> ValueVec;
2050   for (auto I : IdVec)
2051     ValueVec.push_back(getValue(I));
2052   return ValueVec;
2053 }
2054 
2055 std::vector<SPIRVType *>
getValueTypes(const std::vector<SPIRVId> & IdVec) const2056 SPIRVModuleImpl::getValueTypes(const std::vector<SPIRVId> &IdVec) const {
2057   std::vector<SPIRVType *> TypeVec;
2058   for (auto I : IdVec)
2059     TypeVec.push_back(getValue(I)->getType());
2060   return TypeVec;
2061 }
2062 
2063 std::vector<SPIRVId>
getIds(const std::vector<SPIRVEntry * > & ValueVec) const2064 SPIRVModuleImpl::getIds(const std::vector<SPIRVEntry *> &ValueVec) const {
2065   std::vector<SPIRVId> IdVec;
2066   for (auto I : ValueVec)
2067     IdVec.push_back(I->getId());
2068   return IdVec;
2069 }
2070 
2071 std::vector<SPIRVId>
getIds(const std::vector<SPIRVValue * > & ValueVec) const2072 SPIRVModuleImpl::getIds(const std::vector<SPIRVValue *> &ValueVec) const {
2073   std::vector<SPIRVId> IdVec;
2074   for (auto I : ValueVec)
2075     IdVec.push_back(I->getId());
2076   return IdVec;
2077 }
2078 
2079 SPIRVInstTemplateBase *
addInstTemplate(Op OC,SPIRVBasicBlock * BB,SPIRVType * Ty)2080 SPIRVModuleImpl::addInstTemplate(Op OC, SPIRVBasicBlock *BB, SPIRVType *Ty) {
2081   assert(!Ty || !Ty->isTypeVoid());
2082   SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
2083   auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, BB, this);
2084   BB->addInstruction(Ins);
2085   return Ins;
2086 }
2087 
2088 SPIRVInstTemplateBase *
addInstTemplate(Op OC,const std::vector<SPIRVWord> & Ops,SPIRVBasicBlock * BB,SPIRVType * Ty)2089 SPIRVModuleImpl::addInstTemplate(Op OC, const std::vector<SPIRVWord> &Ops,
2090                                  SPIRVBasicBlock *BB, SPIRVType *Ty) {
2091   assert(!Ty || !Ty->isTypeVoid());
2092   SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
2093   auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, Ops, BB, this);
2094   BB->addInstruction(Ins);
2095   return Ins;
2096 }
2097 
addInstTemplate(SPIRVInstTemplateBase * Ins,const std::vector<SPIRVWord> & Ops,SPIRVBasicBlock * BB,SPIRVType * Ty)2098 void SPIRVModuleImpl::addInstTemplate(SPIRVInstTemplateBase *Ins,
2099                                       const std::vector<SPIRVWord> &Ops,
2100                                       SPIRVBasicBlock *BB, SPIRVType *Ty) {
2101   assert(!Ty || !Ty->isTypeVoid());
2102   SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
2103   Ins->init(Ty, Id, BB, this);
2104   Ins->setOpWordsAndValidate(Ops);
2105   BB->addInstruction(Ins);
2106 }
2107 
getExtInstSetId(SPIRVExtInstSetKind Kind) const2108 SPIRVId SPIRVModuleImpl::getExtInstSetId(SPIRVExtInstSetKind Kind) const {
2109   assert(Kind < SPIRVEIS_Count && "Unknown extended instruction set!");
2110   auto Res = ExtInstSetIds.find(Kind);
2111   assert(Res != ExtInstSetIds.end() && "extended instruction set not found!");
2112   return Res->second;
2113 }
2114 
isSpirvBinary(const std::string & Img)2115 bool isSpirvBinary(const std::string &Img) {
2116   if (Img.size() < sizeof(unsigned))
2117     return false;
2118   auto Magic = reinterpret_cast<const unsigned *>(Img.data());
2119   return *Magic == MagicNumber;
2120 }
2121 
2122 #ifdef _SPIRV_SUPPORT_TEXT_FMT
2123 
convertSpirv(std::istream & IS,std::ostream & OS,std::string & ErrMsg,bool FromText,bool ToText)2124 bool convertSpirv(std::istream &IS, std::ostream &OS, std::string &ErrMsg,
2125                   bool FromText, bool ToText) {
2126   auto SaveOpt = SPIRVUseTextFormat;
2127   SPIRVUseTextFormat = FromText;
2128   // Conversion from/to SPIR-V text representation is a side feature of the
2129   // translator which is mostly intended for debug usage. So, this step cannot
2130   // be customized to enable/disable particular extensions or restrict/allow
2131   // particular SPIR-V versions: all known SPIR-V versions are allowed, all
2132   // known SPIR-V extensions are enabled during this conversion
2133   SPIRV::TranslatorOpts DefaultOpts;
2134   DefaultOpts.enableAllExtensions();
2135   SPIRVModuleImpl M(DefaultOpts);
2136   IS >> M;
2137   if (M.getError(ErrMsg) != SPIRVEC_Success) {
2138     SPIRVUseTextFormat = SaveOpt;
2139     return false;
2140   }
2141   SPIRVUseTextFormat = ToText;
2142   OS << M;
2143   if (M.getError(ErrMsg) != SPIRVEC_Success) {
2144     SPIRVUseTextFormat = SaveOpt;
2145     return false;
2146   }
2147   SPIRVUseTextFormat = SaveOpt;
2148   return true;
2149 }
2150 
isSpirvText(const std::string & Img)2151 bool isSpirvText(const std::string &Img) {
2152   std::istringstream SS(Img);
2153   unsigned Magic = 0;
2154   SS >> Magic;
2155   if (SS.bad())
2156     return false;
2157   return Magic == MagicNumber;
2158 }
2159 
convertSpirv(std::string & Input,std::string & Out,std::string & ErrMsg,bool ToText)2160 bool convertSpirv(std::string &Input, std::string &Out, std::string &ErrMsg,
2161                   bool ToText) {
2162   auto FromText = isSpirvText(Input);
2163   if (ToText == FromText) {
2164     Out = Input;
2165     return true;
2166   }
2167   std::istringstream IS(Input);
2168   std::ostringstream OS;
2169   if (!convertSpirv(IS, OS, ErrMsg, FromText, ToText))
2170     return false;
2171   Out = OS.str();
2172   return true;
2173 }
2174 
2175 #endif // _SPIRV_SUPPORT_TEXT_FMT
2176 
2177 } // namespace SPIRV
2178