LLVM 20.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"
20#include "llvm/MC/MCContext.h"
23
24using namespace llvm;
25
26#define DEBUG_TYPE "loongarch-asm-printer"
27
28// Simple pseudo-instructions have their lowering (with expansion to real
29// instructions) auto-generated.
30#include "LoongArchGenMCPseudoLowering.inc"
31
33 LoongArch_MC::verifyInstructionPredicates(
34 MI->getOpcode(), getSubtargetInfo().getFeatureBits());
35
36 // Do any auto-generated pseudo lowerings.
37 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
38 EmitToStreamer(*OutStreamer, OutInst);
39 return;
40 }
41
42 switch (MI->getOpcode()) {
43 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
45 return;
46 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
48 return;
49 case TargetOpcode::PATCHABLE_TAIL_CALL:
51 return;
52 }
53
54 MCInst TmpInst;
55 if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
56 EmitToStreamer(*OutStreamer, TmpInst);
57}
58
60 const char *ExtraCode,
61 raw_ostream &OS) {
62 // First try the generic code, which knows about modifiers like 'c' and 'n'.
63 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
64 return false;
65
66 const MachineOperand &MO = MI->getOperand(OpNo);
67 if (ExtraCode && ExtraCode[0]) {
68 if (ExtraCode[1] != 0)
69 return true; // Unknown modifier.
70
71 switch (ExtraCode[0]) {
72 default:
73 return true; // Unknown modifier.
74 case 'z': // Print $zero register if zero, regular printing otherwise.
75 if (MO.isImm() && MO.getImm() == 0) {
76 OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);
77 return false;
78 }
79 break;
80 case 'w': // Print LSX registers.
81 if (MO.getReg().id() >= LoongArch::VR0 &&
82 MO.getReg().id() <= LoongArch::VR31)
83 break;
84 // The modifier is 'w' but the operand is not an LSX register; Report an
85 // unknown operand error.
86 return true;
87 case 'u': // Print LASX registers.
88 if (MO.getReg().id() >= LoongArch::XR0 &&
89 MO.getReg().id() <= LoongArch::XR31)
90 break;
91 // The modifier is 'u' but the operand is not an LASX register; Report an
92 // unknown operand error.
93 return true;
94 // TODO: handle other extra codes if any.
95 }
96 }
97
98 switch (MO.getType()) {
100 OS << MO.getImm();
101 return false;
104 return false;
107 return false;
108 default:
109 llvm_unreachable("not implemented");
110 }
111
112 return true;
113}
114
116 unsigned OpNo,
117 const char *ExtraCode,
118 raw_ostream &OS) {
119 // TODO: handle extra code.
120 if (ExtraCode)
121 return true;
122
123 // We only support memory operands like "Base + Offset", where base must be a
124 // register, and offset can be a register or an immediate value.
125 const MachineOperand &BaseMO = MI->getOperand(OpNo);
126 // Base address must be a register.
127 if (!BaseMO.isReg())
128 return true;
129 // Print the base address register.
131 // Print the offset operand.
132 const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);
133 MCOperand MCO;
134 if (!lowerOperand(OffsetMO, MCO))
135 return true;
136 if (OffsetMO.isReg())
137 OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());
138 else if (OffsetMO.isImm())
139 OS << ", " << OffsetMO.getImm();
140 else if (OffsetMO.isGlobal() || OffsetMO.isBlockAddress() ||
141 OffsetMO.isMCSymbol())
142 OS << ", " << *MCO.getExpr();
143 else
144 return true;
145
146 return false;
147}
148
150 const MachineInstr &MI) {
151 const Function &F = MF->getFunction();
152 if (F.hasFnAttribute("patchable-function-entry")) {
153 unsigned Num;
154 if (F.getFnAttribute("patchable-function-entry")
155 .getValueAsString()
156 .getAsInteger(10, Num))
157 return;
158 emitNops(Num);
159 return;
160 }
161
163}
164
167}
168
171}
172
174 // For loongarch64 we want to emit the following pattern:
175 //
176 // .Lxray_sled_beginN:
177 // B .Lxray_sled_endN
178 // 11 NOPs (44 bytes)
179 // .Lxray_sled_endN:
180 //
181 // We need the extra bytes because at runtime they may be used for the
182 // actual pattern defined at compiler-rt/lib/xray/xray_loongarch64.cpp.
183 // The count here should be adjusted accordingly if the implementation
184 // changes.
185 const int8_t NoopsInSledCount = 11;
186 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
187 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_begin");
188 MCSymbol *EndOfSled = OutContext.createTempSymbol("xray_sled_end");
189 OutStreamer->emitLabel(BeginOfSled);
191 MCInstBuilder(LoongArch::B)
192 .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
193 emitNops(NoopsInSledCount);
194 OutStreamer->emitLabel(EndOfSled);
195 recordSled(BeginOfSled, MI, Kind, 2);
196}
197
200 // Emit the XRay table for this function.
202 return true;
203}
204
205// Force static initialization.
209}
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:131
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter()
#define F(x, y, z)
Definition: MD5.cpp:55
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
raw_pwrite_stream & OS
void emitNops(unsigned N)
Emit N NOP instructions.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:403
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:104
void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind, uint8_t Version=0)
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:96
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition: AsmPrinter.h:387
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:101
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
Definition: AsmPrinter.cpp:398
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.
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 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)
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)
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:346
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
const MCExpr * getExpr() const
Definition: MCInst.h:114
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:393
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:69
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.
constexpr unsigned id() const
Definition: Register.h:103
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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,...