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