Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
35267 views
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"
16
#include "LoongArchTargetMachine.h"
17
#include "MCTargetDesc/LoongArchInstPrinter.h"
18
#include "TargetInfo/LoongArchTargetInfo.h"
19
#include "llvm/CodeGen/AsmPrinter.h"
20
#include "llvm/MC/MCContext.h"
21
#include "llvm/MC/MCInstBuilder.h"
22
#include "llvm/MC/TargetRegistry.h"
23
24
using 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
32
void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) {
33
LoongArch_MC::verifyInstructionPredicates(
34
MI->getOpcode(), getSubtargetInfo().getFeatureBits());
35
36
// Do any auto-generated pseudo lowerings.
37
if (emitPseudoExpansionLowering(*OutStreamer, MI))
38
return;
39
40
switch (MI->getOpcode()) {
41
case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
42
LowerPATCHABLE_FUNCTION_ENTER(*MI);
43
return;
44
case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
45
LowerPATCHABLE_FUNCTION_EXIT(*MI);
46
return;
47
case TargetOpcode::PATCHABLE_TAIL_CALL:
48
LowerPATCHABLE_TAIL_CALL(*MI);
49
return;
50
}
51
52
MCInst TmpInst;
53
if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
54
EmitToStreamer(*OutStreamer, TmpInst);
55
}
56
57
bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
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()) {
97
case MachineOperand::MO_Immediate:
98
OS << MO.getImm();
99
return false;
100
case MachineOperand::MO_Register:
101
OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg());
102
return false;
103
case MachineOperand::MO_GlobalAddress:
104
PrintSymbolOperand(MO, OS);
105
return false;
106
default:
107
llvm_unreachable("not implemented");
108
}
109
110
return true;
111
}
112
113
bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
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.
128
OS << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg());
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
141
void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
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
154
emitSled(MI, SledKind::FUNCTION_ENTER);
155
}
156
157
void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {
158
emitSled(MI, SledKind::FUNCTION_EXIT);
159
}
160
161
void LoongArchAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {
162
emitSled(MI, SledKind::TAIL_CALL);
163
}
164
165
void LoongArchAsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
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);
182
EmitToStreamer(*OutStreamer,
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
190
bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
191
AsmPrinter::runOnMachineFunction(MF);
192
// Emit the XRay table for this function.
193
emitXRayTable();
194
return true;
195
}
196
197
// Force static initialization.
198
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() {
199
RegisterAsmPrinter<LoongArchAsmPrinter> X(getTheLoongArch32Target());
200
RegisterAsmPrinter<LoongArchAsmPrinter> Y(getTheLoongArch64Target());
201
}
202
203