43#define DEBUG_TYPE "asm-printer"
52 std::unique_ptr<MCStreamer> Streamer)
53 :
AsmPrinter(TM, std::move(Streamer)), ST(
nullptr),
TII(
nullptr) {}
54 bool ModuleSectionsEmitted;
63 void outputMCInst(
MCInst &Inst);
66 void outputGlobalRequirements();
67 void outputEntryPoints();
68 void outputDebugSourceAndStrings(
const Module &M);
69 void outputOpExtInstImports(
const Module &M);
70 void outputOpMemoryModel();
71 void outputOpFunctionEnd();
72 void outputExtFuncDecls();
74 SPIRV::ExecutionMode::ExecutionMode EM,
75 unsigned ExpectMDOps, int64_t DefVal);
76 void outputExecutionModeFromNumthreadsAttribute(
78 SPIRV::ExecutionMode::ExecutionMode EM);
79 void outputExecutionMode(
const Module &M);
80 void outputAnnotations(
const Module &M);
81 void outputModuleSections();
83 return MF->getFunction()
90 void emitFunctionHeader()
override;
108void SPIRVAsmPrinter::getAnalysisUsage(
AnalysisUsage &AU)
const {
115void SPIRVAsmPrinter::emitEndOfAsmFile(
Module &M) {
116 if (ModuleSectionsEmitted ==
false) {
117 outputModuleSections();
118 ModuleSectionsEmitted =
true;
127 unsigned Bound = 2 * (
ST->getBound() + 1) + NLabels;
128 if (
MCAssembler *Asm = OutStreamer->getAssemblerPtr())
130 .setBuildVersion(Major, Minor, Bound);
137void SPIRVAsmPrinter::cleanUp(
Module &M) {
139 for (
StringRef GVName : {
"llvm.global_ctors",
"llvm.global_dtors",
140 "llvm.used",
"llvm.compiler.used"}) {
146void SPIRVAsmPrinter::emitFunctionHeader() {
147 if (ModuleSectionsEmitted ==
false) {
148 outputModuleSections();
149 ModuleSectionsEmitted =
true;
153 TII =
ST->getInstrInfo();
156 if (isVerbose() && !isHidden()) {
157 OutStreamer->getCommentOS()
158 <<
"-- Begin function "
162 auto Section = getObjFileLowering().SectionForGlobal(&
F, TM);
163 MF->setSection(Section);
166void SPIRVAsmPrinter::outputOpFunctionEnd() {
168 FunctionEndInst.
setOpcode(SPIRV::OpFunctionEnd);
169 outputMCInst(FunctionEndInst);
172void SPIRVAsmPrinter::emitFunctionBodyEnd() {
174 outputOpFunctionEnd();
185 outputMCInst(LabelInst);
187 LabeledMBB.insert(&
MBB);
199 if (
MI.getOpcode() == SPIRV::OpFunction)
207void SPIRVAsmPrinter::printOperand(
const MachineInstr *
MI,
int OpNum,
249bool SPIRVAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
251 if (ExtraCode && ExtraCode[0])
260 return TII->isHeaderInstr(*
MI) ||
MI->getOpcode() == SPIRV::OpFunction ||
261 MI->getOpcode() == SPIRV::OpFunctionParameter;
264void SPIRVAsmPrinter::outputMCInst(
MCInst &Inst) {
265 OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
271 MCInstLowering.
lower(
MI, TmpInst, MAI);
272 outputMCInst(TmpInst);
276 SPIRV_MC::verifyInstructionPredicates(
MI->getOpcode(),
277 getSubtargetInfo().getFeatureBits());
279 if (!MAI->getSkipEmission(
MI))
280 outputInstruction(
MI);
286 assert(
MI->getParent()->getNumber() == MF->front().getNumber() &&
287 "OpFunction is not in the front MBB of MF");
288 emitOpLabel(*
MI->getParent());
294 outputInstruction(
MI);
297void SPIRVAsmPrinter::outputDebugSourceAndStrings(
const Module &M) {
299 for (
auto &Str : MAI->SrcExt) {
301 Inst.
setOpcode(SPIRV::OpSourceExtension);
316void SPIRVAsmPrinter::outputOpExtInstImports(
const Module &M) {
317 for (
auto &
CU : MAI->ExtInstSetMap) {
318 unsigned Set =
CU.first;
324 static_cast<SPIRV::InstructionSet::InstructionSet
>(Set)),
330void SPIRVAsmPrinter::outputOpMemoryModel() {
342void SPIRVAsmPrinter::outputEntryPoints() {
346 assert(
MI->getOpcode() == SPIRV::OpVariable);
347 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
348 MI->getOperand(2).getImm());
354 SC == SPIRV::StorageClass::Input ||
SC == SPIRV::StorageClass::Output) {
356 Register Reg = MAI->getRegisterAlias(MF,
MI->getOperand(0).getReg());
365 MCInstLowering.
lower(
MI, TmpInst, MAI);
370 outputMCInst(TmpInst);
375void SPIRVAsmPrinter::outputGlobalRequirements() {
377 MAI->Reqs.checkSatisfiable(*ST);
379 for (
const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
387 for (
const auto &Ext : MAI->Reqs.getExtensions()) {
391 SPIRV::OperandCategory::ExtensionOperand, Ext),
398void SPIRVAsmPrinter::outputExtFuncDecls() {
402 for (;
I != E; ++
I) {
403 outputInstruction(*
I);
404 if ((
I + 1) == E || (*(
I + 1))->
getOpcode() == SPIRV::OpFunction)
405 outputOpFunctionEnd();
417 if (
IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
418 switch (IntTy->getIntegerBitWidth()) {
432 Type *EleTy = VecTy->getElementType();
433 unsigned Size = VecTy->getNumElements();
442 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
446 }
else if (
auto *CE = dyn_cast<Function>(
C)) {
455void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
457 unsigned ExpectMDOps, int64_t DefVal) {
465 unsigned NodeSz =
Node->getNumOperands();
466 if (ExpectMDOps > 0 && NodeSz < ExpectMDOps)
467 for (
unsigned i = NodeSz; i < ExpectMDOps; ++i)
472void SPIRVAsmPrinter::outputExecutionModeFromNumthreadsAttribute(
474 SPIRV::ExecutionMode::ExecutionMode EM) {
475 assert(Attr.
isValid() &&
"Function called with an invalid attribute.");
484 assert(NumThreads.size() == 3 &&
"invalid numthreads");
487 [[maybe_unused]]
bool Result = NumThreads[i].getAsInteger(10, V);
488 assert(!Result &&
"Failed to parse numthreads");
495void SPIRVAsmPrinter::outputExecutionMode(
const Module &M) {
498 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
505 for (
auto FI =
M.begin(), E =
M.end(); FI != E; ++FI) {
513 if (
MDNode *
Node =
F.getMetadata(
"reqd_work_group_size"))
514 outputExecutionModeFromMDNode(FReg,
Node, SPIRV::ExecutionMode::LocalSize,
517 outputExecutionModeFromNumthreadsAttribute(
518 FReg, Attr, SPIRV::ExecutionMode::LocalSize);
519 if (
MDNode *
Node =
F.getMetadata(
"work_group_size_hint"))
520 outputExecutionModeFromMDNode(FReg,
Node,
521 SPIRV::ExecutionMode::LocalSizeHint, 3, 1);
522 if (
MDNode *
Node =
F.getMetadata(
"intel_reqd_sub_group_size"))
523 outputExecutionModeFromMDNode(FReg,
Node,
524 SPIRV::ExecutionMode::SubgroupSize, 0, 0);
525 if (
MDNode *
Node =
F.getMetadata(
"vec_type_hint")) {
529 unsigned EM =
static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
535 if (
ST->isOpenCLEnv() && !
M.getNamedMetadata(
"spirv.ExecutionMode") &&
536 !
M.getNamedMetadata(
"opencl.enable.FP_CONTRACT")) {
540 unsigned EM =
static_cast<unsigned>(SPIRV::ExecutionMode::ContractionOff);
547void SPIRVAsmPrinter::outputAnnotations(
const Module &M) {
550 for (
auto F =
M.global_begin(), E =
M.global_end();
F != E; ++
F) {
551 if ((*F).getName() !=
"llvm.global.annotations")
560 if (!isa<Function>(AnnotatedVar))
564 if (!
Reg.isValid()) {
568 DiagMsg =
"Unknown function in llvm.global.annotations: " + DiagMsg;
581 unsigned Dec =
static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
589void SPIRVAsmPrinter::outputModuleSections() {
590 const Module *
M = MMI->getModule();
593 TII =
ST->getInstrInfo();
595 assert(ST &&
TII && MAI && M &&
"Module analysis is required");
598 outputGlobalRequirements();
600 outputOpExtInstImports(*M);
602 outputOpMemoryModel();
606 outputExecutionMode(*M);
609 outputDebugSourceAndStrings(*M);
615 outputAnnotations(*M);
624 outputExtFuncDecls();
629bool SPIRVAsmPrinter::doInitialization(
Module &M) {
630 ModuleSectionsEmitted =
false;
#define LLVM_EXTERNAL_VISIBILITY
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst, SPIRV::ModuleAnalysisInfo *MAI)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVAsmPrinter()
static bool isFuncOrHeaderInstr(const MachineInstr *MI, const SPIRVInstrInfo *TII)
static unsigned encodeVecTypeHint(Type *Ty)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
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.
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
virtual void emitBasicBlockEnd(const MachineBasicBlock &MBB)
Targets can override this to emit stuff at the end of a basic block.
const MCAsmInfo * MAI
Target Asm Printer information.
virtual void emitFunctionBodyStart()
Targets can override this to emit stuff before the first basic block in the function.
virtual void emitEndOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the end of their file...
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.
virtual void emitBasicBlockStart(const MachineBasicBlock &MBB)
Targets can override this to emit stuff at the start of a basic block.
virtual void emitFunctionBodyEnd()
Targets can override this to emit stuff after the last basic block in the function.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
ConstantArray - Constant Array Declarations.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
Implements a dense probed hash-table based set.
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.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
StringRef getName() const
getName - Get the symbol name.
ArrayRef< MDOperand > operands() const
Tracking metadata reference owned by Metadata.
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.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() 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.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
static const char * getRegisterName(MCRegister Reg)
void lower(const MachineInstr *MI, MCInst &OutMI, SPIRV::ModuleAnalysisInfo *MAI) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
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.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Value * getOperand(unsigned i) const
LLVM Value Representation.
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Represents a version number in the form major[.minor[.subminor[.build]]].
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)
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
@ MB_DebugModuleProcessed
Reg
All possible values of the reg field in the ModR/M byte.
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheSPIRV32Target()
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)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
bool isEntryPoint(const Function &F)
Target & getTheSPIRV64Target()
Target & getTheSPIRVLogicalTarget()
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
Register getFuncReg(const Function *F)