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