xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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