1 //===-- SPIRVAsmPrinter.cpp - SPIR-V LLVM assembly writer ------*- C++ -*--===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to the SPIR-V assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MCTargetDesc/SPIRVInstPrinter.h"
15 #include "SPIRV.h"
16 #include "SPIRVInstrInfo.h"
17 #include "SPIRVMCInstLower.h"
18 #include "SPIRVModuleAnalysis.h"
19 #include "SPIRVSubtarget.h"
20 #include "SPIRVTargetMachine.h"
21 #include "SPIRVUtils.h"
22 #include "TargetInfo/SPIRVTargetInfo.h"
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/Analysis/ValueTracking.h"
25 #include "llvm/CodeGen/AsmPrinter.h"
26 #include "llvm/CodeGen/MachineConstantPool.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/CodeGen/MachineModuleInfo.h"
30 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
31 #include "llvm/MC/MCAsmInfo.h"
32 #include "llvm/MC/MCInst.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSymbol.h"
35 #include "llvm/MC/TargetRegistry.h"
36 #include "llvm/Support/raw_ostream.h"
37 
38 using namespace llvm;
39 
40 #define DEBUG_TYPE "asm-printer"
41 
42 namespace {
43 class SPIRVAsmPrinter : public AsmPrinter {
44 public:
SPIRVAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)45   explicit SPIRVAsmPrinter(TargetMachine &TM,
46                            std::unique_ptr<MCStreamer> Streamer)
47       : AsmPrinter(TM, std::move(Streamer)), ST(nullptr), TII(nullptr) {}
48   bool ModuleSectionsEmitted;
49   const SPIRVSubtarget *ST;
50   const SPIRVInstrInfo *TII;
51 
getPassName() const52   StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
53   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
54   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
55                        const char *ExtraCode, raw_ostream &O) override;
56 
57   void outputMCInst(MCInst &Inst);
58   void outputInstruction(const MachineInstr *MI);
59   void outputModuleSection(SPIRV::ModuleSectionType MSType);
60   void outputGlobalRequirements();
61   void outputEntryPoints();
62   void outputDebugSourceAndStrings(const Module &M);
63   void outputOpExtInstImports(const Module &M);
64   void outputOpMemoryModel();
65   void outputOpFunctionEnd();
66   void outputExtFuncDecls();
67   void outputExecutionModeFromMDNode(Register Reg, MDNode *Node,
68                                      SPIRV::ExecutionMode::ExecutionMode EM);
69   void outputExecutionModeFromNumthreadsAttribute(
70       const Register &Reg, const Attribute &Attr,
71       SPIRV::ExecutionMode::ExecutionMode EM);
72   void outputExecutionMode(const Module &M);
73   void outputAnnotations(const Module &M);
74   void outputModuleSections();
75 
76   void emitInstruction(const MachineInstr *MI) override;
emitFunctionEntryLabel()77   void emitFunctionEntryLabel() override {}
78   void emitFunctionHeader() override;
emitFunctionBodyStart()79   void emitFunctionBodyStart() override {}
80   void emitFunctionBodyEnd() override;
81   void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
emitBasicBlockEnd(const MachineBasicBlock & MBB)82   void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}
emitGlobalVariable(const GlobalVariable * GV)83   void emitGlobalVariable(const GlobalVariable *GV) override {}
84   void emitOpLabel(const MachineBasicBlock &MBB);
85   void emitEndOfAsmFile(Module &M) override;
86   bool doInitialization(Module &M) override;
87 
88   void getAnalysisUsage(AnalysisUsage &AU) const override;
89   SPIRV::ModuleAnalysisInfo *MAI;
90 };
91 } // namespace
92 
getAnalysisUsage(AnalysisUsage & AU) const93 void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
94   AU.addRequired<SPIRVModuleAnalysis>();
95   AU.addPreserved<SPIRVModuleAnalysis>();
96   AsmPrinter::getAnalysisUsage(AU);
97 }
98 
99 // If the module has no functions, we need output global info anyway.
emitEndOfAsmFile(Module & M)100 void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
101   if (ModuleSectionsEmitted == false) {
102     outputModuleSections();
103     ModuleSectionsEmitted = true;
104   }
105 }
106 
emitFunctionHeader()107 void SPIRVAsmPrinter::emitFunctionHeader() {
108   if (ModuleSectionsEmitted == false) {
109     outputModuleSections();
110     ModuleSectionsEmitted = true;
111   }
112   // Get the subtarget from the current MachineFunction.
113   ST = &MF->getSubtarget<SPIRVSubtarget>();
114   TII = ST->getInstrInfo();
115   const Function &F = MF->getFunction();
116 
117   if (isVerbose()) {
118     OutStreamer->getCommentOS()
119         << "-- Begin function "
120         << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';
121   }
122 
123   auto Section = getObjFileLowering().SectionForGlobal(&F, TM);
124   MF->setSection(Section);
125 }
126 
outputOpFunctionEnd()127 void SPIRVAsmPrinter::outputOpFunctionEnd() {
128   MCInst FunctionEndInst;
129   FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd);
130   outputMCInst(FunctionEndInst);
131 }
132 
133 // Emit OpFunctionEnd at the end of MF and clear BBNumToRegMap.
emitFunctionBodyEnd()134 void SPIRVAsmPrinter::emitFunctionBodyEnd() {
135   outputOpFunctionEnd();
136   MAI->BBNumToRegMap.clear();
137 }
138 
emitOpLabel(const MachineBasicBlock & MBB)139 void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
140   MCInst LabelInst;
141   LabelInst.setOpcode(SPIRV::OpLabel);
142   LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));
143   outputMCInst(LabelInst);
144 }
145 
emitBasicBlockStart(const MachineBasicBlock & MBB)146 void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
147   assert(!MBB.empty() && "MBB is empty!");
148 
149   // If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so
150   // OpLabel should be output after them.
151   if (MBB.getNumber() == MF->front().getNumber()) {
152     for (const MachineInstr &MI : MBB)
153       if (MI.getOpcode() == SPIRV::OpFunction)
154         return;
155     // TODO: this case should be checked by the verifier.
156     report_fatal_error("OpFunction is expected in the front MBB of MF");
157   }
158   emitOpLabel(MBB);
159 }
160 
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)161 void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
162                                    raw_ostream &O) {
163   const MachineOperand &MO = MI->getOperand(OpNum);
164 
165   switch (MO.getType()) {
166   case MachineOperand::MO_Register:
167     O << SPIRVInstPrinter::getRegisterName(MO.getReg());
168     break;
169 
170   case MachineOperand::MO_Immediate:
171     O << MO.getImm();
172     break;
173 
174   case MachineOperand::MO_FPImmediate:
175     O << MO.getFPImm();
176     break;
177 
178   case MachineOperand::MO_MachineBasicBlock:
179     O << *MO.getMBB()->getSymbol();
180     break;
181 
182   case MachineOperand::MO_GlobalAddress:
183     O << *getSymbol(MO.getGlobal());
184     break;
185 
186   case MachineOperand::MO_BlockAddress: {
187     MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
188     O << BA->getName();
189     break;
190   }
191 
192   case MachineOperand::MO_ExternalSymbol:
193     O << *GetExternalSymbolSymbol(MO.getSymbolName());
194     break;
195 
196   case MachineOperand::MO_JumpTableIndex:
197   case MachineOperand::MO_ConstantPoolIndex:
198   default:
199     llvm_unreachable("<unknown operand type>");
200   }
201 }
202 
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)203 bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
204                                       const char *ExtraCode, raw_ostream &O) {
205   if (ExtraCode && ExtraCode[0])
206     return true; // Invalid instruction - SPIR-V does not have special modifiers
207 
208   printOperand(MI, OpNo, O);
209   return false;
210 }
211 
isFuncOrHeaderInstr(const MachineInstr * MI,const SPIRVInstrInfo * TII)212 static bool isFuncOrHeaderInstr(const MachineInstr *MI,
213                                 const SPIRVInstrInfo *TII) {
214   return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction ||
215          MI->getOpcode() == SPIRV::OpFunctionParameter;
216 }
217 
outputMCInst(MCInst & Inst)218 void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) {
219   OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
220 }
221 
outputInstruction(const MachineInstr * MI)222 void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) {
223   SPIRVMCInstLower MCInstLowering;
224   MCInst TmpInst;
225   MCInstLowering.lower(MI, TmpInst, MAI);
226   outputMCInst(TmpInst);
227 }
228 
emitInstruction(const MachineInstr * MI)229 void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {
230   SPIRV_MC::verifyInstructionPredicates(MI->getOpcode(),
231                                         getSubtargetInfo().getFeatureBits());
232 
233   if (!MAI->getSkipEmission(MI))
234     outputInstruction(MI);
235 
236   // Output OpLabel after OpFunction and OpFunctionParameter in the first MBB.
237   const MachineInstr *NextMI = MI->getNextNode();
238   if (!MAI->hasMBBRegister(*MI->getParent()) && isFuncOrHeaderInstr(MI, TII) &&
239       (!NextMI || !isFuncOrHeaderInstr(NextMI, TII))) {
240     assert(MI->getParent()->getNumber() == MF->front().getNumber() &&
241            "OpFunction is not in the front MBB of MF");
242     emitOpLabel(*MI->getParent());
243   }
244 }
245 
outputModuleSection(SPIRV::ModuleSectionType MSType)246 void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) {
247   for (MachineInstr *MI : MAI->getMSInstrs(MSType))
248     outputInstruction(MI);
249 }
250 
outputDebugSourceAndStrings(const Module & M)251 void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
252   // Output OpSourceExtensions.
253   for (auto &Str : MAI->SrcExt) {
254     MCInst Inst;
255     Inst.setOpcode(SPIRV::OpSourceExtension);
256     addStringImm(Str.first(), Inst);
257     outputMCInst(Inst);
258   }
259   // Output OpSource.
260   MCInst Inst;
261   Inst.setOpcode(SPIRV::OpSource);
262   Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang)));
263   Inst.addOperand(
264       MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion)));
265   outputMCInst(Inst);
266 }
267 
outputOpExtInstImports(const Module & M)268 void SPIRVAsmPrinter::outputOpExtInstImports(const Module &M) {
269   for (auto &CU : MAI->ExtInstSetMap) {
270     unsigned Set = CU.first;
271     Register Reg = CU.second;
272     MCInst Inst;
273     Inst.setOpcode(SPIRV::OpExtInstImport);
274     Inst.addOperand(MCOperand::createReg(Reg));
275     addStringImm(getExtInstSetName(
276                      static_cast<SPIRV::InstructionSet::InstructionSet>(Set)),
277                  Inst);
278     outputMCInst(Inst);
279   }
280 }
281 
outputOpMemoryModel()282 void SPIRVAsmPrinter::outputOpMemoryModel() {
283   MCInst Inst;
284   Inst.setOpcode(SPIRV::OpMemoryModel);
285   Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr)));
286   Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem)));
287   outputMCInst(Inst);
288 }
289 
290 // Before the OpEntryPoints' output, we need to add the entry point's
291 // interfaces. The interface is a list of IDs of global OpVariable instructions.
292 // These declare the set of global variables from a module that form
293 // the interface of this entry point.
outputEntryPoints()294 void SPIRVAsmPrinter::outputEntryPoints() {
295   // Find all OpVariable IDs with required StorageClass.
296   DenseSet<Register> InterfaceIDs;
297   for (MachineInstr *MI : MAI->GlobalVarList) {
298     assert(MI->getOpcode() == SPIRV::OpVariable);
299     auto SC = static_cast<SPIRV::StorageClass::StorageClass>(
300         MI->getOperand(2).getImm());
301     // Before version 1.4, the interface's storage classes are limited to
302     // the Input and Output storage classes. Starting with version 1.4,
303     // the interface's storage classes are all storage classes used in
304     // declaring all global variables referenced by the entry point call tree.
305     if (ST->getSPIRVVersion() >= 14 || SC == SPIRV::StorageClass::Input ||
306         SC == SPIRV::StorageClass::Output) {
307       MachineFunction *MF = MI->getMF();
308       Register Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
309       InterfaceIDs.insert(Reg);
310     }
311   }
312 
313   // Output OpEntryPoints adding interface args to all of them.
314   for (MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) {
315     SPIRVMCInstLower MCInstLowering;
316     MCInst TmpInst;
317     MCInstLowering.lower(MI, TmpInst, MAI);
318     for (Register Reg : InterfaceIDs) {
319       assert(Reg.isValid());
320       TmpInst.addOperand(MCOperand::createReg(Reg));
321     }
322     outputMCInst(TmpInst);
323   }
324 }
325 
326 // Create global OpCapability instructions for the required capabilities.
outputGlobalRequirements()327 void SPIRVAsmPrinter::outputGlobalRequirements() {
328   // Abort here if not all requirements can be satisfied.
329   MAI->Reqs.checkSatisfiable(*ST);
330 
331   for (const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
332     MCInst Inst;
333     Inst.setOpcode(SPIRV::OpCapability);
334     Inst.addOperand(MCOperand::createImm(Cap));
335     outputMCInst(Inst);
336   }
337 
338   // Generate the final OpExtensions with strings instead of enums.
339   for (const auto &Ext : MAI->Reqs.getExtensions()) {
340     MCInst Inst;
341     Inst.setOpcode(SPIRV::OpExtension);
342     addStringImm(getSymbolicOperandMnemonic(
343                      SPIRV::OperandCategory::ExtensionOperand, Ext),
344                  Inst);
345     outputMCInst(Inst);
346   }
347   // TODO add a pseudo instr for version number.
348 }
349 
outputExtFuncDecls()350 void SPIRVAsmPrinter::outputExtFuncDecls() {
351   // Insert OpFunctionEnd after each declaration.
352   SmallVectorImpl<MachineInstr *>::iterator
353       I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(),
354       E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end();
355   for (; I != E; ++I) {
356     outputInstruction(*I);
357     if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction)
358       outputOpFunctionEnd();
359   }
360 }
361 
362 // Encode LLVM type by SPIR-V execution mode VecTypeHint.
encodeVecTypeHint(Type * Ty)363 static unsigned encodeVecTypeHint(Type *Ty) {
364   if (Ty->isHalfTy())
365     return 4;
366   if (Ty->isFloatTy())
367     return 5;
368   if (Ty->isDoubleTy())
369     return 6;
370   if (IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
371     switch (IntTy->getIntegerBitWidth()) {
372     case 8:
373       return 0;
374     case 16:
375       return 1;
376     case 32:
377       return 2;
378     case 64:
379       return 3;
380     default:
381       llvm_unreachable("invalid integer type");
382     }
383   }
384   if (FixedVectorType *VecTy = dyn_cast<FixedVectorType>(Ty)) {
385     Type *EleTy = VecTy->getElementType();
386     unsigned Size = VecTy->getNumElements();
387     return Size << 16 | encodeVecTypeHint(EleTy);
388   }
389   llvm_unreachable("invalid type");
390 }
391 
addOpsFromMDNode(MDNode * MDN,MCInst & Inst,SPIRV::ModuleAnalysisInfo * MAI)392 static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst,
393                              SPIRV::ModuleAnalysisInfo *MAI) {
394   for (const MDOperand &MDOp : MDN->operands()) {
395     if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
396       Constant *C = CMeta->getValue();
397       if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {
398         Inst.addOperand(MCOperand::createImm(Const->getZExtValue()));
399       } else if (auto *CE = dyn_cast<Function>(C)) {
400         Register FuncReg = MAI->getFuncReg(CE);
401         assert(FuncReg.isValid());
402         Inst.addOperand(MCOperand::createReg(FuncReg));
403       }
404     }
405   }
406 }
407 
outputExecutionModeFromMDNode(Register Reg,MDNode * Node,SPIRV::ExecutionMode::ExecutionMode EM)408 void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
409     Register Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM) {
410   MCInst Inst;
411   Inst.setOpcode(SPIRV::OpExecutionMode);
412   Inst.addOperand(MCOperand::createReg(Reg));
413   Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
414   addOpsFromMDNode(Node, Inst, MAI);
415   outputMCInst(Inst);
416 }
417 
outputExecutionModeFromNumthreadsAttribute(const Register & Reg,const Attribute & Attr,SPIRV::ExecutionMode::ExecutionMode EM)418 void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(
419     const Register &Reg, const Attribute &Attr,
420     SPIRV::ExecutionMode::ExecutionMode EM) {
421   assert(Attr.isValid() && "Function called with an invalid attribute.");
422 
423   MCInst Inst;
424   Inst.setOpcode(SPIRV::OpExecutionMode);
425   Inst.addOperand(MCOperand::createReg(Reg));
426   Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
427 
428   SmallVector<StringRef> NumThreads;
429   Attr.getValueAsString().split(NumThreads, ',');
430   assert(NumThreads.size() == 3 && "invalid numthreads");
431   for (uint32_t i = 0; i < 3; ++i) {
432     uint32_t V;
433     [[maybe_unused]] bool Result = NumThreads[i].getAsInteger(10, V);
434     assert(!Result && "Failed to parse numthreads");
435     Inst.addOperand(MCOperand::createImm(V));
436   }
437 
438   outputMCInst(Inst);
439 }
440 
outputExecutionMode(const Module & M)441 void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {
442   NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode");
443   if (Node) {
444     for (unsigned i = 0; i < Node->getNumOperands(); i++) {
445       MCInst Inst;
446       Inst.setOpcode(SPIRV::OpExecutionMode);
447       addOpsFromMDNode(cast<MDNode>(Node->getOperand(i)), Inst, MAI);
448       outputMCInst(Inst);
449     }
450   }
451   for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
452     const Function &F = *FI;
453     if (F.isDeclaration())
454       continue;
455     Register FReg = MAI->getFuncReg(&F);
456     assert(FReg.isValid());
457     if (MDNode *Node = F.getMetadata("reqd_work_group_size"))
458       outputExecutionModeFromMDNode(FReg, Node,
459                                     SPIRV::ExecutionMode::LocalSize);
460     if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid())
461       outputExecutionModeFromNumthreadsAttribute(
462           FReg, Attr, SPIRV::ExecutionMode::LocalSize);
463     if (MDNode *Node = F.getMetadata("work_group_size_hint"))
464       outputExecutionModeFromMDNode(FReg, Node,
465                                     SPIRV::ExecutionMode::LocalSizeHint);
466     if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size"))
467       outputExecutionModeFromMDNode(FReg, Node,
468                                     SPIRV::ExecutionMode::SubgroupSize);
469     if (MDNode *Node = F.getMetadata("vec_type_hint")) {
470       MCInst Inst;
471       Inst.setOpcode(SPIRV::OpExecutionMode);
472       Inst.addOperand(MCOperand::createReg(FReg));
473       unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
474       Inst.addOperand(MCOperand::createImm(EM));
475       unsigned TypeCode = encodeVecTypeHint(getMDOperandAsType(Node, 0));
476       Inst.addOperand(MCOperand::createImm(TypeCode));
477       outputMCInst(Inst);
478     }
479     if (ST->isOpenCLEnv() && !M.getNamedMetadata("spirv.ExecutionMode") &&
480         !M.getNamedMetadata("opencl.enable.FP_CONTRACT")) {
481       MCInst Inst;
482       Inst.setOpcode(SPIRV::OpExecutionMode);
483       Inst.addOperand(MCOperand::createReg(FReg));
484       unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::ContractionOff);
485       Inst.addOperand(MCOperand::createImm(EM));
486       outputMCInst(Inst);
487     }
488   }
489 }
490 
outputAnnotations(const Module & M)491 void SPIRVAsmPrinter::outputAnnotations(const Module &M) {
492   outputModuleSection(SPIRV::MB_Annotations);
493   // Process llvm.global.annotations special global variable.
494   for (auto F = M.global_begin(), E = M.global_end(); F != E; ++F) {
495     if ((*F).getName() != "llvm.global.annotations")
496       continue;
497     const GlobalVariable *V = &(*F);
498     const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
499     for (Value *Op : CA->operands()) {
500       ConstantStruct *CS = cast<ConstantStruct>(Op);
501       // The first field of the struct contains a pointer to
502       // the annotated variable.
503       Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
504       if (!isa<Function>(AnnotatedVar))
505         report_fatal_error("Unsupported value in llvm.global.annotations");
506       Function *Func = cast<Function>(AnnotatedVar);
507       Register Reg = MAI->getFuncReg(Func);
508 
509       // The second field contains a pointer to a global annotation string.
510       GlobalVariable *GV =
511           cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());
512 
513       StringRef AnnotationString;
514       getConstantStringInfo(GV, AnnotationString);
515       MCInst Inst;
516       Inst.setOpcode(SPIRV::OpDecorate);
517       Inst.addOperand(MCOperand::createReg(Reg));
518       unsigned Dec = static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
519       Inst.addOperand(MCOperand::createImm(Dec));
520       addStringImm(AnnotationString, Inst);
521       outputMCInst(Inst);
522     }
523   }
524 }
525 
outputModuleSections()526 void SPIRVAsmPrinter::outputModuleSections() {
527   const Module *M = MMI->getModule();
528   // Get the global subtarget to output module-level info.
529   ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
530   TII = ST->getInstrInfo();
531   MAI = &SPIRVModuleAnalysis::MAI;
532   assert(ST && TII && MAI && M && "Module analysis is required");
533   // Output instructions according to the Logical Layout of a Module:
534   // 1,2. All OpCapability instructions, then optional OpExtension instructions.
535   outputGlobalRequirements();
536   // 3. Optional OpExtInstImport instructions.
537   outputOpExtInstImports(*M);
538   // 4. The single required OpMemoryModel instruction.
539   outputOpMemoryModel();
540   // 5. All entry point declarations, using OpEntryPoint.
541   outputEntryPoints();
542   // 6. Execution-mode declarations, using OpExecutionMode or OpExecutionModeId.
543   outputExecutionMode(*M);
544   // 7a. Debug: all OpString, OpSourceExtension, OpSource, and
545   // OpSourceContinued, without forward references.
546   outputDebugSourceAndStrings(*M);
547   // 7b. Debug: all OpName and all OpMemberName.
548   outputModuleSection(SPIRV::MB_DebugNames);
549   // 7c. Debug: all OpModuleProcessed instructions.
550   outputModuleSection(SPIRV::MB_DebugModuleProcessed);
551   // 8. All annotation instructions (all decorations).
552   outputAnnotations(*M);
553   // 9. All type declarations (OpTypeXXX instructions), all constant
554   // instructions, and all global variable declarations. This section is
555   // the first section to allow use of: OpLine and OpNoLine debug information;
556   // non-semantic instructions with OpExtInst.
557   outputModuleSection(SPIRV::MB_TypeConstVars);
558   // 10. All function declarations (functions without a body).
559   outputExtFuncDecls();
560   // 11. All function definitions (functions with a body).
561   // This is done in regular function output.
562 }
563 
doInitialization(Module & M)564 bool SPIRVAsmPrinter::doInitialization(Module &M) {
565   ModuleSectionsEmitted = false;
566   // We need to call the parent's one explicitly.
567   return AsmPrinter::doInitialization(M);
568 }
569 
570 // Force static initialization.
LLVMInitializeSPIRVAsmPrinter()571 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVAsmPrinter() {
572   RegisterAsmPrinter<SPIRVAsmPrinter> X(getTheSPIRV32Target());
573   RegisterAsmPrinter<SPIRVAsmPrinter> Y(getTheSPIRV64Target());
574   RegisterAsmPrinter<SPIRVAsmPrinter> Z(getTheSPIRVLogicalTarget());
575 }
576