• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SPIRVDebug.h"
42 #include "SPIRVEntry.h"
43 #include "SPIRVType.h"
44 #include "SPIRVValue.h"
45 #include "SPIRVExtInst.h"
46 #include "SPIRVFunction.h"
47 #include "SPIRVInstruction.h"
48 #include "SPIRVStream.h"
49 
50 #include <set>
51 #include <unordered_map>
52 #include <unordered_set>
53 
54 namespace SPIRV{
55 
SPIRVModule()56 SPIRVModule::SPIRVModule():AutoAddCapability(true), ValidateCapability(false)
57 {}
58 
~SPIRVModule()59 SPIRVModule::~SPIRVModule()
60 {}
61 
62 class SPIRVModuleImpl : public SPIRVModule {
63 public:
SPIRVModuleImpl()64   SPIRVModuleImpl():SPIRVModule(), NextId(1),
65     SPIRVVersion(SPIRV_1_0),
66     GeneratorId(SPIRVGEN_KhronosLLVMSPIRVTranslator),
67     GeneratorVer(0),
68     InstSchema(SPIRVISCH_Default),
69     SrcLang(SourceLanguageOpenCL_C),
70     SrcLangVer(102000),
71     MemoryModel(MemoryModelOpenCL){
72     AddrModel = sizeof(size_t) == 32 ? AddressingModelPhysical32
73         : AddressingModelPhysical64;
74   };
75   virtual ~SPIRVModuleImpl();
76 
77   // Object query functions
78   bool exist(SPIRVId) const;
79   bool exist(SPIRVId, SPIRVEntry **) const;
80   SPIRVId getId(SPIRVId Id = SPIRVID_INVALID, unsigned Increment = 1);
81   virtual SPIRVEntry *getEntry(SPIRVId Id) const;
hasDebugInfo() const82   bool hasDebugInfo() const { return !LineVec.empty();}
83 
84   // Error handling functions
getErrorLog()85   SPIRVErrorLog &getErrorLog() { return ErrLog;}
getError(std::string & ErrMsg)86   SPIRVErrorCode getError(std::string &ErrMsg) { return ErrLog.getError(ErrMsg);}
87 
88   // Module query functions
getAddressingModel()89   SPIRVAddressingModelKind getAddressingModel() { return AddrModel;}
90   SPIRVExtInstSetKind getBuiltinSet(SPIRVId SetId) const;
getCapability() const91   const SPIRVCapMap &getCapability() const { return CapMap; }
hasCapability(SPIRVCapabilityKind Cap) const92   bool hasCapability(SPIRVCapabilityKind Cap) const {
93     return CapMap.find(Cap) != CapMap.end();
94   }
getExtension()95   std::set<std::string> &getExtension() { return SPIRVExt;}
getFunction(unsigned I) const96   SPIRVFunction *getFunction(unsigned I) const { return FuncVec[I];}
getVariable(unsigned I) const97   SPIRVVariable *getVariable(unsigned I) const { return VariableVec[I];}
98   virtual SPIRVValue *getValue(SPIRVId TheId) const;
99   virtual std::vector<SPIRVValue *> getValues(const std::vector<SPIRVId>&)const;
100   virtual std::vector<SPIRVId> getIds(const std::vector<SPIRVEntry *>&)const;
101   virtual std::vector<SPIRVId> getIds(const std::vector<SPIRVValue *>&)const;
102   virtual SPIRVType *getValueType(SPIRVId TheId)const;
103   virtual std::vector<SPIRVType *> getValueTypes(const std::vector<SPIRVId>&)
104       const;
getMemoryModel() const105   SPIRVMemoryModelKind getMemoryModel() const { return MemoryModel;}
106   virtual SPIRVConstant* getLiteralAsConstant(unsigned Literal);
getNumEntryPoints(SPIRVExecutionModelKind EM) const107   unsigned getNumEntryPoints(SPIRVExecutionModelKind EM) const {
108     auto Loc = EntryPointVec.find(EM);
109     if (Loc == EntryPointVec.end())
110       return 0;
111     return Loc->second.size();
112   }
getEntryPoint(SPIRVExecutionModelKind EM,unsigned I) const113   SPIRVFunction *getEntryPoint(SPIRVExecutionModelKind EM, unsigned I) const {
114     auto Loc = EntryPointVec.find(EM);
115     if (Loc == EntryPointVec.end())
116       return nullptr;
117     assert(I < Loc->second.size());
118     return get<SPIRVFunction>(Loc->second[I]);
119   }
getNumFunctions() const120   unsigned getNumFunctions() const { return FuncVec.size();}
getNumVariables() const121   unsigned getNumVariables() const { return VariableVec.size();}
getSourceLanguage(SPIRVWord * Ver=nullptr) const122   SourceLanguage getSourceLanguage(SPIRVWord * Ver = nullptr) const {
123     if (Ver)
124       *Ver = SrcLangVer;
125     return SrcLang;
126   }
getSourceExtension()127   std::set<std::string> &getSourceExtension() { return SrcExtension;}
128   bool isEntryPoint(SPIRVExecutionModelKind, SPIRVId EP) const;
getGeneratorId() const129   unsigned short getGeneratorId() const { return GeneratorId; }
getGeneratorVer() const130   unsigned short getGeneratorVer() const { return GeneratorVer; }
getSPIRVVersion() const131   SPIRVWord getSPIRVVersion() const { return SPIRVVersion; }
132 
133   // Module changing functions
134   bool importBuiltinSet(const std::string &, SPIRVId *);
135   bool importBuiltinSetWithId(const std::string &, SPIRVId);
136   void optimizeDecorates();
setAddressingModel(SPIRVAddressingModelKind AM)137   void setAddressingModel(SPIRVAddressingModelKind AM) { AddrModel = AM;}
138   void setAlignment(SPIRVValue *, SPIRVWord);
setMemoryModel(SPIRVMemoryModelKind MM)139   void setMemoryModel(SPIRVMemoryModelKind MM) {
140     MemoryModel = MM;
141     if (MemoryModel == spv::MemoryModelOpenCL)
142       addCapability(CapabilityKernel);
143   }
144   void setName(SPIRVEntry *E, const std::string &Name);
setSourceLanguage(SourceLanguage Lang,SPIRVWord Ver)145   void setSourceLanguage(SourceLanguage Lang, SPIRVWord Ver) {
146     SrcLang = Lang;
147     SrcLangVer = Ver;
148   }
setGeneratorId(unsigned short Id)149   void setGeneratorId(unsigned short Id) { GeneratorId = Id; }
setGeneratorVer(unsigned short Ver)150   void setGeneratorVer(unsigned short Ver) { GeneratorVer = Ver; }
151   void resolveUnknownStructFields();
152 
setSPIRVVersion(SPIRVWord Ver)153   void setSPIRVVersion(SPIRVWord Ver) override { SPIRVVersion = Ver; }
154 
155   // Object creation functions
156   template<class T> void addTo(std::vector<T *> &V, SPIRVEntry *E);
157   virtual SPIRVEntry *addEntry(SPIRVEntry *E);
158   virtual SPIRVBasicBlock *addBasicBlock(SPIRVFunction *, SPIRVId);
159   virtual SPIRVString *getString(const std::string &Str);
160   virtual SPIRVMemberName *addMemberName(SPIRVTypeStruct *ST,
161       SPIRVWord MemberNumber, const std::string &Name);
162   virtual void addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
163                                      SPIRVId ID);
164   virtual SPIRVLine *addLine(SPIRVEntry *E, SPIRVString *FileName, SPIRVWord Line,
165       SPIRVWord Column);
166   virtual void addCapability(SPIRVCapabilityKind);
167   virtual void addCapabilityInternal(SPIRVCapabilityKind);
168   virtual const SPIRVDecorateGeneric *addDecorate(const SPIRVDecorateGeneric *);
169   virtual SPIRVDecorationGroup *addDecorationGroup();
170   virtual SPIRVDecorationGroup *addDecorationGroup(SPIRVDecorationGroup *Group);
171   virtual SPIRVGroupDecorate *addGroupDecorate(SPIRVDecorationGroup *Group,
172       const std::vector<SPIRVEntry *> &Targets);
173   virtual SPIRVGroupDecorateGeneric *addGroupDecorateGeneric(
174       SPIRVGroupDecorateGeneric *GDec);
175   virtual SPIRVGroupMemberDecorate *addGroupMemberDecorate(
176       SPIRVDecorationGroup *Group, const std::vector<SPIRVEntry *> &Targets);
177   virtual void addEntryPoint(SPIRVExecutionModelKind ExecModel,
178       SPIRVId EntryPoint);
179   virtual SPIRVForward *addForward(SPIRVType *Ty);
180   virtual SPIRVForward *addForward(SPIRVId, SPIRVType *Ty);
181   virtual SPIRVFunction *addFunction(SPIRVFunction *);
182   virtual SPIRVFunction *addFunction(SPIRVTypeFunction *, SPIRVId);
183   virtual SPIRVEntry *replaceForward(SPIRVForward *, SPIRVEntry *);
184 
185   // Type creation functions
186   template<class T> T * addType(T *Ty);
187   virtual SPIRVTypeArray *addArrayType(SPIRVType *, SPIRVConstant *);
188   virtual SPIRVTypeBool *addBoolType();
189   virtual SPIRVTypeFloat *addFloatType(unsigned BitWidth);
190   virtual SPIRVTypeFunction *addFunctionType(SPIRVType *,
191       const std::vector<SPIRVType *> &);
192   virtual SPIRVTypeInt *addIntegerType(unsigned BitWidth);
193   virtual SPIRVTypeOpaque *addOpaqueType(const std::string &);
194   virtual SPIRVTypePointer *addPointerType(SPIRVStorageClassKind, SPIRVType *);
195   virtual SPIRVTypeImage *addImageType(SPIRVType *,
196       const SPIRVTypeImageDescriptor &);
197   virtual SPIRVTypeImage *addImageType(SPIRVType *,
198       const SPIRVTypeImageDescriptor &, SPIRVAccessQualifierKind);
199   virtual SPIRVTypeSampler *addSamplerType();
200   virtual SPIRVTypePipeStorage *addPipeStorageType();
201   virtual SPIRVTypeSampledImage *addSampledImageType(SPIRVTypeImage *T);
202   virtual SPIRVTypeStruct *openStructType(unsigned, const std::string &);
203   virtual void closeStructType(SPIRVTypeStruct *T, bool);
204   virtual SPIRVTypeVector *addVectorType(SPIRVType *, SPIRVWord);
205   virtual SPIRVType *addOpaqueGenericType(Op);
206   virtual SPIRVTypeDeviceEvent *addDeviceEventType();
207   virtual SPIRVTypeQueue *addQueueType();
208   virtual SPIRVTypePipe *addPipeType();
209   virtual SPIRVTypeVoid *addVoidType();
210   virtual void createForwardPointers();
211 
212   // Constant creation functions
213   virtual SPIRVInstruction *addBranchInst(SPIRVLabel *, SPIRVBasicBlock *);
214   virtual SPIRVInstruction *addBranchConditionalInst(SPIRVValue *, SPIRVLabel *,
215       SPIRVLabel *, SPIRVBasicBlock *);
216   virtual SPIRVValue *addCompositeConstant(SPIRVType *,
217       const std::vector<SPIRVValue*>&);
218   virtual SPIRVValue *addConstant(SPIRVValue *);
219   virtual SPIRVValue *addConstant(SPIRVType *, uint64_t);
220   virtual SPIRVValue *addDoubleConstant(SPIRVTypeFloat *, double);
221   virtual SPIRVValue *addFloatConstant(SPIRVTypeFloat *, float);
222   virtual SPIRVValue *addIntegerConstant(SPIRVTypeInt *, uint64_t);
223   virtual SPIRVValue *addNullConstant(SPIRVType *);
224   virtual SPIRVValue *addUndef(SPIRVType *TheType);
225   virtual SPIRVValue *addSamplerConstant(SPIRVType *TheType, SPIRVWord AddrMode,
226       SPIRVWord ParametricMode, SPIRVWord FilterMode);
227   virtual SPIRVValue* addPipeStorageConstant(SPIRVType* TheType,
228     SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity);
229 
230   // Instruction creation functions
231   virtual SPIRVInstruction *addPtrAccessChainInst(SPIRVType *, SPIRVValue *,
232       std::vector<SPIRVValue *>, SPIRVBasicBlock *, bool);
233   virtual SPIRVInstruction *addAsyncGroupCopy(SPIRVValue *Scope,
234       SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride,
235       SPIRVValue *Event, SPIRVBasicBlock *BB);
236   virtual SPIRVInstruction *addExtInst(SPIRVType *,
237       SPIRVWord, SPIRVWord, const std::vector<SPIRVWord> &,
238       SPIRVBasicBlock *);
239   virtual SPIRVInstruction *addExtInst(SPIRVType *,
240       SPIRVWord, SPIRVWord, const std::vector<SPIRVValue *> &,
241       SPIRVBasicBlock *);
242   virtual SPIRVInstruction *addBinaryInst(Op, SPIRVType *, SPIRVValue *,
243       SPIRVValue *, SPIRVBasicBlock *);
244   virtual SPIRVInstruction *addCallInst(SPIRVFunction*,
245       const std::vector<SPIRVWord> &, SPIRVBasicBlock *);
246   virtual SPIRVInstruction *addCmpInst(Op, SPIRVType *, SPIRVValue *,
247       SPIRVValue *, SPIRVBasicBlock *);
248   virtual SPIRVInstruction *addLoadInst(SPIRVValue *,
249       const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
250   virtual SPIRVInstruction *addPhiInst(SPIRVType *, std::vector<SPIRVValue *>,
251       SPIRVBasicBlock *);
252   virtual SPIRVInstruction *addCompositeExtractInst(SPIRVType *, SPIRVValue *,
253       const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
254   virtual SPIRVInstruction *addCompositeInsertInst(SPIRVValue *Object,
255       SPIRVValue *Composite, const std::vector<SPIRVWord>& Indices,
256       SPIRVBasicBlock *BB);
257   virtual SPIRVInstruction *addCopyObjectInst(SPIRVType *TheType,
258       SPIRVValue *Operand, SPIRVBasicBlock *BB);
259   virtual SPIRVInstruction *addCopyMemoryInst(SPIRVValue *, SPIRVValue *,
260     const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
261   virtual SPIRVInstruction *addCopyMemorySizedInst(SPIRVValue *, SPIRVValue *,
262       SPIRVValue *, const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
263   virtual SPIRVInstruction *addControlBarrierInst(
264       SPIRVValue *ExecKind, SPIRVValue *MemKind,
265       SPIRVValue *MemSema, SPIRVBasicBlock *BB);
266   virtual SPIRVInstruction *addGroupInst(Op OpCode, SPIRVType *Type,
267       Scope Scope, const std::vector<SPIRVValue *> &Ops,
268       SPIRVBasicBlock *BB);
269   virtual SPIRVInstruction *addInstruction(SPIRVInstruction *Inst,
270       SPIRVBasicBlock *BB);
271   virtual SPIRVInstTemplateBase *addInstTemplate(Op OC,
272       SPIRVBasicBlock* BB, SPIRVType *Ty);
273   virtual SPIRVInstTemplateBase *addInstTemplate(Op OC,
274       const std::vector<SPIRVWord>& Ops, SPIRVBasicBlock* BB, SPIRVType *Ty);
275   virtual SPIRVInstruction *addMemoryBarrierInst(
276       Scope ScopeKind, SPIRVWord MemFlag, SPIRVBasicBlock *BB);
277   virtual SPIRVInstruction *addReturnInst(SPIRVBasicBlock *);
278   virtual SPIRVInstruction *addReturnValueInst(SPIRVValue *, SPIRVBasicBlock *);
279   virtual SPIRVInstruction *addSelectInst(SPIRVValue *, SPIRVValue *, SPIRVValue *,
280       SPIRVBasicBlock *);
281   virtual SPIRVInstruction *addStoreInst(SPIRVValue *, SPIRVValue *,
282       const std::vector<SPIRVWord>&, SPIRVBasicBlock *);
283   virtual SPIRVInstruction *addSwitchInst(SPIRVValue *, SPIRVBasicBlock *,
284       const std::vector<std::pair<SPIRVWord, SPIRVBasicBlock *>>&,
285       SPIRVBasicBlock *);
286   virtual SPIRVInstruction *addUnaryInst(Op, SPIRVType *, SPIRVValue *,
287       SPIRVBasicBlock *);
288   virtual SPIRVInstruction *addVariable(SPIRVType *, bool, SPIRVLinkageTypeKind,
289     SPIRVValue *, const std::string &, SPIRVStorageClassKind, SPIRVBasicBlock *);
290   virtual SPIRVValue *addVectorShuffleInst(SPIRVType *Type, SPIRVValue *Vec1,
291       SPIRVValue *Vec2, const std::vector<SPIRVWord> &Components,
292       SPIRVBasicBlock *BB);
293   virtual SPIRVInstruction *addVectorExtractDynamicInst(SPIRVValue *,
294       SPIRVValue *, SPIRVBasicBlock *);
295   virtual SPIRVInstruction *addVectorInsertDynamicInst(SPIRVValue *,
296     SPIRVValue *, SPIRVValue*, SPIRVBasicBlock *);
297 
298   // I/O functions
299   friend spv_ostream & operator<<(spv_ostream &O, SPIRVModule& M);
300   friend std::istream & operator>>(std::istream &I, SPIRVModule& M);
301 
302 private:
303   SPIRVErrorLog ErrLog;
304   SPIRVId NextId;
305   SPIRVWord SPIRVVersion;
306   unsigned short GeneratorId;
307   unsigned short GeneratorVer;
308   SPIRVInstructionSchemaKind InstSchema;
309   SourceLanguage SrcLang;
310   SPIRVWord SrcLangVer;
311   std::set<std::string> SrcExtension;
312   std::set<std::string> SPIRVExt;
313   SPIRVAddressingModelKind AddrModel;
314   SPIRVMemoryModelKind MemoryModel;
315 
316   typedef std::map<SPIRVId, SPIRVEntry *> SPIRVIdToEntryMap;
317   typedef std::vector<SPIRVEntry *> SPIRVEntryVector;
318   typedef std::set<SPIRVId> SPIRVIdSet;
319   typedef std::vector<SPIRVId> SPIRVIdVec;
320   typedef std::vector<SPIRVFunction *> SPIRVFunctionVector;
321   typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
322   typedef std::vector<SPIRVType *> SPIRVTypeVec;
323   typedef std::vector<SPIRVValue *> SPIRVConstantVector;
324   typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
325   typedef std::vector<SPIRVString *> SPIRVStringVec;
326   typedef std::vector<SPIRVMemberName *> SPIRVMemberNameVec;
327   typedef std::vector<SPIRVLine *> SPIRVLineVec;
328   typedef std::vector<SPIRVDecorationGroup *> SPIRVDecGroupVec;
329   typedef std::vector<SPIRVGroupDecorateGeneric *> SPIRVGroupDecVec;
330   typedef std::map<SPIRVId, SPIRVExtInstSetKind> SPIRVIdToBuiltinSetMap;
331   typedef std::map<SPIRVExecutionModelKind, SPIRVIdSet> SPIRVExecModelIdSetMap;
332   typedef std::map<SPIRVExecutionModelKind, SPIRVIdVec> SPIRVExecModelIdVecMap;
333   typedef std::unordered_map<std::string, SPIRVString*> SPIRVStringMap;
334   typedef std::map<SPIRVTypeStruct *, std::vector<std::pair<unsigned, SPIRVId>>>
335       SPIRVUnknownStructFieldMap;
336 
337   SPIRVForwardPointerVec ForwardPointerVec;
338   SPIRVTypeVec TypeVec;
339   SPIRVIdToEntryMap IdEntryMap;
340   SPIRVFunctionVector FuncVec;
341   SPIRVConstantVector ConstVec;
342   SPIRVVariableVec VariableVec;
343   SPIRVEntryVector EntryNoId;         // Entries without id
344   SPIRVIdToBuiltinSetMap IdBuiltinMap;
345   SPIRVIdSet NamedId;
346   SPIRVStringVec StringVec;
347   SPIRVMemberNameVec MemberNameVec;
348   SPIRVLineVec LineVec;
349   SPIRVDecorateSet DecorateSet;
350   SPIRVDecGroupVec DecGroupVec;
351   SPIRVGroupDecVec GroupDecVec;
352   SPIRVExecModelIdSetMap EntryPointSet;
353   SPIRVExecModelIdVecMap EntryPointVec;
354   SPIRVStringMap StrMap;
355   SPIRVCapMap CapMap;
356   SPIRVUnknownStructFieldMap UnknownStructFieldMap;
357   std::map<unsigned, SPIRVTypeInt*> IntTypeMap;
358   std::map<unsigned, SPIRVConstant*> LiteralMap;
359 
360   void layoutEntry(SPIRVEntry* Entry);
361 };
362 
~SPIRVModuleImpl()363 SPIRVModuleImpl::~SPIRVModuleImpl() {
364   //ToDo: Fix bug causing crash
365   //for (auto I:IdEntryMap)
366   //  delete I.second;
367 
368   // ToDo: Fix bug causing crash
369   //for (auto I:EntryNoId) {
370   //  bildbgs() << "[delete] " << *I;
371   //  delete I;
372   //}
373 
374   for (auto C : CapMap)
375     delete C.second;
376 }
377 
378 SPIRVLine*
addLine(SPIRVEntry * E,SPIRVString * FileName,SPIRVWord Line,SPIRVWord Column)379 SPIRVModuleImpl::addLine(SPIRVEntry* E, SPIRVString* FileName,
380     SPIRVWord Line, SPIRVWord Column) {
381   auto L = add(new SPIRVLine(E, FileName->getId(), Line, Column));
382   E->setLine(L);
383   return L;
384 }
385 
386 // Creates decoration group and group decorates from decorates shared by
387 // multiple targets.
388 void
optimizeDecorates()389 SPIRVModuleImpl::optimizeDecorates() {
390   SPIRVDBG(spvdbgs() << "[optimizeDecorates] begin\n");
391   for (auto I = DecorateSet.begin(), E = DecorateSet.end(); I != E;) {
392     auto D = *I;
393     SPIRVDBG(spvdbgs() << "  check " << *D << '\n');
394     if (D->getOpCode() == OpMemberDecorate) {
395       ++I;
396       continue;
397     }
398     auto ER = DecorateSet.equal_range(D);
399     SPIRVDBG(spvdbgs() << "  equal range " << **ER.first
400                       << " to ";
401             if (ER.second != DecorateSet.end())
402               spvdbgs() << **ER.second;
403             else
404               spvdbgs() << "end";
405             spvdbgs() << '\n');
406     if (std::distance(ER.first, ER.second) < 2) {
407       I = ER.second;
408       SPIRVDBG(spvdbgs() << "  skip equal range \n");
409       continue;
410     }
411     SPIRVDBG(spvdbgs() << "  add deco group. erase equal range\n");
412     auto G = new SPIRVDecorationGroup(this, getId());
413     std::vector<SPIRVId> Targets;
414     Targets.push_back(D->getTargetId());
415     const_cast<SPIRVDecorateGeneric*>(D)->setTargetId(G->getId());
416     G->getDecorations().insert(D);
417     for (I = ER.first; I != ER.second; ++I) {
418       auto E = *I;
419       if (*E == *D)
420         continue;
421       Targets.push_back(E->getTargetId());
422     }
423 
424     // WordCount is only 16 bits.  We can only have 65535 - FixedWC targtets per
425     // group.
426     // For now, just skip using a group if the number of targets to too big
427     if (Targets.size() < 65530) {
428       DecorateSet.erase(ER.first, ER.second);
429       auto GD = new SPIRVGroupDecorate(G, Targets);
430       DecGroupVec.push_back(G);
431       GroupDecVec.push_back(GD);
432     }
433   }
434 }
435 
436 SPIRVValue*
addSamplerConstant(SPIRVType * TheType,SPIRVWord AddrMode,SPIRVWord ParametricMode,SPIRVWord FilterMode)437 SPIRVModuleImpl::addSamplerConstant(SPIRVType* TheType,
438     SPIRVWord AddrMode, SPIRVWord ParametricMode, SPIRVWord FilterMode) {
439   return addConstant(new SPIRVConstantSampler(this, TheType, getId(), AddrMode,
440       ParametricMode, FilterMode));
441 }
442 
443 SPIRVValue*
addPipeStorageConstant(SPIRVType * TheType,SPIRVWord PacketSize,SPIRVWord PacketAlign,SPIRVWord Capacity)444 SPIRVModuleImpl::addPipeStorageConstant(SPIRVType* TheType,
445     SPIRVWord PacketSize, SPIRVWord PacketAlign, SPIRVWord Capacity) {
446   return addConstant(new SPIRVConstantPipeStorage(this, TheType, getId(),
447     PacketSize, PacketAlign, Capacity));
448 }
449 
450 void
addCapability(SPIRVCapabilityKind Cap)451 SPIRVModuleImpl::addCapability(SPIRVCapabilityKind Cap) {
452   addCapabilities(SPIRV::getCapability(Cap));
453   SPIRVDBG(spvdbgs() << "addCapability: " << Cap << '\n');
454   if (hasCapability(Cap))
455     return;
456 
457   CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap)));
458 }
459 
460 void
addCapabilityInternal(SPIRVCapabilityKind Cap)461 SPIRVModuleImpl::addCapabilityInternal(SPIRVCapabilityKind Cap) {
462   if (AutoAddCapability) {
463     if (hasCapability(Cap))
464       return;
465 
466     CapMap.insert(std::make_pair(Cap, new SPIRVCapability(this, Cap)));
467   }
468 }
469 
470 SPIRVConstant*
getLiteralAsConstant(unsigned Literal)471 SPIRVModuleImpl::getLiteralAsConstant(unsigned Literal) {
472   auto Loc = LiteralMap.find(Literal);
473   if (Loc != LiteralMap.end())
474     return Loc->second;
475   auto Ty = addIntegerType(32);
476   auto V = new SPIRVConstant(this, Ty, getId(), static_cast<uint64_t>(Literal));
477   LiteralMap[Literal] = V;
478   addConstant(V);
479   return V;
480 }
481 
482 void
layoutEntry(SPIRVEntry * E)483 SPIRVModuleImpl::layoutEntry(SPIRVEntry* E) {
484   auto OC = E->getOpCode();
485   switch (OC) {
486   case OpString:
487     addTo(StringVec, E);
488     break;
489   case OpMemberName:
490     addTo(MemberNameVec, E);
491     break;
492   case OpLine:
493     addTo(LineVec, E);
494     break;
495   case OpVariable: {
496     auto BV = static_cast<SPIRVVariable*>(E);
497     if (!BV->getParent())
498       addTo(VariableVec, E);
499     }
500     break;
501   default:
502     if (isTypeOpCode(OC))
503       TypeVec.push_back(static_cast<SPIRVType*>(E));
504     else if (isConstantOpCode(OC))
505       ConstVec.push_back(static_cast<SPIRVConstant*>(E));
506     break;
507   }
508 }
509 
510 // Add an entry to the id to entry map.
511 // Assert if the id is mapped to a different entry.
512 // Certain entries need to be add to specific collectors to maintain
513 // logic layout of SPIRV.
514 SPIRVEntry *
addEntry(SPIRVEntry * Entry)515 SPIRVModuleImpl::addEntry(SPIRVEntry *Entry) {
516   assert(Entry && "Invalid entry");
517   if (Entry->hasId()) {
518     SPIRVId Id = Entry->getId();
519     assert(Entry->getId() != SPIRVID_INVALID && "Invalid id");
520     SPIRVEntry *Mapped = nullptr;
521     if (exist(Id, &Mapped)) {
522       if (Mapped->getOpCode() == OpForward) {
523         replaceForward(static_cast<SPIRVForward *>(Mapped), Entry);
524       } else {
525         assert(Mapped == Entry && "Id used twice");
526       }
527     } else
528       IdEntryMap[Id] = Entry;
529   } else {
530     EntryNoId.push_back(Entry);
531   }
532 
533   Entry->setModule(this);
534 
535   layoutEntry(Entry);
536   if (AutoAddCapability) {
537     for (auto &I:Entry->getRequiredCapability()) {
538       addCapability(I);
539     }
540   }
541   if (ValidateCapability) {
542     for (auto &I:Entry->getRequiredCapability()) {
543       (void) I;
544       assert(CapMap.count(I));
545     }
546   }
547   return Entry;
548 }
549 
550 bool
exist(SPIRVId Id) const551 SPIRVModuleImpl::exist(SPIRVId Id) const {
552   return exist(Id, nullptr);
553 }
554 
555 bool
exist(SPIRVId Id,SPIRVEntry ** Entry) const556 SPIRVModuleImpl::exist(SPIRVId Id, SPIRVEntry **Entry) const {
557   assert (Id != SPIRVID_INVALID && "Invalid Id");
558   SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
559   if (Loc == IdEntryMap.end())
560     return false;
561   if (Entry)
562     *Entry = Loc->second;
563   return true;
564 }
565 
566 // If Id is invalid, returns the next available id.
567 // Otherwise returns the given id and adjust the next available id by increment.
568 SPIRVId
getId(SPIRVId Id,unsigned increment)569 SPIRVModuleImpl::getId(SPIRVId Id, unsigned increment) {
570   if (!isValidId(Id))
571     Id = NextId;
572   else
573     NextId = std::max(Id, NextId);
574   NextId += increment;
575   return Id;
576 }
577 
578 SPIRVEntry *
getEntry(SPIRVId Id) const579 SPIRVModuleImpl::getEntry(SPIRVId Id) const {
580   assert (Id != SPIRVID_INVALID && "Invalid Id");
581   SPIRVIdToEntryMap::const_iterator Loc = IdEntryMap.find(Id);
582   assert (Loc != IdEntryMap.end() && "Id is not in map");
583   return Loc->second;
584 }
585 
586 SPIRVExtInstSetKind
getBuiltinSet(SPIRVId SetId) const587 SPIRVModuleImpl::getBuiltinSet(SPIRVId SetId) const {
588   auto Loc = IdBuiltinMap.find(SetId);
589   assert(Loc != IdBuiltinMap.end() && "Invalid builtin set id");
590   return Loc->second;
591 }
592 
593 bool
isEntryPoint(SPIRVExecutionModelKind ExecModel,SPIRVId EP) const594 SPIRVModuleImpl::isEntryPoint(SPIRVExecutionModelKind ExecModel, SPIRVId EP)
595   const {
596   assert(isValid(ExecModel) && "Invalid execution model");
597   assert(EP != SPIRVID_INVALID && "Invalid function id");
598   auto Loc = EntryPointSet.find(ExecModel);
599   if (Loc == EntryPointSet.end())
600     return false;
601   return Loc->second.count(EP);
602 }
603 
604 // Module change functions
605 bool
importBuiltinSet(const std::string & BuiltinSetName,SPIRVId * BuiltinSetId)606 SPIRVModuleImpl::importBuiltinSet(const std::string& BuiltinSetName,
607     SPIRVId *BuiltinSetId) {
608   SPIRVId TmpBuiltinSetId = getId();
609   if (!importBuiltinSetWithId(BuiltinSetName, TmpBuiltinSetId))
610     return false;
611   if (BuiltinSetId)
612     *BuiltinSetId = TmpBuiltinSetId;
613   return true;
614 }
615 
616 bool
importBuiltinSetWithId(const std::string & BuiltinSetName,SPIRVId BuiltinSetId)617 SPIRVModuleImpl::importBuiltinSetWithId(const std::string& BuiltinSetName,
618     SPIRVId BuiltinSetId) {
619   SPIRVExtInstSetKind BuiltinSet = SPIRVEIS_Count;
620   SPIRVCKRT(SPIRVBuiltinSetNameMap::rfind(BuiltinSetName, &BuiltinSet),
621       InvalidBuiltinSetName, "Actual is " + BuiltinSetName);
622   IdBuiltinMap[BuiltinSetId] = BuiltinSet;
623   return true;
624 }
625 
626 void
setAlignment(SPIRVValue * V,SPIRVWord A)627 SPIRVModuleImpl::setAlignment(SPIRVValue *V, SPIRVWord A) {
628   V->setAlignment(A);
629 }
630 
631 void
setName(SPIRVEntry * E,const std::string & Name)632 SPIRVModuleImpl::setName(SPIRVEntry *E, const std::string &Name) {
633   E->setName(Name);
634   if (!E->hasId())
635     return;
636   if (!Name.empty())
637     NamedId.insert(E->getId());
638   else
639     NamedId.erase(E->getId());
640 }
641 
resolveUnknownStructFields()642 void SPIRVModuleImpl::resolveUnknownStructFields() {
643   for (auto &KV : UnknownStructFieldMap) {
644     auto *Struct = KV.first;
645     for (auto &Indices : KV.second) {
646       unsigned I = Indices.first;
647       SPIRVId ID = Indices.second;
648 
649       auto Ty = static_cast<SPIRVType *>(getEntry(ID));
650       Struct->setMemberType(I, Ty);
651     }
652   }
653 }
654 
655 // Type creation functions
656 template<class T>
657 T *
addType(T * Ty)658 SPIRVModuleImpl::addType(T *Ty) {
659   add(Ty);
660   if (!Ty->getName().empty())
661     setName(Ty, Ty->getName());
662   return Ty;
663 }
664 
665 SPIRVTypeVoid *
addVoidType()666 SPIRVModuleImpl::addVoidType() {
667   return addType(new SPIRVTypeVoid(this, getId()));
668 }
669 
670 SPIRVTypeArray *
addArrayType(SPIRVType * ElementType,SPIRVConstant * Length)671 SPIRVModuleImpl::addArrayType(SPIRVType *ElementType, SPIRVConstant *Length) {
672   return addType(new SPIRVTypeArray(this, getId(), ElementType, Length));
673 }
674 
675 SPIRVTypeBool *
addBoolType()676 SPIRVModuleImpl::addBoolType() {
677   return addType(new SPIRVTypeBool(this, getId()));
678 }
679 
680 SPIRVTypeInt *
addIntegerType(unsigned BitWidth)681 SPIRVModuleImpl::addIntegerType(unsigned BitWidth) {
682   auto Loc = IntTypeMap.find(BitWidth);
683   if (Loc != IntTypeMap.end())
684     return Loc->second;
685   auto Ty = new SPIRVTypeInt(this, getId(), BitWidth, false);
686   IntTypeMap[BitWidth] = Ty;
687   return addType(Ty);
688 }
689 
690 SPIRVTypeFloat *
addFloatType(unsigned BitWidth)691 SPIRVModuleImpl::addFloatType(unsigned BitWidth) {
692   SPIRVTypeFloat *T = addType(new SPIRVTypeFloat(this, getId(), BitWidth));
693   return T;
694 }
695 
696 SPIRVTypePointer *
addPointerType(SPIRVStorageClassKind StorageClass,SPIRVType * ElementType)697 SPIRVModuleImpl::addPointerType(SPIRVStorageClassKind StorageClass,
698     SPIRVType *ElementType) {
699   return addType(new SPIRVTypePointer(this, getId(), StorageClass,
700       ElementType));
701 }
702 
703 SPIRVTypeFunction *
addFunctionType(SPIRVType * ReturnType,const std::vector<SPIRVType * > & ParameterTypes)704 SPIRVModuleImpl::addFunctionType(SPIRVType *ReturnType,
705     const std::vector<SPIRVType *>& ParameterTypes) {
706   return addType(new SPIRVTypeFunction(this, getId(), ReturnType,
707       ParameterTypes));
708 }
709 
710 SPIRVTypeOpaque*
addOpaqueType(const std::string & Name)711 SPIRVModuleImpl::addOpaqueType(const std::string& Name) {
712   return addType(new SPIRVTypeOpaque(this, getId(), Name));
713 }
714 
openStructType(unsigned NumMembers,const std::string & Name)715 SPIRVTypeStruct *SPIRVModuleImpl::openStructType(unsigned NumMembers,
716                                                  const std::string &Name) {
717   auto T = new SPIRVTypeStruct(this, getId(), NumMembers, Name);
718   return T;
719 }
720 
closeStructType(SPIRVTypeStruct * T,bool Packed)721 void SPIRVModuleImpl::closeStructType(SPIRVTypeStruct *T, bool Packed) {
722   addType(T);
723   T->setPacked(Packed);
724 }
725 
726 SPIRVTypeVector*
addVectorType(SPIRVType * CompType,SPIRVWord CompCount)727 SPIRVModuleImpl::addVectorType(SPIRVType* CompType, SPIRVWord CompCount) {
728   return addType(new SPIRVTypeVector(this, getId(), CompType, CompCount));
729 }
730 SPIRVType *
addOpaqueGenericType(Op TheOpCode)731 SPIRVModuleImpl::addOpaqueGenericType(Op TheOpCode) {
732   return addType(new SPIRVTypeOpaqueGeneric(TheOpCode, this, getId()));
733 }
734 
735 SPIRVTypeDeviceEvent *
addDeviceEventType()736 SPIRVModuleImpl::addDeviceEventType() {
737   return addType(new SPIRVTypeDeviceEvent(this, getId()));
738 }
739 
740 SPIRVTypeQueue *
addQueueType()741 SPIRVModuleImpl::addQueueType() {
742   return addType(new SPIRVTypeQueue(this, getId()));
743 }
744 
745 SPIRVTypePipe*
addPipeType()746 SPIRVModuleImpl::addPipeType() {
747   return addType(new SPIRVTypePipe(this, getId()));
748 }
749 
750 SPIRVTypeImage *
addImageType(SPIRVType * SampledType,const SPIRVTypeImageDescriptor & Desc)751 SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
752     const SPIRVTypeImageDescriptor &Desc) {
753   return addType(new SPIRVTypeImage(this, getId(),
754     SampledType ? SampledType->getId() : 0, Desc));
755 }
756 
757 SPIRVTypeImage *
addImageType(SPIRVType * SampledType,const SPIRVTypeImageDescriptor & Desc,SPIRVAccessQualifierKind Acc)758 SPIRVModuleImpl::addImageType(SPIRVType *SampledType,
759     const SPIRVTypeImageDescriptor &Desc, SPIRVAccessQualifierKind Acc) {
760   return addType(new SPIRVTypeImage(this, getId(),
761     SampledType ? SampledType->getId() : 0, Desc, Acc));
762 }
763 
764 SPIRVTypeSampler *
addSamplerType()765 SPIRVModuleImpl::addSamplerType() {
766   return addType(new SPIRVTypeSampler(this, getId()));
767 }
768 
769 SPIRVTypePipeStorage*
addPipeStorageType()770 SPIRVModuleImpl::addPipeStorageType() {
771   return addType(new SPIRVTypePipeStorage(this, getId()));
772 }
773 
774 SPIRVTypeSampledImage *
addSampledImageType(SPIRVTypeImage * T)775 SPIRVModuleImpl::addSampledImageType(SPIRVTypeImage *T) {
776   return addType(new SPIRVTypeSampledImage(this, getId(), T));
777 }
778 
createForwardPointers()779 void SPIRVModuleImpl::createForwardPointers() {
780   std::unordered_set<SPIRVId> Seen;
781 
782   for (auto *T : TypeVec) {
783     if (T->hasId())
784       Seen.insert(T->getId());
785 
786     if (!T->isTypeStruct())
787       continue;
788 
789     auto ST = static_cast<SPIRVTypeStruct *>(T);
790 
791     for (unsigned i = 0; i < ST->getStructMemberCount(); ++i) {
792       auto MemberTy = ST->getStructMemberType(i);
793       if (!MemberTy->isTypePointer()) continue;
794       auto Ptr = static_cast<SPIRVTypePointer *>(MemberTy);
795 
796       if (Seen.find(Ptr->getId()) == Seen.end()) {
797         ForwardPointerVec.push_back(new SPIRVTypeForwardPointer(
798             this, Ptr, Ptr->getPointerStorageClass()));
799       }
800     }
801   }
802 }
803 
804 SPIRVFunction *
addFunction(SPIRVFunction * Func)805 SPIRVModuleImpl::addFunction(SPIRVFunction *Func) {
806   FuncVec.push_back(add(Func));
807   return Func;
808 }
809 
810 SPIRVFunction *
addFunction(SPIRVTypeFunction * FuncType,SPIRVId Id)811 SPIRVModuleImpl::addFunction(SPIRVTypeFunction *FuncType, SPIRVId Id) {
812   return addFunction(new SPIRVFunction(this, FuncType,
813       getId(Id, FuncType->getNumParameters() + 1)));
814 }
815 
816 SPIRVBasicBlock *
addBasicBlock(SPIRVFunction * Func,SPIRVId Id)817 SPIRVModuleImpl::addBasicBlock(SPIRVFunction *Func, SPIRVId Id) {
818   return Func->addBasicBlock(new SPIRVBasicBlock(getId(Id), Func));
819 }
820 
821 const SPIRVDecorateGeneric *
addDecorate(const SPIRVDecorateGeneric * Dec)822 SPIRVModuleImpl::addDecorate(const SPIRVDecorateGeneric *Dec) {
823   SPIRVId Id = Dec->getTargetId();
824   SPIRVEntry *Target = nullptr;
825   bool Found = exist(Id, &Target);
826   (void) Found;
827   assert (Found && "Decorate target does not exist");
828   if (!Dec->getOwner())
829     DecorateSet.insert(Dec);
830   addCapabilities(Dec->getRequiredCapability());
831   return Dec;
832 }
833 
834 void
addEntryPoint(SPIRVExecutionModelKind ExecModel,SPIRVId EntryPoint)835 SPIRVModuleImpl::addEntryPoint(SPIRVExecutionModelKind ExecModel,
836     SPIRVId EntryPoint){
837   assert(isValid(ExecModel) && "Invalid execution model");
838   assert(EntryPoint != SPIRVID_INVALID && "Invalid entry point");
839   EntryPointSet[ExecModel].insert(EntryPoint);
840   EntryPointVec[ExecModel].push_back(EntryPoint);
841   addCapabilities(SPIRV::getCapability(ExecModel));
842 }
843 
844 SPIRVForward *
addForward(SPIRVType * Ty)845 SPIRVModuleImpl::addForward(SPIRVType *Ty) {
846   return add(new SPIRVForward(this, Ty, getId()));
847 }
848 
849 SPIRVForward *
addForward(SPIRVId Id,SPIRVType * Ty)850 SPIRVModuleImpl::addForward(SPIRVId Id, SPIRVType *Ty) {
851   return add(new SPIRVForward(this, Ty, Id));
852 }
853 
854 SPIRVEntry *
replaceForward(SPIRVForward * Forward,SPIRVEntry * Entry)855 SPIRVModuleImpl::replaceForward(SPIRVForward *Forward, SPIRVEntry *Entry) {
856   SPIRVId Id = Entry->getId();
857   SPIRVId ForwardId = Forward->getId();
858   if (ForwardId == Id)
859     IdEntryMap[Id] = Entry;
860   else {
861     auto Loc = IdEntryMap.find(Id);
862     assert(Loc != IdEntryMap.end());
863     IdEntryMap.erase(Loc);
864     Entry->setId(ForwardId);
865     IdEntryMap[ForwardId] = Entry;
866   }
867   // Annotations include name, decorations, execution modes
868   Entry->takeAnnotations(Forward);
869   delete Forward;
870   return Entry;
871 }
872 
873 SPIRVValue *
addConstant(SPIRVValue * C)874 SPIRVModuleImpl::addConstant(SPIRVValue *C) {
875   return add(C);
876 }
877 
878 SPIRVValue *
addConstant(SPIRVType * Ty,uint64_t V)879 SPIRVModuleImpl::addConstant(SPIRVType *Ty, uint64_t V) {
880   if (Ty->isTypeBool()) {
881     if (V)
882       return addConstant(new SPIRVConstantTrue(this, Ty, getId()));
883     else
884       return addConstant(new SPIRVConstantFalse(this, Ty, getId()));
885   }
886   if (Ty->isTypeInt())
887     return addIntegerConstant(static_cast<SPIRVTypeInt*>(Ty), V);
888   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
889 }
890 
891 SPIRVValue *
addIntegerConstant(SPIRVTypeInt * Ty,uint64_t V)892 SPIRVModuleImpl::addIntegerConstant(SPIRVTypeInt *Ty, uint64_t V) {
893   if (Ty->getBitWidth() == 32) {
894     unsigned I32 = V;
895     assert(I32 == V && "Integer value truncated");
896     return getLiteralAsConstant(I32);
897   }
898   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
899 }
900 
901 SPIRVValue *
addFloatConstant(SPIRVTypeFloat * Ty,float V)902 SPIRVModuleImpl::addFloatConstant(SPIRVTypeFloat *Ty, float V) {
903   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
904 }
905 
906 SPIRVValue *
addDoubleConstant(SPIRVTypeFloat * Ty,double V)907 SPIRVModuleImpl::addDoubleConstant(SPIRVTypeFloat *Ty, double V) {
908   return addConstant(new SPIRVConstant(this, Ty, getId(), V));
909 }
910 
911 SPIRVValue *
addNullConstant(SPIRVType * Ty)912 SPIRVModuleImpl::addNullConstant(SPIRVType *Ty) {
913   return addConstant(new SPIRVConstantNull(this, Ty, getId()));
914 }
915 
916 SPIRVValue *
addCompositeConstant(SPIRVType * Ty,const std::vector<SPIRVValue * > & Elements)917 SPIRVModuleImpl::addCompositeConstant(SPIRVType *Ty,
918     const std::vector<SPIRVValue*>& Elements) {
919   return addConstant(new SPIRVConstantComposite(this, Ty, getId(), Elements));
920 }
921 
922 SPIRVValue *
addUndef(SPIRVType * TheType)923 SPIRVModuleImpl::addUndef(SPIRVType *TheType) {
924   return addConstant(new SPIRVUndef(this, TheType, getId()));
925 }
926 
927 // Instruction creation functions
928 
929 SPIRVInstruction *
addStoreInst(SPIRVValue * Target,SPIRVValue * Source,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)930 SPIRVModuleImpl::addStoreInst(SPIRVValue *Target, SPIRVValue *Source,
931     const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
932   return BB->addInstruction(new SPIRVStore(Target->getId(),
933       Source->getId(), TheMemoryAccess, BB));
934 }
935 
936 SPIRVInstruction *
addSwitchInst(SPIRVValue * Select,SPIRVBasicBlock * Default,const std::vector<std::pair<SPIRVWord,SPIRVBasicBlock * >> & Pairs,SPIRVBasicBlock * BB)937 SPIRVModuleImpl::addSwitchInst(SPIRVValue *Select, SPIRVBasicBlock *Default,
938     const std::vector<std::pair<SPIRVWord, SPIRVBasicBlock *>>& Pairs,
939     SPIRVBasicBlock *BB) {
940   return BB->addInstruction(new SPIRVSwitch(Select, Default, Pairs, BB));
941 }
942 
943 SPIRVInstruction *
addGroupInst(Op OpCode,SPIRVType * Type,Scope Scope,const std::vector<SPIRVValue * > & Ops,SPIRVBasicBlock * BB)944 SPIRVModuleImpl::addGroupInst(Op OpCode, SPIRVType *Type,
945     Scope Scope, const std::vector<SPIRVValue *> &Ops,
946     SPIRVBasicBlock *BB) {
947   assert(!Type || !Type->isTypeVoid());
948   auto WordOps = getIds(Ops);
949   WordOps.insert(WordOps.begin(), Scope);
950   return addInstTemplate(OpCode, WordOps, BB, Type);
951 }
952 
953 SPIRVInstruction *
addInstruction(SPIRVInstruction * Inst,SPIRVBasicBlock * BB)954 SPIRVModuleImpl::addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB) {
955   if (BB)
956     return BB->addInstruction(Inst);
957   if (Inst->getOpCode() != OpSpecConstantOp)
958     Inst = createSpecConstantOpInst(Inst);
959   return static_cast<SPIRVInstruction *>(addConstant(Inst));
960 }
961 
962 SPIRVInstruction *
addLoadInst(SPIRVValue * Source,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)963 SPIRVModuleImpl::addLoadInst(SPIRVValue *Source,
964     const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
965   return addInstruction(new SPIRVLoad(getId(), Source->getId(),
966       TheMemoryAccess, BB), BB);
967 }
968 
969 SPIRVInstruction *
addPhiInst(SPIRVType * Type,std::vector<SPIRVValue * > IncomingPairs,SPIRVBasicBlock * BB)970 SPIRVModuleImpl::addPhiInst(SPIRVType *Type,
971     std::vector<SPIRVValue *> IncomingPairs, SPIRVBasicBlock *BB) {
972   return addInstruction(new SPIRVPhi(Type, getId(), IncomingPairs, BB), BB);
973 }
974 
975 SPIRVInstruction *
addExtInst(SPIRVType * TheType,SPIRVWord BuiltinSet,SPIRVWord EntryPoint,const std::vector<SPIRVWord> & Args,SPIRVBasicBlock * BB)976 SPIRVModuleImpl::addExtInst(SPIRVType *TheType, SPIRVWord BuiltinSet,
977     SPIRVWord EntryPoint, const std::vector<SPIRVWord> &Args,
978     SPIRVBasicBlock *BB) {
979   return addInstruction(new SPIRVExtInst(TheType, getId(),
980       BuiltinSet, EntryPoint, Args, BB), BB);
981 }
982 
983 SPIRVInstruction *
addExtInst(SPIRVType * TheType,SPIRVWord BuiltinSet,SPIRVWord EntryPoint,const std::vector<SPIRVValue * > & Args,SPIRVBasicBlock * BB)984 SPIRVModuleImpl::addExtInst(SPIRVType *TheType, SPIRVWord BuiltinSet,
985     SPIRVWord EntryPoint, const std::vector<SPIRVValue *> &Args,
986     SPIRVBasicBlock *BB) {
987   return addInstruction(new SPIRVExtInst(TheType, getId(),
988       BuiltinSet, EntryPoint, Args, BB), BB);
989 }
990 
991 SPIRVInstruction*
addCallInst(SPIRVFunction * TheFunction,const std::vector<SPIRVWord> & TheArguments,SPIRVBasicBlock * BB)992 SPIRVModuleImpl::addCallInst(SPIRVFunction* TheFunction,
993     const std::vector<SPIRVWord> &TheArguments, SPIRVBasicBlock *BB) {
994   return addInstruction(new SPIRVFunctionCall(getId(), TheFunction,
995       TheArguments, BB), BB);
996 }
997 
998 SPIRVInstruction *
addBinaryInst(Op TheOpCode,SPIRVType * Type,SPIRVValue * Op1,SPIRVValue * Op2,SPIRVBasicBlock * BB)999 SPIRVModuleImpl::addBinaryInst(Op TheOpCode, SPIRVType *Type,
1000     SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB){
1001   return addInstruction(SPIRVInstTemplateBase::create(TheOpCode, Type, getId(),
1002       getVec(Op1->getId(), Op2->getId()), BB, this), BB);
1003 }
1004 
1005 SPIRVInstruction *
addReturnInst(SPIRVBasicBlock * BB)1006 SPIRVModuleImpl::addReturnInst(SPIRVBasicBlock *BB) {
1007   return addInstruction(new SPIRVReturn(BB), BB);
1008 }
1009 
1010 SPIRVInstruction *
addReturnValueInst(SPIRVValue * ReturnValue,SPIRVBasicBlock * BB)1011 SPIRVModuleImpl::addReturnValueInst(SPIRVValue *ReturnValue, SPIRVBasicBlock *BB) {
1012   return addInstruction(new SPIRVReturnValue(ReturnValue, BB), BB);
1013 }
1014 
1015 SPIRVInstruction *
addUnaryInst(Op TheOpCode,SPIRVType * TheType,SPIRVValue * Op,SPIRVBasicBlock * BB)1016 SPIRVModuleImpl::addUnaryInst(Op TheOpCode, SPIRVType *TheType,
1017     SPIRVValue *Op, SPIRVBasicBlock *BB) {
1018   return addInstruction(SPIRVInstTemplateBase::create(TheOpCode,
1019       TheType, getId(), getVec(Op->getId()), BB, this), BB);
1020 }
1021 
1022 SPIRVInstruction *
addVectorExtractDynamicInst(SPIRVValue * TheVector,SPIRVValue * Index,SPIRVBasicBlock * BB)1023 SPIRVModuleImpl::addVectorExtractDynamicInst(SPIRVValue *TheVector,
1024     SPIRVValue *Index, SPIRVBasicBlock *BB) {
1025   return addInstruction(new SPIRVVectorExtractDynamic(getId(), TheVector,
1026       Index, BB), BB);
1027 }
1028 
1029 SPIRVInstruction *
addVectorInsertDynamicInst(SPIRVValue * TheVector,SPIRVValue * TheComponent,SPIRVValue * Index,SPIRVBasicBlock * BB)1030 SPIRVModuleImpl::addVectorInsertDynamicInst(SPIRVValue *TheVector,
1031 SPIRVValue *TheComponent, SPIRVValue*Index, SPIRVBasicBlock *BB) {
1032   return addInstruction(new SPIRVVectorInsertDynamic(getId(), TheVector,
1033       TheComponent, Index, BB), BB);
1034 }
1035 
1036 SPIRVValue *
addVectorShuffleInst(SPIRVType * Type,SPIRVValue * Vec1,SPIRVValue * Vec2,const std::vector<SPIRVWord> & Components,SPIRVBasicBlock * BB)1037 SPIRVModuleImpl::addVectorShuffleInst(SPIRVType * Type, SPIRVValue *Vec1,
1038     SPIRVValue *Vec2, const std::vector<SPIRVWord> &Components,
1039     SPIRVBasicBlock *BB) {
1040   return addInstruction(new SPIRVVectorShuffle(getId(), Type, Vec1, Vec2,
1041       Components, BB), BB);
1042 }
1043 
1044 SPIRVInstruction *
addBranchInst(SPIRVLabel * TargetLabel,SPIRVBasicBlock * BB)1045 SPIRVModuleImpl::addBranchInst(SPIRVLabel *TargetLabel, SPIRVBasicBlock *BB) {
1046   return addInstruction(new SPIRVBranch(TargetLabel, BB), BB);
1047 }
1048 
1049 SPIRVInstruction *
addBranchConditionalInst(SPIRVValue * Condition,SPIRVLabel * TrueLabel,SPIRVLabel * FalseLabel,SPIRVBasicBlock * BB)1050 SPIRVModuleImpl::addBranchConditionalInst(SPIRVValue *Condition,
1051     SPIRVLabel *TrueLabel, SPIRVLabel *FalseLabel, SPIRVBasicBlock *BB) {
1052   return addInstruction(new SPIRVBranchConditional(Condition, TrueLabel,
1053       FalseLabel, BB), BB);
1054 }
1055 
1056 SPIRVInstruction *
addCmpInst(Op TheOpCode,SPIRVType * TheType,SPIRVValue * Op1,SPIRVValue * Op2,SPIRVBasicBlock * BB)1057 SPIRVModuleImpl::addCmpInst(Op TheOpCode, SPIRVType *TheType,
1058     SPIRVValue *Op1, SPIRVValue *Op2, SPIRVBasicBlock *BB) {
1059   return addInstruction(SPIRVInstTemplateBase::create(TheOpCode,
1060       TheType, getId(), getVec(Op1->getId(), Op2->getId()), BB, this), BB);
1061 }
1062 
1063 SPIRVInstruction *
addControlBarrierInst(SPIRVValue * ExecKind,SPIRVValue * MemKind,SPIRVValue * MemSema,SPIRVBasicBlock * BB)1064 SPIRVModuleImpl::addControlBarrierInst(SPIRVValue *ExecKind,
1065     SPIRVValue *MemKind, SPIRVValue *MemSema, SPIRVBasicBlock *BB) {
1066   return addInstruction(
1067       new SPIRVControlBarrier(ExecKind, MemKind, MemSema, BB), BB);
1068 }
1069 
1070 SPIRVInstruction *
addMemoryBarrierInst(Scope ScopeKind,SPIRVWord MemFlag,SPIRVBasicBlock * BB)1071 SPIRVModuleImpl::addMemoryBarrierInst(Scope ScopeKind,
1072     SPIRVWord MemFlag, SPIRVBasicBlock *BB) {
1073   return addInstruction(SPIRVInstTemplateBase::create(OpMemoryBarrier,
1074       nullptr, SPIRVID_INVALID,
1075       getVec(static_cast<SPIRVWord>(ScopeKind), MemFlag), BB, this), BB);
1076 }
1077 
1078 SPIRVInstruction *
addSelectInst(SPIRVValue * Condition,SPIRVValue * Op1,SPIRVValue * Op2,SPIRVBasicBlock * BB)1079 SPIRVModuleImpl::addSelectInst(SPIRVValue *Condition, SPIRVValue *Op1,
1080     SPIRVValue *Op2, SPIRVBasicBlock *BB) {
1081   return addInstruction(new SPIRVSelect(getId(), Condition->getId(),
1082       Op1->getId(), Op2->getId(), BB), BB);
1083 }
1084 
1085 SPIRVInstruction *
addPtrAccessChainInst(SPIRVType * Type,SPIRVValue * Base,std::vector<SPIRVValue * > Indices,SPIRVBasicBlock * BB,bool IsInBounds)1086 SPIRVModuleImpl::addPtrAccessChainInst(SPIRVType *Type, SPIRVValue *Base,
1087     std::vector<SPIRVValue *> Indices, SPIRVBasicBlock *BB, bool IsInBounds){
1088   return addInstruction(SPIRVInstTemplateBase::create(
1089     IsInBounds?OpInBoundsPtrAccessChain:OpPtrAccessChain,
1090     Type, getId(), getVec(Base->getId(), Base->getIds(Indices)),
1091     BB, this), BB);
1092 }
1093 
1094 SPIRVInstruction *
addAsyncGroupCopy(SPIRVValue * Scope,SPIRVValue * Dest,SPIRVValue * Src,SPIRVValue * NumElems,SPIRVValue * Stride,SPIRVValue * Event,SPIRVBasicBlock * BB)1095 SPIRVModuleImpl::addAsyncGroupCopy(SPIRVValue *Scope,
1096     SPIRVValue *Dest, SPIRVValue *Src, SPIRVValue *NumElems, SPIRVValue *Stride,
1097     SPIRVValue *Event, SPIRVBasicBlock *BB) {
1098   return addInstruction(new SPIRVGroupAsyncCopy(Scope, getId(), Dest, Src,
1099     NumElems, Stride, Event, BB), BB);
1100 }
1101 
1102 SPIRVInstruction *
addCompositeExtractInst(SPIRVType * Type,SPIRVValue * TheVector,const std::vector<SPIRVWord> & Indices,SPIRVBasicBlock * BB)1103 SPIRVModuleImpl::addCompositeExtractInst(SPIRVType *Type, SPIRVValue *TheVector,
1104     const std::vector<SPIRVWord>& Indices, SPIRVBasicBlock *BB) {
1105   return addInstruction(new SPIRVCompositeExtract(Type, getId(), TheVector,
1106       Indices, BB), BB);
1107 }
1108 
1109 SPIRVInstruction *
addCompositeInsertInst(SPIRVValue * Object,SPIRVValue * Composite,const std::vector<SPIRVWord> & Indices,SPIRVBasicBlock * BB)1110 SPIRVModuleImpl::addCompositeInsertInst(SPIRVValue *Object,
1111     SPIRVValue *Composite, const std::vector<SPIRVWord>& Indices,
1112     SPIRVBasicBlock *BB) {
1113   return addInstruction(new SPIRVCompositeInsert(getId(), Object, Composite,
1114       Indices, BB), BB);
1115 }
1116 
1117 SPIRVInstruction *
addCopyObjectInst(SPIRVType * TheType,SPIRVValue * Operand,SPIRVBasicBlock * BB)1118 SPIRVModuleImpl::addCopyObjectInst(SPIRVType *TheType, SPIRVValue *Operand,
1119     SPIRVBasicBlock *BB) {
1120   return addInstruction(new SPIRVCopyObject(TheType, getId(), Operand, BB), BB);
1121 
1122 }
1123 
1124 SPIRVInstruction *
addCopyMemoryInst(SPIRVValue * TheTarget,SPIRVValue * TheSource,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)1125 SPIRVModuleImpl::addCopyMemoryInst(SPIRVValue *TheTarget, SPIRVValue *TheSource,
1126     const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
1127   return addInstruction(new SPIRVCopyMemory(TheTarget, TheSource,
1128       TheMemoryAccess, BB), BB);
1129 }
1130 
1131 SPIRVInstruction *
addCopyMemorySizedInst(SPIRVValue * TheTarget,SPIRVValue * TheSource,SPIRVValue * TheSize,const std::vector<SPIRVWord> & TheMemoryAccess,SPIRVBasicBlock * BB)1132 SPIRVModuleImpl::addCopyMemorySizedInst(SPIRVValue *TheTarget,
1133     SPIRVValue *TheSource, SPIRVValue *TheSize,
1134     const std::vector<SPIRVWord> &TheMemoryAccess, SPIRVBasicBlock *BB) {
1135   return addInstruction(new SPIRVCopyMemorySized(TheTarget, TheSource, TheSize,
1136     TheMemoryAccess, BB), BB);
1137 }
1138 
1139 SPIRVInstruction*
addVariable(SPIRVType * Type,bool IsConstant,SPIRVLinkageTypeKind LinkageType,SPIRVValue * Initializer,const std::string & Name,SPIRVStorageClassKind StorageClass,SPIRVBasicBlock * BB)1140 SPIRVModuleImpl::addVariable(SPIRVType *Type, bool IsConstant,
1141     SPIRVLinkageTypeKind LinkageType, SPIRVValue *Initializer,
1142     const std::string &Name, SPIRVStorageClassKind StorageClass,
1143     SPIRVBasicBlock *BB) {
1144   SPIRVVariable *Variable = new SPIRVVariable(Type, getId(), Initializer,
1145       Name, StorageClass, BB, this);
1146   if (BB)
1147     return addInstruction(Variable, BB);
1148 
1149   add(Variable);
1150   if (LinkageType != LinkageTypeInternal)
1151     Variable->setLinkageType(LinkageType);
1152   Variable->setIsConstant(IsConstant);
1153   return Variable;
1154 }
1155 
1156 template<class T>
1157 spv_ostream &
operator <<(spv_ostream & O,const std::vector<T * > & V)1158 operator<< (spv_ostream &O, const std::vector<T *>& V) {
1159   for (auto &I: V)
1160     O << *I;
1161   return O;
1162 }
1163 
1164 template<class T, class B>
1165 spv_ostream &
operator <<(spv_ostream & O,const std::multiset<T *,B> & V)1166 operator<< (spv_ostream &O, const std::multiset<T *, B>& V) {
1167   for (auto &I: V)
1168     O << *I;
1169   return O;
1170 }
1171 
1172 // To satisfy SPIR-V spec requirement:
1173 // "All operands must be declared before being used",
1174 // we do DFS based topological sort
1175 // https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
1176 class TopologicalSort {
1177   enum DFSState : char {
1178     Unvisited,
1179     Discovered,
1180     Visited
1181   };
1182   typedef std::vector<SPIRVType *> SPIRVTypeVec;
1183   typedef std::vector<SPIRVValue *> SPIRVConstantVector;
1184   typedef std::vector<SPIRVVariable *> SPIRVVariableVec;
1185   typedef std::vector<SPIRVTypeForwardPointer *> SPIRVForwardPointerVec;
1186   typedef std::function<bool(SPIRVEntry*, SPIRVEntry*)> IdComp;
1187   typedef std::map<SPIRVEntry*, DFSState, IdComp> EntryStateMapTy;
1188 
1189   SPIRVTypeVec TypeIntVec;
1190   SPIRVConstantVector ConstIntVec;
1191   SPIRVTypeVec TypeVec;
1192   SPIRVConstantVector ConstVec;
1193   SPIRVVariableVec VariableVec;
1194   const SPIRVForwardPointerVec& ForwardPointerVec;
1195   EntryStateMapTy EntryStateMap;
1196 
1197   friend spv_ostream & operator<<(spv_ostream &O, const TopologicalSort &S);
1198 
1199 // This method implements recursive depth-first search among all Entries in
1200 // EntryStateMap. Traversing entries and adding them to corresponding container
1201 // after visiting all dependent entries(post-order traversal) guarantees that
1202 // the entry's operands will appear in the container before the entry itslef.
visit(SPIRVEntry * E)1203   void visit(SPIRVEntry* E) {
1204     DFSState& State = EntryStateMap[E];
1205     assert(State != Discovered && "Cyclic dependency detected");
1206     if (State == Visited)
1207       return;
1208     State = Discovered;
1209     for (SPIRVEntry *Op : E->getNonLiteralOperands()) {
1210       auto Comp = [&Op](SPIRVTypeForwardPointer *FwdPtr) {
1211         return FwdPtr->getPointer() == Op;
1212       };
1213       // Skip forward referenced pointers
1214       if (Op->getOpCode() == OpTypePointer &&
1215           find_if(ForwardPointerVec.begin(), ForwardPointerVec.end(), Comp) !=
1216           ForwardPointerVec.end())
1217         continue;
1218       visit(Op);
1219     }
1220     State = Visited;
1221     Op OC = E->getOpCode();
1222     if (OC == OpTypeInt)
1223       TypeIntVec.push_back(static_cast<SPIRVType*>(E));
1224     else if (isConstantOpCode(OC)) {
1225       SPIRVConstant *C = static_cast<SPIRVConstant*>(E);
1226       if (C->getType()->isTypeInt())
1227         ConstIntVec.push_back(C);
1228       else
1229         ConstVec.push_back(C);
1230     } else if (isTypeOpCode(OC))
1231       TypeVec.push_back(static_cast<SPIRVType*>(E));
1232     else if (E->isVariable())
1233       VariableVec.push_back(static_cast<SPIRVVariable*>(E));
1234   }
1235 public:
TopologicalSort(const SPIRVTypeVec & _TypeVec,const SPIRVConstantVector & _ConstVec,const SPIRVVariableVec & _VariableVec,const SPIRVForwardPointerVec & _ForwardPointerVec)1236   TopologicalSort(const SPIRVTypeVec &_TypeVec,
1237                   const SPIRVConstantVector &_ConstVec,
1238                   const SPIRVVariableVec &_VariableVec,
1239                   const SPIRVForwardPointerVec &_ForwardPointerVec) :
1240   ForwardPointerVec(_ForwardPointerVec),
1241   EntryStateMap([](SPIRVEntry* a, SPIRVEntry* b) -> bool {
1242                   return a->getId() < b->getId();
1243                 })
1244   {
1245     // Collect entries for sorting
1246     for (auto *T : _TypeVec)
1247       EntryStateMap[T] = DFSState::Unvisited;
1248     for (auto *C : _ConstVec)
1249       EntryStateMap[C] = DFSState::Unvisited;
1250     for (auto *V : _VariableVec)
1251       EntryStateMap[V] = DFSState::Unvisited;
1252     // Run topoligical sort
1253     for (auto ES : EntryStateMap)
1254       visit(ES.first);
1255   }
1256 };
1257 
1258 spv_ostream &
operator <<(spv_ostream & O,const TopologicalSort & S)1259 operator<< (spv_ostream &O, const TopologicalSort &S) {
1260   O << S.TypeIntVec
1261     << S.ConstIntVec
1262     << S.TypeVec
1263     << S.ConstVec
1264     << S.VariableVec;
1265   return O;
1266 }
1267 
1268 spv_ostream &
operator <<(spv_ostream & O,SPIRVModule & M)1269 operator<< (spv_ostream &O, SPIRVModule &M) {
1270   SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl*>(&M);
1271 
1272   SPIRVEncoder Encoder(O);
1273   Encoder << MagicNumber
1274           << MI.SPIRVVersion
1275           << (((SPIRVWord)MI.GeneratorId << 16) | MI.GeneratorVer)
1276           << MI.NextId /* Bound for Id */
1277           << MI.InstSchema;
1278   O << SPIRVNL();
1279 
1280   for (auto &I:MI.CapMap)
1281     O << *I.second;
1282 
1283   for (auto &I:M.getExtension()) {
1284     assert(!I.empty() && "Invalid extension");
1285     O << SPIRVExtension(&M, I);
1286   }
1287 
1288   for (auto &I:MI.IdBuiltinMap)
1289     O <<  SPIRVExtInstImport(&M, I.first, SPIRVBuiltinSetNameMap::map(I.second));
1290 
1291   O << SPIRVMemoryModel(&M);
1292 
1293   for (auto &I:MI.EntryPointVec)
1294     for (auto &II:I.second)
1295       O << SPIRVEntryPoint(&M, I.first, II,
1296           M.get<SPIRVFunction>(II)->getName());
1297 
1298   for (auto &I:MI.EntryPointVec)
1299     for (auto &II:I.second)
1300       MI.get<SPIRVFunction>(II)->encodeExecutionModes(O);
1301 
1302   O << MI.StringVec;
1303 
1304   for (auto &I:M.getSourceExtension()) {
1305     assert(!I.empty() && "Invalid source extension");
1306     O << SPIRVSourceExtension(&M, I);
1307   }
1308 
1309   O << SPIRVSource(&M);
1310 
1311   for (auto &I:MI.NamedId) {
1312     // Don't output name for entry point since it is redundant
1313     bool IsEntryPoint = false;
1314     for (auto &EPS:MI.EntryPointSet)
1315       if (EPS.second.count(I)) {
1316         IsEntryPoint = true;
1317         break;
1318       }
1319     if (!IsEntryPoint)
1320       M.getEntry(I)->encodeName(O);
1321   }
1322 
1323   O << MI.MemberNameVec
1324     << MI.LineVec
1325     << MI.DecGroupVec
1326     << MI.DecorateSet
1327     << MI.GroupDecVec
1328     << MI.ForwardPointerVec
1329     << TopologicalSort(MI.TypeVec, MI.ConstVec, MI.VariableVec,
1330                        MI.ForwardPointerVec)
1331     << SPIRVNL()
1332     << MI.FuncVec;
1333   return O;
1334 }
1335 
1336 template<class T>
addTo(std::vector<T * > & V,SPIRVEntry * E)1337 void SPIRVModuleImpl::addTo(std::vector<T*>& V, SPIRVEntry* E) {
1338   V.push_back(static_cast<T *>(E));
1339 }
1340 
1341 // The first decoration group includes all the previously defined decorates.
1342 // The second decoration group includes all the decorates defined between the
1343 // first and second decoration group. So long so forth.
1344 SPIRVDecorationGroup*
addDecorationGroup()1345 SPIRVModuleImpl::addDecorationGroup() {
1346   return addDecorationGroup(new SPIRVDecorationGroup(this, getId()));
1347 }
1348 
1349 SPIRVDecorationGroup*
addDecorationGroup(SPIRVDecorationGroup * Group)1350 SPIRVModuleImpl::addDecorationGroup(SPIRVDecorationGroup* Group) {
1351   add(Group);
1352   Group->takeDecorates(DecorateSet);
1353   DecGroupVec.push_back(Group);
1354   SPIRVDBG(spvdbgs() << "[addDecorationGroup] {" << *Group << "}\n";
1355           spvdbgs() << "  Remaining DecorateSet: {" << DecorateSet << "}\n");
1356   assert(DecorateSet.empty());
1357   return Group;
1358 }
1359 
1360 SPIRVGroupDecorateGeneric*
addGroupDecorateGeneric(SPIRVGroupDecorateGeneric * GDec)1361 SPIRVModuleImpl::addGroupDecorateGeneric(SPIRVGroupDecorateGeneric *GDec) {
1362   add(GDec);
1363   GDec->decorateTargets();
1364   GroupDecVec.push_back(GDec);
1365   return GDec;
1366 }
1367 SPIRVGroupDecorate*
addGroupDecorate(SPIRVDecorationGroup * Group,const std::vector<SPIRVEntry * > & Targets)1368 SPIRVModuleImpl::addGroupDecorate(
1369     SPIRVDecorationGroup* Group, const std::vector<SPIRVEntry*>& Targets) {
1370   auto GD = new SPIRVGroupDecorate(Group, getIds(Targets));
1371   addGroupDecorateGeneric(GD);
1372   return GD;
1373 }
1374 
1375 SPIRVGroupMemberDecorate*
addGroupMemberDecorate(SPIRVDecorationGroup * Group,const std::vector<SPIRVEntry * > & Targets)1376 SPIRVModuleImpl::addGroupMemberDecorate(
1377     SPIRVDecorationGroup* Group, const std::vector<SPIRVEntry*>& Targets) {
1378   auto GMD = new SPIRVGroupMemberDecorate(Group, getIds(Targets));
1379   addGroupDecorateGeneric(GMD);
1380   return GMD;
1381 }
1382 
1383 SPIRVString*
getString(const std::string & Str)1384 SPIRVModuleImpl::getString(const std::string& Str) {
1385   auto Loc = StrMap.find(Str);
1386   if (Loc != StrMap.end())
1387     return Loc->second;
1388   auto S = add(new SPIRVString(this, getId(), Str));
1389   StrMap[Str] = S;
1390   return S;
1391 }
1392 
1393 SPIRVMemberName*
addMemberName(SPIRVTypeStruct * ST,SPIRVWord MemberNumber,const std::string & Name)1394 SPIRVModuleImpl::addMemberName(SPIRVTypeStruct* ST,
1395     SPIRVWord MemberNumber, const std::string& Name) {
1396   return add(new SPIRVMemberName(ST, MemberNumber, Name));
1397 }
1398 
addUnknownStructField(SPIRVTypeStruct * Struct,unsigned I,SPIRVId ID)1399 void SPIRVModuleImpl::addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
1400                                             SPIRVId ID) {
1401   UnknownStructFieldMap[Struct].push_back(std::make_pair(I, ID));
1402 }
1403 
1404 std::istream &
operator >>(std::istream & I,SPIRVModule & M)1405 operator>> (std::istream &I, SPIRVModule &M) {
1406   SPIRVDecoder Decoder(I, M);
1407   SPIRVModuleImpl &MI = *static_cast<SPIRVModuleImpl*>(&M);
1408   // Disable automatic capability filling.
1409   MI.setAutoAddCapability(false);
1410 
1411   SPIRVWord Magic;
1412   Decoder >> Magic;
1413   assert(Magic == MagicNumber && "Invalid magic number");
1414 
1415   Decoder >> MI.SPIRVVersion;
1416   assert(MI.SPIRVVersion <= SPV_VERSION && "Unsupported SPIRV version number");
1417 
1418   SPIRVWord Generator = 0;
1419   Decoder >> Generator;
1420   MI.GeneratorId = Generator >> 16;
1421   MI.GeneratorVer = Generator & 0xFFFF;
1422 
1423   // Bound for Id
1424   Decoder >> MI.NextId;
1425 
1426   Decoder >> MI.InstSchema;
1427   assert(MI.InstSchema == SPIRVISCH_Default && "Unsupported instruction schema");
1428 
1429   while(Decoder.getWordCountAndOpCode())
1430     Decoder.getEntry();
1431 
1432   MI.optimizeDecorates();
1433   MI.resolveUnknownStructFields();
1434   MI.createForwardPointers();
1435   return I;
1436 }
1437 
1438 SPIRVModule *
createSPIRVModule()1439 SPIRVModule::createSPIRVModule() {
1440   return new SPIRVModuleImpl;
1441 }
1442 
1443 SPIRVValue *
getValue(SPIRVId TheId) const1444 SPIRVModuleImpl::getValue(SPIRVId TheId)const {
1445   return get<SPIRVValue>(TheId);
1446 }
1447 
1448 SPIRVType *
getValueType(SPIRVId TheId) const1449 SPIRVModuleImpl::getValueType(SPIRVId TheId)const {
1450   return get<SPIRVValue>(TheId)->getType();
1451 }
1452 
1453 std::vector<SPIRVValue *>
getValues(const std::vector<SPIRVId> & IdVec) const1454 SPIRVModuleImpl::getValues(const std::vector<SPIRVId>& IdVec)const {
1455   std::vector<SPIRVValue *> ValueVec;
1456   for (auto i:IdVec)
1457     ValueVec.push_back(getValue(i));
1458   return ValueVec;
1459 }
1460 
1461 std::vector<SPIRVType *>
getValueTypes(const std::vector<SPIRVId> & IdVec) const1462 SPIRVModuleImpl::getValueTypes(const std::vector<SPIRVId>& IdVec)const {
1463   std::vector<SPIRVType *> TypeVec;
1464   for (auto i:IdVec)
1465     TypeVec.push_back(getValue(i)->getType());
1466   return TypeVec;
1467 }
1468 
1469 std::vector<SPIRVId>
getIds(const std::vector<SPIRVEntry * > & ValueVec) const1470 SPIRVModuleImpl::getIds(const std::vector<SPIRVEntry *> &ValueVec)const {
1471   std::vector<SPIRVId> IdVec;
1472   for (auto i:ValueVec)
1473     IdVec.push_back(i->getId());
1474   return IdVec;
1475 }
1476 
1477 std::vector<SPIRVId>
getIds(const std::vector<SPIRVValue * > & ValueVec) const1478 SPIRVModuleImpl::getIds(const std::vector<SPIRVValue *> &ValueVec)const {
1479   std::vector<SPIRVId> IdVec;
1480   for (auto i:ValueVec)
1481     IdVec.push_back(i->getId());
1482   return IdVec;
1483 }
1484 
1485 SPIRVInstTemplateBase*
addInstTemplate(Op OC,SPIRVBasicBlock * BB,SPIRVType * Ty)1486 SPIRVModuleImpl::addInstTemplate(Op OC,
1487     SPIRVBasicBlock* BB, SPIRVType *Ty) {
1488   assert (!Ty || !Ty->isTypeVoid());
1489   SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
1490   auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, BB, this);
1491   BB->addInstruction(Ins);
1492   return Ins;
1493 }
1494 
1495 SPIRVInstTemplateBase*
addInstTemplate(Op OC,const std::vector<SPIRVWord> & Ops,SPIRVBasicBlock * BB,SPIRVType * Ty)1496 SPIRVModuleImpl::addInstTemplate(Op OC,
1497     const std::vector<SPIRVWord>& Ops, SPIRVBasicBlock* BB, SPIRVType *Ty) {
1498   assert (!Ty || !Ty->isTypeVoid());
1499   SPIRVId Id = Ty ? getId() : SPIRVID_INVALID;
1500   auto Ins = SPIRVInstTemplateBase::create(OC, Ty, Id, Ops, BB, this);
1501   BB->addInstruction(Ins);
1502   return Ins;
1503 }
1504 
SPIRVDbgInfo(SPIRVModule * TM)1505 SPIRVDbgInfo::SPIRVDbgInfo(SPIRVModule *TM)
1506 :M(TM){
1507 }
1508 
1509 std::string
getEntryPointFileStr(SPIRVExecutionModelKind EM,unsigned I)1510 SPIRVDbgInfo::getEntryPointFileStr(SPIRVExecutionModelKind EM, unsigned I) {
1511   if (M->getNumEntryPoints(EM) == 0)
1512     return "";
1513   return getFunctionFileStr(M->getEntryPoint(EM, I));
1514 }
1515 
1516 std::string
getFunctionFileStr(SPIRVFunction * F)1517 SPIRVDbgInfo::getFunctionFileStr(SPIRVFunction *F) {
1518   if (F->hasLine())
1519     return F->getLine()->getFileNameStr();
1520   return "";
1521 }
1522 
1523 unsigned
getFunctionLineNo(SPIRVFunction * F)1524 SPIRVDbgInfo::getFunctionLineNo(SPIRVFunction *F) {
1525   if (F->hasLine())
1526     return F->getLine()->getLine();
1527   return 0;
1528 }
1529 
IsSPIRVBinary(const std::string & Img)1530 bool IsSPIRVBinary(const std::string &Img) {
1531   if (Img.size() < sizeof(unsigned))
1532     return false;
1533   auto Magic = reinterpret_cast<const unsigned*>(Img.data());
1534   return *Magic == MagicNumber;
1535 }
1536 
1537 #ifdef _SPIRV_SUPPORT_TEXT_FMT
1538 
ConvertSPIRV(std::istream & IS,spv_ostream & OS,std::string & ErrMsg,bool FromText,bool ToText)1539 bool ConvertSPIRV(std::istream &IS, spv_ostream &OS,
1540     std::string &ErrMsg, bool FromText, bool ToText) {
1541   auto SaveOpt = SPIRVUseTextFormat;
1542   SPIRVUseTextFormat = FromText;
1543   SPIRVModuleImpl M;
1544   IS >> M;
1545   if (M.getError(ErrMsg) != SPIRVEC_Success) {
1546     SPIRVUseTextFormat = SaveOpt;
1547     return false;
1548   }
1549   SPIRVUseTextFormat = ToText;
1550   OS << M;
1551   if (M.getError(ErrMsg) != SPIRVEC_Success) {
1552     SPIRVUseTextFormat = SaveOpt;
1553     return false;
1554   }
1555   SPIRVUseTextFormat = SaveOpt;
1556   return true;
1557 }
1558 
IsSPIRVText(const std::string & Img)1559 bool IsSPIRVText(const std::string &Img) {
1560   std::istringstream SS(Img);
1561   unsigned Magic = 0;
1562   SS >> Magic;
1563   if (SS.bad())
1564     return false;
1565   return Magic == MagicNumber;
1566 }
1567 
ConvertSPIRV(std::string & Input,std::string & Out,std::string & ErrMsg,bool ToText)1568 bool ConvertSPIRV(std::string &Input, std::string &Out,
1569     std::string &ErrMsg, bool ToText) {
1570   auto FromText = IsSPIRVText(Input);
1571   if (ToText == FromText) {
1572     Out = Input;
1573     return true;
1574   }
1575   std::istringstream IS(Input);
1576 #ifdef _SPIRV_LLVM_API
1577   llvm::raw_string_ostream OS(Out);
1578 #else
1579   std::ostringstream OS;
1580 #endif
1581   if (!ConvertSPIRV(IS, OS, ErrMsg, FromText, ToText))
1582     return false;
1583   Out = OS.str();
1584   return true;
1585 }
1586 
1587 #endif // _SPIRV_SUPPORT_TEXT_FMT
1588 
1589 }
1590