| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740 |
- //===--- 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 "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")
- return 0x00010500u;
- return 0x00010000u;
- }
- // Returns true if the BufferBlock decoration is deprecated for the target
- // Vulkan environment.
- bool isBufferBlockDecorationDeprecated(
- const clang::spirv::SpirvCodeGenOptions &opts) {
- return opts.targetEnv.compare("vulkan1.2") >= 0;
- }
- 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) {}
- 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;
- }
- 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) {
- // 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;
- return;
- }
- if (op == spv::Op::OpSelectionMerge || op == spv::Op::OpLoopMerge)
- lastOpWasMergeInst = true;
- if (!isOpLineLegalForOp(op))
- return;
- if (!spvOptions.debugInfoLine)
- return;
- auto fileId = debugMainFileId;
- const auto &sm = astContext.getSourceManager();
- const char *fileName = sm.getPresumedLoc(loc).getFilename();
- if (fileName) {
- auto it = debugFileIdMap.find(fileName);
- if (it == debugFileIdMap.end()) {
- // Emit the OpString for this new fileName.
- SpirvString *inst =
- new (context) SpirvString(/*SourceLocation*/ {}, fileName);
- visit(inst);
- it = debugFileIdMap.find(fileName);
- }
- fileId = it->second;
- }
- if (!fileId) {
- emitError("spvOptions.debugInfoLine is true but no fileId was set");
- return;
- }
- uint32_t line = sm.getPresumedLineNumber(loc);
- uint32_t column = sm.getPresumedColumnNumber(loc);
- if (!line || !column)
- return;
- if (line == debugLine && column == debugColumn)
- return;
- // We must update these two values to emit the next 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;
- mainBinary.insert(mainBinary.end(), curInst.begin(), curInst.end());
- }
- 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, {});
- }
- const auto op = inst->getopcode();
- emitDebugLine(op, inst->getSourceLocation());
- // 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);
- curInst.clear();
- curInst.push_back(static_cast<uint32_t>(op));
- }
- void EmitVisitor::finalizeInstruction() {
- const auto op = static_cast<spv::Op>(curInst[0]);
- curInst[0] |= static_cast<uint32_t>(curInst.size()) << 16;
- switch (op) {
- 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:
- preambleBinary.insert(preambleBinary.end(), curInst.begin(), curInst.end());
- break;
- case spv::Op::OpString:
- case spv::Op::OpSource:
- case spv::Op::OpSourceExtension:
- case spv::Op::OpSourceContinued:
- debugFileBinary.insert(debugFileBinary.end(), curInst.begin(),
- curInst.end());
- break;
- case spv::Op::OpName:
- case spv::Op::OpMemberName:
- debugVariableBinary.insert(debugVariableBinary.end(), curInst.begin(),
- curInst.end());
- break;
- 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:
- annotationsBinary.insert(annotationsBinary.end(), curInst.begin(),
- curInst.end());
- break;
- case spv::Op::OpConstant:
- case spv::Op::OpConstantNull:
- case spv::Op::OpConstantFalse:
- case spv::Op::OpConstantTrue:
- case spv::Op::OpSpecConstantTrue:
- case spv::Op::OpSpecConstantFalse:
- case spv::Op::OpSpecConstant:
- case spv::Op::OpSpecConstantOp:
- typeConstantBinary.insert(typeConstantBinary.end(), curInst.begin(),
- curInst.end());
- break;
- default:
- mainBinary.insert(mainBinary.end(), curInst.begin(), curInst.end());
- break;
- }
- }
- 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(), 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());
- // Emit OpFunction
- initInstruction(spv::Op::OpFunction, fn->getSourceLocation());
- curInst.push_back(returnTypeId);
- curInst.push_back(getOrAssignResultId<SpirvFunction>(fn));
- curInst.push_back(
- static_cast<uint32_t>(spv::FunctionControlMask::MaskNone));
- curInst.push_back(functionTypeId);
- finalizeInstruction();
- 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();
- }
- 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();
- 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();
- return true;
- }
- bool EmitVisitor::visit(SpirvExtension *ext) {
- initInstruction(ext);
- encodeString(ext->getExtensionName());
- finalizeInstruction();
- return true;
- }
- bool EmitVisitor::visit(SpirvExtInstImport *inst) {
- initInstruction(inst);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- encodeString(inst->getExtendedInstSetName());
- finalizeInstruction();
- 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();
- 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();
- 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();
- return true;
- }
- bool EmitVisitor::visit(SpirvString *inst) {
- initInstruction(inst);
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst));
- encodeString(inst->getString());
- finalizeInstruction();
- if (spvOptions.debugInfoLine) {
- if (debugFileIdMap.find(inst->getString()) != debugFileIdMap.end())
- return true;
- debugFileIdMap[inst->getString()] =
- getOrAssignResultId<SpirvInstruction>(inst);
- }
- return true;
- }
- bool EmitVisitor::visit(SpirvSource *inst) {
- // Emit the OpString for the file name.
- if (inst->hasFile()) {
- visit(inst->getFile());
- if (spvOptions.debugInfoLine && !debugMainFileId)
- debugMainFileId = debugFileIdMap[inst->getFile()->getString()];
- }
- // 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 (!inst->getSource().empty()) {
- chopString(inst->getSource(), &choppedSrcCode);
- if (!choppedSrcCode.empty()) {
- firstSnippet = llvm::Optional<llvm::StringRef>(choppedSrcCode.front());
- }
- }
- initInstruction(inst);
- curInst.push_back(static_cast<uint32_t>(inst->getSourceLanguage()));
- curInst.push_back(static_cast<uint32_t>(inst->getVersion()));
- if (inst->hasFile()) {
- curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getFile()));
- }
- 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());
- }
- // 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- return true;
- }
- bool EmitVisitor::visit(SpirvBranch *inst) {
- initInstruction(inst);
- curInst.push_back(
- getOrAssignResultId<SpirvBasicBlock>(inst->getTargetLabel()));
- finalizeInstruction();
- 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();
- return true;
- }
- bool EmitVisitor::visit(SpirvKill *inst) {
- initInstruction(inst);
- finalizeInstruction();
- return true;
- }
- bool EmitVisitor::visit(SpirvReturn *inst) {
- initInstruction(inst);
- if (inst->hasReturnValue()) {
- curInst.push_back(
- getOrAssignResultId<SpirvInstruction>(inst->getReturnValue()));
- }
- finalizeInstruction();
- 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();
- return true;
- }
- bool EmitVisitor::visit(SpirvUnreachable *inst) {
- initInstruction(inst);
- finalizeInstruction();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvEmitVertex *inst) {
- initInstruction(inst);
- finalizeInstruction();
- return true;
- }
- bool EmitVisitor::visit(SpirvEndPrimitive *inst) {
- initInstruction(inst);
- finalizeInstruction();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- 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();
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- return true;
- }
- bool EmitVisitor::visit(SpirvDemoteToHelperInvocationEXT *inst) {
- initInstruction(inst);
- finalizeInstruction();
- 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();
- emitDebugNameForInstruction(getOrAssignResultId<SpirvInstruction>(inst),
- inst->getDebugName());
- 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)
- emitDecoration(id,
- isBufferBlockDecorationDeprecated(spvOptions)
- ? 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();
- }
- // RayQueryProvisionalType KHR type
- else if (const auto *rayQueryType =
- dyn_cast<RayQueryProvisionalTypeKHR>(type)) {
- initTypeInstruction(spv::Op::OpTypeRayQueryProvisionalKHR);
- 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
|