SPIRVEntry.cpp revision c5130a58e2c3c4d66fa2b843aefadaab8cf6fb19
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 56using namespace SPIRV; 57 58namespace SPIRV{ 59 60template<typename T> 61SPIRVEntry* create() { 62 return new T(); 63} 64 65SPIRVEntry * 66SPIRVEntry::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 95std::unique_ptr<SPIRV::SPIRVEntry> 96SPIRVEntry::create_unique(Op OC) { 97 return std::unique_ptr<SPIRVEntry>(create(OC)); 98} 99 100std::unique_ptr<SPIRV::SPIRVExtInst> 101SPIRVEntry::create_unique(SPIRVExtInstSetKind Set, 102 unsigned ExtOp) { 103 return std::unique_ptr<SPIRVExtInst>(new SPIRVExtInst(Set, ExtOp)); 104} 105 106SPIRVErrorLog & 107SPIRVEntry::getErrorLog()const { 108 return Module->getErrorLog(); 109} 110 111bool 112SPIRVEntry::exist(SPIRVId TheId)const { 113 return Module->exist(TheId); 114} 115 116SPIRVEntry * 117SPIRVEntry::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 125SPIRVValue * 126SPIRVEntry::getValue(SPIRVId TheId)const { 127 return get<SPIRVValue>(TheId); 128} 129 130SPIRVType * 131SPIRVEntry::getValueType(SPIRVId TheId)const { 132 return get<SPIRVValue>(TheId)->getType(); 133} 134 135SPIRVEncoder 136SPIRVEntry::getEncoder(spv_ostream &O)const{ 137 return SPIRVEncoder(O); 138} 139 140SPIRVDecoder 141SPIRVEntry::getDecoder(std::istream& I){ 142 return SPIRVDecoder(I, *Module); 143} 144 145void 146SPIRVEntry::setWordCount(SPIRVWord TheWordCount){ 147 WordCount = TheWordCount; 148} 149 150void 151SPIRVEntry::setName(const std::string& TheName) { 152 Name = TheName; 153 SPIRVDBG(spvdbgs() << "Set name for obj " << Id << " " << 154 Name << '\n'); 155} 156 157void 158SPIRVEntry::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 166void 167SPIRVEntry::encode(spv_ostream &O) const { 168 assert (0 && "Not implemented"); 169} 170 171void 172SPIRVEntry::encodeName(spv_ostream &O) const { 173 if (!Name.empty()) 174 O << SPIRVName(this, Name); 175} 176 177void 178SPIRVEntry::encodeAll(spv_ostream &O) const { 179 encodeWordCountOpCode(O); 180 encode(O); 181 encodeChildren(O); 182} 183 184void 185SPIRVEntry::encodeChildren(spv_ostream &O)const { 186} 187 188void 189SPIRVEntry::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. 202void 203SPIRVEntry::decode(std::istream &I) { 204 assert (0 && "Not implemented"); 205} 206 207std::vector<SPIRVValue *> 208SPIRVEntry::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 215std::vector<SPIRVType *> 216SPIRVEntry::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 223std::vector<SPIRVId> 224SPIRVEntry::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 231SPIRVEntry * 232SPIRVEntry::getEntry(SPIRVId TheId) const { 233 return Module->getEntry(TheId); 234} 235 236void 237SPIRVEntry::validateFunctionControlMask(SPIRVWord TheFCtlMask) 238 const { 239 SPIRVCK(isValidFunctionControlMask(TheFCtlMask), 240 InvalidFunctionControlMask, ""); 241} 242 243void 244SPIRVEntry::validateValues(const std::vector<SPIRVId> &Ids)const { 245 for (auto I:Ids) 246 getValue(I)->validate(); 247} 248 249void 250SPIRVEntry::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 257void 258SPIRVEntry::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 264void 265SPIRVEntry::addDecorate(Decoration Kind) { 266 addDecorate(new SPIRVDecorate(Kind, this)); 267} 268 269void 270SPIRVEntry::addDecorate(Decoration Kind, SPIRVWord Literal) { 271 addDecorate(new SPIRVDecorate(Kind, this, Literal)); 272} 273 274void 275SPIRVEntry::eraseDecorate(Decoration Dec){ 276 Decorates.erase(Dec); 277} 278 279void 280SPIRVEntry::takeDecorates(SPIRVEntry *E){ 281 Decorates = std::move(E->Decorates); 282 SPIRVDBG(spvdbgs() << "[takeDecorates] " << Id << '\n';) 283} 284 285void 286SPIRVEntry::setLine(SPIRVLine *L){ 287 Line = L; 288 L->setTargetId(Id); 289 SPIRVDBG(spvdbgs() << "[setLine] " << *L << '\n';) 290} 291 292void 293SPIRVEntry::takeLine(SPIRVEntry *E){ 294 Line = E->Line; 295 if (Line == nullptr) 296 return; 297 Line->setTargetId(Id); 298 E->Line = nullptr; 299} 300 301void 302SPIRVEntry::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 310void 311SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind) { 312 addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this)); 313} 314 315void 316SPIRVEntry::addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind, 317 SPIRVWord Literal) { 318 addMemberDecorate(new SPIRVMemberDecorate(Kind, MemberNumber, this, Literal)); 319} 320 321void 322SPIRVEntry::eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Dec){ 323 MemberDecorates.erase(std::make_pair(MemberNumber, Dec)); 324} 325 326void 327SPIRVEntry::takeMemberDecorates(SPIRVEntry *E){ 328 MemberDecorates = std::move(E->MemberDecorates); 329 SPIRVDBG(spvdbgs() << "[takeMemberDecorates] " << Id << '\n';) 330} 331 332void 333SPIRVEntry::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. 344bool 345SPIRVEntry::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. 355std::set<SPIRVWord> 356SPIRVEntry::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 366bool 367SPIRVEntry::hasLinkageType() const { 368 return OpCode == OpFunction || OpCode == OpVariable; 369} 370 371void 372SPIRVEntry::encodeDecorate(spv_ostream &O) const { 373 for (auto& i:Decorates) 374 O << *i.second; 375} 376 377SPIRVLinkageTypeKind 378SPIRVEntry::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 386void 387SPIRVEntry::setLinkageType(SPIRVLinkageTypeKind LT) { 388 assert(isValid(LT)); 389 assert(hasLinkageType()); 390 addDecorate(new SPIRVDecorateLinkageAttr(this, Name, LT)); 391} 392 393void 394SPIRVEntry::updateModuleVersion() const { 395 if (!Module) 396 return; 397 398 Module->setMinSPIRVVersion(getRequiredSPIRVVersion()); 399} 400 401spv_ostream & 402operator<<(spv_ostream &O, const SPIRVEntry &E) { 403 E.validate(); 404 E.encodeAll(O); 405 O << SPIRVNL(); 406 return O; 407} 408 409std::istream & 410operator>>(std::istream &I, SPIRVEntry &E) { 411 E.decode(I); 412 return I; 413} 414 415SPIRVEntryPoint::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 422void 423SPIRVEntryPoint::encode(spv_ostream &O) const { 424 getEncoder(O) << ExecModel << Target << Name; 425} 426 427void 428SPIRVEntryPoint::decode(std::istream &I) { 429 getDecoder(I) >> ExecModel >> Target >> Name; 430 Module->setName(getOrCreateTarget(), Name); 431 Module->addEntryPoint(ExecModel, Target); 432} 433 434void 435SPIRVExecutionMode::encode(spv_ostream &O) const { 436 getEncoder(O) << Target << ExecMode << WordLiterals; 437} 438 439void 440SPIRVExecutionMode::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 460SPIRVForward * 461SPIRVAnnotationGeneric::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 471SPIRVName::SPIRVName(const SPIRVEntry *TheTarget, const std::string& TheStr) 472 :SPIRVAnnotation(TheTarget, getSizeInWords(TheStr) + 2), Str(TheStr){ 473} 474 475void 476SPIRVName::encode(spv_ostream &O) const { 477 getEncoder(O) << Target << Str; 478} 479 480void 481SPIRVName::decode(std::istream &I) { 482 getDecoder(I) >> Target >> Str; 483 Module->setName(getOrCreateTarget(), Str); 484} 485 486void 487SPIRVName::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 494void 495SPIRVLine::encode(spv_ostream &O) const { 496 getEncoder(O) << Target << FileName << Line << Column; 497} 498 499void 500SPIRVLine::decode(std::istream &I) { 501 getDecoder(I) >> Target >> FileName >> Line >> Column; 502 Module->addLine(getOrCreateTarget(), get<SPIRVString>(FileName), Line, Column); 503} 504 505void 506SPIRVLine::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 515void 516SPIRVMemberName::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 523SPIRVExtInstImport::SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId, 524 const std::string &TheStr): 525 SPIRVEntry(TheModule, 2 + getSizeInWords(TheStr), OC, TheId), Str(TheStr){ 526 validate(); 527} 528 529void 530SPIRVExtInstImport::encode(spv_ostream &O) const { 531 getEncoder(O) << Id << Str; 532} 533 534void 535SPIRVExtInstImport::decode(std::istream &I) { 536 getDecoder(I) >> Id >> Str; 537 Module->importBuiltinSetWithId(Str, Id); 538} 539 540void 541SPIRVExtInstImport::validate() const { 542 SPIRVEntry::validate(); 543 assert(!Str.empty() && "Invalid builtin set"); 544} 545 546void 547SPIRVMemoryModel::encode(spv_ostream &O) const { 548 getEncoder(O) << Module->getAddressingModel() << 549 Module->getMemoryModel(); 550} 551 552void 553SPIRVMemoryModel::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 561void 562SPIRVMemoryModel::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 569void 570SPIRVSource::encode(spv_ostream &O) const { 571 SPIRVWord Ver = SPIRVWORD_MAX; 572 auto Language = Module->getSourceLanguage(&Ver); 573 getEncoder(O) << Language << Ver; 574} 575 576void 577SPIRVSource::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 584SPIRVSourceExtension::SPIRVSourceExtension(SPIRVModule *M, 585 const std::string &SS) 586 :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){} 587 588void 589SPIRVSourceExtension::encode(spv_ostream &O) const { 590 getEncoder(O) << S; 591} 592 593void 594SPIRVSourceExtension::decode(std::istream &I) { 595 getDecoder(I) >> S; 596 Module->getSourceExtension().insert(S); 597} 598 599SPIRVExtension::SPIRVExtension(SPIRVModule *M, const std::string &SS) 600 :SPIRVEntryNoId(M, 1 + getSizeInWords(SS)), S(SS){} 601 602void 603SPIRVExtension::encode(spv_ostream &O) const { 604 getEncoder(O) << S; 605} 606 607void 608SPIRVExtension::decode(std::istream &I) { 609 getDecoder(I) >> S; 610 Module->getExtension().insert(S); 611} 612 613SPIRVCapability::SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K) 614 :SPIRVEntryNoId(M, 2), Kind(K){ 615 updateModuleVersion(); 616} 617 618void 619SPIRVCapability::encode(spv_ostream &O) const { 620 getEncoder(O) << Kind; 621} 622 623void 624SPIRVCapability::decode(std::istream &I) { 625 getDecoder(I) >> Kind; 626 Module->addCapability(Kind); 627} 628 629} // namespace SPIRV 630 631