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: 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 52 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; 77 void emitFunctionEntryLabel() override {} 78 void emitFunctionHeader() override; 79 void emitFunctionBodyStart() override {} 80 void emitFunctionBodyEnd() override; 81 void emitBasicBlockStart(const MachineBasicBlock &MBB) override; 82 void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {} 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 93 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. 100 void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) { 101 if (ModuleSectionsEmitted == false) { 102 outputModuleSections(); 103 ModuleSectionsEmitted = true; 104 } 105 } 106 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 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. 134 void SPIRVAsmPrinter::emitFunctionBodyEnd() { 135 outputOpFunctionEnd(); 136 MAI->BBNumToRegMap.clear(); 137 } 138 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 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 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 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 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 218 void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) { 219 OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo()); 220 } 221 222 void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) { 223 SPIRVMCInstLower MCInstLowering; 224 MCInst TmpInst; 225 MCInstLowering.lower(MI, TmpInst, MAI); 226 outputMCInst(TmpInst); 227 } 228 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 246 void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) { 247 for (MachineInstr *MI : MAI->getMSInstrs(MSType)) 248 outputInstruction(MI); 249 } 250 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 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 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. 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. 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 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. 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 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 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 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 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 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 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 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. 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