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