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