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