1*81ad6265SDimitry Andric //===-- SPIRVAsmPrinter.cpp - SPIR-V LLVM assembly writer ------*- C++ -*--===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // This file contains a printer that converts from our internal representation 10*81ad6265SDimitry Andric // of machine-dependent LLVM code to the SPIR-V assembly language. 11*81ad6265SDimitry Andric // 12*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 13*81ad6265SDimitry Andric 14*81ad6265SDimitry Andric #include "MCTargetDesc/SPIRVInstPrinter.h" 15*81ad6265SDimitry Andric #include "SPIRV.h" 16*81ad6265SDimitry Andric #include "SPIRVInstrInfo.h" 17*81ad6265SDimitry Andric #include "SPIRVMCInstLower.h" 18*81ad6265SDimitry Andric #include "SPIRVModuleAnalysis.h" 19*81ad6265SDimitry Andric #include "SPIRVSubtarget.h" 20*81ad6265SDimitry Andric #include "SPIRVTargetMachine.h" 21*81ad6265SDimitry Andric #include "SPIRVUtils.h" 22*81ad6265SDimitry Andric #include "TargetInfo/SPIRVTargetInfo.h" 23*81ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h" 24*81ad6265SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 25*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 26*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 27*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 28*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 29*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 30*81ad6265SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 31*81ad6265SDimitry Andric #include "llvm/MC/MCInst.h" 32*81ad6265SDimitry Andric #include "llvm/MC/MCStreamer.h" 33*81ad6265SDimitry Andric #include "llvm/MC/MCSymbol.h" 34*81ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 35*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 36*81ad6265SDimitry Andric 37*81ad6265SDimitry Andric using namespace llvm; 38*81ad6265SDimitry Andric 39*81ad6265SDimitry Andric #define DEBUG_TYPE "asm-printer" 40*81ad6265SDimitry Andric 41*81ad6265SDimitry Andric namespace { 42*81ad6265SDimitry Andric class SPIRVAsmPrinter : public AsmPrinter { 43*81ad6265SDimitry Andric public: 44*81ad6265SDimitry Andric explicit SPIRVAsmPrinter(TargetMachine &TM, 45*81ad6265SDimitry Andric std::unique_ptr<MCStreamer> Streamer) 46*81ad6265SDimitry Andric : AsmPrinter(TM, std::move(Streamer)), ST(nullptr), TII(nullptr) {} 47*81ad6265SDimitry Andric bool ModuleSectionsEmitted; 48*81ad6265SDimitry Andric const SPIRVSubtarget *ST; 49*81ad6265SDimitry Andric const SPIRVInstrInfo *TII; 50*81ad6265SDimitry Andric 51*81ad6265SDimitry Andric StringRef getPassName() const override { return "SPIRV Assembly Printer"; } 52*81ad6265SDimitry Andric void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 53*81ad6265SDimitry Andric bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 54*81ad6265SDimitry Andric const char *ExtraCode, raw_ostream &O) override; 55*81ad6265SDimitry Andric 56*81ad6265SDimitry Andric void outputMCInst(MCInst &Inst); 57*81ad6265SDimitry Andric void outputInstruction(const MachineInstr *MI); 58*81ad6265SDimitry Andric void outputModuleSection(SPIRV::ModuleSectionType MSType); 59*81ad6265SDimitry Andric void outputEntryPoints(); 60*81ad6265SDimitry Andric void outputDebugSourceAndStrings(const Module &M); 61*81ad6265SDimitry Andric void outputOpMemoryModel(); 62*81ad6265SDimitry Andric void outputOpFunctionEnd(); 63*81ad6265SDimitry Andric void outputExtFuncDecls(); 64*81ad6265SDimitry Andric void outputModuleSections(); 65*81ad6265SDimitry Andric 66*81ad6265SDimitry Andric void emitInstruction(const MachineInstr *MI) override; 67*81ad6265SDimitry Andric void emitFunctionEntryLabel() override {} 68*81ad6265SDimitry Andric void emitFunctionHeader() override; 69*81ad6265SDimitry Andric void emitFunctionBodyStart() override {} 70*81ad6265SDimitry Andric void emitFunctionBodyEnd() override; 71*81ad6265SDimitry Andric void emitBasicBlockStart(const MachineBasicBlock &MBB) override; 72*81ad6265SDimitry Andric void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {} 73*81ad6265SDimitry Andric void emitGlobalVariable(const GlobalVariable *GV) override {} 74*81ad6265SDimitry Andric void emitOpLabel(const MachineBasicBlock &MBB); 75*81ad6265SDimitry Andric void emitEndOfAsmFile(Module &M) override; 76*81ad6265SDimitry Andric bool doInitialization(Module &M) override; 77*81ad6265SDimitry Andric 78*81ad6265SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 79*81ad6265SDimitry Andric SPIRV::ModuleAnalysisInfo *MAI; 80*81ad6265SDimitry Andric }; 81*81ad6265SDimitry Andric } // namespace 82*81ad6265SDimitry Andric 83*81ad6265SDimitry Andric void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { 84*81ad6265SDimitry Andric AU.addRequired<SPIRVModuleAnalysis>(); 85*81ad6265SDimitry Andric AU.addPreserved<SPIRVModuleAnalysis>(); 86*81ad6265SDimitry Andric AsmPrinter::getAnalysisUsage(AU); 87*81ad6265SDimitry Andric } 88*81ad6265SDimitry Andric 89*81ad6265SDimitry Andric // If the module has no functions, we need output global info anyway. 90*81ad6265SDimitry Andric void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) { 91*81ad6265SDimitry Andric if (ModuleSectionsEmitted == false) { 92*81ad6265SDimitry Andric outputModuleSections(); 93*81ad6265SDimitry Andric ModuleSectionsEmitted = true; 94*81ad6265SDimitry Andric } 95*81ad6265SDimitry Andric } 96*81ad6265SDimitry Andric 97*81ad6265SDimitry Andric void SPIRVAsmPrinter::emitFunctionHeader() { 98*81ad6265SDimitry Andric if (ModuleSectionsEmitted == false) { 99*81ad6265SDimitry Andric outputModuleSections(); 100*81ad6265SDimitry Andric ModuleSectionsEmitted = true; 101*81ad6265SDimitry Andric } 102*81ad6265SDimitry Andric // Get the subtarget from the current MachineFunction. 103*81ad6265SDimitry Andric ST = &MF->getSubtarget<SPIRVSubtarget>(); 104*81ad6265SDimitry Andric TII = ST->getInstrInfo(); 105*81ad6265SDimitry Andric const Function &F = MF->getFunction(); 106*81ad6265SDimitry Andric 107*81ad6265SDimitry Andric if (isVerbose()) { 108*81ad6265SDimitry Andric OutStreamer->getCommentOS() 109*81ad6265SDimitry Andric << "-- Begin function " 110*81ad6265SDimitry Andric << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n'; 111*81ad6265SDimitry Andric } 112*81ad6265SDimitry Andric 113*81ad6265SDimitry Andric auto Section = getObjFileLowering().SectionForGlobal(&F, TM); 114*81ad6265SDimitry Andric MF->setSection(Section); 115*81ad6265SDimitry Andric } 116*81ad6265SDimitry Andric 117*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputOpFunctionEnd() { 118*81ad6265SDimitry Andric MCInst FunctionEndInst; 119*81ad6265SDimitry Andric FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd); 120*81ad6265SDimitry Andric outputMCInst(FunctionEndInst); 121*81ad6265SDimitry Andric } 122*81ad6265SDimitry Andric 123*81ad6265SDimitry Andric // Emit OpFunctionEnd at the end of MF and clear BBNumToRegMap. 124*81ad6265SDimitry Andric void SPIRVAsmPrinter::emitFunctionBodyEnd() { 125*81ad6265SDimitry Andric outputOpFunctionEnd(); 126*81ad6265SDimitry Andric MAI->BBNumToRegMap.clear(); 127*81ad6265SDimitry Andric } 128*81ad6265SDimitry Andric 129*81ad6265SDimitry Andric void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) { 130*81ad6265SDimitry Andric MCInst LabelInst; 131*81ad6265SDimitry Andric LabelInst.setOpcode(SPIRV::OpLabel); 132*81ad6265SDimitry Andric LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB))); 133*81ad6265SDimitry Andric outputMCInst(LabelInst); 134*81ad6265SDimitry Andric } 135*81ad6265SDimitry Andric 136*81ad6265SDimitry Andric void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) { 137*81ad6265SDimitry Andric // If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so 138*81ad6265SDimitry Andric // OpLabel should be output after them. 139*81ad6265SDimitry Andric if (MBB.getNumber() == MF->front().getNumber()) { 140*81ad6265SDimitry Andric for (const MachineInstr &MI : MBB) 141*81ad6265SDimitry Andric if (MI.getOpcode() == SPIRV::OpFunction) 142*81ad6265SDimitry Andric return; 143*81ad6265SDimitry Andric // TODO: this case should be checked by the verifier. 144*81ad6265SDimitry Andric report_fatal_error("OpFunction is expected in the front MBB of MF"); 145*81ad6265SDimitry Andric } 146*81ad6265SDimitry Andric emitOpLabel(MBB); 147*81ad6265SDimitry Andric } 148*81ad6265SDimitry Andric 149*81ad6265SDimitry Andric void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 150*81ad6265SDimitry Andric raw_ostream &O) { 151*81ad6265SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNum); 152*81ad6265SDimitry Andric 153*81ad6265SDimitry Andric switch (MO.getType()) { 154*81ad6265SDimitry Andric case MachineOperand::MO_Register: 155*81ad6265SDimitry Andric O << SPIRVInstPrinter::getRegisterName(MO.getReg()); 156*81ad6265SDimitry Andric break; 157*81ad6265SDimitry Andric 158*81ad6265SDimitry Andric case MachineOperand::MO_Immediate: 159*81ad6265SDimitry Andric O << MO.getImm(); 160*81ad6265SDimitry Andric break; 161*81ad6265SDimitry Andric 162*81ad6265SDimitry Andric case MachineOperand::MO_FPImmediate: 163*81ad6265SDimitry Andric O << MO.getFPImm(); 164*81ad6265SDimitry Andric break; 165*81ad6265SDimitry Andric 166*81ad6265SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 167*81ad6265SDimitry Andric O << *MO.getMBB()->getSymbol(); 168*81ad6265SDimitry Andric break; 169*81ad6265SDimitry Andric 170*81ad6265SDimitry Andric case MachineOperand::MO_GlobalAddress: 171*81ad6265SDimitry Andric O << *getSymbol(MO.getGlobal()); 172*81ad6265SDimitry Andric break; 173*81ad6265SDimitry Andric 174*81ad6265SDimitry Andric case MachineOperand::MO_BlockAddress: { 175*81ad6265SDimitry Andric MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); 176*81ad6265SDimitry Andric O << BA->getName(); 177*81ad6265SDimitry Andric break; 178*81ad6265SDimitry Andric } 179*81ad6265SDimitry Andric 180*81ad6265SDimitry Andric case MachineOperand::MO_ExternalSymbol: 181*81ad6265SDimitry Andric O << *GetExternalSymbolSymbol(MO.getSymbolName()); 182*81ad6265SDimitry Andric break; 183*81ad6265SDimitry Andric 184*81ad6265SDimitry Andric case MachineOperand::MO_JumpTableIndex: 185*81ad6265SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 186*81ad6265SDimitry Andric default: 187*81ad6265SDimitry Andric llvm_unreachable("<unknown operand type>"); 188*81ad6265SDimitry Andric } 189*81ad6265SDimitry Andric } 190*81ad6265SDimitry Andric 191*81ad6265SDimitry Andric bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 192*81ad6265SDimitry Andric const char *ExtraCode, raw_ostream &O) { 193*81ad6265SDimitry Andric if (ExtraCode && ExtraCode[0]) 194*81ad6265SDimitry Andric return true; // Invalid instruction - SPIR-V does not have special modifiers 195*81ad6265SDimitry Andric 196*81ad6265SDimitry Andric printOperand(MI, OpNo, O); 197*81ad6265SDimitry Andric return false; 198*81ad6265SDimitry Andric } 199*81ad6265SDimitry Andric 200*81ad6265SDimitry Andric static bool isFuncOrHeaderInstr(const MachineInstr *MI, 201*81ad6265SDimitry Andric const SPIRVInstrInfo *TII) { 202*81ad6265SDimitry Andric return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction || 203*81ad6265SDimitry Andric MI->getOpcode() == SPIRV::OpFunctionParameter; 204*81ad6265SDimitry Andric } 205*81ad6265SDimitry Andric 206*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) { 207*81ad6265SDimitry Andric OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo()); 208*81ad6265SDimitry Andric } 209*81ad6265SDimitry Andric 210*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) { 211*81ad6265SDimitry Andric SPIRVMCInstLower MCInstLowering; 212*81ad6265SDimitry Andric MCInst TmpInst; 213*81ad6265SDimitry Andric MCInstLowering.lower(MI, TmpInst, MAI); 214*81ad6265SDimitry Andric outputMCInst(TmpInst); 215*81ad6265SDimitry Andric } 216*81ad6265SDimitry Andric 217*81ad6265SDimitry Andric void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) { 218*81ad6265SDimitry Andric if (!MAI->getSkipEmission(MI)) 219*81ad6265SDimitry Andric outputInstruction(MI); 220*81ad6265SDimitry Andric 221*81ad6265SDimitry Andric // Output OpLabel after OpFunction and OpFunctionParameter in the first MBB. 222*81ad6265SDimitry Andric const MachineInstr *NextMI = MI->getNextNode(); 223*81ad6265SDimitry Andric if (!MAI->hasMBBRegister(*MI->getParent()) && isFuncOrHeaderInstr(MI, TII) && 224*81ad6265SDimitry Andric (!NextMI || !isFuncOrHeaderInstr(NextMI, TII))) { 225*81ad6265SDimitry Andric assert(MI->getParent()->getNumber() == MF->front().getNumber() && 226*81ad6265SDimitry Andric "OpFunction is not in the front MBB of MF"); 227*81ad6265SDimitry Andric emitOpLabel(*MI->getParent()); 228*81ad6265SDimitry Andric } 229*81ad6265SDimitry Andric } 230*81ad6265SDimitry Andric 231*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) { 232*81ad6265SDimitry Andric for (MachineInstr *MI : MAI->getMSInstrs(MSType)) 233*81ad6265SDimitry Andric outputInstruction(MI); 234*81ad6265SDimitry Andric } 235*81ad6265SDimitry Andric 236*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) { 237*81ad6265SDimitry Andric // Output OpSource. 238*81ad6265SDimitry Andric MCInst Inst; 239*81ad6265SDimitry Andric Inst.setOpcode(SPIRV::OpSource); 240*81ad6265SDimitry Andric Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang))); 241*81ad6265SDimitry Andric Inst.addOperand( 242*81ad6265SDimitry Andric MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion))); 243*81ad6265SDimitry Andric outputMCInst(Inst); 244*81ad6265SDimitry Andric } 245*81ad6265SDimitry Andric 246*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputOpMemoryModel() { 247*81ad6265SDimitry Andric MCInst Inst; 248*81ad6265SDimitry Andric Inst.setOpcode(SPIRV::OpMemoryModel); 249*81ad6265SDimitry Andric Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr))); 250*81ad6265SDimitry Andric Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem))); 251*81ad6265SDimitry Andric outputMCInst(Inst); 252*81ad6265SDimitry Andric } 253*81ad6265SDimitry Andric 254*81ad6265SDimitry Andric // Before the OpEntryPoints' output, we need to add the entry point's 255*81ad6265SDimitry Andric // interfaces. The interface is a list of IDs of global OpVariable instructions. 256*81ad6265SDimitry Andric // These declare the set of global variables from a module that form 257*81ad6265SDimitry Andric // the interface of this entry point. 258*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputEntryPoints() { 259*81ad6265SDimitry Andric // Find all OpVariable IDs with required StorageClass. 260*81ad6265SDimitry Andric DenseSet<Register> InterfaceIDs; 261*81ad6265SDimitry Andric for (MachineInstr *MI : MAI->GlobalVarList) { 262*81ad6265SDimitry Andric assert(MI->getOpcode() == SPIRV::OpVariable); 263*81ad6265SDimitry Andric auto SC = static_cast<SPIRV::StorageClass>(MI->getOperand(2).getImm()); 264*81ad6265SDimitry Andric // Before version 1.4, the interface's storage classes are limited to 265*81ad6265SDimitry Andric // the Input and Output storage classes. Starting with version 1.4, 266*81ad6265SDimitry Andric // the interface's storage classes are all storage classes used in 267*81ad6265SDimitry Andric // declaring all global variables referenced by the entry point call tree. 268*81ad6265SDimitry Andric if (ST->getSPIRVVersion() >= 14 || SC == SPIRV::StorageClass::Input || 269*81ad6265SDimitry Andric SC == SPIRV::StorageClass::Output) { 270*81ad6265SDimitry Andric MachineFunction *MF = MI->getMF(); 271*81ad6265SDimitry Andric Register Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg()); 272*81ad6265SDimitry Andric InterfaceIDs.insert(Reg); 273*81ad6265SDimitry Andric } 274*81ad6265SDimitry Andric } 275*81ad6265SDimitry Andric 276*81ad6265SDimitry Andric // Output OpEntryPoints adding interface args to all of them. 277*81ad6265SDimitry Andric for (MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) { 278*81ad6265SDimitry Andric SPIRVMCInstLower MCInstLowering; 279*81ad6265SDimitry Andric MCInst TmpInst; 280*81ad6265SDimitry Andric MCInstLowering.lower(MI, TmpInst, MAI); 281*81ad6265SDimitry Andric for (Register Reg : InterfaceIDs) { 282*81ad6265SDimitry Andric assert(Reg.isValid()); 283*81ad6265SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg)); 284*81ad6265SDimitry Andric } 285*81ad6265SDimitry Andric outputMCInst(TmpInst); 286*81ad6265SDimitry Andric } 287*81ad6265SDimitry Andric } 288*81ad6265SDimitry Andric 289*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputExtFuncDecls() { 290*81ad6265SDimitry Andric // Insert OpFunctionEnd after each declaration. 291*81ad6265SDimitry Andric SmallVectorImpl<MachineInstr *>::iterator 292*81ad6265SDimitry Andric I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(), 293*81ad6265SDimitry Andric E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end(); 294*81ad6265SDimitry Andric for (; I != E; ++I) { 295*81ad6265SDimitry Andric outputInstruction(*I); 296*81ad6265SDimitry Andric if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction) 297*81ad6265SDimitry Andric outputOpFunctionEnd(); 298*81ad6265SDimitry Andric } 299*81ad6265SDimitry Andric } 300*81ad6265SDimitry Andric 301*81ad6265SDimitry Andric void SPIRVAsmPrinter::outputModuleSections() { 302*81ad6265SDimitry Andric const Module *M = MMI->getModule(); 303*81ad6265SDimitry Andric // Get the global subtarget to output module-level info. 304*81ad6265SDimitry Andric ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl(); 305*81ad6265SDimitry Andric TII = ST->getInstrInfo(); 306*81ad6265SDimitry Andric MAI = &SPIRVModuleAnalysis::MAI; 307*81ad6265SDimitry Andric assert(ST && TII && MAI && M && "Module analysis is required"); 308*81ad6265SDimitry Andric // Output instructions according to the Logical Layout of a Module: 309*81ad6265SDimitry Andric // TODO: 1,2. All OpCapability instructions, then optional OpExtension 310*81ad6265SDimitry Andric // instructions. 311*81ad6265SDimitry Andric // TODO: 3. Optional OpExtInstImport instructions. 312*81ad6265SDimitry Andric // 4. The single required OpMemoryModel instruction. 313*81ad6265SDimitry Andric outputOpMemoryModel(); 314*81ad6265SDimitry Andric // 5. All entry point declarations, using OpEntryPoint. 315*81ad6265SDimitry Andric outputEntryPoints(); 316*81ad6265SDimitry Andric // 6. Execution-mode declarations, using OpExecutionMode or OpExecutionModeId. 317*81ad6265SDimitry Andric // TODO: 318*81ad6265SDimitry Andric // 7a. Debug: all OpString, OpSourceExtension, OpSource, and 319*81ad6265SDimitry Andric // OpSourceContinued, without forward references. 320*81ad6265SDimitry Andric outputDebugSourceAndStrings(*M); 321*81ad6265SDimitry Andric // 7b. Debug: all OpName and all OpMemberName. 322*81ad6265SDimitry Andric outputModuleSection(SPIRV::MB_DebugNames); 323*81ad6265SDimitry Andric // 7c. Debug: all OpModuleProcessed instructions. 324*81ad6265SDimitry Andric outputModuleSection(SPIRV::MB_DebugModuleProcessed); 325*81ad6265SDimitry Andric // 8. All annotation instructions (all decorations). 326*81ad6265SDimitry Andric outputModuleSection(SPIRV::MB_Annotations); 327*81ad6265SDimitry Andric // 9. All type declarations (OpTypeXXX instructions), all constant 328*81ad6265SDimitry Andric // instructions, and all global variable declarations. This section is 329*81ad6265SDimitry Andric // the first section to allow use of: OpLine and OpNoLine debug information; 330*81ad6265SDimitry Andric // non-semantic instructions with OpExtInst. 331*81ad6265SDimitry Andric outputModuleSection(SPIRV::MB_TypeConstVars); 332*81ad6265SDimitry Andric // 10. All function declarations (functions without a body). 333*81ad6265SDimitry Andric outputExtFuncDecls(); 334*81ad6265SDimitry Andric // 11. All function definitions (functions with a body). 335*81ad6265SDimitry Andric // This is done in regular function output. 336*81ad6265SDimitry Andric } 337*81ad6265SDimitry Andric 338*81ad6265SDimitry Andric bool SPIRVAsmPrinter::doInitialization(Module &M) { 339*81ad6265SDimitry Andric ModuleSectionsEmitted = false; 340*81ad6265SDimitry Andric // We need to call the parent's one explicitly. 341*81ad6265SDimitry Andric return AsmPrinter::doInitialization(M); 342*81ad6265SDimitry Andric } 343*81ad6265SDimitry Andric 344*81ad6265SDimitry Andric // Force static initialization. 345*81ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVAsmPrinter() { 346*81ad6265SDimitry Andric RegisterAsmPrinter<SPIRVAsmPrinter> X(getTheSPIRV32Target()); 347*81ad6265SDimitry Andric RegisterAsmPrinter<SPIRVAsmPrinter> Y(getTheSPIRV64Target()); 348*81ad6265SDimitry Andric } 349