48 #define DEBUG_TYPE "asm-printer"
58 AArch64AsmPrinter(
TargetMachine &
TM, std::unique_ptr<MCStreamer> Streamer)
59 :
AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *
this),
60 SM(*
this), AArch64FI(
nullptr) {}
62 StringRef getPassName()
const override {
return "AArch64 Assembly Printer"; }
67 return MCInstLowering.lowerOperand(MO, MCOp);
75 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &MI);
76 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &MI);
83 bool emitPseudoExpansionLowering(
MCStreamer &OutStreamer,
108 bool PrintAsmOperand(
const MachineInstr *MI,
unsigned OpNum,
109 unsigned AsmVariant,
const char *ExtraCode,
111 bool PrintAsmMemoryOperand(
const MachineInstr *MI,
unsigned OpNum,
112 unsigned AsmVariant,
const char *ExtraCode,
117 void EmitFunctionBodyEnd()
override;
119 MCSymbol *GetCPISymbol(
unsigned CPID)
const override;
120 void EmitEndOfAsmFile(
Module &M)
override;
129 typedef std::map<const MachineInstr *, MCSymbol *> MInstToMCSymbol;
130 MInstToMCSymbol LOHInstToLabel;
137 void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr &
MI)
139 EmitSled(MI, SledKind::FUNCTION_ENTER);
142 void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr &
MI)
144 EmitSled(MI, SledKind::FUNCTION_EXIT);
147 void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr &
MI)
149 EmitSled(MI, SledKind::TAIL_CALL);
154 static const int8_t NoopsInSledCount = 7;
175 OutStreamer->EmitCodeAlignment(4);
176 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
177 OutStreamer->EmitLabel(CurSled);
178 auto Target = OutContext.createTempSymbol();
185 for (int8_t
I = 0;
I < NoopsInSledCount;
I++)
186 EmitToStreamer(*OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
188 OutStreamer->EmitLabel(
Target);
189 recordSled(CurSled, MI, Kind);
192 void AArch64AsmPrinter::EmitEndOfAsmFile(
Module &M) {
193 const Triple &TT =
TM.getTargetTriple();
201 SM.serializeToStackMapSection();
205 void AArch64AsmPrinter::EmitLOHs() {
208 for (
const auto &
D : AArch64FI->getLOHContainer()) {
210 MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
211 assert(LabelIt != LOHInstToLabel.end() &&
212 "Label hasn't been inserted for LOH related instruction");
215 OutStreamer->EmitLOHDirective(
D.getKind(), MCArgs);
220 void AArch64AsmPrinter::EmitFunctionBodyEnd() {
221 if (!AArch64FI->getLOHRelated().empty())
226 MCSymbol *AArch64AsmPrinter::GetCPISymbol(
unsigned CPID)
const {
230 if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
231 return OutContext.getOrCreateSymbol(
232 Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) +
"CPI" +
233 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
235 return OutContext.getOrCreateSymbol(
236 Twine(getDataLayout().getPrivateGlobalPrefix()) +
"CPI" +
237 Twine(getFunctionNumber()) +
"_" +
Twine(CPID));
254 int64_t Imm = MO.
getImm();
274 unsigned Reg = MO.
getReg();
293 bool AArch64AsmPrinter::printAsmRegInClass(
const MachineOperand &MO,
296 assert(MO.
isReg() &&
"Should only get here with a register!");
298 unsigned Reg = MO.
getReg();
299 unsigned RegToPrint = RC->
getRegister(RI->getEncodingValue(Reg));
300 assert(RI->regsOverlap(RegToPrint, Reg));
302 RegToPrint, isVector ? AArch64::vreg : AArch64::NoRegAltName);
306 bool AArch64AsmPrinter::PrintAsmOperand(
const MachineInstr *MI,
unsigned OpNum,
316 if (ExtraCode && ExtraCode[0]) {
317 if (ExtraCode[1] != 0)
320 switch (ExtraCode[0]) {
328 unsigned Reg = ExtraCode[0] ==
'w' ? AArch64::WZR : AArch64::XZR;
341 switch (ExtraCode[0]) {
343 RC = &AArch64::FPR8RegClass;
346 RC = &AArch64::FPR16RegClass;
349 RC = &AArch64::FPR32RegClass;
352 RC = &AArch64::FPR64RegClass;
355 RC = &AArch64::FPR128RegClass;
360 return printAsmRegInClass(MO, RC,
false , O);
370 unsigned Reg = MO.
getReg();
373 if (AArch64::GPR32allRegClass.
contains(Reg) ||
374 AArch64::GPR64allRegClass.
contains(Reg))
378 return printAsmRegInClass(MO, &AArch64::FPR128RegClass,
true ,
386 bool AArch64AsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *MI,
389 const char *ExtraCode,
391 if (ExtraCode && ExtraCode[0])
395 assert(MO.
isReg() &&
"unexpected inline asm memory operand");
400 void AArch64AsmPrinter::PrintDebugValueComment(
const MachineInstr *MI,
404 OS <<
'\t' << MAI->getCommentString() <<
"DEBUG_VALUE: ";
425 assert(NumNOPBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
431 while (NumNOPBytes > 0) {
432 if (MII == MBB.
end() || MII->isCall() ||
433 MII->getOpcode() == AArch64::DBG_VALUE ||
434 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
435 MII->getOpcode() == TargetOpcode::STACKMAP)
442 for (
unsigned i = 0;
i < NumNOPBytes;
i += 4)
454 int64_t CallTarget = Opers.getCallTarget().getImm();
455 unsigned EncodedBytes = 0;
457 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
458 "High 16 bits of call target should be zero.");
464 .addImm((CallTarget >> 32) & 0xFFFF)
469 .addImm((CallTarget >> 16) & 0xFFFF)
474 .addImm(CallTarget & 0xFFFF)
476 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
479 unsigned NumBytes = Opers.getNumPatchBytes();
480 assert(NumBytes >= EncodedBytes &&
481 "Patchpoint can't request size less than the length of a call.");
482 assert((NumBytes - EncodedBytes) % 4 == 0 &&
483 "Invalid number of NOP bytes requested!");
484 for (
unsigned i = EncodedBytes;
i < NumBytes;
i += 4)
485 EmitToStreamer(OutStreamer,
MCInstBuilder(AArch64::HINT).addImm(0));
488 void AArch64AsmPrinter::EmitFMov0(
const MachineInstr &MI) {
490 if (STI->hasZeroCycleZeroing()) {
492 if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31) {
493 DestReg = AArch64::Q0 + (DestReg - AArch64::S0);
495 assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
496 DestReg = AArch64::Q0 + (DestReg - AArch64::D0);
502 EmitToStreamer(*OutStreamer, MOVI);
507 case AArch64::FMOVS0:
512 case AArch64::FMOVD0:
518 EmitToStreamer(*OutStreamer, FMov);
524 #include "AArch64GenMCPseudoLowering.inc"
526 void AArch64AsmPrinter::EmitInstruction(
const MachineInstr *MI) {
528 if (emitPseudoExpansionLowering(*OutStreamer, MI))
531 if (AArch64FI->getLOHRelated().count(MI)) {
533 MCSymbol *LOHLabel = createTempSymbol(
"loh");
535 LOHInstToLabel[
MI] = LOHLabel;
543 case AArch64::DBG_VALUE: {
547 PrintDebugValueComment(MI, OS);
556 case AArch64::TCRETURNri: {
560 EmitToStreamer(*OutStreamer, TmpInst);
563 case AArch64::TCRETURNdi: {
565 MCInstLowering.lowerOperand(MI->
getOperand(0), Dest);
569 EmitToStreamer(*OutStreamer, TmpInst);
582 MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
586 MCInstLowering.lowerOperand(MO_Sym, Sym);
587 MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
588 MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
594 EmitToStreamer(*OutStreamer, Adrp);
602 EmitToStreamer(*OutStreamer, Ldr);
610 EmitToStreamer(*OutStreamer, Add);
615 TLSDescCall.
setOpcode(AArch64::TLSDESCCALL);
617 EmitToStreamer(*OutStreamer, TLSDescCall);
622 EmitToStreamer(*OutStreamer, Blr);
627 case AArch64::FMOVS0:
628 case AArch64::FMOVD0:
632 case TargetOpcode::STACKMAP:
633 return LowerSTACKMAP(*OutStreamer, SM, *MI);
635 case TargetOpcode::PATCHPOINT:
636 return LowerPATCHPOINT(*OutStreamer, SM, *MI);
638 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
639 LowerPATCHABLE_FUNCTION_ENTER(*MI);
642 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
643 LowerPATCHABLE_FUNCTION_EXIT(*MI);
646 case TargetOpcode::PATCHABLE_TAIL_CALL:
647 LowerPATCHABLE_TAIL_CALL(*MI);
653 MCInstLowering.Lower(MI, TmpInst);
654 EmitToStreamer(*OutStreamer, TmpInst);
void push_back(const T &Elt)
Target & getTheAArch64beTarget()
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
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. ...
Target & getTheAArch64leTarget()
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
return AArch64::GPR64RegClass contains(Reg)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
void LLVMInitializeAArch64AsmPrinter()
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
Reg
All possible values of the reg field in the ModR/M byte.
static StringRef getName(Value *V)
Target & getTheARM64Target()
unsigned getNumOperands() const
Access to explicit operands of the instruction.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
Expected< const typename ELFT::Sym * > getSymbol(typename ELFT::SymRange Symbols, uint32_t Index)
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
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
Address of a global value.
unsigned getTargetFlags() const
Streaming machine code generation interface.
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
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void recordPatchPoint(const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Triple - Helper class for working with autoconf configuration names.
void setOpcode(unsigned Op)
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...
bool isVector(MCInstrInfo const &MCII, MCInst const &MCI)
Target - Wrapper for Target specific information.
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.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
Representation of each machine instruction.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
AArch64MCInstLower - This class is used to lower an MachineInstr into an MCInst.
MI-level stackmap operands.
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)