40#define DEBUG_TYPE "asm-printer"
46 std::unique_ptr<MCStreamer> Streamer)
48 bool ModuleSectionsEmitted;
57 void outputMCInst(
MCInst &Inst);
60 void outputGlobalRequirements();
61 void outputEntryPoints();
62 void outputDebugSourceAndStrings(
const Module &M);
63 void outputOpExtInstImports(
const Module &M);
64 void outputOpMemoryModel();
65 void outputOpFunctionEnd();
66 void outputExtFuncDecls();
68 SPIRV::ExecutionMode::ExecutionMode EM);
69 void outputExecutionMode(
const Module &M);
70 void outputAnnotations(
const Module &M);
71 void outputModuleSections();
75 void emitFunctionHeader()
override;
90void SPIRVAsmPrinter::getAnalysisUsage(
AnalysisUsage &AU)
const {
97void SPIRVAsmPrinter::emitEndOfAsmFile(
Module &M) {
98 if (ModuleSectionsEmitted ==
false) {
99 outputModuleSections();
100 ModuleSectionsEmitted =
true;
104void SPIRVAsmPrinter::emitFunctionHeader() {
105 if (ModuleSectionsEmitted ==
false) {
106 outputModuleSections();
107 ModuleSectionsEmitted =
true;
111 TII =
ST->getInstrInfo();
115 OutStreamer->getCommentOS()
116 <<
"-- Begin function "
120 auto Section = getObjFileLowering().SectionForGlobal(&
F,
TM);
121 MF->setSection(Section);
124void SPIRVAsmPrinter::outputOpFunctionEnd() {
126 FunctionEndInst.
setOpcode(SPIRV::OpFunctionEnd);
127 outputMCInst(FunctionEndInst);
131void SPIRVAsmPrinter::emitFunctionBodyEnd() {
132 outputOpFunctionEnd();
133 MAI->BBNumToRegMap.clear();
137 if (MAI->MBBsToSkip.contains(&
MBB))
142 outputMCInst(LabelInst);
150 if (
MI.getOpcode() == SPIRV::OpFunction)
158void SPIRVAsmPrinter::printOperand(
const MachineInstr *
MI,
int OpNum,
200bool SPIRVAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
202 if (ExtraCode && ExtraCode[0])
211 return TII->isHeaderInstr(*
MI) ||
MI->getOpcode() == SPIRV::OpFunction ||
212 MI->getOpcode() == SPIRV::OpFunctionParameter;
215void SPIRVAsmPrinter::outputMCInst(
MCInst &Inst) {
216 OutStreamer->emitInstruction(Inst, *OutContext.getSubtargetInfo());
222 MCInstLowering.
lower(
MI, TmpInst, MAI);
223 outputMCInst(TmpInst);
227 SPIRV_MC::verifyInstructionPredicates(
MI->getOpcode(),
228 getSubtargetInfo().getFeatureBits());
230 if (!MAI->getSkipEmission(
MI))
231 outputInstruction(
MI);
237 assert(
MI->getParent()->getNumber() == MF->front().getNumber() &&
238 "OpFunction is not in the front MBB of MF");
239 emitOpLabel(*
MI->getParent());
245 outputInstruction(
MI);
248void SPIRVAsmPrinter::outputDebugSourceAndStrings(
const Module &M) {
250 for (
auto &Str : MAI->SrcExt) {
252 Inst.
setOpcode(SPIRV::OpSourceExtension);
265void SPIRVAsmPrinter::outputOpExtInstImports(
const Module &M) {
266 for (
auto &
CU : MAI->ExtInstSetMap) {
267 unsigned Set =
CU.first;
273 static_cast<SPIRV::InstructionSet::InstructionSet
>(Set)),
279void SPIRVAsmPrinter::outputOpMemoryModel() {
291void SPIRVAsmPrinter::outputEntryPoints() {
295 assert(
MI->getOpcode() == SPIRV::OpVariable);
296 auto SC =
static_cast<SPIRV::StorageClass::StorageClass
>(
297 MI->getOperand(2).getImm());
302 if (
ST->getSPIRVVersion() >= 14 ||
SC == SPIRV::StorageClass::Input ||
303 SC == SPIRV::StorageClass::Output) {
305 Register Reg = MAI->getRegisterAlias(MF,
MI->getOperand(0).getReg());
314 MCInstLowering.
lower(
MI, TmpInst, MAI);
319 outputMCInst(TmpInst);
324void SPIRVAsmPrinter::outputGlobalRequirements() {
326 MAI->Reqs.checkSatisfiable(*ST);
328 for (
const auto &Cap : MAI->Reqs.getMinimalCapabilities()) {
336 for (
const auto &Ext : MAI->Reqs.getExtensions()) {
340 SPIRV::OperandCategory::ExtensionOperand, Ext),
347void SPIRVAsmPrinter::outputExtFuncDecls() {
352 for (;
I !=
E; ++
I) {
353 outputInstruction(*
I);
354 if ((
I + 1) ==
E || (*(
I + 1))->
getOpcode() == SPIRV::OpFunction)
355 outputOpFunctionEnd();
367 if (
IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) {
368 switch (IntTy->getIntegerBitWidth()) {
382 Type *EleTy = VecTy->getElementType();
383 unsigned Size = VecTy->getNumElements();
392 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
396 }
else if (
auto *CE = dyn_cast<Function>(
C)) {
405void SPIRVAsmPrinter::outputExecutionModeFromMDNode(
415void SPIRVAsmPrinter::outputExecutionMode(
const Module &M) {
418 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
425 for (
auto FI =
M.begin(),
E =
M.end(); FI !=
E; ++FI) {
427 if (
F.isDeclaration())
431 if (
MDNode *
Node =
F.getMetadata(
"reqd_work_group_size"))
432 outputExecutionModeFromMDNode(FReg,
Node,
433 SPIRV::ExecutionMode::LocalSize);
434 if (
MDNode *
Node =
F.getMetadata(
"work_group_size_hint"))
435 outputExecutionModeFromMDNode(FReg,
Node,
436 SPIRV::ExecutionMode::LocalSizeHint);
437 if (
MDNode *
Node =
F.getMetadata(
"intel_reqd_sub_group_size"))
438 outputExecutionModeFromMDNode(FReg,
Node,
439 SPIRV::ExecutionMode::SubgroupSize);
440 if (
MDNode *
Node =
F.getMetadata(
"vec_type_hint")) {
444 unsigned EM =
static_cast<unsigned>(SPIRV::ExecutionMode::VecTypeHint);
450 if (!
M.getNamedMetadata(
"spirv.ExecutionMode") &&
451 !
M.getNamedMetadata(
"opencl.enable.FP_CONTRACT")) {
455 unsigned EM =
static_cast<unsigned>(SPIRV::ExecutionMode::ContractionOff);
462void SPIRVAsmPrinter::outputAnnotations(
const Module &M) {
465 for (
auto F =
M.global_begin(),
E =
M.global_end();
F !=
E; ++
F) {
466 if ((*F).getName() !=
"llvm.global.annotations")
475 if (!isa<Function>(AnnotatedVar))
489 unsigned Dec =
static_cast<unsigned>(SPIRV::Decoration::UserSemantic);
497void SPIRVAsmPrinter::outputModuleSections() {
498 const Module *
M = MMI->getModule();
501 TII =
ST->getInstrInfo();
503 assert(ST &&
TII && MAI && M &&
"Module analysis is required");
506 outputGlobalRequirements();
508 outputOpExtInstImports(*M);
510 outputOpMemoryModel();
514 outputExecutionMode(*M);
517 outputDebugSourceAndStrings(*M);
523 outputAnnotations(*M);
530 outputExtFuncDecls();
535bool SPIRVAsmPrinter::doInitialization(
Module &M) {
536 ModuleSectionsEmitted =
false;
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#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")
const char LLVMTargetMachineRef TM
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)
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.
ConstantArray - Constant Array Declarations.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
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(unsigned 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.
static const char * getRegisterName(MCRegister Reg)
void lower(const MachineInstr *MI, MCInst &OutMI, SPIRV::ModuleAnalysisInfo *MAI) const
typename SuperClass::iterator iterator
StringRef - Represent a constant reference to a string, i.e.
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.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
std::pair< iterator, bool > insert(const ValueT &V)
This class implements an extremely fast bulk output stream that can only output to a stream.
#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.
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)
Target & getTheSPIRV64Target()
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)