LLVM 23.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"
20#include "SPIRVSubtarget.h"
21#include "SPIRVTargetMachine.h"
22#include "SPIRVUtils.h"
24#include "llvm/ADT/DenseMap.h"
31#include "llvm/MC/MCAsmInfo.h"
32#include "llvm/MC/MCAssembler.h"
33#include "llvm/MC/MCInst.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSymbol.h"
41
42using namespace llvm;
43
44#define DEBUG_TYPE "asm-printer"
45
46namespace {
47class SPIRVAsmPrinter : public AsmPrinter {
48 unsigned NLabels = 0;
50
51public:
52 explicit SPIRVAsmPrinter(TargetMachine &TM,
53 std::unique_ptr<MCStreamer> Streamer)
54 : AsmPrinter(TM, std::move(Streamer), ID), ModuleSectionsEmitted(false),
55 ST(nullptr), TII(nullptr), MAI(nullptr) {}
56 static char ID;
57 bool ModuleSectionsEmitted;
58 const SPIRVSubtarget *ST;
59 const SPIRVInstrInfo *TII;
60
61 StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
62 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
63 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
64 const char *ExtraCode, raw_ostream &O) override;
65
66 void outputMCInst(MCInst &Inst);
67 void outputInstruction(const MachineInstr *MI);
68 void outputModuleSection(SPIRV::ModuleSectionType MSType);
69 void outputGlobalRequirements();
70 void outputEntryPoints();
71 void outputDebugSourceAndStrings(const Module &M);
72 void outputOpExtInstImports(const Module &M);
73 void outputOpMemoryModel();
74 void outputOpFunctionEnd();
75 void outputExtFuncDecls();
76 void outputExecutionModeFromMDNode(MCRegister Reg, MDNode *Node,
77 SPIRV::ExecutionMode::ExecutionMode EM,
78 unsigned ExpectMDOps, int64_t DefVal);
79 void outputExecutionModeFromNumthreadsAttribute(
80 const MCRegister &Reg, const Attribute &Attr,
81 SPIRV::ExecutionMode::ExecutionMode EM);
82 void outputExecutionModeFromEnableMaximalReconvergenceAttr(
83 const MCRegister &Reg, const SPIRVSubtarget &ST);
84 void outputExecutionMode(const Module &M);
85 void outputAnnotations(const Module &M);
86 void outputModuleSections();
87 void outputFPFastMathDefaultInfo();
88 bool isHidden() {
89 return MF->getFunction()
90 .getFnAttribute(SPIRV_BACKEND_SERVICE_FUN_NAME)
91 .isValid();
92 }
93
94 void emitInstruction(const MachineInstr *MI) override;
95 void emitFunctionEntryLabel() override {}
96 void emitFunctionHeader() override;
97 void emitFunctionBodyStart() override {}
98 void emitFunctionBodyEnd() override;
99 void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
100 void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}
101 void emitGlobalVariable(const GlobalVariable *GV) override {}
102 void emitOpLabel(const MachineBasicBlock &MBB);
103 void emitEndOfAsmFile(Module &M) override;
104 bool doInitialization(Module &M) override;
105
106 void getAnalysisUsage(AnalysisUsage &AU) const override;
108
109 // Non-owning pointer to the NSDI handler registered via addAsmPrinterHandler.
110 // The handler's lifetime is managed by AsmPrinter (the base class of this
111 // object), so this pointer cannot dangle.
112 SPIRVNonSemanticDebugHandler *NSDebugHandler = nullptr;
113
114protected:
115 void cleanUp(Module &M);
116};
117} // namespace
118
119void SPIRVAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
120 AU.addRequired<SPIRVModuleAnalysis>();
121 AU.addPreserved<SPIRVModuleAnalysis>();
123}
124
125// If the module has no functions, we need output global info anyway.
126void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
127 if (!ModuleSectionsEmitted) {
128 outputModuleSections();
129 ModuleSectionsEmitted = true;
130 }
131
132 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
133 // SPIRVModuleAnalysis sets GR->Bound = MAI->MaxID before printing. Any IDs
134 // allocated by AsmPrinter handlers (e.g. SPIRVNonSemanticDebugHandler) during
135 // outputModuleSections() are not counted. Refresh the bound here so the
136 // formula below sees the final allocation count.
137 if (MAI)
138 ST->getSPIRVGlobalRegistry()->setBound(MAI->MaxID);
139 VersionTuple SPIRVVersion = ST->getSPIRVVersion();
140 uint32_t Major = SPIRVVersion.getMajor();
141 uint32_t Minor = SPIRVVersion.getMinor().value_or(0);
142 // Bound is an approximation that accounts for the maximum used register
143 // number and number of generated OpLabels
144 unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;
145 if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())
146 static_cast<SPIRVObjectWriter &>(Asm->getWriter())
147 .setBuildVersion(Major, Minor, Bound);
148
149 cleanUp(M);
150}
151
152// Any cleanup actions with the Module after we don't care about its content
153// anymore.
154void SPIRVAsmPrinter::cleanUp(Module &M) {
155 // Verifier disallows uses of intrinsic global variables.
156 for (StringRef GVName :
157 {"llvm.global_ctors", "llvm.global_dtors", "llvm.used"}) {
158 if (GlobalVariable *GV = M.getNamedGlobal(GVName))
159 GV->setName("");
160 }
161}
162
163void SPIRVAsmPrinter::emitFunctionHeader() {
164 if (!ModuleSectionsEmitted) {
165 outputModuleSections();
166 ModuleSectionsEmitted = true;
167 }
168 // Get the subtarget from the current MachineFunction.
169 ST = &MF->getSubtarget<SPIRVSubtarget>();
170 TII = ST->getInstrInfo();
171 const Function &F = MF->getFunction();
172
173 if (isVerbose() && !isHidden()) {
174 OutStreamer->getCommentOS()
175 << "-- Begin function "
176 << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';
177 }
178
179 auto Section = getObjFileLowering().SectionForGlobal(&F, TM);
180 MF->setSection(Section);
181
182 // SPIRVAsmPrinter::emitFunctionHeader() does not call the base class,
183 // so handlers never receive beginFunction() from the normal path. Drive the
184 // per-function lifecycle here, matching what AsmPrinter::emitFunctionHeader()
185 // does for other targets.
186 for (auto &Handler : Handlers) {
187 Handler->beginFunction(MF);
188 Handler->beginBasicBlockSection(MF->front());
189 }
190}
191
192void SPIRVAsmPrinter::outputOpFunctionEnd() {
193 MCInst FunctionEndInst;
194 FunctionEndInst.setOpcode(SPIRV::OpFunctionEnd);
195 outputMCInst(FunctionEndInst);
196}
197
198void SPIRVAsmPrinter::emitFunctionBodyEnd() {
199 if (!isHidden())
200 outputOpFunctionEnd();
201}
202
203void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
204 // Do not emit anything if it's an internal service function.
205 if (isHidden())
206 return;
207
208 MCInst LabelInst;
209 LabelInst.setOpcode(SPIRV::OpLabel);
210 LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));
211 outputMCInst(LabelInst);
212 ++NLabels;
213 LabeledMBB.insert(&MBB);
214}
215
216void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
217 // Do not emit anything if it's an internal service function.
218 if (MBB.empty() || isHidden())
219 return;
220
221 // If it's the first MBB in MF, it has OpFunction and OpFunctionParameter, so
222 // OpLabel should be output after them.
223 if (MBB.getNumber() == MF->front().getNumber()) {
224 for (const MachineInstr &MI : MBB)
225 if (MI.getOpcode() == SPIRV::OpFunction)
226 return;
227 // TODO: this case should be checked by the verifier.
228 report_fatal_error("OpFunction is expected in the front MBB of MF");
229 }
230 emitOpLabel(MBB);
231}
232
233void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
234 raw_ostream &O) {
235 const MachineOperand &MO = MI->getOperand(OpNum);
236
237 switch (MO.getType()) {
240 break;
241
243 O << MO.getImm();
244 break;
245
247 O << MO.getFPImm();
248 break;
249
251 O << *MO.getMBB()->getSymbol();
252 break;
253
255 O << *getSymbol(MO.getGlobal());
256 break;
257
259 MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
260 O << BA->getName();
261 break;
262 }
263
265 O << *GetExternalSymbolSymbol(MO.getSymbolName());
266 break;
267
270 default:
271 llvm_unreachable("<unknown operand type>");
272 }
273}
274
275bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
276 const char *ExtraCode, raw_ostream &O) {
277 if (ExtraCode && ExtraCode[0])
278 return true; // Invalid instruction - SPIR-V does not have special modifiers
279
280 printOperand(MI, OpNo, O);
281 return false;
282}
283
285 const SPIRVInstrInfo *TII) {
286 return TII->isHeaderInstr(*MI) || MI->getOpcode() == SPIRV::OpFunction ||
287 MI->getOpcode() == SPIRV::OpFunctionParameter;
288}
289
290void SPIRVAsmPrinter::outputMCInst(MCInst &Inst) {
291 OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
292}
293
294void SPIRVAsmPrinter::outputInstruction(const MachineInstr *MI) {
295 SPIRVMCInstLower MCInstLowering;
296 MCInst TmpInst;
297 MCInstLowering.lower(MI, TmpInst, MAI);
298 outputMCInst(TmpInst);
299}
300
301void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {
302 SPIRV_MC::verifyInstructionPredicates(MI->getOpcode(),
303 getSubtargetInfo().getFeatureBits());
304
305 if (!MAI->getSkipEmission(MI))
306 outputInstruction(MI);
307
308 // Output OpLabel after OpFunction and OpFunctionParameter in the first MBB.
309 const MachineInstr *NextMI = MI->getNextNode();
310 if (!LabeledMBB.contains(MI->getParent()) && isFuncOrHeaderInstr(MI, TII) &&
311 (!NextMI || !isFuncOrHeaderInstr(NextMI, TII))) {
312 assert(MI->getParent()->getNumber() == MF->front().getNumber() &&
313 "OpFunction is not in the front MBB of MF");
314 emitOpLabel(*MI->getParent());
315 }
316}
317
318void SPIRVAsmPrinter::outputModuleSection(SPIRV::ModuleSectionType MSType) {
319 for (const MachineInstr *MI : MAI->getMSInstrs(MSType))
320 outputInstruction(MI);
321}
322
323void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
324 // Output OpSourceExtensions.
325 for (auto &Str : MAI->SrcExt) {
326 MCInst Inst;
327 Inst.setOpcode(SPIRV::OpSourceExtension);
328 addStringImm(Str.first(), Inst);
329 outputMCInst(Inst);
330 }
331 // Output OpString.
332 outputModuleSection(SPIRV::MB_DebugStrings);
333 // Output OpSource.
334 MCInst Inst;
335 Inst.setOpcode(SPIRV::OpSource);
336 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->SrcLang)));
337 Inst.addOperand(
338 MCOperand::createImm(static_cast<unsigned>(MAI->SrcLangVersion)));
339 outputMCInst(Inst);
340 // Emit OpString instructions for NSDI file paths and type names here, in
341 // section 7. OpString must precede type/constant declarations per the SPIR-V
342 // module layout (section 2.4). The OpExtInst instructions that reference
343 // these strings are emitted later at section 10 by
344 // emitNonSemanticGlobalDebugInfo().
345 if (NSDebugHandler)
346 NSDebugHandler->emitNonSemanticDebugStrings(*MAI);
347}
348
349void SPIRVAsmPrinter::outputOpExtInstImports(const Module &M) {
350 for (auto &CU : MAI->ExtInstSetMap) {
351 unsigned Set = CU.first;
352 MCRegister Reg = CU.second;
353 MCInst Inst;
354 Inst.setOpcode(SPIRV::OpExtInstImport);
357 static_cast<SPIRV::InstructionSet::InstructionSet>(Set)),
358 Inst);
359 outputMCInst(Inst);
360 }
361}
362
363void SPIRVAsmPrinter::outputOpMemoryModel() {
364 MCInst Inst;
365 Inst.setOpcode(SPIRV::OpMemoryModel);
366 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Addr)));
367 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(MAI->Mem)));
368 outputMCInst(Inst);
369}
370
371// Before the OpEntryPoints' output, we need to add the entry point's
372// interfaces. The interface is a list of IDs of global OpVariable instructions.
373// These declare the set of global variables from a module that form
374// the interface of this entry point.
375void SPIRVAsmPrinter::outputEntryPoints() {
376 // Find all OpVariable IDs with required StorageClass.
377 DenseSet<MCRegister> InterfaceIDs;
378 for (const MachineInstr *MI : MAI->GlobalVarList) {
379 assert(MI->getOpcode() == SPIRV::OpVariable);
380 auto SC = static_cast<SPIRV::StorageClass::StorageClass>(
381 MI->getOperand(2).getImm());
382 // Before version 1.4, the interface's storage classes are limited to
383 // the Input and Output storage classes. Starting with version 1.4,
384 // the interface's storage classes are all storage classes used in
385 // declaring all global variables referenced by the entry point call tree.
386 if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) ||
387 SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) {
388 const MachineFunction *MF = MI->getMF();
389 MCRegister Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
390 InterfaceIDs.insert(Reg);
391 }
392 }
393
394 // Output OpEntryPoints adding interface args to all of them.
395 for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_EntryPoints)) {
396 SPIRVMCInstLower MCInstLowering;
397 MCInst TmpInst;
398 MCInstLowering.lower(MI, TmpInst, MAI);
399 for (MCRegister Reg : InterfaceIDs) {
400 assert(Reg.isValid());
402 }
403 outputMCInst(TmpInst);
404 }
405}
406
407// Create global OpCapability instructions for the required capabilities.
408void SPIRVAsmPrinter::outputGlobalRequirements() {
409 // Abort here if not all requirements can be satisfied.
410 MAI->Reqs.checkSatisfiable(*ST);
411
412 for (const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
413 MCInst Inst;
414 Inst.setOpcode(SPIRV::OpCapability);
416 outputMCInst(Inst);
417 }
418
419 // Generate the final OpExtensions with strings instead of enums.
420 for (const auto &Ext : MAI->Reqs.getExtensions()) {
421 MCInst Inst;
422 Inst.setOpcode(SPIRV::OpExtension);
424 SPIRV::OperandCategory::ExtensionOperand, Ext),
425 Inst);
426 outputMCInst(Inst);
427 }
428 // TODO add a pseudo instr for version number.
429}
430
431void SPIRVAsmPrinter::outputExtFuncDecls() {
432 // Insert OpFunctionEnd after each declaration.
433 auto I = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).begin(),
434 E = MAI->getMSInstrs(SPIRV::MB_ExtFuncDecls).end();
435 for (; I != E; ++I) {
436 outputInstruction(*I);
437 if ((I + 1) == E || (*(I + 1))->getOpcode() == SPIRV::OpFunction)
438 outputOpFunctionEnd();
439 }
440}
441
442// Encode LLVM type by SPIR-V execution mode VecTypeHint.
443static unsigned encodeVecTypeHint(Type *Ty) {
444 if (Ty->isHalfTy())
445 return 4;
446 if (Ty->isFloatTy())
447 return 5;
448 if (Ty->isDoubleTy())
449 return 6;
450 if (IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
451 switch (IntTy->getIntegerBitWidth()) {
452 case 8:
453 return 0;
454 case 16:
455 return 1;
456 case 32:
457 return 2;
458 case 64:
459 return 3;
460 default:
461 llvm_unreachable("invalid integer type");
462 }
463 }
465 Type *EleTy = VecTy->getElementType();
466 unsigned Size = VecTy->getNumElements();
467 return Size << 16 | encodeVecTypeHint(EleTy);
468 }
469 llvm_unreachable("invalid type");
470}
471
472static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst,
474 for (const MDOperand &MDOp : MDN->operands()) {
475 if (auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
476 Constant *C = CMeta->getValue();
477 if (ConstantInt *Const = dyn_cast<ConstantInt>(C)) {
478 Inst.addOperand(MCOperand::createImm(Const->getZExtValue()));
479 } else if (auto *CE = dyn_cast<Function>(C)) {
480 MCRegister FuncReg = MAI->getGlobalObjReg(CE);
481 assert(FuncReg.isValid());
482 Inst.addOperand(MCOperand::createReg(FuncReg));
483 }
484 }
485 }
486}
487
488void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
489 MCRegister Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM,
490 unsigned ExpectMDOps, int64_t DefVal) {
491 MCInst Inst;
492 Inst.setOpcode(SPIRV::OpExecutionMode);
494 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
495 addOpsFromMDNode(Node, Inst, MAI);
496 // reqd_work_group_size and work_group_size_hint require 3 operands,
497 // if metadata contains less operands, just add a default value
498 unsigned NodeSz = Node->getNumOperands();
499 if (ExpectMDOps > 0 && NodeSz < ExpectMDOps)
500 for (unsigned i = NodeSz; i < ExpectMDOps; ++i)
501 Inst.addOperand(MCOperand::createImm(DefVal));
502 outputMCInst(Inst);
503}
504
505void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(
506 const MCRegister &Reg, const Attribute &Attr,
507 SPIRV::ExecutionMode::ExecutionMode EM) {
508 assert(Attr.isValid() && "Function called with an invalid attribute.");
509
510 MCInst Inst;
511 Inst.setOpcode(SPIRV::OpExecutionMode);
513 Inst.addOperand(MCOperand::createImm(static_cast<unsigned>(EM)));
514
515 SmallVector<StringRef> NumThreads;
516 Attr.getValueAsString().split(NumThreads, ',');
517 assert(NumThreads.size() == 3 && "invalid numthreads");
518 for (uint32_t i = 0; i < 3; ++i) {
519 uint32_t V;
520 [[maybe_unused]] bool Result = NumThreads[i].getAsInteger(10, V);
521 assert(!Result && "Failed to parse numthreads");
523 }
524
525 outputMCInst(Inst);
526}
527
528void SPIRVAsmPrinter::outputExecutionModeFromEnableMaximalReconvergenceAttr(
529 const MCRegister &Reg, const SPIRVSubtarget &ST) {
530 assert(ST.canUseExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence) &&
531 "Function called when SPV_KHR_maximal_reconvergence is not enabled.");
532
533 MCInst Inst;
534 Inst.setOpcode(SPIRV::OpExecutionMode);
536 unsigned EM =
537 static_cast<unsigned>(SPIRV::ExecutionMode::MaximallyReconvergesKHR);
539 outputMCInst(Inst);
540}
541
542void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {
543 NamedMDNode *Node = M.getNamedMetadata("spirv.ExecutionMode");
544 if (Node) {
545 for (unsigned i = 0; i < Node->getNumOperands(); i++) {
546 const auto EM =
548 cast<ConstantAsMetadata>((Node->getOperand(i))->getOperand(1))
549 ->getValue())
550 ->getZExtValue();
551 // Skip ArithmeticPoisonKHR to avoid a duplicate.
552 if (EM == SPIRV::ExecutionMode::ArithmeticPoisonKHR)
553 continue;
554 // If SPV_KHR_float_controls2 is enabled and we find any of
555 // FPFastMathDefault, ContractionOff or SignedZeroInfNanPreserve execution
556 // modes, skip it, it'll be done somewhere else.
557 if (ST->canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
558 if (EM == SPIRV::ExecutionMode::FPFastMathDefault ||
559 EM == SPIRV::ExecutionMode::ContractionOff ||
560 EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve)
561 continue;
562 }
563
564 MCInst Inst;
565 Inst.setOpcode(SPIRV::OpExecutionMode);
566 addOpsFromMDNode(cast<MDNode>(Node->getOperand(i)), Inst, MAI);
567 outputMCInst(Inst);
568 }
569 outputFPFastMathDefaultInfo();
570 }
571 for (auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
572 const Function &F = *FI;
573 // Only operands of OpEntryPoint instructions are allowed to be
574 // <Entry Point> operands of OpExecutionMode
575 if (F.isDeclaration() || !isEntryPoint(F))
576 continue;
577 MCRegister FReg = MAI->getGlobalObjReg(&F);
578 assert(FReg.isValid());
579
580 if (Attribute Attr = F.getFnAttribute("hlsl.shader"); Attr.isValid()) {
581 // SPIR-V common validation: Fragment requires OriginUpperLeft or
582 // OriginLowerLeft.
583 // VUID-StandaloneSpirv-OriginLowerLeft-04653: Fragment must declare
584 // OriginUpperLeft.
585 if (Attr.getValueAsString() == "pixel") {
586 MCInst Inst;
587 Inst.setOpcode(SPIRV::OpExecutionMode);
589 unsigned EM =
590 static_cast<unsigned>(SPIRV::ExecutionMode::OriginUpperLeft);
592 outputMCInst(Inst);
593 }
594 }
595 if (MDNode *Node = F.getMetadata("reqd_work_group_size"))
596 outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize,
597 3, 1);
598 if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid())
599 outputExecutionModeFromNumthreadsAttribute(
600 FReg, Attr, SPIRV::ExecutionMode::LocalSize);
601 if (Attribute Attr = F.getFnAttribute("enable-maximal-reconvergence");
602 Attr.getValueAsBool()) {
603 outputExecutionModeFromEnableMaximalReconvergenceAttr(FReg, *ST);
604 }
605 if (MDNode *Node = F.getMetadata("work_group_size_hint"))
606 outputExecutionModeFromMDNode(FReg, Node,
607 SPIRV::ExecutionMode::LocalSizeHint, 3, 1);
608 if (MDNode *Node = F.getMetadata("reqd_sub_group_size"))
609 outputExecutionModeFromMDNode(FReg, Node,
610 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
611 if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size"))
612 outputExecutionModeFromMDNode(FReg, Node,
613 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
614 if (MDNode *Node = F.getMetadata("max_work_group_size")) {
615 if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_kernel_attributes))
616 outputExecutionModeFromMDNode(
617 FReg, Node, SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, 3, 1);
618 }
619 if (MDNode *Node = F.getMetadata("vec_type_hint")) {
620 MCInst Inst;
621 Inst.setOpcode(SPIRV::OpExecutionMode);
623 unsigned EM = static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
625 unsigned TypeCode = encodeVecTypeHint(getMDOperandAsType(Node, 0));
626 Inst.addOperand(MCOperand::createImm(TypeCode));
627 outputMCInst(Inst);
628 }
629 // Per SPV_KHR_poison_freeze description of PoisonFreezeKHR "If declared,
630 // all entry points must use the ArithmeticPoisonKHR execution mode".
631 if (llvm::is_contained(MAI->Reqs.getMinimalCapabilities(),
632 SPIRV::Capability::PoisonFreezeKHR)) {
633 MCInst Inst;
634 Inst.setOpcode(SPIRV::OpExecutionMode);
636 unsigned EM =
637 static_cast<unsigned>(SPIRV::ExecutionMode::ArithmeticPoisonKHR);
639 outputMCInst(Inst);
640 }
641 if (ST->isKernel() && !M.getNamedMetadata("spirv.ExecutionMode") &&
642 !M.getNamedMetadata("opencl.enable.FP_CONTRACT")) {
643 if (ST->canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
644 // When SPV_KHR_float_controls2 is enabled, ContractionOff is
645 // deprecated. We need to use FPFastMathDefault with the appropriate
646 // flags instead. Since FPFastMathDefault takes a target type, we need
647 // to emit it for each floating-point type that exists in the module
648 // to match the effect of ContractionOff. As of now, there are 3 FP
649 // types: fp16, fp32 and fp64.
650
651 // We only end up here because there is no "spirv.ExecutionMode"
652 // metadata, so that means no FPFastMathDefault. Therefore, we only
653 // need to make sure AllowContract is set to 0, as the rest of flags.
654 // We still need to emit the OpExecutionMode instruction, otherwise
655 // it's up to the client API to define the flags. Therefore, we need
656 // to find the constant with 0 value.
657
658 // Collect the SPIRVTypes for fp16, fp32, and fp64 and the constant of
659 // type int32 with 0 value to represent the FP Fast Math Mode.
660 std::vector<const MachineInstr *> SPIRVFloatTypes;
661 const MachineInstr *ConstZeroInt32 = nullptr;
662 for (const MachineInstr *MI :
663 MAI->getMSInstrs(SPIRV::MB_TypeConstVars)) {
664 unsigned OpCode = MI->getOpcode();
665
666 // Collect the SPIRV type if it's a float.
667 if (OpCode == SPIRV::OpTypeFloat) {
668 // Skip if the target type is not fp16, fp32, fp64.
669 const unsigned OpTypeFloatSize = MI->getOperand(1).getImm();
670 if (OpTypeFloatSize != 16 && OpTypeFloatSize != 32 &&
671 OpTypeFloatSize != 64) {
672 continue;
673 }
674 SPIRVFloatTypes.push_back(MI);
675 continue;
676 }
677
678 if (OpCode == SPIRV::OpConstantNull) {
679 // Check if the constant is int32, if not skip it.
680 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
681 MachineInstr *TypeMI = MRI.getVRegDef(MI->getOperand(1).getReg());
682 bool IsInt32Ty = TypeMI &&
683 TypeMI->getOpcode() == SPIRV::OpTypeInt &&
684 TypeMI->getOperand(1).getImm() == 32;
685 if (IsInt32Ty)
686 ConstZeroInt32 = MI;
687 }
688 }
689
690 // When SPV_KHR_float_controls2 is enabled, ContractionOff is
691 // deprecated. We need to use FPFastMathDefault with the appropriate
692 // flags instead. Since FPFastMathDefault takes a target type, we need
693 // to emit it for each floating-point type that exists in the module
694 // to match the effect of ContractionOff. As of now, there are 3 FP
695 // types: fp16, fp32 and fp64.
696 for (const MachineInstr *MI : SPIRVFloatTypes) {
697 MCInst Inst;
698 Inst.setOpcode(SPIRV::OpExecutionModeId);
700 unsigned EM =
701 static_cast<unsigned>(SPIRV::ExecutionMode::FPFastMathDefault);
703 const MachineFunction *MF = MI->getMF();
704 MCRegister TypeReg =
705 MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
706 Inst.addOperand(MCOperand::createReg(TypeReg));
707 assert(ConstZeroInt32 && "There should be a constant zero.");
708 MCRegister ConstReg = MAI->getRegisterAlias(
709 ConstZeroInt32->getMF(), ConstZeroInt32->getOperand(0).getReg());
710 Inst.addOperand(MCOperand::createReg(ConstReg));
711 outputMCInst(Inst);
712 }
713 } else {
714 MCInst Inst;
715 Inst.setOpcode(SPIRV::OpExecutionMode);
717 unsigned EM =
718 static_cast<unsigned>(SPIRV::ExecutionMode::ContractionOff);
720 outputMCInst(Inst);
721 }
722 }
723 }
724}
725
726void SPIRVAsmPrinter::outputAnnotations(const Module &M) {
727 outputModuleSection(SPIRV::MB_Annotations);
728 // Process llvm.global.annotations special global variable.
729 for (auto F = M.global_begin(), E = M.global_end(); F != E; ++F) {
730 if ((*F).getName() != "llvm.global.annotations")
731 continue;
732 const GlobalVariable *V = &(*F);
733 const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
734 for (Value *Op : CA->operands()) {
735 ConstantStruct *CS = cast<ConstantStruct>(Op);
736 // The first field of the struct contains a pointer to
737 // the annotated variable.
738 Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
739 auto *GO = dyn_cast<GlobalObject>(AnnotatedVar);
740 MCRegister Reg = GO ? MAI->getGlobalObjReg(GO) : MCRegister();
741 if (!Reg.isValid()) {
742 std::string DiagMsg;
743 raw_string_ostream OS(DiagMsg);
744 AnnotatedVar->print(OS);
745 DiagMsg = "Unsupported value in llvm.global.annotations: " + DiagMsg;
746 report_fatal_error(DiagMsg.c_str());
747 }
748
749 // The second field contains a pointer to a global annotation string.
750 GlobalVariable *GV =
752
753 StringRef AnnotationString;
754 [[maybe_unused]] bool Success =
755 getConstantStringInfo(GV, AnnotationString);
756 assert(Success && "Failed to get annotation string");
757 MCInst Inst;
758 Inst.setOpcode(SPIRV::OpDecorate);
760 unsigned Dec = static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
762 addStringImm(AnnotationString, Inst);
763 outputMCInst(Inst);
764 }
765 }
766}
767
768void SPIRVAsmPrinter::outputFPFastMathDefaultInfo() {
769 // Collect the SPIRVTypes that are OpTypeFloat and the constants of type
770 // int32, that might be used as FP Fast Math Mode.
771 std::vector<const MachineInstr *> SPIRVFloatTypes;
772 // Hashtable to associate immediate values with the constant holding them.
773 std::unordered_map<int, const MachineInstr *> ConstMap;
774 for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_TypeConstVars)) {
775 // Skip if the instruction is not OpTypeFloat or OpConstant.
776 unsigned OpCode = MI->getOpcode();
777 if (OpCode != SPIRV::OpTypeFloat && OpCode != SPIRV::OpConstantI &&
778 OpCode != SPIRV::OpConstantNull)
779 continue;
780
781 // Collect the SPIRV type if it's a float.
782 if (OpCode == SPIRV::OpTypeFloat) {
783 SPIRVFloatTypes.push_back(MI);
784 } else {
785 // Check if the constant is int32, if not skip it.
786 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
787 MachineInstr *TypeMI = MRI.getVRegDef(MI->getOperand(1).getReg());
788 if (!TypeMI || TypeMI->getOpcode() != SPIRV::OpTypeInt ||
789 TypeMI->getOperand(1).getImm() != 32)
790 continue;
791
792 if (OpCode == SPIRV::OpConstantI)
793 ConstMap[MI->getOperand(2).getImm()] = MI;
794 else
795 ConstMap[0] = MI;
796 }
797 }
798
799 for (const auto &[Func, FPFastMathDefaultInfoVec] :
800 MAI->FPFastMathDefaultInfoMap) {
801 if (FPFastMathDefaultInfoVec.empty())
802 continue;
803
804 for (const MachineInstr *MI : SPIRVFloatTypes) {
805 unsigned OpTypeFloatSize = MI->getOperand(1).getImm();
808 assert(Index < FPFastMathDefaultInfoVec.size() &&
809 "Index out of bounds for FPFastMathDefaultInfoVec");
810 const auto &FPFastMathDefaultInfo = FPFastMathDefaultInfoVec[Index];
811 assert(FPFastMathDefaultInfo.Ty &&
812 "Expected target type for FPFastMathDefaultInfo");
813 assert(FPFastMathDefaultInfo.Ty->getScalarSizeInBits() ==
814 OpTypeFloatSize &&
815 "Mismatched float type size");
816 MCInst Inst;
817 Inst.setOpcode(SPIRV::OpExecutionModeId);
818 MCRegister FuncReg = MAI->getGlobalObjReg(Func);
819 assert(FuncReg.isValid());
820 Inst.addOperand(MCOperand::createReg(FuncReg));
821 Inst.addOperand(
822 MCOperand::createImm(SPIRV::ExecutionMode::FPFastMathDefault));
823 MCRegister TypeReg =
824 MAI->getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
825 Inst.addOperand(MCOperand::createReg(TypeReg));
826 unsigned Flags = FPFastMathDefaultInfo.FastMathFlags;
827 if (FPFastMathDefaultInfo.ContractionOff &&
828 (Flags & SPIRV::FPFastMathMode::AllowContract))
830 "Conflicting FPFastMathFlags: ContractionOff and AllowContract");
831
832 if (FPFastMathDefaultInfo.SignedZeroInfNanPreserve &&
833 !(Flags &
834 (SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
835 SPIRV::FPFastMathMode::NSZ))) {
836 if (FPFastMathDefaultInfo.FPFastMathDefault)
837 report_fatal_error("Conflicting FPFastMathFlags: "
838 "SignedZeroInfNanPreserve but at least one of "
839 "NotNaN/NotInf/NSZ is enabled.");
840 }
841
842 // Don't emit if none of the execution modes was used.
843 if (Flags == SPIRV::FPFastMathMode::None &&
844 !FPFastMathDefaultInfo.ContractionOff &&
845 !FPFastMathDefaultInfo.SignedZeroInfNanPreserve &&
846 !FPFastMathDefaultInfo.FPFastMathDefault)
847 continue;
848
849 // Retrieve the constant instruction for the immediate value.
850 auto It = ConstMap.find(Flags);
851 if (It == ConstMap.end())
852 report_fatal_error("Expected constant instruction for FP Fast Math "
853 "Mode operand of FPFastMathDefault execution mode.");
854 const MachineInstr *ConstMI = It->second;
855 MCRegister ConstReg = MAI->getRegisterAlias(
856 ConstMI->getMF(), ConstMI->getOperand(0).getReg());
857 Inst.addOperand(MCOperand::createReg(ConstReg));
858 outputMCInst(Inst);
859 }
860 }
861}
862
863void SPIRVAsmPrinter::outputModuleSections() {
864 const Module *M = MMI->getModule();
865 // Get the global subtarget to output module-level info.
866 ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
867 TII = ST->getInstrInfo();
868 MAI = &getAnalysis<SPIRVModuleAnalysis>().MAI;
869 assert(ST && TII && MAI && M && "Module analysis is required");
870
871 // Let the NSDI handler add its extension and ext inst import entry to MAI
872 // before the module header sections are emitted.
873 if (NSDebugHandler)
874 NSDebugHandler->prepareModuleOutput(*ST, *MAI);
875
876 // Output instructions according to the Logical Layout of a Module:
877 // 1,2. All OpCapability instructions, then optional OpExtension
878 // instructions.
879 outputGlobalRequirements();
880 // 3. Optional OpExtInstImport instructions.
881 outputOpExtInstImports(*M);
882 // 4. The single required OpMemoryModel instruction.
883 outputOpMemoryModel();
884 // 5. All entry point declarations, using OpEntryPoint.
885 outputEntryPoints();
886 // 6. Execution-mode declarations, using OpExecutionMode or
887 // OpExecutionModeId.
888 outputExecutionMode(*M);
889 // 7a. Debug: all OpString, OpSourceExtension, OpSource, and
890 // OpSourceContinued, without forward references.
891 outputDebugSourceAndStrings(*M);
892 // 7b. Debug: all OpName and all OpMemberName.
893 outputModuleSection(SPIRV::MB_DebugNames);
894 // 7c. Debug: all OpModuleProcessed instructions.
895 outputModuleSection(SPIRV::MB_DebugModuleProcessed);
896 // xxx. SPV_INTEL_memory_access_aliasing instructions go before 8.
897 // "All annotation instructions"
898 outputModuleSection(SPIRV::MB_AliasingInsts);
899 // 8. All annotation instructions (all decorations).
900 outputAnnotations(*M);
901 // 9. All type declarations (OpTypeXXX instructions), all constant
902 // instructions, and all global variable declarations. This section is
903 // the first section to allow use of: OpLine and OpNoLine debug information;
904 // non-semantic instructions with OpExtInst.
905 outputModuleSection(SPIRV::MB_TypeConstVars);
906 // 10. All global NonSemantic.Shader.DebugInfo.100 instructions. The
907 // SPIRVNonSemanticDebugHandler emits these directly as MCInsts; the
908 // MB_NonSemanticGlobalDI section in MAI is intentionally left empty.
909 if (NSDebugHandler)
910 NSDebugHandler->emitNonSemanticGlobalDebugInfo(*MAI);
911 // 11. All function declarations (functions without a body).
912 outputExtFuncDecls();
913 // 12. All function definitions (functions with a body).
914 // This is done in regular function output.
915}
916
917bool SPIRVAsmPrinter::doInitialization(Module &M) {
918 ModuleSectionsEmitted = false;
919 // Register the NSDI handler before calling the base class so that
920 // AsmPrinter::doInitialization() calls Handler->beginModule(M) for it.
921 if (M.getNamedMetadata("llvm.dbg.cu")) {
922 auto Handler = std::make_unique<SPIRVNonSemanticDebugHandler>(*this);
923 NSDebugHandler = Handler.get();
924 addAsmPrinterHandler(std::move(Handler));
925 }
926 // We need to call the parent's one explicitly.
928}
929
930char SPIRVAsmPrinter::ID = 0;
931
932INITIALIZE_PASS(SPIRVAsmPrinter, "spirv-asm-printer", "SPIRV Assembly Printer",
933 false, false)
934
935// Force static initialization.
937LLVMInitializeSPIRVAsmPrinter() {
941}
#define Success
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
#define X(NUM, ENUM, NAME)
Definition ELF.h:853
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
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
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:528
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")
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:91
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:105
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
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:261
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
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
iterator end()
Definition DenseMap.h:85
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:41
constexpr bool isValid() const
Definition MCRegister.h:84
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
Metadata node.
Definition Metadata.h:1080
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1442
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
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.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
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.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
constexpr bool isValid() const
Definition Register.h:112
static const char * getRegisterName(MCRegister Reg)
void lower(const MachineInstr *MI, MCInst &OutMI, SPIRV::ModuleAnalysisInfo *MAI) const
AsmPrinter handler that emits NonSemantic.Shader.DebugInfo.100 (NSDI) instructions for the SPIR-V bac...
void emitNonSemanticDebugStrings(SPIRV::ModuleAnalysisInfo &MAI)
Emit OpString instructions for all NSDI file paths and basic type names into the debug section (secti...
void emitNonSemanticGlobalDebugInfo(SPIRV::ModuleAnalysisInfo &MAI)
Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit, DebugTypeBasic,...
void prepareModuleOutput(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
Add SPV_KHR_non_semantic_info extension and NonSemantic.Shader.DebugInfo.100 ext inst set entry to MA...
const SPIRVInstrInfo * getInstrInfo() const override
bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const
SPIRVGlobalRegistry * getSPIRVGlobalRegistry() 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.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:730
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:46
op_range operands()
Definition User.h:267
Value * getOperand(unsigned i) const
Definition User.h:207
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:712
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:212
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
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:643
DenseMap< Value *, Constant * > ConstMap
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:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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:559
Type * getMDOperandAsType(const MDNode *N, unsigned I)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1946
void addStringImm(const StringRef &Str, MCInst &Inst)
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
static size_t computeFPFastMathDefaultInfoVecIndex(size_t BitWidth)
Definition SPIRVUtils.h:148
MCRegister getGlobalObjReg(const GlobalObject *GO)