Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
35266 views
//===-- SPIRVAsmPrinter.cpp - SPIR-V LLVM assembly writer ------*- C++ -*--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a printer that converts from our internal representation9// of machine-dependent LLVM code to the SPIR-V assembly language.10//11//===----------------------------------------------------------------------===//1213#include "MCTargetDesc/SPIRVInstPrinter.h"14#include "SPIRV.h"15#include "SPIRVInstrInfo.h"16#include "SPIRVMCInstLower.h"17#include "SPIRVModuleAnalysis.h"18#include "SPIRVSubtarget.h"19#include "SPIRVTargetMachine.h"20#include "SPIRVUtils.h"21#include "TargetInfo/SPIRVTargetInfo.h"22#include "llvm/ADT/DenseMap.h"23#include "llvm/Analysis/ValueTracking.h"24#include "llvm/CodeGen/AsmPrinter.h"25#include "llvm/CodeGen/MachineConstantPool.h"26#include "llvm/CodeGen/MachineFunctionPass.h"27#include "llvm/CodeGen/MachineInstr.h"28#include "llvm/CodeGen/MachineModuleInfo.h"29#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"30#include "llvm/MC/MCAsmInfo.h"31#include "llvm/MC/MCAssembler.h"32#include "llvm/MC/MCInst.h"33#include "llvm/MC/MCObjectStreamer.h"34#include "llvm/MC/MCSPIRVObjectWriter.h"35#include "llvm/MC/MCStreamer.h"36#include "llvm/MC/MCSymbol.h"37#include "llvm/MC/TargetRegistry.h"38#include "llvm/Support/raw_ostream.h"3940using namespace llvm;4142#define DEBUG_TYPE "asm-printer"4344namespace {45class SPIRVAsmPrinter : public AsmPrinter {46unsigned NLabels = 0;4748public:49explicit SPIRVAsmPrinter(TargetMachine &TM,50std::unique_ptr<MCStreamer> Streamer)51: AsmPrinter(TM, std::move(Streamer)), ST(nullptr), TII(nullptr) {}52bool ModuleSectionsEmitted;53const SPIRVSubtarget *ST;54const SPIRVInstrInfo *TII;5556StringRef getPassName() const override { return "SPIRV Assembly Printer"; }57void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);58bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,59const char *ExtraCode, raw_ostream &O) override;6061void outputMCInst(MCInst &Inst);62void outputInstruction(const MachineInstr *MI);63void outputModuleSection(SPIRV::ModuleSectionType MSType);64void outputGlobalRequirements();65void outputEntryPoints();66void outputDebugSourceAndStrings(const Module &M);67void outputOpExtInstImports(const Module &M);68void outputOpMemoryModel();69void outputOpFunctionEnd();70void outputExtFuncDecls();71void outputExecutionModeFromMDNode(Register Reg, MDNode *Node,72SPIRV::ExecutionMode::ExecutionMode EM,73unsigned ExpectMDOps, int64_t DefVal);74void outputExecutionModeFromNumthreadsAttribute(75const Register &Reg, const Attribute &Attr,76SPIRV::ExecutionMode::ExecutionMode EM);77void outputExecutionMode(const Module &M);78void outputAnnotations(const Module &M);79void outputModuleSections();8081void emitInstruction(const MachineInstr *MI) override;82void emitFunctionEntryLabel() override {}83void emitFunctionHeader() override;84void emitFunctionBodyStart() override {}85void emitFunctionBodyEnd() override;86void emitBasicBlockStart(const MachineBasicBlock &MBB) override;87void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}88void emitGlobalVariable(const GlobalVariable *GV) override {}89void emitOpLabel(const MachineBasicBlock &MBB);90void emitEndOfAsmFile(Module &M) override;91bool doInitialization(Module &M) override;9293void getAnalysisUsage(AnalysisUsage &AU) const override;94SPIRV::ModuleAnalysisInfo *MAI;95};96} // namespace9798void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {99AU.addRequired<SPIRVModuleAnalysis>();100AU.addPreserved<SPIRVModuleAnalysis>();101AsmPrinter::getAnalysisUsage(AU);102}103104// If the module has no functions, we need output global info anyway.105void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {106if (ModuleSectionsEmitted == false) {107outputModuleSections();108ModuleSectionsEmitted = true;109}110111ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();112VersionTuple SPIRVVersion = ST->getSPIRVVersion();113uint32_t Major = SPIRVVersion.getMajor();114uint32_t Minor = SPIRVVersion.getMinor().value_or(0);115// Bound is an approximation that accounts for the maximum used register116// number and number of generated OpLabels117unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;118if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())119static_cast<SPIRVObjectWriter &>(Asm->getWriter())120.setBuildVersion(Major, Minor, Bound);121}122123void SPIRVAsmPrinter::emitFunctionHeader() {124if (ModuleSectionsEmitted == false) {125outputModuleSections();126ModuleSectionsEmitted = true;127}128// Get the subtarget from the current MachineFunction.129ST = &MF->getSubtarget<SPIRVSubtarget>();130TII = ST->getInstrInfo();131const Function &F = MF->getFunction();132133if (isVerbose()) {134OutStreamer->getCommentOS()135<< "-- Begin function "136<< GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';137}138139auto Section = getObjFileLowering().SectionForGlobal(&F, TM);140MF->setSection(Section);141}142143void SPIRVAsmPrinter::outputOpFunctionEnd() {144MCInst FunctionEndInst;145FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd);146outputMCInst(FunctionEndInst);147}148149// Emit OpFunctionEnd at the end of MF and clear BBNumToRegMap.150void SPIRVAsmPrinter::emitFunctionBodyEnd() {151outputOpFunctionEnd();152MAI->BBNumToRegMap.clear();153}154155void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {156MCInst LabelInst;157LabelInst.setOpcode(SPIRV::OpLabel);158LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));159outputMCInst(LabelInst);160++NLabels;161}162163void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {164assert(!MBB.empty() && "MBB is empty!");165166// If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so167// OpLabel should be output after them.168if (MBB.getNumber() == MF->front().getNumber()) {169for (const MachineInstr &MI : MBB)170if (MI.getOpcode() == SPIRV::OpFunction)171return;172// TODO: this case should be checked by the verifier.173report_fatal_error("OpFunction is expected in the front MBB of MF");174}175emitOpLabel(MBB);176}177178void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,179raw_ostream &O) {180const MachineOperand &MO = MI->getOperand(OpNum);181182switch (MO.getType()) {183case MachineOperand::MO_Register:184O << SPIRVInstPrinter::getRegisterName(MO.getReg());185break;186187case MachineOperand::MO_Immediate:188O << MO.getImm();189break;190191case MachineOperand::MO_FPImmediate:192O << MO.getFPImm();193break;194195case MachineOperand::MO_MachineBasicBlock:196O << *MO.getMBB()->getSymbol();197break;198199case MachineOperand::MO_GlobalAddress:200O << *getSymbol(MO.getGlobal());201break;202203case MachineOperand::MO_BlockAddress: {204MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());205O << BA->getName();206break;207}208209case MachineOperand::MO_ExternalSymbol:210O << *GetExternalSymbolSymbol(MO.getSymbolName());211break;212213case MachineOperand::MO_JumpTableIndex:214case MachineOperand::MO_ConstantPoolIndex:215default:216llvm_unreachable("<unknown operand type>");217}218}219220bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,221const char *ExtraCode, raw_ostream &O) {222if (ExtraCode && ExtraCode[0])223return true; // Invalid instruction - SPIR-V does not have special modifiers224225printOperand(MI, OpNo, O);226return false;227}228229static bool isFuncOrHeaderInstr(const MachineInstr *MI,230const SPIRVInstrInfo *TII) {231return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction ||232MI->getOpcode() == SPIRV::OpFunctionParameter;233}234235void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) {236OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());237}238239void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) {240SPIRVMCInstLower MCInstLowering;241MCInst TmpInst;242MCInstLowering.lower(MI, TmpInst, MAI);243outputMCInst(TmpInst);244}245246void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {247SPIRV_MC::verifyInstructionPredicates(MI->getOpcode(),248getSubtargetInfo().getFeatureBits());249250if (!MAI->getSkipEmission(MI))251outputInstruction(MI);252253// Output OpLabel after OpFunction and OpFunctionParameter in the first MBB.254const MachineInstr *NextMI = MI->getNextNode();255if (!MAI->hasMBBRegister(*MI->getParent()) && isFuncOrHeaderInstr(MI, TII) &&256(!NextMI || !isFuncOrHeaderInstr(NextMI, TII))) {257assert(MI->getParent()->getNumber() == MF->front().getNumber() &&258"OpFunction is not in the front MBB of MF");259emitOpLabel(*MI->getParent());260}261}262263void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) {264for (MachineInstr *MI : MAI->getMSInstrs(MSType))265outputInstruction(MI);266}267268void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {269// Output OpSourceExtensions.270for (auto &Str : MAI->SrcExt) {271MCInst Inst;272Inst.setOpcode(SPIRV::OpSourceExtension);273addStringImm(Str.first(), Inst);274outputMCInst(Inst);275}276// Output OpSource.277MCInst Inst;278Inst.setOpcode(SPIRV::OpSource);279Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang)));280Inst.addOperand(281MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion)));282outputMCInst(Inst);283}284285void SPIRVAsmPrinter::outputOpExtInstImports(const Module &M) {286for (auto &CU : MAI->ExtInstSetMap) {287unsigned Set = CU.first;288Register Reg = CU.second;289MCInst Inst;290Inst.setOpcode(SPIRV::OpExtInstImport);291Inst.addOperand(MCOperand::createReg(Reg));292addStringImm(getExtInstSetName(293static_cast<SPIRV::InstructionSet::InstructionSet>(Set)),294Inst);295outputMCInst(Inst);296}297}298299void SPIRVAsmPrinter::outputOpMemoryModel() {300MCInst Inst;301Inst.setOpcode(SPIRV::OpMemoryModel);302Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr)));303Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem)));304outputMCInst(Inst);305}306307// Before the OpEntryPoints' output, we need to add the entry point's308// interfaces. The interface is a list of IDs of global OpVariable instructions.309// These declare the set of global variables from a module that form310// the interface of this entry point.311void SPIRVAsmPrinter::outputEntryPoints() {312// Find all OpVariable IDs with required StorageClass.313DenseSet<Register> InterfaceIDs;314for (MachineInstr *MI : MAI->GlobalVarList) {315assert(MI->getOpcode() == SPIRV::OpVariable);316auto SC = static_cast<SPIRV::StorageClass::StorageClass>(317MI->getOperand(2).getImm());318// Before version 1.4, the interface's storage classes are limited to319// the Input and Output storage classes. Starting with version 1.4,320// the interface's storage classes are all storage classes used in321// declaring all global variables referenced by the entry point call tree.322if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) ||323SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) {324MachineFunction *MF = MI->getMF();325Register Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());326InterfaceIDs.insert(Reg);327}328}329330// Output OpEntryPoints adding interface args to all of them.331for (MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) {332SPIRVMCInstLower MCInstLowering;333MCInst TmpInst;334MCInstLowering.lower(MI, TmpInst, MAI);335for (Register Reg : InterfaceIDs) {336assert(Reg.isValid());337TmpInst.addOperand(MCOperand::createReg(Reg));338}339outputMCInst(TmpInst);340}341}342343// Create global OpCapability instructions for the required capabilities.344void SPIRVAsmPrinter::outputGlobalRequirements() {345// Abort here if not all requirements can be satisfied.346MAI->Reqs.checkSatisfiable(*ST);347348for (const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {349MCInst Inst;350Inst.setOpcode(SPIRV::OpCapability);351Inst.addOperand(MCOperand::createImm(Cap));352outputMCInst(Inst);353}354355// Generate the final OpExtensions with strings instead of enums.356for (const auto &Ext : MAI->Reqs.getExtensions()) {357MCInst Inst;358Inst.setOpcode(SPIRV::OpExtension);359addStringImm(getSymbolicOperandMnemonic(360SPIRV::OperandCategory::ExtensionOperand, Ext),361Inst);362outputMCInst(Inst);363}364// TODO add a pseudo instr for version number.365}366367void SPIRVAsmPrinter::outputExtFuncDecls() {368// Insert OpFunctionEnd after each declaration.369SmallVectorImpl<MachineInstr *>::iterator370I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(),371E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end();372for (; I != E; ++I) {373outputInstruction(*I);374if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction)375outputOpFunctionEnd();376}377}378379// Encode LLVM type by SPIR-V execution mode VecTypeHint.380static unsigned encodeVecTypeHint(Type *Ty) {381if (Ty->isHalfTy())382return 4;383if (Ty->isFloatTy())384return 5;385if (Ty->isDoubleTy())386return 6;387if (IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {388switch (IntTy->getIntegerBitWidth()) {389case 8:390return 0;391case 16:392return 1;393case 32:394return 2;395case 64:396return 3;397default:398llvm_unreachable("invalid integer type");399}400}401if (FixedVectorType *VecTy = dyn_cast<FixedVectorType>(Ty)) {402Type *EleTy = VecTy->getElementType();403unsigned Size = VecTy->getNumElements();404return Size << 16 | encodeVecTypeHint(EleTy);405}406llvm_unreachable("invalid type");407}408409static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst,410SPIRV::ModuleAnalysisInfo *MAI) {411for (const MDOperand &MDOp : MDN->operands()) {412if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {413Constant *C = CMeta->getValue();414if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {415Inst.addOperand(MCOperand::createImm(Const->getZExtValue()));416} else if (auto *CE = dyn_cast<Function>(C)) {417Register FuncReg = MAI->getFuncReg(CE);418assert(FuncReg.isValid());419Inst.addOperand(MCOperand::createReg(FuncReg));420}421}422}423}424425void SPIRVAsmPrinter::outputExecutionModeFromMDNode(426Register Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM,427unsigned ExpectMDOps, int64_t DefVal) {428MCInst Inst;429Inst.setOpcode(SPIRV::OpExecutionMode);430Inst.addOperand(MCOperand::createReg(Reg));431Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));432addOpsFromMDNode(Node, Inst, MAI);433// reqd_work_group_size and work_group_size_hint require 3 operands,434// if metadata contains less operands, just add a default value435unsigned NodeSz = Node->getNumOperands();436if (ExpectMDOps > 0 && NodeSz < ExpectMDOps)437for (unsigned i = NodeSz; i < ExpectMDOps; ++i)438Inst.addOperand(MCOperand::createImm(DefVal));439outputMCInst(Inst);440}441442void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(443const Register &Reg, const Attribute &Attr,444SPIRV::ExecutionMode::ExecutionMode EM) {445assert(Attr.isValid() && "Function called with an invalid attribute.");446447MCInst Inst;448Inst.setOpcode(SPIRV::OpExecutionMode);449Inst.addOperand(MCOperand::createReg(Reg));450Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));451452SmallVector<StringRef> NumThreads;453Attr.getValueAsString().split(NumThreads, ',');454assert(NumThreads.size() == 3 && "invalid numthreads");455for (uint32_t i = 0; i < 3; ++i) {456uint32_t V;457[[maybe_unused]] bool Result = NumThreads[i].getAsInteger(10, V);458assert(!Result && "Failed to parse numthreads");459Inst.addOperand(MCOperand::createImm(V));460}461462outputMCInst(Inst);463}464465void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {466NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode");467if (Node) {468for (unsigned i = 0; i < Node->getNumOperands(); i++) {469MCInst Inst;470Inst.setOpcode(SPIRV::OpExecutionMode);471addOpsFromMDNode(cast<MDNode>(Node->getOperand(i)), Inst, MAI);472outputMCInst(Inst);473}474}475for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {476const Function &F = *FI;477// Only operands of OpEntryPoint instructions are allowed to be478// <Entry Point> operands of OpExecutionMode479if (F.isDeclaration() || !isEntryPoint(F))480continue;481Register FReg = MAI->getFuncReg(&F);482assert(FReg.isValid());483if (MDNode *Node = F.getMetadata("reqd_work_group_size"))484outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize,4853, 1);486if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid())487outputExecutionModeFromNumthreadsAttribute(488FReg, Attr, SPIRV::ExecutionMode::LocalSize);489if (MDNode *Node = F.getMetadata("work_group_size_hint"))490outputExecutionModeFromMDNode(FReg, Node,491SPIRV::ExecutionMode::LocalSizeHint, 3, 1);492if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size"))493outputExecutionModeFromMDNode(FReg, Node,494SPIRV::ExecutionMode::SubgroupSize, 0, 0);495if (MDNode *Node = F.getMetadata("vec_type_hint")) {496MCInst Inst;497Inst.setOpcode(SPIRV::OpExecutionMode);498Inst.addOperand(MCOperand::createReg(FReg));499unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);500Inst.addOperand(MCOperand::createImm(EM));501unsigned TypeCode = encodeVecTypeHint(getMDOperandAsType(Node, 0));502Inst.addOperand(MCOperand::createImm(TypeCode));503outputMCInst(Inst);504}505if (ST->isOpenCLEnv() && !M.getNamedMetadata("spirv.ExecutionMode") &&506!M.getNamedMetadata("opencl.enable.FP_CONTRACT")) {507MCInst Inst;508Inst.setOpcode(SPIRV::OpExecutionMode);509Inst.addOperand(MCOperand::createReg(FReg));510unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::ContractionOff);511Inst.addOperand(MCOperand::createImm(EM));512outputMCInst(Inst);513}514}515}516517void SPIRVAsmPrinter::outputAnnotations(const Module &M) {518outputModuleSection(SPIRV::MB_Annotations);519// Process llvm.global.annotations special global variable.520for (auto F = M.global_begin(), E = M.global_end(); F != E; ++F) {521if ((*F).getName() != "llvm.global.annotations")522continue;523const GlobalVariable *V = &(*F);524const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));525for (Value *Op : CA->operands()) {526ConstantStruct *CS = cast<ConstantStruct>(Op);527// The first field of the struct contains a pointer to528// the annotated variable.529Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();530if (!isa<Function>(AnnotatedVar))531report_fatal_error("Unsupported value in llvm.global.annotations");532Function *Func = cast<Function>(AnnotatedVar);533Register Reg = MAI->getFuncReg(Func);534if (!Reg.isValid()) {535std::string DiagMsg;536raw_string_ostream OS(DiagMsg);537AnnotatedVar->print(OS);538DiagMsg = "Unknown function in llvm.global.annotations: " + DiagMsg;539report_fatal_error(DiagMsg.c_str());540}541542// The second field contains a pointer to a global annotation string.543GlobalVariable *GV =544cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());545546StringRef AnnotationString;547getConstantStringInfo(GV, AnnotationString);548MCInst Inst;549Inst.setOpcode(SPIRV::OpDecorate);550Inst.addOperand(MCOperand::createReg(Reg));551unsigned Dec = static_cast<unsigned>(SPIRV::Decoration::UserSemantic);552Inst.addOperand(MCOperand::createImm(Dec));553addStringImm(AnnotationString, Inst);554outputMCInst(Inst);555}556}557}558559void SPIRVAsmPrinter::outputModuleSections() {560const Module *M = MMI->getModule();561// Get the global subtarget to output module-level info.562ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();563TII = ST->getInstrInfo();564MAI = &SPIRVModuleAnalysis::MAI;565assert(ST && TII && MAI && M && "Module analysis is required");566// Output instructions according to the Logical Layout of a Module:567// 1,2. All OpCapability instructions, then optional OpExtension instructions.568outputGlobalRequirements();569// 3. Optional OpExtInstImport instructions.570outputOpExtInstImports(*M);571// 4. The single required OpMemoryModel instruction.572outputOpMemoryModel();573// 5. All entry point declarations, using OpEntryPoint.574outputEntryPoints();575// 6. Execution-mode declarations, using OpExecutionMode or OpExecutionModeId.576outputExecutionMode(*M);577// 7a. Debug: all OpString, OpSourceExtension, OpSource, and578// OpSourceContinued, without forward references.579outputDebugSourceAndStrings(*M);580// 7b. Debug: all OpName and all OpMemberName.581outputModuleSection(SPIRV::MB_DebugNames);582// 7c. Debug: all OpModuleProcessed instructions.583outputModuleSection(SPIRV::MB_DebugModuleProcessed);584// 8. All annotation instructions (all decorations).585outputAnnotations(*M);586// 9. All type declarations (OpTypeXXX instructions), all constant587// instructions, and all global variable declarations. This section is588// the first section to allow use of: OpLine and OpNoLine debug information;589// non-semantic instructions with OpExtInst.590outputModuleSection(SPIRV::MB_TypeConstVars);591// 10. All function declarations (functions without a body).592outputExtFuncDecls();593// 11. All function definitions (functions with a body).594// This is done in regular function output.595}596597bool SPIRVAsmPrinter::doInitialization(Module &M) {598ModuleSectionsEmitted = false;599// We need to call the parent's one explicitly.600return AsmPrinter::doInitialization(M);601}602603// Force static initialization.604extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVAsmPrinter() {605RegisterAsmPrinter<SPIRVAsmPrinter> X(getTheSPIRV32Target());606RegisterAsmPrinter<SPIRVAsmPrinter> Y(getTheSPIRV64Target());607RegisterAsmPrinter<SPIRVAsmPrinter> Z(getTheSPIRVLogicalTarget());608}609610611