| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241 |
- //===--- EmitVisitor.cpp - SPIR-V Emit Visitor Implementation ----*- C++ -*-==//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- #include "EmitVisitor.h"
- #include "dxc/Support/Global.h"
- #include "dxc/Support/WinIncludes.h"
- #include "dxc/Support/dxcapi.use.h"
- #include "dxc/Support/HLSLOptions.h"
- #include "dxc/Support/FileIOHelper.h"
- #include "clang/SPIRV/BitwiseCast.h"
- #include "clang/SPIRV/SpirvBasicBlock.h"
- #include "clang/SPIRV/SpirvFunction.h"
- #include "clang/SPIRV/SpirvInstruction.h"
- #include "clang/SPIRV/SpirvType.h"
- #include "clang/SPIRV/String.h"
- namespace {
- /// Chops the given original string into multiple smaller ones to make sure they
- /// can be encoded in a sequence of OpSourceContinued instructions following an
- /// OpSource instruction.
- void chopString(llvm::StringRef original,
- llvm::SmallVectorImpl<llvm::StringRef> *chopped) {
- const uint32_t maxCharInOpSource = 0xFFFFu - 5u; // Minus operands and nul
- const uint32_t maxCharInContinue = 0xFFFFu - 2u; // Minus opcode and nul
- chopped->clear();
- if (original.size() > maxCharInOpSource) {
- chopped->push_back(llvm::StringRef(original.data(), maxCharInOpSource));
- original = llvm::StringRef(original.data() + maxCharInOpSource,
- original.size() - maxCharInOpSource);
- while (original.size() > maxCharInContinue) {
- chopped->push_back(llvm::StringRef(original.data(), maxCharInContinue));
- original = llvm::StringRef(original.data() + maxCharInContinue,
- original.size() - maxCharInContinue);
- }
- if (!original.empty()) {
- chopped->push_back(original);
- }
- } else if (!original.empty()) {
- chopped->push_back(original);
- }
- }
- /// Returns true if an OpLine instruction can be emitted for the given OpCode.
- /// According to the SPIR-V Spec section 2.4 (Logical Layout of a Module), the
- /// first section to allow use of OpLine debug information is after all
- /// annotation instructions.
- bool isOpLineLegalForOp(spv::Op op) {
- switch (op) {
- // Preamble binary
- case spv::Op::OpCapability:
- case spv::Op::OpExtension:
- case spv::Op::OpExtInstImport:
- case spv::Op::OpMemoryModel:
- case spv::Op::OpEntryPoint:
- case spv::Op::OpExecutionMode:
- case spv::Op::OpExecutionModeId:
- // Debug binary
- case spv::Op::OpString:
- case spv::Op::OpSource:
- case spv::Op::OpSourceExtension:
- case spv::Op::OpSourceContinued:
- case spv::Op::OpName:
- case spv::Op::OpMemberName:
- // Annotation binary
- case spv::Op::OpModuleProcessed:
- case spv::Op::OpDecorate:
- case spv::Op::OpDecorateId:
- case spv::Op::OpMemberDecorate:
- case spv::Op::OpGroupDecorate:
- case spv::Op::OpGroupMemberDecorate:
- case spv::Op::OpDecorationGroup:
- case spv::Op::OpDecorateStringGOOGLE:
- case spv::Op::OpMemberDecorateStringGOOGLE:
- return false;
- default:
- return true;
- }
- }
- // Returns SPIR-V version that will be used in SPIR-V header section.
- uint32_t getHeaderVersion(llvm::StringRef env) {
- if (env == "vulkan1.1")
- return 0x00010300u;
- if (env == "vulkan1.2" || env == "universal1.5")
- return 0x00010500u;
- return 0x00010000u;
- }
- // Read the file in |filePath| and returns its contents as a string.
- // This function will be used by DebugSource to get its source code.
- std::string ReadSourceCode(llvm::StringRef filePath) {
- try {
- dxc::DxcDllSupport dllSupport;
- IFT(dllSupport.Initialize());
- CComPtr<IDxcLibrary> pLibrary;
- IFT(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
- CComPtr<IDxcBlobEncoding> pSource;
- std::wstring srcFile(filePath.begin(), filePath.end());
- IFT(pLibrary->CreateBlobFromFile(srcFile.c_str(), nullptr, &pSource));
- CComPtr<IDxcBlobUtf8> utf8Source;
- IFT(hlsl::DxcGetBlobAsUtf8(pSource, nullptr, &utf8Source));
- return std::string(utf8Source->GetStringPointer(),
- utf8Source->GetStringLength());
- } catch (...) {
- // An exception has occured while reading the file
- return "";
- }
- }
- constexpr uint32_t kGeneratorNumber = 14;
- constexpr uint32_t kToolVersion = 0;
- } // anonymous namespace
- namespace clang {
- namespace spirv {
- EmitVisitor::Header::Header(uint32_t bound_, uint32_t version_)
- // We are using the unfied header, which shows spv::Version as the newest
- // version. But we need to stick to 1.0 for Vulkan consumption by default.
- : magicNumber(spv::MagicNumber), version(version_),
- generator((kGeneratorNumber << 16) | kToolVersion), bound(bound_),
- reserved(0) {}
- EmitVisitor::~EmitVisitor() {
- for (auto *i : spvInstructions)
- i->releaseMemory();
- }
- template <>
- uint32_t
- EmitVisitor::getOrAssignResultId<SpirvInstruction>(SpirvInstruction *obj) {
- auto *str = dyn_cast<SpirvString>(obj);
- if (str != nullptr) {
- auto it = stringIdMap.find(str->getString());
- if (it != stringIdMap.end()) {
- return it->second;
- }
- }
- if (!obj->getResultId()) {
- obj->setResultId(takeNextId());
- }
- if (str != nullptr) {
- stringIdMap[str->getString()] = obj->getResultId();
- }
- return obj->getResultId();
- }
- std::vector<uint32_t> EmitVisitor::Header::takeBinary() {
- std::vector<uint32_t> words;
- words.push_back(magicNumber);
- words.push_back(version);
- words.push_back(generator);
- words.push_back(bound);
- words.push_back(reserved);
- return words;
- }
- uint32_t EmitVisitor::getOrCreateOpStringId(llvm::StringRef str) {
- auto it = stringIdMap.find(str);
- if (it != stringIdMap.end()) {
- return it->second;
- }
- SpirvString *opString = new (context) SpirvString(/*SourceLocation*/ {}, str);
- visit(opString);
- spvInstructions.push_back(opString);
- return getOrAssignResultId<SpirvInstruction>(opString);
- }
- void EmitVisitor::emitDebugNameForInstruction(uint32_t resultId,
- llvm::StringRef debugName) {
- // Most instructions do not have a debug name associated with them.
- if (debugName.empty())
- return;
- curInst.clear();
- curInst.push_back(static_cast<uint32_t>(spv::Op::OpName));
- curInst.push_back(resultId);
- encodeString(debugName);
- curInst[0] |= static_cast<uint32_t>(curInst.size()) << 16;
- debugVariableBinary.insert(debugVariableBinary.end(), curInst.begin(),
- curInst.end());
- }
- void EmitVisitor::emitDebugLine(spv::Op op, const SourceLocation &loc,
- std::vector<uint32_t> *section,
- bool isDebugScope) {
- if (!spvOptions.debugInfoLine)
- return;
- // Technically entry function wrappers do not exist in HLSL. They are just
- // created by DXC. We do not want to emit line information for their
- // instructions. To prevent spirv-opt from removing all debug info, we emit
- // at least a single OpLine to specify the end of the shader.
- if (inEntryFunctionWrapper && op != spv::Op::OpReturn)
- return;
- // Based on SPIR-V spec, OpSelectionMerge must immediately precede either an
- // OpBranchConditional or OpSwitch instruction. Similarly OpLoopMerge must
- // immediately precede either an OpBranch or OpBranchConditional instruction.
- if (lastOpWasMergeInst) {
- lastOpWasMergeInst = false;
- debugLine = 0;
- debugColumn = 0;
- return;
- }
- if (op == spv::Op::OpSelectionMerge || op == spv::Op::OpLoopMerge)
- lastOpWasMergeInst = true;
- if (!isOpLineLegalForOp(op))
- return;
- // DebugGlobalVariable and DebugLocalVariable of OpenCL.DebugInfo.100 already
- // has the line and the column information. We do not want to emit OpLine
- // for global variables and local variables. Instead, we want to emit OpLine
- // for their initialization if exists.
- if (op == spv::Op::OpVariable)
- return;
- // If no SourceLocation is provided, we have to emit OpNoLine to
- // specify the previous OpLine is not applied to this instruction.
- if (loc == SourceLocation()) {
- if (!isDebugScope && (debugLine != 0 || debugColumn != 0)) {
- curInst.clear();
- curInst.push_back(static_cast<uint32_t>(spv::Op::OpNoLine));
- curInst[0] |= static_cast<uint32_t>(curInst.size()) << 16;
- section->insert(section->end(), curInst.begin(), curInst.end());
- }
- debugLine = 0;
- debugColumn = 0;
- return;
- }
- auto fileId = debugMainFileId;
- const auto &sm = astContext.getSourceManager();
- const char *fileName = sm.getPresumedLoc(loc).getFilename();
- if (fileName)
- fileId = getOrCreateOpStringId(fileName);
- uint32_t line = sm.getPresumedLineNumber(loc);
- uint32_t column = sm.getPresumedColumnNumber(loc);
- // If it is a terminator, just reset the last line and column because
- // a terminator makes the OpLine not effective.
- bool resetLine = (op >= spv::Op::OpBranch && op <= spv::Op::OpUnreachable) ||
- op == spv::Op::OpTerminateInvocation;
- if (!fileId || !line || !column ||
- (line == debugLine && column == debugColumn)) {
- if (resetLine) {
- debugLine = 0;
- debugColumn = 0;
- }
- return;
- }
- assert(section);
- if (resetLine) {
- debugLine = 0;
- debugColumn = 0;
- } else {
- // Keep the last line and column to avoid printing the duplicated OpLine.
- debugLine = line;
- debugColumn = column;
- }
- curInst.clear();
- curInst.push_back(static_cast<uint32_t>(spv::Op::OpLine));
- curInst.push_back(fileId);
- curInst.push_back(line);
- curInst.push_back(column);
- curInst[0] |= static_cast<uint32_t>(curInst.size()) << 16;
- section->insert(section->end(), curInst.begin(), curInst.end());
- if (dumpedFiles.count(fileId) == 0) {
- SpirvString *fileNameInst =
- new (context) SpirvString(/*SourceLocation*/ {}, fileName);
- visit(fileNameInst);
- SpirvSource *src = new (context)
- SpirvSource(/*SourceLocation*/ {}, spv::SourceLanguage::HLSL,
- hlslVersion, fileNameInst, "");
- visit(src);
- spvInstructions.push_back(fileNameInst);
- spvInstructions.push_back(src);
- dumpedFiles.insert(fileId);
- }
- }
- void EmitVisitor::initInstruction(SpirvInstruction *inst) {
- // Emit the result type if the instruction has a result type.
- if (inst->hasResultType()) {
- const uint32_t resultTypeId = typeHandler.emitType(inst->getResultType());
- inst->setResultTypeId(resultTypeId);
- }
- // Emit NonUniformEXT decoration (if any).
- if (inst->isNonUniform()) {
- typeHandler.emitDecoration(getOrAssignResultId<SpirvInstruction>(inst),
- spv::Decoration::NonUniformEXT, {});
- }
- // Emit RelaxedPrecision decoration (if any).
- if (inst->isRelaxedPrecision()) {
- typeHandler.emitDecoration(getOrAssignResultId<SpirvInstruction>(inst),
- spv::Decoration::RelaxedPrecision, {});
- }
- // Emit NoContraction decoration (if any).
- if (inst->isPrecise() && inst->isArithmeticInstruction()) {
- typeHandler.emitDecoration(getOrAssignResultId<SpirvInstruction>(inst),
- spv::Decoration::NoContraction, {});
- }
- // According to Section 2.4. Logical Layout of a Module in the SPIR-V spec:
- // OpLine is always emitted to the main binary, except for global variables.
- // Global variables (variables whose storage class is NOT function) are
- // emitted before the main binary. They are allowed to have an OpLine
- // associated with them.
- bool isGlobalVar = false;
- if (auto *var = dyn_cast<SpirvVariable>(inst))
- isGlobalVar = var->getStorageClass() != spv::StorageClass::Function;
- const auto op = inst->getopcode();
- emitDebugLine(op, inst->getSourceLocation(),
- isGlobalVar ? &globalVarsBinary : &mainBinary,
- isa<SpirvDebugScope>(inst));
- // Initialize the current instruction for emitting.
- curInst.clear();
- curInst.push_back(static_cast<uint32_t>(op));
- }
- void EmitVisitor::initInstruction(spv::Op op, const SourceLocation &loc) {
- emitDebugLine(op, loc, &mainBinary);
- curInst.clear();
- curInst.push_back(static_cast<uint32_t>(op));
- }
- void EmitVisitor::finalizeInstruction(std::vector<uint32_t> *section) {
- assert(section);
- curInst[0] |= static_cast<uint32_t>(curInst.size()) << 16;
- section->insert(section->end(), curInst.begin(), curInst.end());
- }
- std::vector<uint32_t> EmitVisitor::takeBinary() {
- std::vector<uint32_t> result;
- Header header(takeNextId(), getHeaderVersion(spvOptions.targetEnv));
- auto headerBinary = header.takeBinary();
- result.insert(result.end(), headerBinary.begin(), headerBinary.end());
- result.insert(result.end(), preambleBinary.begin(), preambleBinary.end());
- result.insert(result.end(), debugFileBinary.begin(), debugFileBinary.end());
- result.insert(result.end(), debugVariableBinary.begin(),
- debugVariableBinary.end());
- result.insert(result.end(), annotationsBinary.begin(),
- annotationsBinary.end());
- result.insert(result.end(), typeConstantBinary.begin(),
- typeConstantBinary.end());
- result.insert(result.end(), globalVarsBinary.begin(), globalVarsBinary.end());
- result.insert(result.end(), richDebugInfo.begin(), richDebugInfo.end());
- result.insert(result.end(), mainBinary.begin(), mainBinary.end());
- return result;
- }
- void EmitVisitor::encodeString(llvm::StringRef value) {
- const auto &words = string::encodeSPIRVString(value);
- curInst.insert(curInst.end(), words.begin(), words.end());
- }
- bool EmitVisitor::visit(SpirvModule *, Phase) {
- // No pre-visit operations needed for SpirvModule.
- return true;
- }
- bool EmitVisitor::visit(SpirvFunction *fn, Phase phase) {
- assert(fn);
- // Before emitting the function
- if (phase == Visitor::Phase::Init) {
- const uint32_t returnTypeId = typeHandler.emitType(fn->getReturnType());
- const uint32_t functionTypeId = typeHandler.emitType(fn->getFunctionType());
- if (fn->isEntryFunctionWrapper())
- inEntryFunctionWrapper = true;
- // Emit OpFunction
- initInstruction(spv::Op::OpFunction, fn->getSourceLocation());
- curInst.push_back(returnTypeId);
- curInst.push_back(getOrAssignResultId<SpirvFunction>(fn));
- curInst.push_back(fn->isNoInline() ?
- static_cast<uint32_t>(spv::FunctionControlMask::DontInline) :
- static_cast<uint32_t>(spv::FunctionControlMask::MaskNone));
- curInst.push_back(functionTypeId);
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvFunction>(fn),
- fn->getFunctionName());
- // RelaxedPrecision decoration may be applied to an OpFunction instruction.
- if (fn->isRelaxedPrecision())
- typeHandler.emitDecoration(getOrAssignResultId<SpirvFunction>(fn),
- spv::Decoration::RelaxedPrecision, {});
- }
- // After emitting the function
- else if (phase == Visitor::Phase::Done) {
- // Emit OpFunctionEnd
- initInstruction(spv::Op::OpFunctionEnd, /* SourceLocation */ {});
- finalizeInstruction(&mainBinary);
- inEntryFunctionWrapper = false;
- }
- return true;
- }
- bool EmitVisitor::visit(SpirvBasicBlock *bb, Phase phase) {
- assert(bb);
- // Before emitting the basic block.
- if (phase == Visitor::Phase::Init) {
- // Emit OpLabel
- initInstruction(spv::Op::OpLabel, /* SourceLocation */ {});
- curInst.push_back(getOrAssignResultId<SpirvBasicBlock>(bb));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvBasicBlock>(bb),
- bb->getName());
- }
- // After emitting the basic block
- else if (phase == Visitor::Phase::Done) {
- assert(bb->hasTerminator());
- }
- return true;
- }
- bool EmitVisitor::visit(SpirvCapability *cap) {
- initInstruction(cap);
- curInst.push_back(static_cast<uint32_t>(cap->getCapability()));
- finalizeInstruction(&preambleBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvExtension *ext) {
- initInstruction(ext);
- encodeString(ext->getExtensionName());
- finalizeInstruction(&preambleBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvExtInstImport *inst) {
- initInstruction(inst);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- encodeString(inst->getExtendedInstSetName());
- finalizeInstruction(&preambleBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvMemoryModel *inst) {
- initInstruction(inst);
- curInst.push_back(static_cast<uint32_t>(inst->getAddressingModel()));
- curInst.push_back(static_cast<uint32_t>(inst->getMemoryModel()));
- finalizeInstruction(&preambleBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvEntryPoint *inst) {
- initInstruction(inst);
- curInst.push_back(static_cast<uint32_t>(inst->getExecModel()));
- curInst.push_back(getOrAssignResultId<SpirvFunction>(inst->getEntryPoint()));
- encodeString(inst->getEntryPointName());
- for (auto *var : inst->getInterface())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(var));
- finalizeInstruction(&preambleBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvExecutionMode *inst) {
- initInstruction(inst);
- curInst.push_back(getOrAssignResultId<SpirvFunction>(inst->getEntryPoint()));
- curInst.push_back(static_cast<uint32_t>(inst->getExecutionMode()));
- curInst.insert(curInst.end(), inst->getParams().begin(),
- inst->getParams().end());
- finalizeInstruction(&preambleBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvString *inst) {
- auto it = stringIdMap.find(inst->getString());
- if (it != stringIdMap.end())
- return true;
- uint32_t strId = getOrAssignResultId<SpirvInstruction>(inst);
- initInstruction(inst);
- curInst.push_back(strId);
- encodeString(inst->getString());
- finalizeInstruction(&debugFileBinary);
- stringIdMap[inst->getString()] = strId;
- return true;
- }
- bool EmitVisitor::visit(SpirvSource *inst) {
- // We should either emit OpSource or DebugSource, not both.
- // Therefore if rich debug info is being generated, we will skip
- // emitting OpSource.
- if (spvOptions.debugInfoRich)
- return true;
- // Emit the OpString for the file name.
- uint32_t fileId = debugMainFileId;
- if (inst->hasFile()) {
- fileId = getOrCreateOpStringId(inst->getFile()->getString());
- if (!debugMainFileId)
- debugMainFileId = fileId;
- }
- if (dumpedFiles.count(fileId) != 0)
- return true;
- dumpedFiles.insert(fileId);
- initInstruction(inst);
- curInst.push_back(static_cast<uint32_t>(inst->getSourceLanguage()));
- curInst.push_back(static_cast<uint32_t>(inst->getVersion()));
- if (hlslVersion == 0)
- hlslVersion = inst->getVersion();
- if (inst->hasFile())
- curInst.push_back(fileId);
- // Chop up the source into multiple segments if it is too long.
- llvm::Optional<llvm::StringRef> firstSnippet = llvm::None;
- llvm::SmallVector<llvm::StringRef, 2> choppedSrcCode;
- if (spvOptions.debugInfoSource && inst->hasFile()) {
- auto text = ReadSourceCode(inst->getFile()->getString());
- if (!text.empty()) {
- chopString(text, &choppedSrcCode);
- if (!choppedSrcCode.empty()) {
- firstSnippet = llvm::Optional<llvm::StringRef>(choppedSrcCode.front());
- }
- }
- if (firstSnippet.hasValue()) {
- // Note: in order to improve performance and avoid multiple copies, we
- // encode this (potentially large) string directly into the
- // debugFileBinary.
- const auto &words = string::encodeSPIRVString(firstSnippet.getValue());
- const auto numWordsInInstr = curInst.size() + words.size();
- curInst[0] |= static_cast<uint32_t>(numWordsInInstr) << 16;
- debugFileBinary.insert(debugFileBinary.end(), curInst.begin(),
- curInst.end());
- debugFileBinary.insert(debugFileBinary.end(), words.begin(), words.end());
- } else {
- curInst[0] |= static_cast<uint32_t>(curInst.size()) << 16;
- debugFileBinary.insert(debugFileBinary.end(), curInst.begin(),
- curInst.end());
- }
- } else {
- curInst[0] |= static_cast<uint32_t>(curInst.size()) << 16;
- debugFileBinary.insert(debugFileBinary.end(), curInst.begin(),
- curInst.end());
- }
- // Now emit OpSourceContinued for the [second:last] snippet.
- for (uint32_t i = 1; i < choppedSrcCode.size(); ++i) {
- initInstruction(spv::Op::OpSourceContinued, /* SourceLocation */ {});
- // Note: in order to improve performance and avoid multiple copies, we
- // encode this (potentially large) string directly into the debugFileBinary.
- const auto &words = string::encodeSPIRVString(choppedSrcCode[i]);
- const auto numWordsInInstr = curInst.size() + words.size();
- curInst[0] |= static_cast<uint32_t>(numWordsInInstr) << 16;
- debugFileBinary.insert(debugFileBinary.end(), curInst.begin(),
- curInst.end());
- debugFileBinary.insert(debugFileBinary.end(), words.begin(), words.end());
- }
- return true;
- }
- bool EmitVisitor::visit(SpirvModuleProcessed *inst) {
- initInstruction(inst);
- encodeString(inst->getProcess());
- finalizeInstruction(&annotationsBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvDecoration *inst) {
- initInstruction(inst);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getTarget()));
- if (inst->isMemberDecoration())
- curInst.push_back(inst->getMemberIndex());
- curInst.push_back(static_cast<uint32_t>(inst->getDecoration()));
- if (!inst->getParams().empty()) {
- curInst.insert(curInst.end(), inst->getParams().begin(),
- inst->getParams().end());
- }
- if (!inst->getIdParams().empty()) {
- for (auto *paramInstr : inst->getIdParams())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(paramInstr));
- }
- finalizeInstruction(&annotationsBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvVariable *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(static_cast<uint32_t>(inst->getStorageClass()));
- if (inst->hasInitializer())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInitializer()));
- finalizeInstruction(inst->getStorageClass() == spv::StorageClass::Function
- ? &mainBinary
- : &globalVarsBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- if (spvOptions.enableReflect && inst->hasBinding() &&
- !inst->getHlslUserType().empty()) {
- typeHandler.emitDecoration(
- getOrAssignResultId<SpirvInstruction>(inst),
- spv::Decoration::UserTypeGOOGLE,
- string::encodeSPIRVString(inst->getHlslUserType().lower()));
- }
- return true;
- }
- bool EmitVisitor::visit(SpirvFunctionParameter *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvLoopMerge *inst) {
- initInstruction(inst);
- curInst.push_back(
- getOrAssignResultId<SpirvBasicBlock>(inst->getMergeBlock()));
- curInst.push_back(
- getOrAssignResultId<SpirvBasicBlock>(inst->getContinueTarget()));
- curInst.push_back(static_cast<uint32_t>(inst->getLoopControlMask()));
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvSelectionMerge *inst) {
- initInstruction(inst);
- curInst.push_back(
- getOrAssignResultId<SpirvBasicBlock>(inst->getMergeBlock()));
- curInst.push_back(static_cast<uint32_t>(inst->getSelectionControlMask()));
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvBranch *inst) {
- initInstruction(inst);
- curInst.push_back(
- getOrAssignResultId<SpirvBasicBlock>(inst->getTargetLabel()));
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvBranchConditional *inst) {
- initInstruction(inst);
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getCondition()));
- curInst.push_back(getOrAssignResultId<SpirvBasicBlock>(inst->getTrueLabel()));
- curInst.push_back(
- getOrAssignResultId<SpirvBasicBlock>(inst->getFalseLabel()));
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvKill *inst) {
- initInstruction(inst);
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvReturn *inst) {
- initInstruction(inst);
- if (inst->hasReturnValue()) {
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getReturnValue()));
- }
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvSwitch *inst) {
- initInstruction(inst);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSelector()));
- curInst.push_back(
- getOrAssignResultId<SpirvBasicBlock>(inst->getDefaultLabel()));
- for (const auto &target : inst->getTargets()) {
- curInst.push_back(target.first);
- curInst.push_back(getOrAssignResultId<SpirvBasicBlock>(target.second));
- }
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvUnreachable *inst) {
- initInstruction(inst);
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvAccessChain *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getBase()));
- for (const auto index : inst->getIndexes())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(index));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvAtomic *inst) {
- const auto op = inst->getopcode();
- initInstruction(inst);
- if (op != spv::Op::OpAtomicStore && op != spv::Op::OpAtomicFlagClear) {
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- }
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getPointer()));
- curInst.push_back(typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, static_cast<uint32_t>(inst->getScope())),
- context.getUIntType(32), /*isSpecConst */ false));
- curInst.push_back(typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, static_cast<uint32_t>(inst->getMemorySemantics())),
- context.getUIntType(32), /*isSpecConst */ false));
- if (inst->hasComparator())
- curInst.push_back(typeHandler.getOrCreateConstantInt(
- llvm::APInt(32,
- static_cast<uint32_t>(inst->getMemorySemanticsUnequal())),
- context.getUIntType(32), /*isSpecConst */ false));
- if (inst->hasValue())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getValue()));
- if (inst->hasComparator())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getComparator()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvBarrier *inst) {
- const uint32_t executionScopeId =
- inst->isControlBarrier()
- ? typeHandler.getOrCreateConstantInt(
- llvm::APInt(32,
- static_cast<uint32_t>(inst->getExecutionScope())),
- context.getUIntType(32), /*isSpecConst */ false)
- : 0;
- const uint32_t memoryScopeId = typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, static_cast<uint32_t>(inst->getMemoryScope())),
- context.getUIntType(32), /*isSpecConst */ false);
- const uint32_t memorySemanticsId = typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, static_cast<uint32_t>(inst->getMemorySemantics())),
- context.getUIntType(32), /* isSpecConst */ false);
- initInstruction(inst);
- if (inst->isControlBarrier())
- curInst.push_back(executionScopeId);
- curInst.push_back(memoryScopeId);
- curInst.push_back(memorySemanticsId);
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvBinaryOp *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOperand1()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOperand2()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvBitFieldExtract *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getBase()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOffset()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getCount()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvBitFieldInsert *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getBase()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getInsert()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOffset()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getCount()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvConstantBoolean *inst) {
- typeHandler.getOrCreateConstant(inst);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvConstantInteger *inst) {
- // Note: Since array types need to create uint 32-bit constants for result-id
- // of array length, the typeHandler keeps track of uint32 constant uniqueness.
- // Therefore emitting uint32 constants should be handled by the typeHandler.
- typeHandler.getOrCreateConstant(inst);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvConstantFloat *inst) {
- typeHandler.getOrCreateConstant(inst);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvConstantComposite *inst) {
- typeHandler.getOrCreateConstant(inst);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvConstantNull *inst) {
- typeHandler.getOrCreateConstant(inst);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvCompositeConstruct *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- for (const auto constituent : inst->getConstituents())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(constituent));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvCompositeExtract *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getComposite()));
- for (const auto constituent : inst->getIndexes())
- curInst.push_back(constituent);
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvCompositeInsert *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getObject()));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getComposite()));
- for (const auto constituent : inst->getIndexes())
- curInst.push_back(constituent);
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvEmitVertex *inst) {
- initInstruction(inst);
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvEndPrimitive *inst) {
- initInstruction(inst);
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvExtInst *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getInstruction());
- for (const auto operand : inst->getOperands())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(operand));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvFunctionCall *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvFunction>(inst->getFunction()));
- for (const auto arg : inst->getArgs())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(arg));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvNonUniformBinaryOp *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, static_cast<uint32_t>(inst->getExecutionScope())),
- context.getUIntType(32), /* isSpecConst */ false));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getArg1()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getArg2()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvNonUniformElect *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, static_cast<uint32_t>(inst->getExecutionScope())),
- context.getUIntType(32), /* isSpecConst */ false));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvNonUniformUnaryOp *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, static_cast<uint32_t>(inst->getExecutionScope())),
- context.getUIntType(32), /* isSpecConst */ false));
- if (inst->hasGroupOp())
- curInst.push_back(static_cast<uint32_t>(inst->getGroupOp()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getArg()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvImageOp *inst) {
- initInstruction(inst);
- if (!inst->isImageWrite()) {
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- }
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getImage()));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getCoordinate()));
- if (inst->isImageWrite())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getTexelToWrite()));
- if (inst->hasDref())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getDref()));
- if (inst->hasComponent())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getComponent()));
- curInst.push_back(static_cast<uint32_t>(inst->getImageOperandsMask()));
- if (inst->getImageOperandsMask() != spv::ImageOperandsMask::MaskNone) {
- if (inst->hasBias())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getBias()));
- if (inst->hasLod())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getLod()));
- if (inst->hasGrad()) {
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getGradDx()));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getGradDy()));
- }
- if (inst->hasConstOffset())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getConstOffset()));
- if (inst->hasOffset())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getOffset()));
- if (inst->hasConstOffsets())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getConstOffsets()));
- if (inst->hasSample())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getSample()));
- if (inst->hasMinLod())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getMinLod()));
- }
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvImageQuery *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getImage()));
- if (inst->hasCoordinate())
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getCoordinate()));
- if (inst->hasLod())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getLod()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvImageSparseTexelsResident *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getResidentCode()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvImageTexelPointer *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getImage()));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getCoordinate()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSample()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvLoad *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getPointer()));
- if (inst->hasMemoryAccessSemantics())
- curInst.push_back(static_cast<uint32_t>(inst->getMemoryAccess()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvCopyObject *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getPointer()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvSampledImage *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getImage()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSampler()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvSelect *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getCondition()));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getTrueObject()));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getFalseObject()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvSpecConstantBinaryOp *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(static_cast<uint32_t>(inst->getSpecConstantopcode()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOperand1()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOperand2()));
- finalizeInstruction(&typeConstantBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvSpecConstantUnaryOp *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(static_cast<uint32_t>(inst->getSpecConstantopcode()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOperand()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvStore *inst) {
- initInstruction(inst);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getPointer()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getObject()));
- if (inst->hasMemoryAccessSemantics())
- curInst.push_back(static_cast<uint32_t>(inst->getMemoryAccess()));
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvUnaryOp *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getOperand()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvVectorShuffle *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getVec1()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getVec2()));
- for (const auto component : inst->getComponents())
- curInst.push_back(component);
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvArrayLength *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getStructure()));
- curInst.push_back(inst->getArrayMember());
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvRayTracingOpNV *inst) {
- initInstruction(inst);
- if (inst->hasResultType()) {
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- }
- for (const auto operand : inst->getOperands())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(operand));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvDemoteToHelperInvocationEXT *inst) {
- initInstruction(inst);
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugInfoNone *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugSource *inst) {
- uint32_t fileId = getOrCreateOpStringId(inst->getFile());
- if (!debugMainFileId)
- debugMainFileId = fileId;
- uint32_t textId = 0;
- if (spvOptions.debugInfoSource) {
- auto text = ReadSourceCode(inst->getFile());
- if (!text.empty())
- textId = getOrCreateOpStringId(text);
- }
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(fileId);
- if (textId)
- curInst.push_back(textId);
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugCompilationUnit *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(inst->getSpirvVersion());
- curInst.push_back(inst->getDwarfVersion());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugSource()));
- curInst.push_back(static_cast<uint32_t>(inst->getLanguage()));
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugLexicalBlock *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getParentScope()));
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugScope *inst) {
- // Technically entry function wrappers do not exist in HLSL. They
- // are just created by DXC. We do not want to emit DebugScope for
- // it.
- if (inEntryFunctionWrapper)
- return true;
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getScope()));
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugFunctionDeclaration *inst) {
- uint32_t nameId = getOrCreateOpStringId(inst->getDebugName());
- uint32_t linkageNameId = getOrCreateOpStringId(inst->getLinkageName());
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(nameId);
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugType()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getParentScope()));
- curInst.push_back(linkageNameId);
- curInst.push_back(inst->getFlags());
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugFunction *inst) {
- uint32_t nameId = getOrCreateOpStringId(inst->getDebugName());
- uint32_t linkageNameId = getOrCreateOpStringId(inst->getLinkageName());
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(nameId);
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugType()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getParentScope()));
- curInst.push_back(linkageNameId);
- curInst.push_back(inst->getFlags());
- curInst.push_back(inst->getScopeLine());
- auto *fn = inst->getSpirvFunction();
- if (fn) {
- curInst.push_back(getOrAssignResultId<SpirvFunction>(fn));
- } else {
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugInfoNone()));
- }
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeBasic *inst) {
- uint32_t typeNameId = getOrCreateOpStringId(inst->getDebugName());
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(typeNameId);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSize()));
- curInst.push_back(inst->getEncoding());
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeVector *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getElementType()));
- curInst.push_back(inst->getElementCount());
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeArray *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getElementType()));
- // This is a reverse order of dimensions, thereby emitting in a reverse order.
- for (auto it = inst->getElementCount().rbegin();
- it != inst->getElementCount().rend(); ++it) {
- const auto countId = typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, *it), context.getUIntType(32),
- /* isSpecConst */ false);
- curInst.push_back(countId);
- }
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeFunction *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(inst->getDebugFlags());
- if (inst->getReturnType()) {
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getReturnType()));
- } else {
- // If return type is void, the return instruction must be OpTypeVoid.
- curInst.push_back(typeHandler.emitType(context.getVoidType()));
- }
- for (auto *paramType : inst->getParamTypes()) {
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(paramType));
- }
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeComposite *inst) {
- uint32_t typeNameId = getOrCreateOpStringId(inst->getDebugName());
- uint32_t linkageNameId = getOrCreateOpStringId(inst->getLinkageName());
- const auto size = typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, inst->getSizeInBits()), context.getUIntType(32),
- /* isSpecConst */ false);
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(typeNameId);
- curInst.push_back(inst->getTag());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getParentScope()));
- curInst.push_back(linkageNameId);
- if (inst->getDebugInfoNone()) {
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugInfoNone()));
- } else {
- curInst.push_back(size);
- }
- curInst.push_back(inst->getDebugFlags());
- for (auto *member : inst->getMembers()) {
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(member));
- }
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeMember *inst) {
- uint32_t typeNameId = getOrCreateOpStringId(inst->getDebugName());
- const auto offset = typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, inst->getOffsetInBits()), context.getUIntType(32),
- /* isSpecConst */ false);
- const auto size = typeHandler.getOrCreateConstantInt(
- llvm::APInt(32, inst->getSizeInBits()), context.getUIntType(32),
- /* isSpecConst */ false);
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(typeNameId);
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugType()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getParentScope()));
- curInst.push_back(offset);
- curInst.push_back(size);
- curInst.push_back(inst->getDebugFlags());
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeTemplate *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getTarget()));
- for (auto *param : inst->getParams()) {
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(param));
- }
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugTypeTemplateParameter *inst) {
- uint32_t typeNameId = getOrCreateOpStringId(inst->getDebugName());
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(typeNameId);
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getActualType()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getValue()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugLocalVariable *inst) {
- uint32_t nameId = getOrCreateOpStringId(inst->getDebugName());
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(nameId);
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugType()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getParentScope()));
- curInst.push_back(inst->getFlags());
- if (inst->getArgNumber().hasValue())
- curInst.push_back(inst->getArgNumber().getValue());
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugDeclare *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugLocalVariable()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getVariable()));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugExpression()));
- finalizeInstruction(&mainBinary);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugGlobalVariable *inst) {
- uint32_t nameId = getOrCreateOpStringId(inst->getDebugName());
- uint32_t linkageNameId = getOrCreateOpStringId(inst->getLinkageName());
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- curInst.push_back(nameId);
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getDebugType()));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getSource()));
- curInst.push_back(inst->getLine());
- curInst.push_back(inst->getColumn());
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getParentScope()));
- curInst.push_back(linkageNameId);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getVariable()));
- curInst.push_back(inst->getFlags());
- if (inst->getStaticMemberDebugDecl().hasValue())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(
- inst->getStaticMemberDebugDecl().getValue()));
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvDebugExpression *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getInstructionSet()));
- curInst.push_back(inst->getDebugOpcode());
- for (const auto &op : inst->getOperations())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(op));
- finalizeInstruction(&richDebugInfo);
- return true;
- }
- bool EmitVisitor::visit(SpirvRayQueryOpKHR *inst) {
- initInstruction(inst);
- if (inst->hasResultType()) {
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- }
- for (const auto operand : inst->getOperands())
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(operand));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvReadClock *inst) {
- initInstruction(inst);
- curInst.push_back(inst->getResultTypeId());
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getScope()));
- finalizeInstruction(&mainBinary);
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvRayTracingTerminateOpKHR *inst) {
- initInstruction(inst);
- finalizeInstruction(&mainBinary);
- return true;
- }
- // EmitTypeHandler ------
- void EmitTypeHandler::initTypeInstruction(spv::Op op) {
- curTypeInst.clear();
- curTypeInst.push_back(static_cast<uint32_t>(op));
- }
- void EmitTypeHandler::finalizeTypeInstruction() {
- curTypeInst[0] |= static_cast<uint32_t>(curTypeInst.size()) << 16;
- typeConstantBinary->insert(typeConstantBinary->end(), curTypeInst.begin(),
- curTypeInst.end());
- }
- uint32_t EmitTypeHandler::getResultIdForType(const SpirvType *type,
- bool *alreadyExists) {
- assert(alreadyExists);
- auto foundType = emittedTypes.find(type);
- if (foundType != emittedTypes.end()) {
- *alreadyExists = true;
- return foundType->second;
- }
- *alreadyExists = false;
- const uint32_t id = takeNextIdFunction();
- emittedTypes[type] = id;
- return id;
- }
- uint32_t EmitTypeHandler::getOrCreateConstant(SpirvConstant *inst) {
- if (auto *constInt = dyn_cast<SpirvConstantInteger>(inst)) {
- return getOrCreateConstantInt(constInt->getValue(),
- constInt->getResultType(),
- inst->isSpecConstant(), inst);
- } else if (auto *constFloat = dyn_cast<SpirvConstantFloat>(inst)) {
- return getOrCreateConstantFloat(constFloat);
- } else if (auto *constComposite = dyn_cast<SpirvConstantComposite>(inst)) {
- return getOrCreateConstantComposite(constComposite);
- } else if (auto *constNull = dyn_cast<SpirvConstantNull>(inst)) {
- return getOrCreateConstantNull(constNull);
- } else if (auto *constBool = dyn_cast<SpirvConstantBoolean>(inst)) {
- return getOrCreateConstantBool(constBool);
- }
- llvm_unreachable("cannot emit unknown constant type");
- }
- uint32_t EmitTypeHandler::getOrCreateConstantBool(SpirvConstantBoolean *inst) {
- const auto index = static_cast<uint32_t>(inst->getValue());
- const bool isSpecConst = inst->isSpecConstant();
- // SpecConstants are not unique. We should not reuse them. e.g. it is possible
- // to have multiple OpSpecConstantTrue instructions.
- if (!isSpecConst && emittedConstantBools[index]) {
- // Already emitted this constant. Reuse.
- inst->setResultId(emittedConstantBools[index]->getResultId());
- } else {
- // Constant wasn't emitted in the past.
- const uint32_t typeId = emitType(inst->getResultType());
- initTypeInstruction(inst->getopcode());
- curTypeInst.push_back(typeId);
- curTypeInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- finalizeTypeInstruction();
- // Remember this constant for the future (if not a spec constant)
- if (!isSpecConst)
- emittedConstantBools[index] = inst;
- }
- return inst->getResultId();
- }
- uint32_t EmitTypeHandler::getOrCreateConstantNull(SpirvConstantNull *inst) {
- auto found =
- std::find_if(emittedConstantNulls.begin(), emittedConstantNulls.end(),
- [inst](SpirvConstantNull *cachedConstant) {
- return *cachedConstant == *inst;
- });
- if (found != emittedConstantNulls.end()) {
- // We have already emitted this constant. Reuse.
- inst->setResultId((*found)->getResultId());
- } else {
- // Constant wasn't emitted in the past.
- const uint32_t typeId = emitType(inst->getResultType());
- initTypeInstruction(spv::Op::OpConstantNull);
- curTypeInst.push_back(typeId);
- curTypeInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- finalizeTypeInstruction();
- // Remember this constant for the future
- emittedConstantNulls.push_back(inst);
- }
- return inst->getResultId();
- }
- uint32_t EmitTypeHandler::getOrCreateConstantFloat(SpirvConstantFloat *inst) {
- llvm::APFloat value = inst->getValue();
- const SpirvType *type = inst->getResultType();
- const bool isSpecConst = inst->isSpecConstant();
- assert(isa<FloatType>(type));
- const auto *floatType = dyn_cast<FloatType>(type);
- const auto typeBitwidth = floatType->getBitwidth();
- const auto valueBitwidth = llvm::APFloat::getSizeInBits(value.getSemantics());
- auto valueToUse = value;
- // If the type and the value have different widths, we need to convert the
- // value to the width of the type. Error out if the conversion is lossy.
- if (valueBitwidth != typeBitwidth) {
- bool losesInfo = false;
- const llvm::fltSemantics &targetSemantics =
- typeBitwidth == 16 ? llvm::APFloat::IEEEhalf
- : typeBitwidth == 32 ? llvm::APFloat::IEEEsingle
- : llvm::APFloat::IEEEdouble;
- const auto status = valueToUse.convert(
- targetSemantics, llvm::APFloat::roundingMode::rmTowardZero, &losesInfo);
- if (status != llvm::APFloat::opStatus::opOK &&
- status != llvm::APFloat::opStatus::opInexact) {
- emitError(
- "evaluating float literal %0 at a lower bitwidth loses information",
- {})
- // Converting from 16bit to 32/64-bit won't lose information.
- // So only 32/64-bit values can reach here.
- << std::to_string(valueBitwidth == 32 ? valueToUse.convertToFloat()
- : valueToUse.convertToDouble());
- return 0;
- }
- }
- auto valueTypePair = std::pair<uint64_t, const SpirvType *>(
- valueToUse.bitcastToAPInt().getZExtValue(), type);
- // SpecConstant instructions are not unique, so we should not re-use existing
- // spec constants.
- if (!isSpecConst) {
- // If this constant has already been emitted, return its result-id.
- auto foundResultId = emittedConstantFloats.find(valueTypePair);
- if (foundResultId != emittedConstantFloats.end()) {
- const uint32_t existingConstantResultId = foundResultId->second;
- inst->setResultId(existingConstantResultId);
- return existingConstantResultId;
- }
- }
- // Start constructing the instruction
- const uint32_t typeId = emitType(type);
- initTypeInstruction(inst->getopcode());
- curTypeInst.push_back(typeId);
- const uint32_t constantResultId = getOrAssignResultId<SpirvInstruction>(inst);
- curTypeInst.push_back(constantResultId);
- // Start constructing the value word / words
- if (typeBitwidth == 16) {
- // According to the SPIR-V Spec:
- // When the type's bit width is less than 32-bits, the literal's value
- // appears in the low-order bits of the word, and the high-order bits must
- // be 0 for a floating-point type.
- curTypeInst.push_back(
- static_cast<uint32_t>(valueToUse.bitcastToAPInt().getZExtValue()));
- } else if (typeBitwidth == 32) {
- curTypeInst.push_back(
- cast::BitwiseCast<uint32_t, float>(valueToUse.convertToFloat()));
- } else {
- // TODO: The ordering of the 2 words depends on the endian-ness of the
- // host machine.
- struct wideFloat {
- uint32_t word0;
- uint32_t word1;
- };
- wideFloat words =
- cast::BitwiseCast<wideFloat, double>(valueToUse.convertToDouble());
- curTypeInst.push_back(words.word0);
- curTypeInst.push_back(words.word1);
- }
- finalizeTypeInstruction();
- // Remember this constant for future (if not a SpecConstant)
- if (!isSpecConst)
- emittedConstantFloats[valueTypePair] = constantResultId;
- return constantResultId;
- }
- uint32_t
- EmitTypeHandler::getOrCreateConstantInt(llvm::APInt value,
- const SpirvType *type, bool isSpecConst,
- SpirvInstruction *constantInstruction) {
- auto valueTypePair =
- std::pair<uint64_t, const SpirvType *>(value.getZExtValue(), type);
- // SpecConstant instructions are not unique, so we should not re-use existing
- // spec constants.
- if (!isSpecConst) {
- // If this constant has already been emitted, return its result-id.
- auto foundResultId = emittedConstantInts.find(valueTypePair);
- if (foundResultId != emittedConstantInts.end()) {
- const uint32_t existingConstantResultId = foundResultId->second;
- if (constantInstruction)
- constantInstruction->setResultId(existingConstantResultId);
- return existingConstantResultId;
- }
- }
- assert(isa<IntegerType>(type));
- const auto *intType = dyn_cast<IntegerType>(type);
- const auto bitwidth = intType->getBitwidth();
- const auto isSigned = intType->isSignedInt();
- // Start constructing the instruction
- const uint32_t typeId = emitType(type);
- initTypeInstruction(isSpecConst ? spv::Op::OpSpecConstant
- : spv::Op::OpConstant);
- curTypeInst.push_back(typeId);
- // Assign a result-id if one has not been provided.
- uint32_t constantResultId = 0;
- if (constantInstruction)
- constantResultId =
- getOrAssignResultId<SpirvInstruction>(constantInstruction);
- else
- constantResultId = takeNextIdFunction();
- curTypeInst.push_back(constantResultId);
- // Start constructing the value word / words
- // For 16-bit and 32-bit cases, the value occupies 1 word in the instruction
- if (bitwidth == 16 || bitwidth == 32) {
- if (isSigned) {
- curTypeInst.push_back(static_cast<int32_t>(value.getSExtValue()));
- } else {
- curTypeInst.push_back(static_cast<uint32_t>(value.getZExtValue()));
- }
- }
- // 64-bit cases
- else {
- struct wideInt {
- uint32_t word0;
- uint32_t word1;
- };
- wideInt words;
- if (isSigned) {
- words = cast::BitwiseCast<wideInt, int64_t>(value.getSExtValue());
- } else {
- words = cast::BitwiseCast<wideInt, uint64_t>(value.getZExtValue());
- }
- curTypeInst.push_back(words.word0);
- curTypeInst.push_back(words.word1);
- }
- finalizeTypeInstruction();
- // Remember this constant for future (not needed for SpecConstants)
- if (!isSpecConst)
- emittedConstantInts[valueTypePair] = constantResultId;
- return constantResultId;
- }
- uint32_t
- EmitTypeHandler::getOrCreateConstantComposite(SpirvConstantComposite *inst) {
- // First make sure all constituents have been visited and have a result-id.
- for (auto constituent : inst->getConstituents())
- getOrCreateConstant(constituent);
- // SpecConstant instructions are not unique, so we should not re-use existing
- // spec constants.
- const bool isSpecConst = inst->isSpecConstant();
- SpirvConstantComposite **found = nullptr;
- if (!isSpecConst) {
- found = std::find_if(
- emittedConstantComposites.begin(), emittedConstantComposites.end(),
- [inst](SpirvConstantComposite *cachedConstant) {
- if (inst->getopcode() != cachedConstant->getopcode())
- return false;
- auto instConstituents = inst->getConstituents();
- auto cachedConstituents = cachedConstant->getConstituents();
- if (instConstituents.size() != cachedConstituents.size())
- return false;
- for (size_t i = 0; i < instConstituents.size(); ++i)
- if (instConstituents[i]->getResultId() !=
- cachedConstituents[i]->getResultId())
- return false;
- return true;
- });
- }
- if (!isSpecConst && found != emittedConstantComposites.end()) {
- // We have already emitted this constant. Reuse.
- inst->setResultId((*found)->getResultId());
- } else {
- // Constant wasn't emitted in the past.
- const uint32_t typeId = emitType(inst->getResultType());
- initTypeInstruction(spv::Op::OpConstantComposite);
- curTypeInst.push_back(typeId);
- curTypeInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- for (auto constituent : inst->getConstituents())
- curTypeInst.push_back(getOrAssignResultId<SpirvInstruction>(constituent));
- finalizeTypeInstruction();
- // Remember this constant for the future (if not a spec constant)
- if (!isSpecConst)
- emittedConstantComposites.push_back(inst);
- }
- return inst->getResultId();
- }
- uint32_t EmitTypeHandler::emitType(const SpirvType *type) {
- // First get the decorations that would apply to this type.
- bool alreadyExists = false;
- const uint32_t id = getResultIdForType(type, &alreadyExists);
- // If the type has already been emitted, we just need to return its
- // <result-id>.
- if (alreadyExists)
- return id;
- // Emit OpName for the type (if any).
- emitNameForType(type->getName(), id);
- if (isa<VoidType>(type)) {
- initTypeInstruction(spv::Op::OpTypeVoid);
- curTypeInst.push_back(id);
- finalizeTypeInstruction();
- }
- // Boolean types
- else if (isa<BoolType>(type)) {
- initTypeInstruction(spv::Op::OpTypeBool);
- curTypeInst.push_back(id);
- finalizeTypeInstruction();
- }
- // Integer types
- else if (const auto *intType = dyn_cast<IntegerType>(type)) {
- initTypeInstruction(spv::Op::OpTypeInt);
- curTypeInst.push_back(id);
- curTypeInst.push_back(intType->getBitwidth());
- curTypeInst.push_back(intType->isSignedInt() ? 1 : 0);
- finalizeTypeInstruction();
- }
- // Float types
- else if (const auto *floatType = dyn_cast<FloatType>(type)) {
- initTypeInstruction(spv::Op::OpTypeFloat);
- curTypeInst.push_back(id);
- curTypeInst.push_back(floatType->getBitwidth());
- finalizeTypeInstruction();
- }
- // Vector types
- else if (const auto *vecType = dyn_cast<VectorType>(type)) {
- const uint32_t elementTypeId = emitType(vecType->getElementType());
- initTypeInstruction(spv::Op::OpTypeVector);
- curTypeInst.push_back(id);
- curTypeInst.push_back(elementTypeId);
- curTypeInst.push_back(vecType->getElementCount());
- finalizeTypeInstruction();
- }
- // Matrix types
- else if (const auto *matType = dyn_cast<MatrixType>(type)) {
- const uint32_t vecTypeId = emitType(matType->getVecType());
- initTypeInstruction(spv::Op::OpTypeMatrix);
- curTypeInst.push_back(id);
- curTypeInst.push_back(vecTypeId);
- curTypeInst.push_back(matType->getVecCount());
- finalizeTypeInstruction();
- // Note that RowMajor and ColMajor decorations only apply to structure
- // members, and should not be handled here.
- }
- // Image types
- else if (const auto *imageType = dyn_cast<ImageType>(type)) {
- const uint32_t sampledTypeId = emitType(imageType->getSampledType());
- initTypeInstruction(spv::Op::OpTypeImage);
- curTypeInst.push_back(id);
- curTypeInst.push_back(sampledTypeId);
- curTypeInst.push_back(static_cast<uint32_t>(imageType->getDimension()));
- curTypeInst.push_back(static_cast<uint32_t>(imageType->getDepth()));
- curTypeInst.push_back(imageType->isArrayedImage() ? 1 : 0);
- curTypeInst.push_back(imageType->isMSImage() ? 1 : 0);
- curTypeInst.push_back(static_cast<uint32_t>(imageType->withSampler()));
- curTypeInst.push_back(static_cast<uint32_t>(imageType->getImageFormat()));
- finalizeTypeInstruction();
- }
- // Sampler types
- else if (const auto *samplerType = dyn_cast<SamplerType>(type)) {
- initTypeInstruction(spv::Op::OpTypeSampler);
- curTypeInst.push_back(id);
- finalizeTypeInstruction();
- }
- // SampledImage types
- else if (const auto *sampledImageType = dyn_cast<SampledImageType>(type)) {
- const uint32_t imageTypeId = emitType(sampledImageType->getImageType());
- initTypeInstruction(spv::Op::OpTypeSampledImage);
- curTypeInst.push_back(id);
- curTypeInst.push_back(imageTypeId);
- finalizeTypeInstruction();
- }
- // Array types
- else if (const auto *arrayType = dyn_cast<ArrayType>(type)) {
- // Emit the OpConstant instruction that is needed to get the result-id for
- // the array length.
- const auto length = getOrCreateConstantInt(
- llvm::APInt(32, arrayType->getElementCount()), context.getUIntType(32),
- /* isSpecConst */ false);
- // Emit the OpTypeArray instruction
- const uint32_t elemTypeId = emitType(arrayType->getElementType());
- initTypeInstruction(spv::Op::OpTypeArray);
- curTypeInst.push_back(id);
- curTypeInst.push_back(elemTypeId);
- curTypeInst.push_back(length);
- finalizeTypeInstruction();
- auto stride = arrayType->getStride();
- if (stride.hasValue())
- emitDecoration(id, spv::Decoration::ArrayStride, {stride.getValue()});
- }
- // RuntimeArray types
- else if (const auto *raType = dyn_cast<RuntimeArrayType>(type)) {
- const uint32_t elemTypeId = emitType(raType->getElementType());
- initTypeInstruction(spv::Op::OpTypeRuntimeArray);
- curTypeInst.push_back(id);
- curTypeInst.push_back(elemTypeId);
- finalizeTypeInstruction();
- auto stride = raType->getStride();
- if (stride.hasValue())
- emitDecoration(id, spv::Decoration::ArrayStride, {stride.getValue()});
- }
- // Structure types
- else if (const auto *structType = dyn_cast<StructType>(type)) {
- llvm::ArrayRef<StructType::FieldInfo> fields = structType->getFields();
- size_t numFields = fields.size();
- // Emit OpMemberName for the struct members.
- for (size_t i = 0; i < numFields; ++i)
- emitNameForType(fields[i].name, id, i);
- llvm::SmallVector<uint32_t, 4> fieldTypeIds;
- for (auto &field : fields) {
- fieldTypeIds.push_back(emitType(field.type));
- }
- for (size_t i = 0; i < numFields; ++i) {
- auto &field = fields[i];
- // Offset decorations
- if (field.offset.hasValue())
- emitDecoration(id, spv::Decoration::Offset, {field.offset.getValue()},
- i);
- // MatrixStride decorations
- if (field.matrixStride.hasValue())
- emitDecoration(id, spv::Decoration::MatrixStride,
- {field.matrixStride.getValue()}, i);
- // RowMajor/ColMajor decorations
- if (field.isRowMajor.hasValue())
- emitDecoration(id,
- field.isRowMajor.getValue() ? spv::Decoration::RowMajor
- : spv::Decoration::ColMajor,
- {}, i);
- // RelaxedPrecision decorations
- if (field.isRelaxedPrecision)
- emitDecoration(id, spv::Decoration::RelaxedPrecision, {}, i);
- // NonWritable decorations
- if (structType->isReadOnly())
- emitDecoration(id, spv::Decoration::NonWritable, {}, i);
- }
- // Emit Block or BufferBlock decorations if necessary.
- auto interfaceType = structType->getInterfaceType();
- if (interfaceType == StructInterfaceType::StorageBuffer)
- // BufferBlock decoration is deprecated in Vulkan 1.2 and later.
- emitDecoration(id,
- featureManager.isTargetEnvVulkan1p2OrAbove()
- ? spv::Decoration::Block
- : spv::Decoration::BufferBlock,
- {});
- else if (interfaceType == StructInterfaceType::UniformBuffer)
- emitDecoration(id, spv::Decoration::Block, {});
- initTypeInstruction(spv::Op::OpTypeStruct);
- curTypeInst.push_back(id);
- for (auto fieldTypeId : fieldTypeIds)
- curTypeInst.push_back(fieldTypeId);
- finalizeTypeInstruction();
- }
- // Pointer types
- else if (const auto *ptrType = dyn_cast<SpirvPointerType>(type)) {
- const uint32_t pointeeType = emitType(ptrType->getPointeeType());
- initTypeInstruction(spv::Op::OpTypePointer);
- curTypeInst.push_back(id);
- curTypeInst.push_back(static_cast<uint32_t>(ptrType->getStorageClass()));
- curTypeInst.push_back(pointeeType);
- finalizeTypeInstruction();
- }
- // Function types
- else if (const auto *fnType = dyn_cast<FunctionType>(type)) {
- const uint32_t retTypeId = emitType(fnType->getReturnType());
- llvm::SmallVector<uint32_t, 4> paramTypeIds;
- for (auto *paramType : fnType->getParamTypes())
- paramTypeIds.push_back(emitType(paramType));
- initTypeInstruction(spv::Op::OpTypeFunction);
- curTypeInst.push_back(id);
- curTypeInst.push_back(retTypeId);
- for (auto paramTypeId : paramTypeIds)
- curTypeInst.push_back(paramTypeId);
- finalizeTypeInstruction();
- }
- // Acceleration Structure NV type
- else if (const auto *accType = dyn_cast<AccelerationStructureTypeNV>(type)) {
- initTypeInstruction(spv::Op::OpTypeAccelerationStructureNV);
- curTypeInst.push_back(id);
- finalizeTypeInstruction();
- }
- // RayQueryType KHR type
- else if (const auto *rayQueryType =
- dyn_cast<RayQueryTypeKHR>(type)) {
- initTypeInstruction(spv::Op::OpTypeRayQueryKHR);
- curTypeInst.push_back(id);
- finalizeTypeInstruction();
- }
- // Hybrid Types
- // Note: The type lowering pass should lower all types to SpirvTypes.
- // Therefore, if we find a hybrid type when going through the emitting pass,
- // that is clearly a bug.
- else if (const auto *hybridType = dyn_cast<HybridType>(type)) {
- llvm_unreachable("found hybrid type when emitting SPIR-V");
- }
- // Unhandled types
- else {
- llvm_unreachable("unhandled type in emitType");
- }
- return id;
- }
- void EmitTypeHandler::emitDecoration(uint32_t typeResultId,
- spv::Decoration decoration,
- llvm::ArrayRef<uint32_t> decorationParams,
- llvm::Optional<uint32_t> memberIndex) {
- spv::Op op =
- memberIndex.hasValue() ? spv::Op::OpMemberDecorate : spv::Op::OpDecorate;
- if (decoration == spv::Decoration::UserTypeGOOGLE) {
- op = memberIndex.hasValue() ? spv::Op::OpMemberDecorateString
- : spv::Op::OpDecorateString;
- }
- assert(curDecorationInst.empty());
- curDecorationInst.push_back(static_cast<uint32_t>(op));
- curDecorationInst.push_back(typeResultId);
- if (memberIndex.hasValue())
- curDecorationInst.push_back(memberIndex.getValue());
- curDecorationInst.push_back(static_cast<uint32_t>(decoration));
- for (auto param : decorationParams)
- curDecorationInst.push_back(param);
- curDecorationInst[0] |= static_cast<uint32_t>(curDecorationInst.size()) << 16;
- // Add to the full annotations list
- annotationsBinary->insert(annotationsBinary->end(), curDecorationInst.begin(),
- curDecorationInst.end());
- curDecorationInst.clear();
- }
- void EmitTypeHandler::emitNameForType(llvm::StringRef name,
- uint32_t targetTypeId,
- llvm::Optional<uint32_t> memberIndex) {
- if (name.empty())
- return;
- std::vector<uint32_t> nameInstr;
- auto op = memberIndex.hasValue() ? spv::Op::OpMemberName : spv::Op::OpName;
- nameInstr.push_back(static_cast<uint32_t>(op));
- nameInstr.push_back(targetTypeId);
- if (memberIndex.hasValue())
- nameInstr.push_back(memberIndex.getValue());
- const auto &words = string::encodeSPIRVString(name);
- nameInstr.insert(nameInstr.end(), words.begin(), words.end());
- nameInstr[0] |= static_cast<uint32_t>(nameInstr.size()) << 16;
- debugVariableBinary->insert(debugVariableBinary->end(), nameInstr.begin(),
- nameInstr.end());
- }
- } // end namespace spirv
- } // end namespace clang
|