1 //===-- LoongArchMCExpr.cpp - LoongArch specific MC expression classes ----===//
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 the implementation of the assembly expression modifiers
10 // accepted by the LoongArch architecture.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "LoongArchMCExpr.h"
15 #include "LoongArchAsmBackend.h"
16 #include "LoongArchFixupKinds.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCStreamer.h"
19 #include "llvm/MC/MCSymbolELF.h"
20 #include "llvm/MC/MCValue.h"
21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/ErrorHandling.h"
23
24 using namespace llvm;
25
26 #define DEBUG_TYPE "loongarch-mcexpr"
27
create(const MCExpr * Expr,VariantKind Kind,MCContext & Ctx,bool Hint)28 const LoongArchMCExpr *LoongArchMCExpr::create(const MCExpr *Expr,
29 VariantKind Kind, MCContext &Ctx,
30 bool Hint) {
31 return new (Ctx) LoongArchMCExpr(Expr, Kind, Hint);
32 }
33
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const34 void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
35 VariantKind Kind = getKind();
36 bool HasVariant =
37 ((Kind != VK_LoongArch_None) && (Kind != VK_LoongArch_CALL));
38
39 if (HasVariant)
40 OS << '%' << getVariantKindName(getKind()) << '(';
41 Expr->print(OS, MAI);
42 if (HasVariant)
43 OS << ')';
44 }
45
evaluateAsRelocatableImpl(MCValue & Res,const MCAssembler * Asm,const MCFixup * Fixup) const46 bool LoongArchMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
47 const MCAssembler *Asm,
48 const MCFixup *Fixup) const {
49 // Explicitly drop the layout and assembler to prevent any symbolic folding in
50 // the expression handling. This is required to preserve symbolic difference
51 // expressions to emit the paired relocations.
52 if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr))
53 return false;
54
55 Res =
56 MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
57 // Custom fixup types are not valid with symbol difference expressions.
58 return Res.getSymB() ? getKind() == VK_LoongArch_None : true;
59 }
60
visitUsedExpr(MCStreamer & Streamer) const61 void LoongArchMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
62 Streamer.visitUsedExpr(*getSubExpr());
63 }
64
getVariantKindName(VariantKind Kind)65 StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) {
66 switch (Kind) {
67 default:
68 llvm_unreachable("Invalid ELF symbol kind");
69 case VK_LoongArch_CALL_PLT:
70 return "plt";
71 case VK_LoongArch_B16:
72 return "b16";
73 case VK_LoongArch_B21:
74 return "b21";
75 case VK_LoongArch_B26:
76 return "b26";
77 case VK_LoongArch_ABS_HI20:
78 return "abs_hi20";
79 case VK_LoongArch_ABS_LO12:
80 return "abs_lo12";
81 case VK_LoongArch_ABS64_LO20:
82 return "abs64_lo20";
83 case VK_LoongArch_ABS64_HI12:
84 return "abs64_hi12";
85 case VK_LoongArch_PCALA_HI20:
86 return "pc_hi20";
87 case VK_LoongArch_PCALA_LO12:
88 return "pc_lo12";
89 case VK_LoongArch_PCALA64_LO20:
90 return "pc64_lo20";
91 case VK_LoongArch_PCALA64_HI12:
92 return "pc64_hi12";
93 case VK_LoongArch_GOT_PC_HI20:
94 return "got_pc_hi20";
95 case VK_LoongArch_GOT_PC_LO12:
96 return "got_pc_lo12";
97 case VK_LoongArch_GOT64_PC_LO20:
98 return "got64_pc_lo20";
99 case VK_LoongArch_GOT64_PC_HI12:
100 return "got64_pc_hi12";
101 case VK_LoongArch_GOT_HI20:
102 return "got_hi20";
103 case VK_LoongArch_GOT_LO12:
104 return "got_lo12";
105 case VK_LoongArch_GOT64_LO20:
106 return "got64_lo20";
107 case VK_LoongArch_GOT64_HI12:
108 return "got64_hi12";
109 case VK_LoongArch_TLS_LE_HI20:
110 return "le_hi20";
111 case VK_LoongArch_TLS_LE_LO12:
112 return "le_lo12";
113 case VK_LoongArch_TLS_LE64_LO20:
114 return "le64_lo20";
115 case VK_LoongArch_TLS_LE64_HI12:
116 return "le64_hi12";
117 case VK_LoongArch_TLS_IE_PC_HI20:
118 return "ie_pc_hi20";
119 case VK_LoongArch_TLS_IE_PC_LO12:
120 return "ie_pc_lo12";
121 case VK_LoongArch_TLS_IE64_PC_LO20:
122 return "ie64_pc_lo20";
123 case VK_LoongArch_TLS_IE64_PC_HI12:
124 return "ie64_pc_hi12";
125 case VK_LoongArch_TLS_IE_HI20:
126 return "ie_hi20";
127 case VK_LoongArch_TLS_IE_LO12:
128 return "ie_lo12";
129 case VK_LoongArch_TLS_IE64_LO20:
130 return "ie64_lo20";
131 case VK_LoongArch_TLS_IE64_HI12:
132 return "ie64_hi12";
133 case VK_LoongArch_TLS_LD_PC_HI20:
134 return "ld_pc_hi20";
135 case VK_LoongArch_TLS_LD_HI20:
136 return "ld_hi20";
137 case VK_LoongArch_TLS_GD_PC_HI20:
138 return "gd_pc_hi20";
139 case VK_LoongArch_TLS_GD_HI20:
140 return "gd_hi20";
141 case VK_LoongArch_CALL36:
142 return "call36";
143 case VK_LoongArch_TLS_DESC_PC_HI20:
144 return "desc_pc_hi20";
145 case VK_LoongArch_TLS_DESC_PC_LO12:
146 return "desc_pc_lo12";
147 case VK_LoongArch_TLS_DESC64_PC_LO20:
148 return "desc64_pc_lo20";
149 case VK_LoongArch_TLS_DESC64_PC_HI12:
150 return "desc64_pc_hi12";
151 case VK_LoongArch_TLS_DESC_HI20:
152 return "desc_hi20";
153 case VK_LoongArch_TLS_DESC_LO12:
154 return "desc_lo12";
155 case VK_LoongArch_TLS_DESC64_LO20:
156 return "desc64_lo20";
157 case VK_LoongArch_TLS_DESC64_HI12:
158 return "desc64_hi12";
159 case VK_LoongArch_TLS_DESC_LD:
160 return "desc_ld";
161 case VK_LoongArch_TLS_DESC_CALL:
162 return "desc_call";
163 case VK_LoongArch_TLS_LE_HI20_R:
164 return "le_hi20_r";
165 case VK_LoongArch_TLS_LE_ADD_R:
166 return "le_add_r";
167 case VK_LoongArch_TLS_LE_LO12_R:
168 return "le_lo12_r";
169 case VK_LoongArch_PCREL20_S2:
170 return "pcrel_20";
171 case VK_LoongArch_TLS_LD_PCREL20_S2:
172 return "ld_pcrel_20";
173 case VK_LoongArch_TLS_GD_PCREL20_S2:
174 return "gd_pcrel_20";
175 case VK_LoongArch_TLS_DESC_PCREL20_S2:
176 return "desc_pcrel_20";
177 }
178 }
179
180 LoongArchMCExpr::VariantKind
getVariantKindForName(StringRef name)181 LoongArchMCExpr::getVariantKindForName(StringRef name) {
182 return StringSwitch<LoongArchMCExpr::VariantKind>(name)
183 .Case("plt", VK_LoongArch_CALL_PLT)
184 .Case("b16", VK_LoongArch_B16)
185 .Case("b21", VK_LoongArch_B21)
186 .Case("b26", VK_LoongArch_B26)
187 .Case("abs_hi20", VK_LoongArch_ABS_HI20)
188 .Case("abs_lo12", VK_LoongArch_ABS_LO12)
189 .Case("abs64_lo20", VK_LoongArch_ABS64_LO20)
190 .Case("abs64_hi12", VK_LoongArch_ABS64_HI12)
191 .Case("pc_hi20", VK_LoongArch_PCALA_HI20)
192 .Case("pc_lo12", VK_LoongArch_PCALA_LO12)
193 .Case("pc64_lo20", VK_LoongArch_PCALA64_LO20)
194 .Case("pc64_hi12", VK_LoongArch_PCALA64_HI12)
195 .Case("got_pc_hi20", VK_LoongArch_GOT_PC_HI20)
196 .Case("got_pc_lo12", VK_LoongArch_GOT_PC_LO12)
197 .Case("got64_pc_lo20", VK_LoongArch_GOT64_PC_LO20)
198 .Case("got64_pc_hi12", VK_LoongArch_GOT64_PC_HI12)
199 .Case("got_hi20", VK_LoongArch_GOT_HI20)
200 .Case("got_lo12", VK_LoongArch_GOT_LO12)
201 .Case("got64_lo20", VK_LoongArch_GOT64_LO20)
202 .Case("got64_hi12", VK_LoongArch_GOT64_HI12)
203 .Case("le_hi20", VK_LoongArch_TLS_LE_HI20)
204 .Case("le_lo12", VK_LoongArch_TLS_LE_LO12)
205 .Case("le64_lo20", VK_LoongArch_TLS_LE64_LO20)
206 .Case("le64_hi12", VK_LoongArch_TLS_LE64_HI12)
207 .Case("ie_pc_hi20", VK_LoongArch_TLS_IE_PC_HI20)
208 .Case("ie_pc_lo12", VK_LoongArch_TLS_IE_PC_LO12)
209 .Case("ie64_pc_lo20", VK_LoongArch_TLS_IE64_PC_LO20)
210 .Case("ie64_pc_hi12", VK_LoongArch_TLS_IE64_PC_HI12)
211 .Case("ie_hi20", VK_LoongArch_TLS_IE_HI20)
212 .Case("ie_lo12", VK_LoongArch_TLS_IE_LO12)
213 .Case("ie64_lo20", VK_LoongArch_TLS_IE64_LO20)
214 .Case("ie64_hi12", VK_LoongArch_TLS_IE64_HI12)
215 .Case("ld_pc_hi20", VK_LoongArch_TLS_LD_PC_HI20)
216 .Case("ld_hi20", VK_LoongArch_TLS_LD_HI20)
217 .Case("gd_pc_hi20", VK_LoongArch_TLS_GD_PC_HI20)
218 .Case("gd_hi20", VK_LoongArch_TLS_GD_HI20)
219 .Case("call36", VK_LoongArch_CALL36)
220 .Case("desc_pc_hi20", VK_LoongArch_TLS_DESC_PC_HI20)
221 .Case("desc_pc_lo12", VK_LoongArch_TLS_DESC_PC_LO12)
222 .Case("desc64_pc_lo20", VK_LoongArch_TLS_DESC64_PC_LO20)
223 .Case("desc64_pc_hi12", VK_LoongArch_TLS_DESC64_PC_HI12)
224 .Case("desc_hi20", VK_LoongArch_TLS_DESC_HI20)
225 .Case("desc_lo12", VK_LoongArch_TLS_DESC_LO12)
226 .Case("desc64_lo20", VK_LoongArch_TLS_DESC64_LO20)
227 .Case("desc64_hi12", VK_LoongArch_TLS_DESC64_HI12)
228 .Case("desc_ld", VK_LoongArch_TLS_DESC_LD)
229 .Case("desc_call", VK_LoongArch_TLS_DESC_CALL)
230 .Case("le_hi20_r", VK_LoongArch_TLS_LE_HI20_R)
231 .Case("le_add_r", VK_LoongArch_TLS_LE_ADD_R)
232 .Case("le_lo12_r", VK_LoongArch_TLS_LE_LO12_R)
233 .Case("pcrel_20", VK_LoongArch_PCREL20_S2)
234 .Case("ld_pcrel_20", VK_LoongArch_TLS_LD_PCREL20_S2)
235 .Case("gd_pcrel_20", VK_LoongArch_TLS_GD_PCREL20_S2)
236 .Case("desc_pcrel_20", VK_LoongArch_TLS_DESC_PCREL20_S2)
237 .Default(VK_LoongArch_Invalid);
238 }
239
fixELFSymbolsInTLSFixupsImpl(const MCExpr * Expr,MCAssembler & Asm)240 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
241 switch (Expr->getKind()) {
242 case MCExpr::Target:
243 llvm_unreachable("Can't handle nested target expression");
244 break;
245 case MCExpr::Constant:
246 break;
247 case MCExpr::Unary:
248 fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
249 break;
250 case MCExpr::Binary: {
251 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
252 fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
253 fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
254 break;
255 }
256 case MCExpr::SymbolRef: {
257 // We're known to be under a TLS fixup, so any symbol should be
258 // modified. There should be only one.
259 const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
260 cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
261 break;
262 }
263 }
264 }
265
fixELFSymbolsInTLSFixups(MCAssembler & Asm) const266 void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
267 switch (getKind()) {
268 default:
269 return;
270 case VK_LoongArch_TLS_LE_HI20:
271 case VK_LoongArch_TLS_IE_PC_HI20:
272 case VK_LoongArch_TLS_IE_HI20:
273 case VK_LoongArch_TLS_LD_PC_HI20:
274 case VK_LoongArch_TLS_LD_HI20:
275 case VK_LoongArch_TLS_GD_PC_HI20:
276 case VK_LoongArch_TLS_GD_HI20:
277 case VK_LoongArch_TLS_DESC_PC_HI20:
278 case VK_LoongArch_TLS_DESC_HI20:
279 case VK_LoongArch_TLS_LD_PCREL20_S2:
280 case VK_LoongArch_TLS_GD_PCREL20_S2:
281 case VK_LoongArch_TLS_DESC_PCREL20_S2:
282 break;
283 }
284 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
285 }
286