1 //===- SPIRVEntry.cpp - Base Class for SPIR-V Entities -----------*- 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 base class for SPIR-V entities. 37 /// 38 //===----------------------------------------------------------------------===// 39 40 #include "SPIRVEntry.h" 41 #include "SPIRVDebug.h" 42 #include "SPIRVType.h" 43 #include "SPIRVFunction.h" 44 #include "SPIRVBasicBlock.h" 45 #include "SPIRVInstruction.h" 46 #include "SPIRVDecorate.h" 47 #include "SPIRVStream.h" 48 49 #include <algorithm> 50 #include <map> 51 #include <set> 52 #include <sstream> 53 #include <string> 54 #include <utility> 55 56 using namespace SPIRV; 57 58 namespace SPIRV{ 59 60 template<typename T> 61 SPIRVEntry* create() { 62 return new T(); 63 } 64 65 SPIRVEntry * 66 SPIRVEntry::create(Op OpCode) { 67 typedef SPIRVEntry *(*SPIRVFactoryTy)(); 68 struct TableEntry { 69 Op Opn; 70 SPIRVFactoryTy Factory; 71 operator std::pair<const Op, SPIRVFactoryTy>() { 72 return std::make_pair(Opn, Factory); 73 } 74 }; 75 76 static TableEntry Table[] = { 77 #define _SPIRV_OP(x,...) {Op##x, &SPIRV::create<SPIRV##x>}, 78 #include "SPIRVOpCodeEnum.h" 79 #undef _SPIRV_OP 80 }; 81 82 typedef std::map<Op, SPIRVFactoryTy> OpToFactoryMapTy; 83 static const OpToFactoryMapTy OpToFactoryMap(std::begin(Table), 84 std::end(Table)); 85 86 OpToFactoryMapTy::const_iterator Loc = OpToFactoryMap.find(OpCode); 87 if (Loc != OpToFactoryMap.end()) 88 return Loc->second(); 89 90 SPIRVDBG(spvdbgs() << "No factory for OpCode " << (unsigned)OpCode << '\n';) 91 assert (0 && "Not implemented"); 92 return 0; 93 } 94 95 std::unique_ptr<SPIRV::SPIRVEntry> 96 SPIRVEntry::create_unique(Op OC) { 97 return std::unique_ptr<SPIRVEntry>(create(OC)); 98 } 99 100 std::unique_ptr<SPIRV::SPIRVExtInst> 101 SPIRVEntry::create_unique(SPIRVExtInstSetKind Set, 102 unsigned ExtOp) { 103 return std::unique_ptr<SPIRVExtInst>(new SPIRVExtInst(Set, ExtOp)); 104 } 105 106 SPIRVErrorLog & 107 SPIRVEntry::getErrorLog()const { 108 return Module->getErrorLog(); 109 } 110 111 bool 112 SPIRVEntry::exist(SPIRVId TheId)const { 113 return Module->exist(TheId); 114 } 115 116 SPIRVEntry * 117 SPIRVEntry::getOrCreate(SPIRVId TheId)const { 118 SPIRVEntry *Entry = nullptr; 119 bool Found = Module->exist(TheId, &Entry); 120 if (!Found) 121 return Module->addForward(TheId, nullptr); 122 return Entry; 123 } 124 125 SPIRVValue * 126 SPIRVEntry::getValue(SPIRVId TheId)const { 127 return get<SPIRVValue>(TheId); 128 } 129 130 SPIRVType * 131 SPIRVEntry::getValueType(SPIRVId TheId)const { 132 return get<SPIRVValue>(TheId)->getType(); 133 } 134 135 SPIRVEncoder 136 SPIRVEntry::getEncoder(spv_ostream &O)const{ 137 return SPIRVEncoder(O); 138 } 139 140 SPIRVDecoder 141 SPIRVEntry::getDecoder(std::istream& I){ 142 return SPIRVDecoder(I, *Module); 143 } 144 145 void 146 SPIRVEntry::setWordCount(SPIRVWord TheWordCount){ 147 WordCount = TheWordCount; 148 } 149 150 void 151 SPIRVEntry::setName(const std::string& TheName) { 152 Name = TheName; 153 SPIRVDBG(spvdbgs() << "Set name for obj " << Id << " " << 154 Name << '\n'); 155 } 156 157 void 158 SPIRVEntry::setModule(SPIRVModule *TheModule) { 159 assert(TheModule && "Invalid module"); 160 if (TheModule == Module) 161 return; 162 assert(Module == NULL && "Cannot change owner of entry"); 163 Module = TheModule; 164 } 165 166 void 167 SPIRVEntry::encode(spv_ostream &O) const { 168 assert (0 && "Not implemented"); 169 } 170 171 void 172 SPIRVEntry::encodeName(spv_ostream &O) const { 173 if (!Name.empty()) 174 O << SPIRVName(this, Name); 175 } 176 177 void 178 SPIRVEntry::encodeAll(spv_ostream &O) const { 179 encodeWordCountOpCode(O); 180 encode(O); 181 encodeChildren(O); 182 } 183 184 void 185 SPIRVEntry::encodeChildren(spv_ostream &O)const { 186 } 187 188 void 189 SPIRVEntry::encodeWordCountOpCode(spv_ostream &O) const { 190 #ifdef _SPIRV_SUPPORT_TEXT_FMT 191 if (SPIRVUseTextFormat) { 192 getEncoder(O) << WordCount << OpCode; 193 return; 194 } 195 #endif 196 getEncoder(O) << mkWord(WordCount, OpCode); 197 } 198 // Read words from SPIRV binary and create members for SPIRVEntry. 199 // The word count and op code has already been read before calling this 200 // function for creating the SPIRVEntry. Therefore the input stream only 201 // contains the remaining part of the words for the SPIRVEntry. 202 void 203 SPIRVEntry::decode(std::istream &I) { 204 assert (0 && "Not implemented"); 205 } 206 207 std::vector<SPIRVValue *> 208 SPIRVEntry::getValues(const std::vector<SPIRVId>& IdVec)const { 209 std::vector<SPIRVValue *> ValueVec; 210 for (auto i:IdVec) 211 ValueVec.push_back(getValue(i)); 212 return ValueVec; 213 } 214 215 std::vector<SPIRVType *> 216 SPIRVEntry::getValueTypes(const std::vector<SPIRVId>& IdVec)const { 217 std::vector<SPIRVType *> TypeVec; 218 for (auto i:IdVec) 219 TypeVec.push_back(getValue(i)->getType()); 220 return TypeVec; 221 } 222 223 std::vector<SPIRVId> 224 SPIRVEntry::getIds(const std::vector<SPIRVValue *> ValueVec)const { 225 std::vector<SPIRVId> IdVec; 226 for (auto i:ValueVec) 227 IdVec.push_back(i->getId()); 228 return IdVec; 229 } 230 231 SPIRVEntry * 232 SPIRVEntry::getEntry(SPIRVId TheId) const { 233 return Module->getEntry(TheId); 234 } 235 236 void 237 SPIRVEntry::validateFunctionControlMask(SPIRVWord TheFCtlMask) 238 const { 239 SPIRVCK(isValidFunctionControlMask(TheFCtlMask), 240 InvalidFunctionControlMask, ""); 241 } 242 243 void 244 SPIRVEntry::validateValues(const std::vector<SPIRVId> &Ids)const { 245 for (auto I:Ids) 246 getValue(I)->validate(); 247 } 248 249 void 250 SPIRVEntry::validateBuiltin(SPIRVWord TheSet, SPIRVWord Index)const { 251 (void) TheSet; 252 (void) Index; 253 assert(TheSet != SPIRVWORD_MAX && Index != SPIRVWORD_MAX && 254 "Invalid builtin"); 255 } 256 257 void 258 SPIRVEntry::addDecorate(const SPIRVDecorate *Dec){ 259 Decorates.insert(std::make_pair(Dec->getDecorateKind(), Dec)); 260 Module->addDecorate(Dec); 261 SPIRVDBG(spvdbgs() << "[addDecorate] " << *Dec << '\n';) 262 } 263 264 void 265 SPIRVEntry::addDecorate(Decoration Kind) { 266 addDecorate(new SPIRVDecorate(Kind, this)); 267 } 268 269 void 270 SPIRVEntry::addDecorate(Decoration Kind, SPIRVWord Literal) { 271 addDecorate(new SPIRVDecorate(Kind, this, Literal)); 272 } 273 274 void 275 SPIRVEntry::eraseDecorate(Decoration Dec){ 276 Decorates.erase(Dec); 277 } 278 279 void 280 SPIRVEntry::takeDecorates(SPIRVEntry *E){ 281 Decorates = std::move(E->Decorates); 282 SPIRVDBG(spvdbgs() << "[takeDecorates] " << Id << '\n';) 283 } 284 285 void 286 SPIRVEntry::setLine(SPIRVLine *L){ 287 Line = L; 288 L->setTargetId(Id); 289 SPIRVDBG(spvdbgs() << "[setLine] " << *L << '\n';) 290 } 291 292 void 293 SPIRVEntry::takeLine(SPIRVEntry *E){ 294 Line = E->Line; 295 if (Line == nullptr) 296 return; 297 Line->setTargetId(Id); 298 E->Line = nullptr; 299 } 300 301 void 302 SPIRVEntry::addMemberDecorate(const SPIRVMemberDecorate *Dec){ 303 assert(canHaveMemberDecorates() && MemberDecorates.find(Dec->getPair()) == 304 MemberDecorates.end()); 305 MemberDecorates[Dec->getPair()] = Dec; 306 Module->addDecorate(Dec); 307 SPIRVDBG(spvdbgs() << "[addMemberDecorate] " << *Dec << '\n';) 308 } 309 310 void 311 SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind) { 312 addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this)); 313 } 314 315 void 316 SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind, 317 SPIRVWord Literal) { 318 addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this, Literal)); 319 } 320 321 void 322 SPIRVEntry::eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Dec){ 323 MemberDecorates.erase(std::make_pair(MemberNumber, Dec)); 324 } 325 326 void 327 SPIRVEntry::takeMemberDecorates(SPIRVEntry *E){ 328 MemberDecorates = std::move(E->MemberDecorates); 329 SPIRVDBG(spvdbgs() << "[takeMemberDecorates] " << Id << '\n';) 330 } 331 332 void 333 SPIRVEntry::takeAnnotations(SPIRVForward *E){ 334 Module->setName(this, E->getName()); 335 takeDecorates(E); 336 takeMemberDecorates(E); 337 takeLine(E); 338 if (OpCode == OpFunction) 339 static_cast<SPIRVFunction *>(this)->takeExecutionModes(E); 340 } 341 342 // Check if an entry has Kind of decoration and get the literal of the 343 // first decoration of such kind at Index. 344 bool 345 SPIRVEntry::hasDecorate(Decoration Kind, size_t Index, SPIRVWord *Result)const { 346 DecorateMapType::const_iterator Loc = Decorates.find(Kind); 347 if (Loc == Decorates.end()) 348 return false; 349 if (Result) 350 *Result = Loc->second->getLiteral(Index); 351 return true; 352 } 353 354 // Get literals of all decorations of Kind at Index. 355 std::set<SPIRVWord> 356 SPIRVEntry::getDecorate(Decoration Kind, size_t Index) const { 357 auto Range = Decorates.equal_range(Kind); 358 std::set<SPIRVWord> Value; 359 for (auto I = Range.first, E = Range.second; I != E; ++I) { 360 assert(Index < I->second->getLiteralCount() && "Invalid index"); 361 Value.insert(I->second->getLiteral(Index)); 362 } 363 return Value; 364 } 365 366 bool 367 SPIRVEntry::hasLinkageType() const { 368 return OpCode == OpFunction || OpCode == OpVariable; 369 } 370 371 void 372 SPIRVEntry::encodeDecorate(spv_ostream &O) const { 373 for (auto& i:Decorates) 374 O << *i.second; 375 } 376 377 SPIRVLinkageTypeKind 378 SPIRVEntry::getLinkageType() const { 379 assert(hasLinkageType()); 380 DecorateMapType::const_iterator Loc = Decorates.find(DecorationLinkageAttributes); 381 if (Loc == Decorates.end()) 382 return LinkageTypeInternal; 383 return static_cast<const SPIRVDecorateLinkageAttr*>(Loc->second)->getLinkageType(); 384 } 385 386 void 387 SPIRVEntry::setLinkageType(SPIRVLinkageTypeKind LT) { 388 assert(isValid(LT)); 389 assert(hasLinkageType()); 390 addDecorate(new SPIRVDecorateLinkageAttr(this, Name, LT)); 391 } 392 393 void 394 SPIRVEntry::updateModuleVersion() const { 395 if (!Module) 396 return; 397 398 Module->setMinSPIRVVersion(getRequiredSPIRVVersion()); 399 } 400 401 spv_ostream & 402 operator<<(spv_ostream &O, const SPIRVEntry &E) { 403 E.validate(); 404 E.encodeAll(O); 405 O << SPIRVNL(); 406 return O; 407 } 408 409 std::istream & 410 operator>>(std::istream &I, SPIRVEntry &E) { 411 E.decode(I); 412 return I; 413 } 414 415 SPIRVEntryPoint::SPIRVEntryPoint(SPIRVModule *TheModule, 416 SPIRVExecutionModelKind TheExecModel, SPIRVId TheId, 417 const std::string &TheName) 418 :SPIRVAnnotation(TheModule->get<SPIRVFunction>(TheId), 419 getSizeInWords(TheName) + 3), ExecModel(TheExecModel), Name(TheName){ 420 } 421 422 void 423 SPIRVEntryPoint::encode(spv_ostream &O) const { 424 getEncoder(O) << ExecModel << Target << Name; 425 } 426 427 void 428 SPIRVEntryPoint::decode(std::istream &I) { 429 getDecoder(I) >> ExecModel >> Target >> Name; 430 Module->setName(getOrCreateTarget(), Name); 431 Module->addEntryPoint(ExecModel, Target); 432 } 433 434 void 435 SPIRVExecutionMode::encode(spv_ostream &O) const { 436 getEncoder(O) << Target << ExecMode << WordLiterals; 437 } 438 439 void 440 SPIRVExecutionMode::decode(std::istream &I) { 441 getDecoder(I) >> Target >> ExecMode; 442 switch(ExecMode) { 443 case ExecutionModeLocalSize: 444 case ExecutionModeLocalSizeHint: 445 WordLiterals.resize(3); 446 break; 447 case ExecutionModeInvocations: 448 case ExecutionModeOutputVertices: 449 case ExecutionModeVecTypeHint: 450 WordLiterals.resize(1); 451 break; 452 default: 453 // Do nothing. Keep this to avoid VS2013 warning. 454 break; 455 } 456 getDecoder(I) >> WordLiterals; 457 getOrCreateTarget()->addExecutionMode(this); 458 } 459 460 SPIRVForward * 461 SPIRVAnnotationGeneric::getOrCreateTarget()const { 462 SPIRVEntry *Entry = nullptr; 463 bool Found = Module->exist(Target, &Entry); 464 assert((!Found || Entry->getOpCode() == OpForward) && 465 "Annotations only allowed on forward"); 466 if (!Found) 467 Entry = Module->addForward(Target, nullptr); 468 return static_cast<SPIRVForward *>(Entry); 469 } 470 471 SPIRVName::SPIRVName(const SPIRVEntry *TheTarget, const std::string& TheStr) 472 :SPIRVAnnotation(TheTarget, getSizeInWords(TheStr) + 2), Str(TheStr){ 473 } 474 475 void 476 SPIRVName::encode(spv_ostream &O) const { 477 getEncoder(O) << Target << Str; 478 } 479 480 void 481 SPIRVName::decode(std::istream &I) { 482 getDecoder(I) >> Target >> Str; 483 Module->setName(getOrCreateTarget(), Str); 484 } 485 486 void 487 SPIRVName::validate() const { 488 assert(WordCount == getSizeInWords(Str) + 2 && "Incorrect word count"); 489 } 490 491 _SPIRV_IMP_ENCDEC2(SPIRVString, Id, Str) 492 _SPIRV_IMP_ENCDEC3(SPIRVMemberName, Target, MemberNumber, Str) 493 494 void 495 SPIRVLine::encode(spv_ostream &O) const { 496 getEncoder(O) << Target << FileName << Line << Column; 497 } 498 499 void 500 SPIRVLine::decode(std::istream &I) { 501 getDecoder(I) >> Target >> FileName >> Line >> Column; 502 Module->addLine(getOrCreateTarget(), get<SPIRVString>(FileName), Line, Column); 503 } 504 505 void 506 SPIRVLine::validate() const { 507 assert(OpCode == OpLine); 508 assert(WordCount == 5); 509 assert(get<SPIRVEntry>(Target)); 510 assert(get<SPIRVEntry>(FileName)->getOpCode() == OpString); 511 assert(Line != SPIRVWORD_MAX); 512 assert(Column != SPIRVWORD_MAX); 513 } 514 515 void 516 SPIRVMemberName::validate() const { 517 assert(OpCode == OpMemberName); 518 assert(WordCount == getSizeInWords(Str) + FixedWC); 519 assert(get<SPIRVEntry>(Target)->getOpCode() == OpTypeStruct); 520 assert(MemberNumber < get<SPIRVTypeStruct>(Target)->getStructMemberCount()); 521 } 522 523 SPIRVExtInstImport::SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId, 524 const std::string &TheStr): 525 SPIRVEntry(TheModule, 2 + getSizeInWords(TheStr), OC, TheId), Str(TheStr){ 526 validate(); 527 } 528 529 void 530 SPIRVExtInstImport::encode(spv_ostream &O) const { 531 getEncoder(O) << Id << Str; 532 } 533 534 void 535 SPIRVExtInstImport::decode(std::istream &I) { 536 getDecoder(I) >> Id >> Str; 537 Module->importBuiltinSetWithId(Str, Id); 538 } 539 540 void 541 SPIRVExtInstImport::validate() const { 542 SPIRVEntry::validate(); 543 assert(!Str.empty() && "Invalid builtin set"); 544 } 545 546 void 547 SPIRVMemoryModel::encode(spv_ostream &O) const { 548 getEncoder(O) << Module->getAddressingModel() << 549 Module->getMemoryModel(); 550 } 551 552 void 553 SPIRVMemoryModel::decode(std::istream &I) { 554 SPIRVAddressingModelKind AddrModel; 555 SPIRVMemoryModelKind MemModel; 556 getDecoder(I) >> AddrModel >> MemModel; 557 Module->setAddressingModel(AddrModel); 558 Module->setMemoryModel(MemModel); 559 } 560 561 void 562 SPIRVMemoryModel::validate() const { 563 auto AM = Module->getAddressingModel(); 564 auto MM = Module->getMemoryModel(); 565 SPIRVCK(isValid(AM), InvalidAddressingModel, "Actual is "+AM ); 566 SPIRVCK(isValid(MM), InvalidMemoryModel, "Actual is "+MM); 567 } 568 569 void 570 SPIRVSource::encode(spv_ostream &O) const { 571 SPIRVWord Ver = SPIRVWORD_MAX; 572 auto Language = Module->getSourceLanguage(&Ver); 573 getEncoder(O) << Language << Ver; 574 } 575 576 void 577 SPIRVSource::decode(std::istream &I) { 578 SourceLanguage Lang = SourceLanguageUnknown; 579 SPIRVWord Ver = SPIRVWORD_MAX; 580 getDecoder(I) >> Lang >> Ver; 581 Module->setSourceLanguage(Lang, Ver); 582 } 583 584 SPIRVSourceExtension::SPIRVSourceExtension(SPIRVModule *M, 585 const std::string &SS) 586 :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){} 587 588 void 589 SPIRVSourceExtension::encode(spv_ostream &O) const { 590 getEncoder(O) << S; 591 } 592 593 void 594 SPIRVSourceExtension::decode(std::istream &I) { 595 getDecoder(I) >> S; 596 Module->getSourceExtension().insert(S); 597 } 598 599 SPIRVExtension::SPIRVExtension(SPIRVModule *M, const std::string &SS) 600 :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){} 601 602 void 603 SPIRVExtension::encode(spv_ostream &O) const { 604 getEncoder(O) << S; 605 } 606 607 void 608 SPIRVExtension::decode(std::istream &I) { 609 getDecoder(I) >> S; 610 Module->getExtension().insert(S); 611 } 612 613 SPIRVCapability::SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K) 614 :SPIRVEntryNoId(M, 2), Kind(K){ 615 updateModuleVersion(); 616 } 617 618 void 619 SPIRVCapability::encode(spv_ostream &O) const { 620 getEncoder(O) << Kind; 621 } 622 623 void 624 SPIRVCapability::decode(std::istream &I) { 625 getDecoder(I) >> Kind; 626 Module->addCapability(Kind); 627 } 628 629 } // namespace SPIRV 630 631