LLVM 19.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.
38 return;
39
40 switch (MI->getOpcode()) {
41 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
43 return;
44 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
46 return;
47 case TargetOpcode::PATCHABLE_TAIL_CALL:
49 return;
50 }
51
52 MCInst TmpInst;
53 if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
54 EmitToStreamer(*OutStreamer, TmpInst);
55}
56
58 const char *ExtraCode,
59 raw_ostream &OS) {
60 // First try the generic code, which knows about modifiers like 'c' and 'n'.
61 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
62 return false;
63
64 const MachineOperand &MO = MI->getOperand(OpNo);
65 if (ExtraCode && ExtraCode[0]) {
66 if (ExtraCode[1] != 0)
67 return true; // Unknown modifier.
68
69 switch (ExtraCode[0]) {
70 default:
71 return true; // Unknown modifier.
72 case 'z': // Print $zero register if zero, regular printing otherwise.
73 if (MO.isImm() && MO.getImm() == 0) {
74 OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);
75 return false;
76 }
77 break;
78 case 'w': // Print LSX registers.
79 if (MO.getReg().id() >= LoongArch::VR0 &&
80 MO.getReg().id() <= LoongArch::VR31)
81 break;
82 // The modifier is 'w' but the operand is not an LSX register; Report an
83 // unknown operand error.
84 return true;
85 case 'u': // Print LASX registers.
86 if (MO.getReg().id() >= LoongArch::XR0 &&
87 MO.getReg().id() <= LoongArch::XR31)
88 break;
89 // The modifier is 'u' but the operand is not an LASX register; Report an
90 // unknown operand error.
91 return true;
92 // TODO: handle other extra codes if any.
93 }
94 }
95
96 switch (MO.getType()) {
98 OS << MO.getImm();
99 return false;
102 return false;
105 return false;
106 default:
107 llvm_unreachable("not implemented");
108 }
109
110 return true;
111}
112
114 unsigned OpNo,
115 const char *ExtraCode,
116 raw_ostream &OS) {
117 // TODO: handle extra code.
118 if (ExtraCode)
119 return true;
120
121 // We only support memory operands like "Base + Offset", where base must be a
122 // register, and offset can be a register or an immediate value.
123 const MachineOperand &BaseMO = MI->getOperand(OpNo);
124 // Base address must be a register.
125 if (!BaseMO.isReg())
126 return true;
127 // Print the base address register.
129 // Print the offset operand.
130 const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);
131 if (OffsetMO.isReg())
132 OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());
133 else if (OffsetMO.isImm())
134 OS << ", " << OffsetMO.getImm();
135 else
136 return true;
137
138 return false;
139}
140
142 const MachineInstr &MI) {
143 const Function &F = MF->getFunction();
144 if (F.hasFnAttribute("patchable-function-entry")) {
145 unsigned Num;
146 if (F.getFnAttribute("patchable-function-entry")
147 .getValueAsString()
148 .getAsInteger(10, Num))
149 return;
150 emitNops(Num);
151 return;
152 }
153
155}
156
159}
160
163}
164
166 // For loongarch64 we want to emit the following pattern:
167 //
168 // .Lxray_sled_beginN:
169 // B .Lxray_sled_endN
170 // 11 NOPs (44 bytes)
171 // .Lxray_sled_endN:
172 //
173 // We need the extra bytes because at runtime they may be used for the
174 // actual pattern defined at compiler-rt/lib/xray/xray_loongarch64.cpp.
175 // The count here should be adjusted accordingly if the implementation
176 // changes.
177 const int8_t NoopsInSledCount = 11;
178 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
179 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_begin");
180 MCSymbol *EndOfSled = OutContext.createTempSymbol("xray_sled_end");
181 OutStreamer->emitLabel(BeginOfSled);
183 MCInstBuilder(LoongArch::B)
184 .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
185 emitNops(NoopsInSledCount);
186 OutStreamer->emitLabel(EndOfSled);
187 recordSled(BeginOfSled, MI, Kind, 2);
188}
189
192 // Emit the XRay table for this function.
194 return true;
195}
196
197// Force static initialization.
201}
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
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:418
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:102
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:94
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition: AsmPrinter.h:395
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:99
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
Definition: AsmPrinter.cpp:413
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)
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, const MachineInstr *MI)
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 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:321
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:389
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:68
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 isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this 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,...