Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
SPIRVAsmPrinter.cpp
Go to the documentation of this file.
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
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"
23#include "llvm/ADT/DenseMap.h"
30#include "llvm/MC/MCAsmInfo.h"
31#include "llvm/MC/MCAssembler.h"
32#include "llvm/MC/MCInst.h"
35#include "llvm/MC/MCStreamer.h"
36#include "llvm/MC/MCSymbol.h"
40
41using namespace llvm;
42
43#define DEBUG_TYPE "asm-printer"
44
45namespace {
46class SPIRVAsmPrinter : public AsmPrinter {
47 unsigned NLabels = 0;
49
50public:
51 explicit SPIRVAsmPrinter(TargetMachine &TM,
52 std::unique_ptr<MCStreamer> Streamer)
53 : AsmPrinter(TM, std::move(Streamer), ID), ModuleSectionsEmitted(false),
54 ST(nullptr), TII(nullptr), MAI(nullptr) {}
55 static char ID;
56 bool ModuleSectionsEmitted;
57 const SPIRVSubtarget *ST;
58 const SPIRVInstrInfo *TII;
59
60 StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
61 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
62 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
63 const char *ExtraCode, raw_ostream &O) override;
64
65 void outputMCInst(MCInst &Inst);
66 void outputInstruction(const MachineInstr *MI);
67 void outputModuleSection(SPIRV::ModuleSectionType MSType);
68 void outputGlobalRequirements();
69 void outputEntryPoints();
70 void outputDebugSourceAndStrings(const Module &M);
71 void outputOpExtInstImports(const Module &M);
72 void outputOpMemoryModel();
73 void outputOpFunctionEnd();
74 void outputExtFuncDecls();
75 void outputExecutionModeFromMDNode(MCRegister Reg, MDNode *Node,
76 SPIRV::ExecutionMode::ExecutionMode EM,
77 unsigned ExpectMDOps, int64_t DefVal);
78 void outputExecutionModeFromNumthreadsAttribute(
79 const MCRegister &Reg, const Attribute &Attr,
80 SPIRV::ExecutionMode::ExecutionMode EM);
81 void outputExecutionMode(const Module &M);
82 void outputAnnotations(const Module &M);
83 void outputModuleSections();
84 bool isHidden() {
85 return MF->getFunction()
86 .getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME)
87 .isValid();
88 }
89
90 void emitInstruction(const MachineInstr *MI) override;
91 void emitFunctionEntryLabel() override {}
92 void emitFunctionHeader() override;
93 void emitFunctionBodyStart() override {}
94 void emitFunctionBodyEnd() override;
95 void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
96 void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}
97 void emitGlobalVariable(const GlobalVariable *GV) override {}
98 void emitOpLabel(const MachineBasicBlock &MBB);
99 void emitEndOfAsmFile(Module &M) override;
100 bool doInitialization(Module &M) override;
101
102 void getAnalysisUsage(AnalysisUsage &AU) const override;
104
105protected:
106 void cleanUp(Module &M);
107};
108} // namespace
109
110void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
111 AU.addRequired<SPIRVModuleAnalysis>();
112 AU.addPreserved<SPIRVModuleAnalysis>();
114}
115
116// If the module has no functions, we need output global info anyway.
117void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
118 if (ModuleSectionsEmitted == false) {
119 outputModuleSections();
120 ModuleSectionsEmitted = true;
121 }
122
123 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
124 VersionTuple SPIRVVersion = ST->getSPIRVVersion();
125 uint32_t Major = SPIRVVersion.getMajor();
126 uint32_t Minor = SPIRVVersion.getMinor().value_or(0);
127 // Bound is an approximation that accounts for the maximum used register
128 // number and number of generated OpLabels
129 unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;
130 if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())
131 static_cast<SPIRVObjectWriter &>(Asm->getWriter())
132 .setBuildVersion(Major, Minor, Bound);
133
134 cleanUp(M);
135}
136
137// Any cleanup actions with the Module after we don't care about its content
138// anymore.
139void SPIRVAsmPrinter::cleanUp(Module &M) {
140 // Verifier disallows uses of intrinsic global variables.
141 for (StringRef GVName : {"llvm.global_ctors", "llvm.global_dtors",
142 "llvm.used", "llvm.compiler.used"}) {
143 if (GlobalVariable *GV = M.getNamedGlobal(GVName))
144 GV->setName("");
145 }
146}
147
148void SPIRVAsmPrinter::emitFunctionHeader() {
149 if (ModuleSectionsEmitted == false) {
150 outputModuleSections();
151 ModuleSectionsEmitted = true;
152 }
153 // Get the subtarget from the current MachineFunction.
154 ST = &MF->getSubtarget<SPIRVSubtarget>();
155 TII = ST->getInstrInfo();
156 const Function &F = MF->getFunction();
157
158 if (isVerbose() && !isHidden()) {
159 OutStreamer->getCommentOS()
160 << "-- Begin function "
161 << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';
162 }
163
164 auto Section = getObjFileLowering().SectionForGlobal(&F, TM);
165 MF->setSection(Section);
166}
167
168void SPIRVAsmPrinter::outputOpFunctionEnd() {
169 MCInst FunctionEndInst;
170 FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd);
171 outputMCInst(FunctionEndInst);
172}
173
174void SPIRVAsmPrinter::emitFunctionBodyEnd() {
175 if (!isHidden())
176 outputOpFunctionEnd();
177}
178
179void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
180 // Do not emit anything if it's an internal service function.
181 if (isHidden())
182 return;
183
184 MCInst LabelInst;
185 LabelInst.setOpcode(SPIRV::OpLabel);
186 LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));
187 outputMCInst(LabelInst);
188 ++NLabels;
189 LabeledMBB.insert(&MBB);
190}
191
192void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
193 // Do not emit anything if it's an internal service function.
194 if (MBB.empty())
195 return;
196
197 // If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so
198 // OpLabel should be output after them.
199 if (MBB.getNumber() == MF->front().getNumber()) {
200 for (const MachineInstr &MI : MBB)
201 if (MI.getOpcode() == SPIRV::OpFunction)
202 return;
203 // TODO: this case should be checked by the verifier.
204 report_fatal_error("OpFunction is expected in the front MBB of MF");
205 }
206 emitOpLabel(MBB);
207}
208
209void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
210 raw_ostream &O) {
211 const MachineOperand &MO = MI->getOperand(OpNum);
212
213 switch (MO.getType()) {
216 break;
217
219 O << MO.getImm();
220 break;
221
223 O << MO.getFPImm();
224 break;
225
227 O << *MO.getMBB()->getSymbol();
228 break;
229
231 O << *getSymbol(MO.getGlobal());
232 break;
233
235 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
236 O << BA->getName();
237 break;
238 }
239
241 O << *GetExternalSymbolSymbol(MO.getSymbolName());
242 break;
243
246 default:
247 llvm_unreachable("<unknown operand type>");
248 }
249}
250
251bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
252 const char *ExtraCode, raw_ostream &O) {
253 if (ExtraCode && ExtraCode[0])
254 return true; // Invalid instruction - SPIR-V does not have special modifiers
255
256 printOperand(MI, OpNo, O);
257 return false;
258}
259
261 const SPIRVInstrInfo *TII) {
262 return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction ||
263 MI->getOpcode() == SPIRV::OpFunctionParameter;
264}
265
266void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) {
267 OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
268}
269
270void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) {
271 SPIRVMCInstLower MCInstLowering;
272 MCInst TmpInst;
273 MCInstLowering.lower(MI, TmpInst, MAI);
274 outputMCInst(TmpInst);
275}
276
277void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {
278 SPIRV_MC::verifyInstructionPredicates(MI->getOpcode(),
279 getSubtargetInfo().getFeatureBits());
280
281 if (!MAI->getSkipEmission(MI))
282 outputInstruction(MI);
283
284 // Output OpLabel after OpFunction and OpFunctionParameter in the first MBB.
285 const MachineInstr *NextMI = MI->getNextNode();
286 if (!LabeledMBB.contains(MI->getParent()) && isFuncOrHeaderInstr(MI, TII) &&
287 (!NextMI || !isFuncOrHeaderInstr(NextMI, TII))) {
288 assert(MI->getParent()->getNumber() == MF->front().getNumber() &&
289 "OpFunction is not in the front MBB of MF");
290 emitOpLabel(*MI->getParent());
291 }
292}
293
294void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) {
295 for (const MachineInstr *MI : MAI->getMSInstrs(MSType))
296 outputInstruction(MI);
297}
298
299void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
300 // Output OpSourceExtensions.
301 for (auto &Str : MAI->SrcExt) {
302 MCInst Inst;
303 Inst.setOpcode(SPIRV::OpSourceExtension);
304 addStringImm(Str.first(), Inst);
305 outputMCInst(Inst);
306 }
307 // Output OpString.
308 outputModuleSection(SPIRV::MB_DebugStrings);
309 // Output OpSource.
310 MCInst Inst;
311 Inst.setOpcode(SPIRV::OpSource);
312 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang)));
313 Inst.addOperand(
314 MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion)));
315 outputMCInst(Inst);
316}
317
318void SPIRVAsmPrinter::outputOpExtInstImports(const Module &M) {
319 for (auto &CU : MAI->ExtInstSetMap) {
320 unsigned Set = CU.first;
321 MCRegister Reg = CU.second;
322 MCInst Inst;
323 Inst.setOpcode(SPIRV::OpExtInstImport);
326 static_cast<SPIRV::InstructionSet::InstructionSet>(Set)),
327 Inst);
328 outputMCInst(Inst);
329 }
330}
331
332void SPIRVAsmPrinter::outputOpMemoryModel() {
333 MCInst Inst;
334 Inst.setOpcode(SPIRV::OpMemoryModel);
335 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr)));
336 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem)));
337 outputMCInst(Inst);
338}
339
340// Before the OpEntryPoints' output, we need to add the entry point's
341// interfaces. The interface is a list of IDs of global OpVariable instructions.
342// These declare the set of global variables from a module that form
343// the interface of this entry point.
344void SPIRVAsmPrinter::outputEntryPoints() {
345 // Find all OpVariable IDs with required StorageClass.
346 DenseSet<MCRegister> InterfaceIDs;
347 for (const MachineInstr *MI : MAI->GlobalVarList) {
348 assert(MI->getOpcode() == SPIRV::OpVariable);
349 auto SC = static_cast<SPIRV::StorageClass::StorageClass>(
350 MI->getOperand(2).getImm());
351 // Before version 1.4, the interface's storage classes are limited to
352 // the Input and Output storage classes. Starting with version 1.4,
353 // the interface's storage classes are all storage classes used in
354 // declaring all global variables referenced by the entry point call tree.
355 if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) ||
356 SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) {
357 const MachineFunction *MF = MI->getMF();
358 MCRegister Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
359 InterfaceIDs.insert(Reg);
360 }
361 }
362
363 // Output OpEntryPoints adding interface args to all of them.
364 for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) {
365 SPIRVMCInstLower MCInstLowering;
366 MCInst TmpInst;
367 MCInstLowering.lower(MI, TmpInst, MAI);
368 for (MCRegister Reg : InterfaceIDs) {
369 assert(Reg.isValid());
371 }
372 outputMCInst(TmpInst);
373 }
374}
375
376// Create global OpCapability instructions for the required capabilities.
377void SPIRVAsmPrinter::outputGlobalRequirements() {
378 // Abort here if not all requirements can be satisfied.
379 MAI->Reqs.checkSatisfiable(*ST);
380
381 for (const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
382 MCInst Inst;
383 Inst.setOpcode(SPIRV::OpCapability);
385 outputMCInst(Inst);
386 }
387
388 // Generate the final OpExtensions with strings instead of enums.
389 for (const auto &Ext : MAI->Reqs.getExtensions()) {
390 MCInst Inst;
391 Inst.setOpcode(SPIRV::OpExtension);
393 SPIRV::OperandCategory::ExtensionOperand, Ext),
394 Inst);
395 outputMCInst(Inst);
396 }
397 // TODO add a pseudo instr for version number.
398}
399
400void SPIRVAsmPrinter::outputExtFuncDecls() {
401 // Insert OpFunctionEnd after each declaration.
402 auto I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(),
403 E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end();
404 for (; I != E; ++I) {
405 outputInstruction(*I);
406 if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction)
407 outputOpFunctionEnd();
408 }
409}
410
411// Encode LLVM type by SPIR-V execution mode VecTypeHint.
412static unsigned encodeVecTypeHint(Type *Ty) {
413 if (Ty->isHalfTy())
414 return 4;
415 if (Ty->isFloatTy())
416 return 5;
417 if (Ty->isDoubleTy())
418 return 6;
419 if (IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
420 switch (IntTy->getIntegerBitWidth()) {
421 case 8:
422 return 0;
423 case 16:
424 return 1;
425 case 32:
426 return 2;
427 case 64:
428 return 3;
429 default:
430 llvm_unreachable("invalid integer type");
431 }
432 }
434 Type *EleTy = VecTy->getElementType();
435 unsigned Size = VecTy->getNumElements();
436 return Size << 16 | encodeVecTypeHint(EleTy);
437 }
438 llvm_unreachable("invalid type");
439}
440
441static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst,
443 for (const MDOperand &MDOp : MDN->operands()) {
444 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
445 Constant *C = CMeta->getValue();
446 if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {
447 Inst.addOperand(MCOperand::createImm(Const->getZExtValue()));
448 } else if (auto *CE = dyn_cast<Function>(C)) {
449 MCRegister FuncReg = MAI->getFuncReg(CE);
450 assert(FuncReg.isValid());
451 Inst.addOperand(MCOperand::createReg(FuncReg));
452 }
453 }
454 }
455}
456
457void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
458 MCRegister Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM,
459 unsigned ExpectMDOps, int64_t DefVal) {
460 MCInst Inst;
461 Inst.setOpcode(SPIRV::OpExecutionMode);
463 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
464 addOpsFromMDNode(Node, Inst, MAI);
465 // reqd_work_group_size and work_group_size_hint require 3 operands,
466 // if metadata contains less operands, just add a default value
467 unsigned NodeSz = Node->getNumOperands();
468 if (ExpectMDOps > 0 && NodeSz < ExpectMDOps)
469 for (unsigned i = NodeSz; i < ExpectMDOps; ++i)
470 Inst.addOperand(MCOperand::createImm(DefVal));
471 outputMCInst(Inst);
472}
473
474void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(
475 const MCRegister &Reg, const Attribute &Attr,
476 SPIRV::ExecutionMode::ExecutionMode EM) {
477 assert(Attr.isValid() && "Function called with an invalid attribute.");
478
479 MCInst Inst;
480 Inst.setOpcode(SPIRV::OpExecutionMode);
482 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
483
484 SmallVector<StringRef> NumThreads;
485 Attr.getValueAsString().split(NumThreads, ',');
486 assert(NumThreads.size() == 3 && "invalid numthreads");
487 for (uint32_t i = 0; i < 3; ++i) {
488 uint32_t V;
489 [[maybe_unused]] bool Result = NumThreads[i].getAsInteger(10, V);
490 assert(!Result && "Failed to parse numthreads");
492 }
493
494 outputMCInst(Inst);
495}
496
497void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {
498 NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode");
499 if (Node) {
500 for (unsigned i = 0; i < Node->getNumOperands(); i++) {
501 MCInst Inst;
502 Inst.setOpcode(SPIRV::OpExecutionMode);
503 addOpsFromMDNode(cast<MDNode>(Node->getOperand(i)), Inst, MAI);
504 outputMCInst(Inst);
505 }
506 }
507 for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
508 const Function &F = *FI;
509 // Only operands of OpEntryPoint instructions are allowed to be
510 // <Entry Point> operands of OpExecutionMode
511 if (F.isDeclaration() || !isEntryPoint(F))
512 continue;
513 MCRegister FReg = MAI->getFuncReg(&F);
514 assert(FReg.isValid());
515
516 if (Attribute Attr = F.getFnAttribute("hlsl.shader"); Attr.isValid()) {
517 // SPIR-V common validation: Fragment requires OriginUpperLeft or
518 // OriginLowerLeft.
519 // VUID-StandaloneSpirv-OriginLowerLeft-04653: Fragment must declare
520 // OriginUpperLeft.
521 if (Attr.getValueAsString() == "pixel") {
522 MCInst Inst;
523 Inst.setOpcode(SPIRV::OpExecutionMode);
525 unsigned EM =
526 static_cast<unsigned>(SPIRV::ExecutionMode::OriginUpperLeft);
528 outputMCInst(Inst);
529 }
530 }
531 if (MDNode *Node = F.getMetadata("reqd_work_group_size"))
532 outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize,
533 3, 1);
534 if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid())
535 outputExecutionModeFromNumthreadsAttribute(
536 FReg, Attr, SPIRV::ExecutionMode::LocalSize);
537 if (MDNode *Node = F.getMetadata("work_group_size_hint"))
538 outputExecutionModeFromMDNode(FReg, Node,
539 SPIRV::ExecutionMode::LocalSizeHint, 3, 1);
540 if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size"))
541 outputExecutionModeFromMDNode(FReg, Node,
542 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
543 if (MDNode *Node = F.getMetadata("vec_type_hint")) {
544 MCInst Inst;
545 Inst.setOpcode(SPIRV::OpExecutionMode);
547 unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
549 unsigned TypeCode = encodeVecTypeHint(getMDOperandAsType(Node, 0));
550 Inst.addOperand(MCOperand::createImm(TypeCode));
551 outputMCInst(Inst);
552 }
553 if (ST->isKernel() && !M.getNamedMetadata("spirv.ExecutionMode") &&
554 !M.getNamedMetadata("opencl.enable.FP_CONTRACT")) {
555 MCInst Inst;
556 Inst.setOpcode(SPIRV::OpExecutionMode);
558 unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::ContractionOff);
560 outputMCInst(Inst);
561 }
562 }
563}
564
565void SPIRVAsmPrinter::outputAnnotations(const Module &M) {
566 outputModuleSection(SPIRV::MB_Annotations);
567 // Process llvm.global.annotations special global variable.
568 for (auto F = M.global_begin(), E = M.global_end(); F != E; ++F) {
569 if ((*F).getName() != "llvm.global.annotations")
570 continue;
571 const GlobalVariable *V = &(*F);
572 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
573 for (Value *Op : CA->operands()) {
574 ConstantStruct *CS = cast<ConstantStruct>(Op);
575 // The first field of the struct contains a pointer to
576 // the annotated variable.
577 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
578 if (!isa<Function>(AnnotatedVar))
579 report_fatal_error("Unsupported value in llvm.global.annotations");
580 Function *Func = cast<Function>(AnnotatedVar);
581 MCRegister Reg = MAI->getFuncReg(Func);
582 if (!Reg.isValid()) {
583 std::string DiagMsg;
584 raw_string_ostream OS(DiagMsg);
585 AnnotatedVar->print(OS);
586 DiagMsg = "Unknown function in llvm.global.annotations: " + DiagMsg;
587 report_fatal_error(DiagMsg.c_str());
588 }
589
590 // The second field contains a pointer to a global annotation string.
591 GlobalVariable *GV =
593
594 StringRef AnnotationString;
595 [[maybe_unused]] bool Success =
596 getConstantStringInfo(GV, AnnotationString);
597 assert(Success && "Failed to get annotation string");
598 MCInst Inst;
599 Inst.setOpcode(SPIRV::OpDecorate);
601 unsigned Dec = static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
603 addStringImm(AnnotationString, Inst);
604 outputMCInst(Inst);
605 }
606 }
607}
608
609void SPIRVAsmPrinter::outputModuleSections() {
610 const Module *M = MMI->getModule();
611 // Get the global subtarget to output module-level info.
612 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
613 TII = ST->getInstrInfo();
615 assert(ST && TII && MAI && M && "Module analysis is required");
616 // Output instructions according to the Logical Layout of a Module:
617 // 1,2. All OpCapability instructions, then optional OpExtension instructions.
618 outputGlobalRequirements();
619 // 3. Optional OpExtInstImport instructions.
620 outputOpExtInstImports(*M);
621 // 4. The single required OpMemoryModel instruction.
622 outputOpMemoryModel();
623 // 5. All entry point declarations, using OpEntryPoint.
624 outputEntryPoints();
625 // 6. Execution-mode declarations, using OpExecutionMode or OpExecutionModeId.
626 outputExecutionMode(*M);
627 // 7a. Debug: all OpString, OpSourceExtension, OpSource, and
628 // OpSourceContinued, without forward references.
629 outputDebugSourceAndStrings(*M);
630 // 7b. Debug: all OpName and all OpMemberName.
631 outputModuleSection(SPIRV::MB_DebugNames);
632 // 7c. Debug: all OpModuleProcessed instructions.
633 outputModuleSection(SPIRV::MB_DebugModuleProcessed);
634 // xxx. SPV_INTEL_memory_access_aliasing instructions go before 8.
635 // "All annotation instructions"
636 outputModuleSection(SPIRV::MB_AliasingInsts);
637 // 8. All annotation instructions (all decorations).
638 outputAnnotations(*M);
639 // 9. All type declarations (OpTypeXXX instructions), all constant
640 // instructions, and all global variable declarations. This section is
641 // the first section to allow use of: OpLine and OpNoLine debug information;
642 // non-semantic instructions with OpExtInst.
643 outputModuleSection(SPIRV::MB_TypeConstVars);
644 // 10. All global NonSemantic.Shader.DebugInfo.100 instructions.
645 outputModuleSection(SPIRV::MB_NonSemanticGlobalDI);
646 // 11. All function declarations (functions without a body).
647 outputExtFuncDecls();
648 // 12. All function definitions (functions with a body).
649 // This is done in regular function output.
650}
651
652bool SPIRVAsmPrinter::doInitialization(Module &M) {
653 ModuleSectionsEmitted = false;
654 // We need to call the parent's one explicitly.
656}
657
658char SPIRVAsmPrinter::ID = 0;
659
660INITIALIZE_PASS(SPIRVAsmPrinter, "spirv-asm-printer", "SPIRV Assembly Printer",
661 false, false)
662
663// Force static initialization.
665LLVMInitializeSPIRVAsmPrinter() {
669}
#define Success
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
This file defines the DenseMap class.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
Machine Check Debug Module
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register Reg
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst, SPIRV::ModuleAnalysisInfo *MAI)
static bool isFuncOrHeaderInstr(const MachineInstr *MI, const SPIRVInstrInfo *TII)
static unsigned encodeVecTypeHint(Type *Ty)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:452
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition VPlanSLP.cpp:247
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:90
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:69
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:223
This is the shared class of boolean and integer constants.
Definition Constants.h:87
This is an important base class in LLVM.
Definition Constant.h:43
Class to represent fixed width SIMD vectors.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
Class to represent integer types.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:33
constexpr bool isValid() const
Definition MCRegister.h:76
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
Metadata node.
Definition Metadata.h:1077
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1439
Tracking metadata reference owned by Metadata.
Definition Metadata.h:899
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Representation of each machine instruction.
const GlobalValue * getGlobal() const
int64_t getImm() const
MachineBasicBlock * getMBB() const
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
@ MO_FPImmediate
Floating-point immediate operand.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
constexpr bool isValid() const
Definition Register.h:107
static const char * getRegisterName(MCRegister Reg)
void lower(const MachineInstr *MI, MCInst &OutMI, SPIRV::ModuleAnalysisInfo *MAI) const
const SPIRVInstrInfo * getInstrInfo() const override
bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const
VersionTuple getSPIRVVersion() const
unsigned getBound() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:710
Primary interface to the complete machine description for the target machine.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
op_range operands()
Definition User.h:292
Value * getOperand(unsigned i) const
Definition User.h:232
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:701
unsigned getMajor() const
Retrieve the major version number.
std::optional< unsigned > getMinor() const
Retrieve the minor version number, if provided.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:194
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
Target & getTheSPIRV32Target()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str, bool TrimAtNul=true)
This function computes the length of a null-terminated C string pointed to by V.
std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
bool isEntryPoint(const Function &F)
Target & getTheSPIRV64Target()
Target & getTheSPIRVLogicalTarget()
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
Type * getMDOperandAsType(const MDNode *N, unsigned I)
void addStringImm(const StringRef &Str, MCInst &Inst)
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
static struct SPIRV::ModuleAnalysisInfo MAI
MCRegister getFuncReg(const Function *F)