45 #define DEBUG_TYPE "asm-printer"
54 AArch64AsmPrinter(
TargetMachine &
TM, std::unique_ptr<MCStreamer> Streamer)
55 :
AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *
this),
56 SM(*
this), AArch64FI(
nullptr) {}
58 const char *getPassName()
const override {
59 return "AArch64 Assembly Printer";
65 return MCInstLowering.lowerOperand(MO, MCOp);
74 bool emitPseudoExpansionLowering(
MCStreamer &OutStreamer,
97 bool PrintAsmOperand(
const MachineInstr *MI,
unsigned OpNum,
98 unsigned AsmVariant,
const char *ExtraCode,
100 bool PrintAsmMemoryOperand(
const MachineInstr *MI,
unsigned OpNum,
101 unsigned AsmVariant,
const char *ExtraCode,
106 void EmitFunctionBodyEnd()
override;
108 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
109 void EmitEndOfAsmFile(
Module &M)
override;
115 typedef std::map<const MachineInstr *, MCSymbol *> MInstToMCSymbol;
116 MInstToMCSymbol LOHInstToLabel;
123 void AArch64AsmPrinter::EmitEndOfAsmFile(
Module &M) {
124 const Triple &TT =
TM.getTargetTriple();
132 SM.serializeToStackMapSection();
137 AArch64AsmPrinter::getDebugValueLocation(
const MachineInstr *
MI)
const {
139 assert(MI->
getNumOperands() == 4 &&
"Invalid no. of machine operands!");
144 DEBUG(
dbgs() <<
"DBG_VALUE instruction ignored! " << *MI <<
"\n");
149 void AArch64AsmPrinter::EmitLOHs() {
152 for (
const auto &D : AArch64FI->getLOHContainer()) {
154 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
155 assert(LabelIt != LOHInstToLabel.end() &&
156 "Label hasn't been inserted for LOH related instruction");
159 OutStreamer->EmitLOHDirective(D.getKind(), MCArgs);
164 void AArch64AsmPrinter::EmitFunctionBodyEnd() {
165 if (!AArch64FI->getLOHRelated().empty())
170 MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
174 if (getDataLayout().getLinkerPrivateGlobalPrefix()[0])
175 return OutContext.getOrCreateSymbol(
176 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
177 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
179 return OutContext.getOrCreateSymbol(
180 Twine(getDataLayout().getPrivateGlobalPrefix()) +
"CPI" +
181 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
193 assert(!MO.
getSubReg() &&
"Subregs should be eliminated!");
198 int64_t Imm = MO.
getImm();
218 unsigned Reg = MO.
getReg();
237 bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
240 assert(MO.
isReg() &&
"Should only get here with a register!");
243 unsigned Reg = MO.
getReg();
244 unsigned RegToPrint = RC->
getRegister(RI->getEncodingValue(Reg));
245 assert(RI->regsOverlap(RegToPrint, Reg));
247 RegToPrint, isVector ? AArch64::vreg : AArch64::NoRegAltName);
251 bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *MI,
unsigned OpNum,
261 if (ExtraCode && ExtraCode[0]) {
262 if (ExtraCode[1] != 0)
265 switch (ExtraCode[0]) {
273 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
286 switch (ExtraCode[0]) {
288 RC = &AArch64::FPR8RegClass;
291 RC = &AArch64::FPR16RegClass;
294 RC = &AArch64::FPR32RegClass;
297 RC = &AArch64::FPR64RegClass;
300 RC = &AArch64::FPR128RegClass;
305 return printAsmRegInClass(MO, RC,
false , O);
315 unsigned Reg = MO.
getReg();
318 if (AArch64::GPR32allRegClass.
contains(Reg) ||
319 AArch64::GPR64allRegClass.
contains(Reg))
323 return printAsmRegInClass(MO, &AArch64::FPR128RegClass,
true ,
331 bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *MI,
334 const char *ExtraCode,
336 if (ExtraCode && ExtraCode[0])
340 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
345 void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *MI,
349 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
370 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
376 while (NumNOPBytes > 0) {
377 if (MII == MBB.
end() || MII->isCall() ||
387 for (
unsigned i = 0; i < NumNOPBytes; i += 4)
400 unsigned EncodedBytes = 0;
402 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
403 "High 16 bits of call target should be zero.");
409 .addImm((CallTarget >> 32) & 0xFFFF)
414 .addImm((CallTarget >> 16) & 0xFFFF)
419 .addImm(CallTarget & 0xFFFF)
421 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
425 assert(NumBytes >= EncodedBytes &&
426 "Patchpoint can't request size less than the length of a call.");
427 assert((NumBytes - EncodedBytes) % 4 == 0 &&
428 "Invalid number of NOP bytes requested!");
429 for (
unsigned i = EncodedBytes; i < NumBytes; i += 4)
430 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
435 #include "AArch64GenMCPseudoLowering.inc"
437 void AArch64AsmPrinter::EmitInstruction(
const MachineInstr *MI) {
439 if (emitPseudoExpansionLowering(*OutStreamer, MI))
442 if (AArch64FI->getLOHRelated().count(MI)) {
444 MCSymbol *LOHLabel = createTempSymbol(
"loh");
446 LOHInstToLabel[
MI] = LOHLabel;
458 PrintDebugValueComment(MI, OS);
467 case AArch64::TCRETURNri: {
471 EmitToStreamer(*OutStreamer, TmpInst);
474 case AArch64::TCRETURNdi: {
476 MCInstLowering.lowerOperand(MI->
getOperand(0), Dest);
480 EmitToStreamer(*OutStreamer, TmpInst);
493 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
497 MCInstLowering.lowerOperand(MO_Sym, Sym);
498 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
499 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
505 EmitToStreamer(*OutStreamer, Adrp);
513 EmitToStreamer(*OutStreamer, Ldr);
521 EmitToStreamer(*OutStreamer, Add);
526 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
528 EmitToStreamer(*OutStreamer, TLSDescCall);
533 EmitToStreamer(*OutStreamer, Blr);
539 return LowerSTACKMAP(*OutStreamer, SM, *MI);
542 return LowerPATCHPOINT(*OutStreamer, SM, *MI);
547 MCInstLowering.Lower(MI, TmpInst);
548 EmitToStreamer(*OutStreamer, TmpInst);
void push_back(const T &Elt)
static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO, char Mode, raw_ostream &O)
const GlobalValue * getGlobal() const
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
static const char * getRegisterName(unsigned RegNo, unsigned AltIdx=AArch64::NoRegAltName)
void EmitRawText(const Twine &String)
If this file is backed by a assembly streamer, this dumps the specified string in the output ...
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
unsigned getRegister(unsigned i) const
getRegister - Return the specified register in the class.
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
A Module instance is used to store all the information related to an LLVM module. ...
A Stackmap instruction captures the location of live variables at its position in the instruction str...
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText...
A raw_ostream that writes to an SmallVector or SmallString.
static unsigned getXRegFromWReg(unsigned Reg)
const MDNode * getMetadata() const
static MCOperand createReg(unsigned Reg)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void LLVMInitializeAArch64AsmPrinter()
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Reg
All possible values of the reg field in the ModR/M byte.
static StringRef getName(Value *V)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
unsigned getNumOperands() const
Access to explicit operands of the instruction.
static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx, uint64_t Operand, uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
Print Opcode's operand number OperandIdx which has value Operand.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Instances of this class represent a single low-level machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static unsigned getWRegFromXReg(unsigned Reg)
const MachineBasicBlock * getParent() const
DBG_VALUE - a mapping of the llvm.dbg.value intrinsic.
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
Address of a global value.
unsigned getTargetFlags() const
Streaming machine code generation interface.
Patchable call instruction - this instruction represents a call to a constant address, followed by a series of NOPs.
Control flow instructions. These all have token chains.
const MachineOperand & getOperand(unsigned i) const
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant...
This class is intended to be used as a driving class for all asm writers.
Represent the analysis usage information of a pass.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
.subsections_via_symbols (MachO)
int64_t getOffset() const
Return the offset from the symbol in this operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
MI-level patchpoint operands.
unsigned getSubReg() const
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
void recordPatchPoint(const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Triple - Helper class for working with autoconf configuration names.
Target TheAArch64leTarget
void setOpcode(unsigned Op)
Target TheAArch64beTarget
virtual void EmitLabel(MCSymbol *Symbol)
Emit a label for Symbol into the current section.
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void recordStackMap(const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
void setPreservesAll()
Set by analyses that do not transform their input at all.
Representation of each machine instruction.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
bundle_iterator< const MachineInstr, const_instr_iterator > const_iterator
static bool isPhysicalRegister(unsigned Reg)
isPhysicalRegister - Return true if the specified register number is in the physical register namespa...
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
void set(unsigned R)
Make this location a direct register location.
unsigned getReg() const
getReg - Returns the register number.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
This class implements an extremely fast bulk output stream that can only output to a stream...
Primary interface to the complete machine description for the target machine.
void addOperand(const MCOperand &Op)
StringRef - Represent a constant reference to a string, i.e.
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
Instances of this class represent operands of the MCInst class.
static MCOperand createImm(int64_t Val)