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