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