LLVM 24.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"
24#include "llvm/IR/Module.h"
25#include "llvm/MC/MCAsmInfo.h"
26#include "llvm/MC/MCContext.h"
31
32using namespace llvm;
33
34#define DEBUG_TYPE "loongarch-asm-printer"
35
37 "loongarch-annotate-tablejump", cl::Hidden,
39 "Annotate table jump instruction to correlate it with the jump table."),
40 cl::init(false));
41
42// Simple pseudo-instructions have their lowering (with expansion to real
43// instructions) auto-generated.
44#include "LoongArchGenMCPseudoLowering.inc"
45
46LoongArchTargetStreamer &LoongArchAsmPrinter::getTargetStreamer() const {
47 return static_cast<LoongArchTargetStreamer &>(
48 *OutStreamer->getTargetStreamer());
49}
50
52 StringRef ABIName = M.getTargetABIFromMD();
53 if (!ABIName.empty()) {
54 getTargetStreamer().setTargetABI(LoongArchABI::computeTargetABI(
55 TM.getTargetTriple(), TM.getMCSubtargetInfo().getFeatureBits(),
56 ABIName));
57 }
58}
59
61 LoongArch_MC::verifyInstructionPredicates(
62 MI->getOpcode(), getSubtargetInfo().getFeatureBits());
63
64 // Do any auto-generated pseudo lowerings.
65 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
66 EmitToStreamer(*OutStreamer, OutInst);
67 return;
68 }
69
70 switch (MI->getOpcode()) {
71 case TargetOpcode::STATEPOINT:
73 return;
74 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
76 return;
77 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
79 return;
80 case TargetOpcode::PATCHABLE_TAIL_CALL:
82 return;
83 }
84
85 MCInst TmpInst;
86 if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
87 EmitToStreamer(*OutStreamer, TmpInst);
88}
89
91 const char *ExtraCode,
92 raw_ostream &OS) {
93 // First try the generic code, which knows about modifiers like 'c' and 'n'.
94 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
95 return false;
96
97 const MachineOperand &MO = MI->getOperand(OpNo);
98 if (ExtraCode && ExtraCode[0]) {
99 if (ExtraCode[1] != 0)
100 return true; // Unknown modifier.
101
102 switch (ExtraCode[0]) {
103 default:
104 return true; // Unknown modifier.
105 case 'z': // Print $zero register if zero, regular printing otherwise.
106 if (MO.isImm() && MO.getImm() == 0) {
107 OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);
108 return false;
109 }
110 break;
111 case 'u': // Print LASX registers.
112 case 'w': // Print LSX registers.
113 {
114 // If the operand is an LASX, LSX or floating point register, print the
115 // name of LASX or LSX register with the same index in that register
116 // class.
117 unsigned RegID = MO.getReg().id(), FirstReg;
118 if (RegID >= LoongArch::XR0 && RegID <= LoongArch::XR31)
119 FirstReg = LoongArch::XR0;
120 else if (RegID >= LoongArch::VR0 && RegID <= LoongArch::VR31)
121 FirstReg = LoongArch::VR0;
122 else if (RegID >= LoongArch::F0_64 && RegID <= LoongArch::F31_64)
123 FirstReg = LoongArch::F0_64;
124 else if (RegID >= LoongArch::F0 && RegID <= LoongArch::F31)
125 FirstReg = LoongArch::F0;
126 else
127 return true;
128 OS << '$'
130 RegID - FirstReg +
131 (ExtraCode[0] == 'u' ? LoongArch::XR0 : LoongArch::VR0));
132 return false;
133 }
134 // TODO: handle other extra codes if any.
135 }
136 }
137
138 switch (MO.getType()) {
140 OS << MO.getImm();
141 return false;
144 return false;
146 PrintSymbolOperand(MO, OS);
147 return false;
148 default:
149 llvm_unreachable("not implemented");
150 }
151
152 return true;
153}
154
156 unsigned OpNo,
157 const char *ExtraCode,
158 raw_ostream &OS) {
159 // TODO: handle extra code.
160 if (ExtraCode)
161 return true;
162
163 // We only support memory operands like "Base + Offset", where base must be a
164 // register, and offset can be a register or an immediate value.
165 const MachineOperand &BaseMO = MI->getOperand(OpNo);
166 // Base address must be a register.
167 if (!BaseMO.isReg())
168 return true;
169 // Print the base address register.
170 OS << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg());
171 // Print the offset operand.
172 const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);
173 MCOperand MCO;
174 if (!lowerOperand(OffsetMO, MCO))
175 return true;
176 if (OffsetMO.isReg())
177 OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());
178 else if (OffsetMO.isImm())
179 OS << ", " << OffsetMO.getImm();
180 else if (OffsetMO.isGlobal() || OffsetMO.isBlockAddress() ||
181 OffsetMO.isMCSymbol() || OffsetMO.isCPI()) {
182 OS << ", ";
183 MAI.printExpr(OS, *MCO.getExpr());
184 } else
185 return true;
186
187 return false;
188}
189
191 StatepointOpers SOpers(&MI);
192 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
193 assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
194 emitNops(PatchBytes / 4);
195 } else {
196 // Lower call target and choose correct opcode.
197 const MachineOperand &CallTarget = SOpers.getCallTarget();
198 MCOperand CallTargetMCOp;
199 switch (CallTarget.getType()) {
202 lowerOperand(CallTarget, CallTargetMCOp);
204 MCInstBuilder(LoongArch::BL).addOperand(CallTargetMCOp));
205 break;
207 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
209 MCInstBuilder(LoongArch::BL).addOperand(CallTargetMCOp));
210 break;
212 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
213 EmitToStreamer(*OutStreamer, MCInstBuilder(LoongArch::JIRL)
214 .addReg(LoongArch::R1)
215 .addOperand(CallTargetMCOp)
216 .addImm(0));
217 break;
218 default:
219 llvm_unreachable("Unsupported operand type in statepoint call target");
220 break;
221 }
222 }
223
224 auto &Ctx = OutStreamer->getContext();
225 MCSymbol *MILabel = Ctx.createTempSymbol();
226 OutStreamer->emitLabel(MILabel);
227 SM.recordStatepoint(*MILabel, MI);
228}
229
231 const MachineInstr &MI) {
232 const Function &F = MF->getFunction();
233 if (F.hasFnAttribute("patchable-function-entry")) {
234 unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry");
235 emitNops(Num);
236 return;
237 }
238
240}
241
245
249
251 // For loongarch64 we want to emit the following pattern:
252 //
253 // .Lxray_sled_beginN:
254 // B .Lxray_sled_endN
255 // 11 NOPs (44 bytes)
256 // .Lxray_sled_endN:
257 //
258 // We need the extra bytes because at runtime they may be used for the
259 // actual pattern defined at compiler-rt/lib/xray/xray_loongarch64.cpp.
260 // The count here should be adjusted accordingly if the implementation
261 // changes.
262 const int8_t NoopsInSledCount = 11;
263 OutStreamer->emitCodeAlignment(Align(4), getSubtargetInfo());
264 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_begin");
265 MCSymbol *EndOfSled = OutContext.createTempSymbol("xray_sled_end");
266 OutStreamer->emitLabel(BeginOfSled);
268 MCInstBuilder(LoongArch::B)
269 .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
270 emitNops(NoopsInSledCount);
271 OutStreamer->emitLabel(EndOfSled);
272 recordSled(BeginOfSled, MI, Kind, 2);
273}
274
277
279 return;
280
281 assert(TM.getTargetTriple().isOSBinFormatELF());
282
283 auto *LAFI = MF->getInfo<LoongArchMachineFunctionInfo>();
284 unsigned EntrySize = LAFI->getJumpInfoSize();
285 auto JTI = MF->getJumpTableInfo();
286
287 if (!JTI || 0 == EntrySize)
288 return;
289
290 unsigned Size = getDataLayout().getPointerSize();
291 const auto &JT = JTI->getJumpTables();
292
293 // Emit an additional section to store the correlation info as pairs of
294 // addresses, each pair contains the address of a jump instruction (jr) and
295 // the address of the jump table.
296 OutStreamer->switchSection(MMI->getContext().getELFSection(
297 ".discard.tablejump_annotate", ELF::SHT_PROGBITS, 0));
298
299 for (unsigned Idx = 0; Idx < EntrySize; ++Idx) {
300 int JTIIdx = LAFI->getJumpInfoJTIIndex(Idx);
301 if (JT[JTIIdx].MBBs.empty())
302 continue;
303 OutStreamer->emitValue(
304 MCSymbolRefExpr::create(LAFI->getJumpInfoJrMI(Idx)->getPreInstrSymbol(),
305 OutContext),
306 Size);
307 OutStreamer->emitValue(
309 }
310}
311
312// Emit .dtprelword or .dtpreldword directive
313// and value for debug thread local expression.
315 unsigned Size) const {
316 if (auto *Expr = dyn_cast<MCSpecifierExpr>(Value)) {
317 if (Expr->getSpecifier() == LoongArchMCExpr::VK_DTPREL) {
318 switch (Size) {
319 case 4:
320 getTargetStreamer().emitDTPRel32Value(Expr->getSubExpr());
321 break;
322 case 8:
323 getTargetStreamer().emitDTPRel64Value(Expr->getSubExpr());
324 break;
325 default:
326 llvm_unreachable("Unexpected size of expression value.");
327 }
328 return;
329 }
330 }
332}
333
336 // Emit the XRay table for this function.
338 return true;
339}
340
342
343INITIALIZE_PASS(LoongArchAsmPrinter, "loongarch-asm-printer",
344 "LoongArch Assembly Printer", false, false)
345
346// Force static initialization.
348LLVMInitializeLoongArchAsmPrinter() {
351}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
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:54
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
void emitNops(unsigned N)
Emit N NOP instructions.
virtual void emitDebugValue(const MCExpr *Value, unsigned Size) const
Emit the directive and value for debug thread local expression.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
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.
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
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:112
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:456
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
const DataLayout & getDataLayout() const
Return information about data layout.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
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.
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 emitDebugValue(const MCExpr *Value, unsigned Size) const override
Emit the directive and value for debug thread local expression.
void emitStartOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the start of their fi...
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...
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
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:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex 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.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
constexpr unsigned id() const
Definition Register.h:100
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
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
LLVM Value Representation.
Definition Value.h:75
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.
@ SHT_PROGBITS
Definition ELF.h:1157
ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, StringRef ABIName)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheLoongArch64Target()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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,...