LLVM 22.0.0git
LoongArchAsmPrinter.cpp
Go to the documentation of this file.
1//===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer -*- 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 GAS-format LoongArch assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "LoongArchAsmPrinter.h"
15#include "LoongArch.h"
23#include "llvm/MC/MCAsmInfo.h"
24#include "llvm/MC/MCContext.h"
29
30using namespace llvm;
31
32#define DEBUG_TYPE "loongarch-asm-printer"
33
35 "loongarch-annotate-tablejump", cl::Hidden,
37 "Annotate table jump instruction to correlate it with the jump table."),
38 cl::init(false));
39
40// Simple pseudo-instructions have their lowering (with expansion to real
41// instructions) auto-generated.
42#include "LoongArchGenMCPseudoLowering.inc"
43
45 LoongArch_MC::verifyInstructionPredicates(
46 MI->getOpcode(), getSubtargetInfo().getFeatureBits());
47
48 // Do any auto-generated pseudo lowerings.
49 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
50 EmitToStreamer(*OutStreamer, OutInst);
51 return;
52 }
53
54 switch (MI->getOpcode()) {
55 case TargetOpcode::STATEPOINT:
57 return;
58 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
60 return;
61 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
63 return;
64 case TargetOpcode::PATCHABLE_TAIL_CALL:
66 return;
67 }
68
69 MCInst TmpInst;
70 if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
71 EmitToStreamer(*OutStreamer, TmpInst);
72}
73
75 const char *ExtraCode,
76 raw_ostream &OS) {
77 // First try the generic code, which knows about modifiers like 'c' and 'n'.
78 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
79 return false;
80
81 const MachineOperand &MO = MI->getOperand(OpNo);
82 if (ExtraCode && ExtraCode[0]) {
83 if (ExtraCode[1] != 0)
84 return true; // Unknown modifier.
85
86 switch (ExtraCode[0]) {
87 default:
88 return true; // Unknown modifier.
89 case 'z': // Print $zero register if zero, regular printing otherwise.
90 if (MO.isImm() && MO.getImm() == 0) {
91 OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);
92 return false;
93 }
94 break;
95 case 'u': // Print LASX registers.
96 case 'w': // Print LSX registers.
97 {
98 // If the operand is an LASX, LSX or floating point register, print the
99 // name of LASX or LSX register with the same index in that register
100 // class.
101 unsigned RegID = MO.getReg().id(), FirstReg;
102 if (RegID >= LoongArch::XR0 && RegID <= LoongArch::XR31)
103 FirstReg = LoongArch::XR0;
104 else if (RegID >= LoongArch::VR0 && RegID <= LoongArch::VR31)
105 FirstReg = LoongArch::VR0;
106 else if (RegID >= LoongArch::F0_64 && RegID <= LoongArch::F31_64)
107 FirstReg = LoongArch::F0_64;
108 else if (RegID >= LoongArch::F0 && RegID <= LoongArch::F31)
109 FirstReg = LoongArch::F0;
110 else
111 return true;
112 OS << '$'
114 RegID - FirstReg +
115 (ExtraCode[0] == 'u' ? LoongArch::XR0 : LoongArch::VR0));
116 return false;
117 }
118 // TODO: handle other extra codes if any.
119 }
120 }
121
122 switch (MO.getType()) {
124 OS << MO.getImm();
125 return false;
128 return false;
131 return false;
132 default:
133 llvm_unreachable("not implemented");
134 }
135
136 return true;
137}
138
140 unsigned OpNo,
141 const char *ExtraCode,
142 raw_ostream &OS) {
143 // TODO: handle extra code.
144 if (ExtraCode)
145 return true;
146
147 // We only support memory operands like "Base + Offset", where base must be a
148 // register, and offset can be a register or an immediate value.
149 const MachineOperand &BaseMO = MI->getOperand(OpNo);
150 // Base address must be a register.
151 if (!BaseMO.isReg())
152 return true;
153 // Print the base address register.
155 // Print the offset operand.
156 const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);
157 MCOperand MCO;
158 if (!lowerOperand(OffsetMO, MCO))
159 return true;
160 if (OffsetMO.isReg())
161 OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());
162 else if (OffsetMO.isImm())
163 OS << ", " << OffsetMO.getImm();
164 else if (OffsetMO.isGlobal() || OffsetMO.isBlockAddress() ||
165 OffsetMO.isMCSymbol()) {
166 OS << ", ";
167 MAI->printExpr(OS, *MCO.getExpr());
168 } else
169 return true;
170
171 return false;
172}
173
175 StatepointOpers SOpers(&MI);
176 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
177 assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
178 emitNops(PatchBytes / 4);
179 } else {
180 // Lower call target and choose correct opcode.
181 const MachineOperand &CallTarget = SOpers.getCallTarget();
182 MCOperand CallTargetMCOp;
183 switch (CallTarget.getType()) {
186 lowerOperand(CallTarget, CallTargetMCOp);
188 MCInstBuilder(LoongArch::BL).addOperand(CallTargetMCOp));
189 break;
191 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
193 MCInstBuilder(LoongArch::BL).addOperand(CallTargetMCOp));
194 break;
196 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
197 EmitToStreamer(*OutStreamer, MCInstBuilder(LoongArch::JIRL)
198 .addReg(LoongArch::R1)
199 .addOperand(CallTargetMCOp)
200 .addImm(0));
201 break;
202 default:
203 llvm_unreachable("Unsupported operand type in statepoint call target");
204 break;
205 }
206 }
207
208 auto &Ctx = OutStreamer->getContext();
209 MCSymbol *MILabel = Ctx.createTempSymbol();
210 OutStreamer->emitLabel(MILabel);
211 SM.recordStatepoint(*MILabel, MI);
212}
213
215 const MachineInstr &MI) {
216 const Function &F = MF->getFunction();
217 if (F.hasFnAttribute("patchable-function-entry")) {
218 unsigned Num;
219 if (F.getFnAttribute("patchable-function-entry")
220 .getValueAsString()
221 .getAsInteger(10, Num))
222 return;
223 emitNops(Num);
224 return;
225 }
226
228}
229
232}
233
236}
237
239 // For loongarch64 we want to emit the following pattern:
240 //
241 // .Lxray_sled_beginN:
242 // B .Lxray_sled_endN
243 // 11 NOPs (44 bytes)
244 // .Lxray_sled_endN:
245 //
246 // We need the extra bytes because at runtime they may be used for the
247 // actual pattern defined at compiler-rt/lib/xray/xray_loongarch64.cpp.
248 // The count here should be adjusted accordingly if the implementation
249 // changes.
250 const int8_t NoopsInSledCount = 11;
251 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
252 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_begin");
253 MCSymbol *EndOfSled = OutContext.createTempSymbol("xray_sled_end");
254 OutStreamer->emitLabel(BeginOfSled);
256 MCInstBuilder(LoongArch::B)
257 .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
258 emitNops(NoopsInSledCount);
259 OutStreamer->emitLabel(EndOfSled);
260 recordSled(BeginOfSled, MI, Kind, 2);
261}
262
265
267 return;
268
270
271 auto *LAFI = MF->getInfo<LoongArchMachineFunctionInfo>();
272 unsigned EntrySize = LAFI->getJumpInfoSize();
273 auto JTI = MF->getJumpTableInfo();
274
275 if (!JTI || 0 == EntrySize)
276 return;
277
278 unsigned Size = getDataLayout().getPointerSize();
279 auto JT = JTI->getJumpTables();
280
281 // Emit an additional section to store the correlation info as pairs of
282 // addresses, each pair contains the address of a jump instruction (jr) and
283 // the address of the jump table.
284 OutStreamer->switchSection(MMI->getContext().getELFSection(
285 ".discard.tablejump_annotate", ELF::SHT_PROGBITS, 0));
286
287 for (unsigned Idx = 0; Idx < EntrySize; ++Idx) {
288 int JTIIdx = LAFI->getJumpInfoJTIIndex(Idx);
289 if (JT[JTIIdx].MBBs.empty())
290 continue;
291 OutStreamer->emitValue(
292 MCSymbolRefExpr::create(LAFI->getJumpInfoJrMI(Idx)->getPreInstrSymbol(),
293 OutContext),
294 Size);
295 OutStreamer->emitValue(
297 }
298}
299
302 // Emit the XRay table for this function.
304 return true;
305}
306
308
309INITIALIZE_PASS(LoongArchAsmPrinter, "loongarch-asm-printer",
310 "LoongArch Assembly Printer", false, false)
311
312// Force static initialization.
314LLVMInitializeLoongArchAsmPrinter() {
317}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Size
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
cl::opt< bool > LArchAnnotateTableJump("loongarch-annotate-tablejump", cl::Hidden, cl::desc("Annotate table jump instruction to correlate it with the jump table."), cl::init(false))
#define F(x, y, z)
Definition: MD5.cpp:55
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
raw_pwrite_stream & OS
void emitNops(unsigned N)
Emit N NOP instructions.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:433
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:93
void emitXRayTable()
Emit a table with all XRay instrumentation points.
virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS)
Print the MachineOperand as a symbol.
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:96
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:108
virtual void emitJumpTableInfo()
Print assembly representations of the jump tables used by the current function to the current output ...
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind, uint8_t Version=0)
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition: AsmPrinter.h:111
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:100
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition: AsmPrinter.h:452
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:105
StackMaps SM
Definition: AsmPrinter.h:248
const DataLayout & getDataLayout() const
Return information about data layout.
Definition: AsmPrinter.cpp:417
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
Definition: AsmPrinter.cpp:428
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.
LLVM_ABI unsigned getPointerSize(unsigned AS=0) const
The pointer representation size in bytes, rounded up to a whole number of bytes.
Definition: DataLayout.cpp:738
void emitSled(const MachineInstr &MI, SledKind Kind)
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
void LowerSTATEPOINT(const MachineInstr &MI)
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const
bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst)
void emitJumpTableInfo() override
Print assembly representations of the jump tables used by the current function to the current output ...
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
static const char * getRegisterName(MCRegister Reg)
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void printExpr(raw_ostream &, const MCExpr &) const
Definition: MCAsmInfo.cpp:153
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:386
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition: MCContext.h:549
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:145
const MCExpr * getExpr() const
Definition: MCInst.h:118
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
Representation of each machine instruction.
Definition: MachineInstr.h:72
const MCContext & getContext() const
MachineOperand class - Representation of each machine instruction operand.
bool isMCSymbol() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
constexpr unsigned id() const
Definition: Register.h:95
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
Definition: StackMaps.cpp:560
MI-level Statepoint operands.
Definition: StackMaps.h:159
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Definition: StackMaps.h:208
const MachineOperand & getCallTarget() const
Return the target of the underlying call.
Definition: StackMaps.h:213
const Triple & getTargetTriple() const
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:766
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.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ SHT_PROGBITS
Definition: ELF.h:1140
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:444
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheLoongArch64Target()
bool lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)
Target & getTheLoongArch32Target()
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...