1 | //===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// |
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 | #include "llvm/MC/MCExpr.h" |
10 | #include "llvm/ADT/Statistic.h" |
11 | #include "llvm/ADT/StringSwitch.h" |
12 | #include "llvm/Config/llvm-config.h" |
13 | #include "llvm/MC/MCAsmBackend.h" |
14 | #include "llvm/MC/MCAsmInfo.h" |
15 | #include "llvm/MC/MCAsmLayout.h" |
16 | #include "llvm/MC/MCAssembler.h" |
17 | #include "llvm/MC/MCContext.h" |
18 | #include "llvm/MC/MCObjectWriter.h" |
19 | #include "llvm/MC/MCSymbol.h" |
20 | #include "llvm/MC/MCValue.h" |
21 | #include "llvm/Support/Casting.h" |
22 | #include "llvm/Support/Compiler.h" |
23 | #include "llvm/Support/Debug.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | #include <cassert> |
27 | #include <cstdint> |
28 | |
29 | using namespace llvm; |
30 | |
31 | #define DEBUG_TYPE "mcexpr" |
32 | |
33 | namespace { |
34 | namespace stats { |
35 | |
36 | STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations" ); |
37 | |
38 | } // end namespace stats |
39 | } // end anonymous namespace |
40 | |
41 | void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { |
42 | switch (getKind()) { |
43 | case MCExpr::Target: |
44 | return cast<MCTargetExpr>(Val: this)->printImpl(OS, MAI); |
45 | case MCExpr::Constant: { |
46 | auto Value = cast<MCConstantExpr>(Val: *this).getValue(); |
47 | auto PrintInHex = cast<MCConstantExpr>(Val: *this).useHexFormat(); |
48 | auto SizeInBytes = cast<MCConstantExpr>(Val: *this).getSizeInBytes(); |
49 | if (Value < 0 && MAI && !MAI->supportsSignedData()) |
50 | PrintInHex = true; |
51 | if (PrintInHex) |
52 | switch (SizeInBytes) { |
53 | default: |
54 | OS << "0x" << Twine::utohexstr(Val: Value); |
55 | break; |
56 | case 1: |
57 | OS << format(Fmt: "0x%02" PRIx64, Vals: Value); |
58 | break; |
59 | case 2: |
60 | OS << format(Fmt: "0x%04" PRIx64, Vals: Value); |
61 | break; |
62 | case 4: |
63 | OS << format(Fmt: "0x%08" PRIx64, Vals: Value); |
64 | break; |
65 | case 8: |
66 | OS << format(Fmt: "0x%016" PRIx64, Vals: Value); |
67 | break; |
68 | } |
69 | else |
70 | OS << Value; |
71 | return; |
72 | } |
73 | case MCExpr::SymbolRef: { |
74 | const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Val: *this); |
75 | const MCSymbol &Sym = SRE.getSymbol(); |
76 | // Parenthesize names that start with $ so that they don't look like |
77 | // absolute names. |
78 | bool UseParens = MAI && MAI->useParensForDollarSignNames() && !InParens && |
79 | !Sym.getName().empty() && Sym.getName()[0] == '$'; |
80 | |
81 | if (UseParens) { |
82 | OS << '('; |
83 | Sym.print(OS, MAI); |
84 | OS << ')'; |
85 | } else |
86 | Sym.print(OS, MAI); |
87 | |
88 | const MCSymbolRefExpr::VariantKind Kind = SRE.getKind(); |
89 | if (Kind != MCSymbolRefExpr::VK_None) { |
90 | if (MAI && MAI->useParensForSymbolVariant()) // ARM |
91 | OS << '(' << MCSymbolRefExpr::getVariantKindName(Kind) << ')'; |
92 | else |
93 | OS << '@' << MCSymbolRefExpr::getVariantKindName(Kind); |
94 | } |
95 | |
96 | return; |
97 | } |
98 | |
99 | case MCExpr::Unary: { |
100 | const MCUnaryExpr &UE = cast<MCUnaryExpr>(Val: *this); |
101 | switch (UE.getOpcode()) { |
102 | case MCUnaryExpr::LNot: OS << '!'; break; |
103 | case MCUnaryExpr::Minus: OS << '-'; break; |
104 | case MCUnaryExpr::Not: OS << '~'; break; |
105 | case MCUnaryExpr::Plus: OS << '+'; break; |
106 | } |
107 | bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary; |
108 | if (Binary) OS << "(" ; |
109 | UE.getSubExpr()->print(OS, MAI); |
110 | if (Binary) OS << ")" ; |
111 | return; |
112 | } |
113 | |
114 | case MCExpr::Binary: { |
115 | const MCBinaryExpr &BE = cast<MCBinaryExpr>(Val: *this); |
116 | |
117 | // Only print parens around the LHS if it is non-trivial. |
118 | if (isa<MCConstantExpr>(Val: BE.getLHS()) || isa<MCSymbolRefExpr>(Val: BE.getLHS())) { |
119 | BE.getLHS()->print(OS, MAI); |
120 | } else { |
121 | OS << '('; |
122 | BE.getLHS()->print(OS, MAI); |
123 | OS << ')'; |
124 | } |
125 | |
126 | switch (BE.getOpcode()) { |
127 | case MCBinaryExpr::Add: |
128 | // Print "X-42" instead of "X+-42". |
129 | if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(Val: BE.getRHS())) { |
130 | if (RHSC->getValue() < 0) { |
131 | OS << RHSC->getValue(); |
132 | return; |
133 | } |
134 | } |
135 | |
136 | OS << '+'; |
137 | break; |
138 | case MCBinaryExpr::AShr: OS << ">>" ; break; |
139 | case MCBinaryExpr::And: OS << '&'; break; |
140 | case MCBinaryExpr::Div: OS << '/'; break; |
141 | case MCBinaryExpr::EQ: OS << "==" ; break; |
142 | case MCBinaryExpr::GT: OS << '>'; break; |
143 | case MCBinaryExpr::GTE: OS << ">=" ; break; |
144 | case MCBinaryExpr::LAnd: OS << "&&" ; break; |
145 | case MCBinaryExpr::LOr: OS << "||" ; break; |
146 | case MCBinaryExpr::LShr: OS << ">>" ; break; |
147 | case MCBinaryExpr::LT: OS << '<'; break; |
148 | case MCBinaryExpr::LTE: OS << "<=" ; break; |
149 | case MCBinaryExpr::Mod: OS << '%'; break; |
150 | case MCBinaryExpr::Mul: OS << '*'; break; |
151 | case MCBinaryExpr::NE: OS << "!=" ; break; |
152 | case MCBinaryExpr::Or: OS << '|'; break; |
153 | case MCBinaryExpr::OrNot: OS << '!'; break; |
154 | case MCBinaryExpr::Shl: OS << "<<" ; break; |
155 | case MCBinaryExpr::Sub: OS << '-'; break; |
156 | case MCBinaryExpr::Xor: OS << '^'; break; |
157 | } |
158 | |
159 | // Only print parens around the LHS if it is non-trivial. |
160 | if (isa<MCConstantExpr>(Val: BE.getRHS()) || isa<MCSymbolRefExpr>(Val: BE.getRHS())) { |
161 | BE.getRHS()->print(OS, MAI); |
162 | } else { |
163 | OS << '('; |
164 | BE.getRHS()->print(OS, MAI); |
165 | OS << ')'; |
166 | } |
167 | return; |
168 | } |
169 | } |
170 | |
171 | llvm_unreachable("Invalid expression kind!" ); |
172 | } |
173 | |
174 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
175 | LLVM_DUMP_METHOD void MCExpr::dump() const { |
176 | dbgs() << *this; |
177 | dbgs() << '\n'; |
178 | } |
179 | #endif |
180 | |
181 | /* *** */ |
182 | |
183 | const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS, |
184 | const MCExpr *RHS, MCContext &Ctx, |
185 | SMLoc Loc) { |
186 | return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc); |
187 | } |
188 | |
189 | const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr, |
190 | MCContext &Ctx, SMLoc Loc) { |
191 | return new (Ctx) MCUnaryExpr(Opc, Expr, Loc); |
192 | } |
193 | |
194 | const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx, |
195 | bool PrintInHex, |
196 | unsigned SizeInBytes) { |
197 | return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes); |
198 | } |
199 | |
200 | /* *** */ |
201 | |
202 | MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, |
203 | const MCAsmInfo *MAI, SMLoc Loc) |
204 | : MCExpr(MCExpr::SymbolRef, Loc, |
205 | encodeSubclassData(Kind, HasSubsectionsViaSymbols: MAI->hasSubsectionsViaSymbols())), |
206 | Symbol(Symbol) { |
207 | assert(Symbol); |
208 | } |
209 | |
210 | const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym, |
211 | VariantKind Kind, |
212 | MCContext &Ctx, SMLoc Loc) { |
213 | return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc); |
214 | } |
215 | |
216 | const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind, |
217 | MCContext &Ctx) { |
218 | return create(Sym: Ctx.getOrCreateSymbol(Name), Kind, Ctx); |
219 | } |
220 | |
221 | StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { |
222 | switch (Kind) { |
223 | case VK_Invalid: return "<<invalid>>" ; |
224 | case VK_None: return "<<none>>" ; |
225 | |
226 | case VK_DTPOFF: return "DTPOFF" ; |
227 | case VK_DTPREL: return "DTPREL" ; |
228 | case VK_GOT: return "GOT" ; |
229 | case VK_GOTOFF: return "GOTOFF" ; |
230 | case VK_GOTREL: return "GOTREL" ; |
231 | case VK_PCREL: return "PCREL" ; |
232 | case VK_GOTPCREL: return "GOTPCREL" ; |
233 | case VK_GOTPCREL_NORELAX: return "GOTPCREL_NORELAX" ; |
234 | case VK_GOTTPOFF: return "GOTTPOFF" ; |
235 | case VK_INDNTPOFF: return "INDNTPOFF" ; |
236 | case VK_NTPOFF: return "NTPOFF" ; |
237 | case VK_GOTNTPOFF: return "GOTNTPOFF" ; |
238 | case VK_PLT: return "PLT" ; |
239 | case VK_TLSGD: return "TLSGD" ; |
240 | case VK_TLSLD: return "TLSLD" ; |
241 | case VK_TLSLDM: return "TLSLDM" ; |
242 | case VK_TPOFF: return "TPOFF" ; |
243 | case VK_TPREL: return "TPREL" ; |
244 | case VK_TLSCALL: return "tlscall" ; |
245 | case VK_TLSDESC: return "tlsdesc" ; |
246 | case VK_TLVP: return "TLVP" ; |
247 | case VK_TLVPPAGE: return "TLVPPAGE" ; |
248 | case VK_TLVPPAGEOFF: return "TLVPPAGEOFF" ; |
249 | case VK_PAGE: return "PAGE" ; |
250 | case VK_PAGEOFF: return "PAGEOFF" ; |
251 | case VK_GOTPAGE: return "GOTPAGE" ; |
252 | case VK_GOTPAGEOFF: return "GOTPAGEOFF" ; |
253 | case VK_SECREL: return "SECREL32" ; |
254 | case VK_SIZE: return "SIZE" ; |
255 | case VK_WEAKREF: return "WEAKREF" ; |
256 | case VK_X86_ABS8: return "ABS8" ; |
257 | case VK_X86_PLTOFF: return "PLTOFF" ; |
258 | case VK_ARM_NONE: return "none" ; |
259 | case VK_ARM_GOT_PREL: return "GOT_PREL" ; |
260 | case VK_ARM_TARGET1: return "target1" ; |
261 | case VK_ARM_TARGET2: return "target2" ; |
262 | case VK_ARM_PREL31: return "prel31" ; |
263 | case VK_ARM_SBREL: return "sbrel" ; |
264 | case VK_ARM_TLSLDO: return "tlsldo" ; |
265 | case VK_ARM_TLSDESCSEQ: return "tlsdescseq" ; |
266 | case VK_AVR_NONE: return "none" ; |
267 | case VK_AVR_LO8: return "lo8" ; |
268 | case VK_AVR_HI8: return "hi8" ; |
269 | case VK_AVR_HLO8: return "hlo8" ; |
270 | case VK_AVR_DIFF8: return "diff8" ; |
271 | case VK_AVR_DIFF16: return "diff16" ; |
272 | case VK_AVR_DIFF32: return "diff32" ; |
273 | case VK_AVR_PM: return "pm" ; |
274 | case VK_PPC_LO: return "l" ; |
275 | case VK_PPC_HI: return "h" ; |
276 | case VK_PPC_HA: return "ha" ; |
277 | case VK_PPC_HIGH: return "high" ; |
278 | case VK_PPC_HIGHA: return "higha" ; |
279 | case VK_PPC_HIGHER: return "higher" ; |
280 | case VK_PPC_HIGHERA: return "highera" ; |
281 | case VK_PPC_HIGHEST: return "highest" ; |
282 | case VK_PPC_HIGHESTA: return "highesta" ; |
283 | case VK_PPC_GOT_LO: return "got@l" ; |
284 | case VK_PPC_GOT_HI: return "got@h" ; |
285 | case VK_PPC_GOT_HA: return "got@ha" ; |
286 | case VK_PPC_TOCBASE: return "tocbase" ; |
287 | case VK_PPC_TOC: return "toc" ; |
288 | case VK_PPC_TOC_LO: return "toc@l" ; |
289 | case VK_PPC_TOC_HI: return "toc@h" ; |
290 | case VK_PPC_TOC_HA: return "toc@ha" ; |
291 | case VK_PPC_U: return "u" ; |
292 | case VK_PPC_L: return "l" ; |
293 | case VK_PPC_DTPMOD: return "dtpmod" ; |
294 | case VK_PPC_TPREL_LO: return "tprel@l" ; |
295 | case VK_PPC_TPREL_HI: return "tprel@h" ; |
296 | case VK_PPC_TPREL_HA: return "tprel@ha" ; |
297 | case VK_PPC_TPREL_HIGH: return "tprel@high" ; |
298 | case VK_PPC_TPREL_HIGHA: return "tprel@higha" ; |
299 | case VK_PPC_TPREL_HIGHER: return "tprel@higher" ; |
300 | case VK_PPC_TPREL_HIGHERA: return "tprel@highera" ; |
301 | case VK_PPC_TPREL_HIGHEST: return "tprel@highest" ; |
302 | case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta" ; |
303 | case VK_PPC_DTPREL_LO: return "dtprel@l" ; |
304 | case VK_PPC_DTPREL_HI: return "dtprel@h" ; |
305 | case VK_PPC_DTPREL_HA: return "dtprel@ha" ; |
306 | case VK_PPC_DTPREL_HIGH: return "dtprel@high" ; |
307 | case VK_PPC_DTPREL_HIGHA: return "dtprel@higha" ; |
308 | case VK_PPC_DTPREL_HIGHER: return "dtprel@higher" ; |
309 | case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera" ; |
310 | case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest" ; |
311 | case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta" ; |
312 | case VK_PPC_GOT_TPREL: return "got@tprel" ; |
313 | case VK_PPC_GOT_TPREL_LO: return "got@tprel@l" ; |
314 | case VK_PPC_GOT_TPREL_HI: return "got@tprel@h" ; |
315 | case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha" ; |
316 | case VK_PPC_GOT_DTPREL: return "got@dtprel" ; |
317 | case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l" ; |
318 | case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h" ; |
319 | case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha" ; |
320 | case VK_PPC_TLS: return "tls" ; |
321 | case VK_PPC_GOT_TLSGD: return "got@tlsgd" ; |
322 | case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l" ; |
323 | case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h" ; |
324 | case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha" ; |
325 | case VK_PPC_TLSGD: return "tlsgd" ; |
326 | case VK_PPC_AIX_TLSGD: |
327 | return "gd" ; |
328 | case VK_PPC_AIX_TLSGDM: |
329 | return "m" ; |
330 | case VK_PPC_AIX_TLSIE: |
331 | return "ie" ; |
332 | case VK_PPC_AIX_TLSLE: |
333 | return "le" ; |
334 | case VK_PPC_GOT_TLSLD: return "got@tlsld" ; |
335 | case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l" ; |
336 | case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h" ; |
337 | case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha" ; |
338 | case VK_PPC_GOT_PCREL: |
339 | return "got@pcrel" ; |
340 | case VK_PPC_GOT_TLSGD_PCREL: |
341 | return "got@tlsgd@pcrel" ; |
342 | case VK_PPC_GOT_TLSLD_PCREL: |
343 | return "got@tlsld@pcrel" ; |
344 | case VK_PPC_GOT_TPREL_PCREL: |
345 | return "got@tprel@pcrel" ; |
346 | case VK_PPC_TLS_PCREL: |
347 | return "tls@pcrel" ; |
348 | case VK_PPC_TLSLD: return "tlsld" ; |
349 | case VK_PPC_LOCAL: return "local" ; |
350 | case VK_PPC_NOTOC: return "notoc" ; |
351 | case VK_PPC_PCREL_OPT: return "<<invalid>>" ; |
352 | case VK_COFF_IMGREL32: return "IMGREL" ; |
353 | case VK_Hexagon_LO16: return "LO16" ; |
354 | case VK_Hexagon_HI16: return "HI16" ; |
355 | case VK_Hexagon_GPREL: return "GPREL" ; |
356 | case VK_Hexagon_GD_GOT: return "GDGOT" ; |
357 | case VK_Hexagon_LD_GOT: return "LDGOT" ; |
358 | case VK_Hexagon_GD_PLT: return "GDPLT" ; |
359 | case VK_Hexagon_LD_PLT: return "LDPLT" ; |
360 | case VK_Hexagon_IE: return "IE" ; |
361 | case VK_Hexagon_IE_GOT: return "IEGOT" ; |
362 | case VK_WASM_TYPEINDEX: return "TYPEINDEX" ; |
363 | case VK_WASM_MBREL: return "MBREL" ; |
364 | case VK_WASM_TLSREL: return "TLSREL" ; |
365 | case VK_WASM_TBREL: return "TBREL" ; |
366 | case VK_WASM_GOT_TLS: return "GOT@TLS" ; |
367 | case VK_WASM_FUNCINDEX: return "FUNCINDEX" ; |
368 | case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo" ; |
369 | case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi" ; |
370 | case VK_AMDGPU_REL32_LO: return "rel32@lo" ; |
371 | case VK_AMDGPU_REL32_HI: return "rel32@hi" ; |
372 | case VK_AMDGPU_REL64: return "rel64" ; |
373 | case VK_AMDGPU_ABS32_LO: return "abs32@lo" ; |
374 | case VK_AMDGPU_ABS32_HI: return "abs32@hi" ; |
375 | case VK_VE_HI32: return "hi" ; |
376 | case VK_VE_LO32: return "lo" ; |
377 | case VK_VE_PC_HI32: return "pc_hi" ; |
378 | case VK_VE_PC_LO32: return "pc_lo" ; |
379 | case VK_VE_GOT_HI32: return "got_hi" ; |
380 | case VK_VE_GOT_LO32: return "got_lo" ; |
381 | case VK_VE_GOTOFF_HI32: return "gotoff_hi" ; |
382 | case VK_VE_GOTOFF_LO32: return "gotoff_lo" ; |
383 | case VK_VE_PLT_HI32: return "plt_hi" ; |
384 | case VK_VE_PLT_LO32: return "plt_lo" ; |
385 | case VK_VE_TLS_GD_HI32: return "tls_gd_hi" ; |
386 | case VK_VE_TLS_GD_LO32: return "tls_gd_lo" ; |
387 | case VK_VE_TPOFF_HI32: return "tpoff_hi" ; |
388 | case VK_VE_TPOFF_LO32: return "tpoff_lo" ; |
389 | } |
390 | llvm_unreachable("Invalid variant kind" ); |
391 | } |
392 | |
393 | MCSymbolRefExpr::VariantKind |
394 | MCSymbolRefExpr::getVariantKindForName(StringRef Name) { |
395 | return StringSwitch<VariantKind>(Name.lower()) |
396 | .Case(S: "dtprel" , Value: VK_DTPREL) |
397 | .Case(S: "dtpoff" , Value: VK_DTPOFF) |
398 | .Case(S: "got" , Value: VK_GOT) |
399 | .Case(S: "gotoff" , Value: VK_GOTOFF) |
400 | .Case(S: "gotrel" , Value: VK_GOTREL) |
401 | .Case(S: "pcrel" , Value: VK_PCREL) |
402 | .Case(S: "gotpcrel" , Value: VK_GOTPCREL) |
403 | .Case(S: "gotpcrel_norelax" , Value: VK_GOTPCREL_NORELAX) |
404 | .Case(S: "gottpoff" , Value: VK_GOTTPOFF) |
405 | .Case(S: "indntpoff" , Value: VK_INDNTPOFF) |
406 | .Case(S: "ntpoff" , Value: VK_NTPOFF) |
407 | .Case(S: "gotntpoff" , Value: VK_GOTNTPOFF) |
408 | .Case(S: "plt" , Value: VK_PLT) |
409 | .Case(S: "tlscall" , Value: VK_TLSCALL) |
410 | .Case(S: "tlsdesc" , Value: VK_TLSDESC) |
411 | .Case(S: "tlsgd" , Value: VK_TLSGD) |
412 | .Case(S: "tlsld" , Value: VK_TLSLD) |
413 | .Case(S: "tlsldm" , Value: VK_TLSLDM) |
414 | .Case(S: "tpoff" , Value: VK_TPOFF) |
415 | .Case(S: "tprel" , Value: VK_TPREL) |
416 | .Case(S: "tlvp" , Value: VK_TLVP) |
417 | .Case(S: "tlvppage" , Value: VK_TLVPPAGE) |
418 | .Case(S: "tlvppageoff" , Value: VK_TLVPPAGEOFF) |
419 | .Case(S: "page" , Value: VK_PAGE) |
420 | .Case(S: "pageoff" , Value: VK_PAGEOFF) |
421 | .Case(S: "gotpage" , Value: VK_GOTPAGE) |
422 | .Case(S: "gotpageoff" , Value: VK_GOTPAGEOFF) |
423 | .Case(S: "imgrel" , Value: VK_COFF_IMGREL32) |
424 | .Case(S: "secrel32" , Value: VK_SECREL) |
425 | .Case(S: "size" , Value: VK_SIZE) |
426 | .Case(S: "abs8" , Value: VK_X86_ABS8) |
427 | .Case(S: "pltoff" , Value: VK_X86_PLTOFF) |
428 | .Case(S: "l" , Value: VK_PPC_LO) |
429 | .Case(S: "h" , Value: VK_PPC_HI) |
430 | .Case(S: "ha" , Value: VK_PPC_HA) |
431 | .Case(S: "high" , Value: VK_PPC_HIGH) |
432 | .Case(S: "higha" , Value: VK_PPC_HIGHA) |
433 | .Case(S: "higher" , Value: VK_PPC_HIGHER) |
434 | .Case(S: "highera" , Value: VK_PPC_HIGHERA) |
435 | .Case(S: "highest" , Value: VK_PPC_HIGHEST) |
436 | .Case(S: "highesta" , Value: VK_PPC_HIGHESTA) |
437 | .Case(S: "got@l" , Value: VK_PPC_GOT_LO) |
438 | .Case(S: "got@h" , Value: VK_PPC_GOT_HI) |
439 | .Case(S: "got@ha" , Value: VK_PPC_GOT_HA) |
440 | .Case(S: "local" , Value: VK_PPC_LOCAL) |
441 | .Case(S: "tocbase" , Value: VK_PPC_TOCBASE) |
442 | .Case(S: "toc" , Value: VK_PPC_TOC) |
443 | .Case(S: "toc@l" , Value: VK_PPC_TOC_LO) |
444 | .Case(S: "toc@h" , Value: VK_PPC_TOC_HI) |
445 | .Case(S: "toc@ha" , Value: VK_PPC_TOC_HA) |
446 | .Case(S: "u" , Value: VK_PPC_U) |
447 | .Case(S: "l" , Value: VK_PPC_L) |
448 | .Case(S: "tls" , Value: VK_PPC_TLS) |
449 | .Case(S: "dtpmod" , Value: VK_PPC_DTPMOD) |
450 | .Case(S: "tprel@l" , Value: VK_PPC_TPREL_LO) |
451 | .Case(S: "tprel@h" , Value: VK_PPC_TPREL_HI) |
452 | .Case(S: "tprel@ha" , Value: VK_PPC_TPREL_HA) |
453 | .Case(S: "tprel@high" , Value: VK_PPC_TPREL_HIGH) |
454 | .Case(S: "tprel@higha" , Value: VK_PPC_TPREL_HIGHA) |
455 | .Case(S: "tprel@higher" , Value: VK_PPC_TPREL_HIGHER) |
456 | .Case(S: "tprel@highera" , Value: VK_PPC_TPREL_HIGHERA) |
457 | .Case(S: "tprel@highest" , Value: VK_PPC_TPREL_HIGHEST) |
458 | .Case(S: "tprel@highesta" , Value: VK_PPC_TPREL_HIGHESTA) |
459 | .Case(S: "dtprel@l" , Value: VK_PPC_DTPREL_LO) |
460 | .Case(S: "dtprel@h" , Value: VK_PPC_DTPREL_HI) |
461 | .Case(S: "dtprel@ha" , Value: VK_PPC_DTPREL_HA) |
462 | .Case(S: "dtprel@high" , Value: VK_PPC_DTPREL_HIGH) |
463 | .Case(S: "dtprel@higha" , Value: VK_PPC_DTPREL_HIGHA) |
464 | .Case(S: "dtprel@higher" , Value: VK_PPC_DTPREL_HIGHER) |
465 | .Case(S: "dtprel@highera" , Value: VK_PPC_DTPREL_HIGHERA) |
466 | .Case(S: "dtprel@highest" , Value: VK_PPC_DTPREL_HIGHEST) |
467 | .Case(S: "dtprel@highesta" , Value: VK_PPC_DTPREL_HIGHESTA) |
468 | .Case(S: "got@tprel" , Value: VK_PPC_GOT_TPREL) |
469 | .Case(S: "got@tprel@l" , Value: VK_PPC_GOT_TPREL_LO) |
470 | .Case(S: "got@tprel@h" , Value: VK_PPC_GOT_TPREL_HI) |
471 | .Case(S: "got@tprel@ha" , Value: VK_PPC_GOT_TPREL_HA) |
472 | .Case(S: "got@dtprel" , Value: VK_PPC_GOT_DTPREL) |
473 | .Case(S: "got@dtprel@l" , Value: VK_PPC_GOT_DTPREL_LO) |
474 | .Case(S: "got@dtprel@h" , Value: VK_PPC_GOT_DTPREL_HI) |
475 | .Case(S: "got@dtprel@ha" , Value: VK_PPC_GOT_DTPREL_HA) |
476 | .Case(S: "got@tlsgd" , Value: VK_PPC_GOT_TLSGD) |
477 | .Case(S: "got@tlsgd@l" , Value: VK_PPC_GOT_TLSGD_LO) |
478 | .Case(S: "got@tlsgd@h" , Value: VK_PPC_GOT_TLSGD_HI) |
479 | .Case(S: "got@tlsgd@ha" , Value: VK_PPC_GOT_TLSGD_HA) |
480 | .Case(S: "got@tlsld" , Value: VK_PPC_GOT_TLSLD) |
481 | .Case(S: "got@tlsld@l" , Value: VK_PPC_GOT_TLSLD_LO) |
482 | .Case(S: "got@tlsld@h" , Value: VK_PPC_GOT_TLSLD_HI) |
483 | .Case(S: "got@tlsld@ha" , Value: VK_PPC_GOT_TLSLD_HA) |
484 | .Case(S: "got@pcrel" , Value: VK_PPC_GOT_PCREL) |
485 | .Case(S: "got@tlsgd@pcrel" , Value: VK_PPC_GOT_TLSGD_PCREL) |
486 | .Case(S: "got@tlsld@pcrel" , Value: VK_PPC_GOT_TLSLD_PCREL) |
487 | .Case(S: "got@tprel@pcrel" , Value: VK_PPC_GOT_TPREL_PCREL) |
488 | .Case(S: "tls@pcrel" , Value: VK_PPC_TLS_PCREL) |
489 | .Case(S: "notoc" , Value: VK_PPC_NOTOC) |
490 | .Case(S: "gdgot" , Value: VK_Hexagon_GD_GOT) |
491 | .Case(S: "gdplt" , Value: VK_Hexagon_GD_PLT) |
492 | .Case(S: "iegot" , Value: VK_Hexagon_IE_GOT) |
493 | .Case(S: "ie" , Value: VK_Hexagon_IE) |
494 | .Case(S: "ldgot" , Value: VK_Hexagon_LD_GOT) |
495 | .Case(S: "ldplt" , Value: VK_Hexagon_LD_PLT) |
496 | .Case(S: "none" , Value: VK_ARM_NONE) |
497 | .Case(S: "got_prel" , Value: VK_ARM_GOT_PREL) |
498 | .Case(S: "target1" , Value: VK_ARM_TARGET1) |
499 | .Case(S: "target2" , Value: VK_ARM_TARGET2) |
500 | .Case(S: "prel31" , Value: VK_ARM_PREL31) |
501 | .Case(S: "sbrel" , Value: VK_ARM_SBREL) |
502 | .Case(S: "tlsldo" , Value: VK_ARM_TLSLDO) |
503 | .Case(S: "lo8" , Value: VK_AVR_LO8) |
504 | .Case(S: "hi8" , Value: VK_AVR_HI8) |
505 | .Case(S: "hlo8" , Value: VK_AVR_HLO8) |
506 | .Case(S: "typeindex" , Value: VK_WASM_TYPEINDEX) |
507 | .Case(S: "tbrel" , Value: VK_WASM_TBREL) |
508 | .Case(S: "mbrel" , Value: VK_WASM_MBREL) |
509 | .Case(S: "tlsrel" , Value: VK_WASM_TLSREL) |
510 | .Case(S: "got@tls" , Value: VK_WASM_GOT_TLS) |
511 | .Case(S: "funcindex" , Value: VK_WASM_FUNCINDEX) |
512 | .Case(S: "gotpcrel32@lo" , Value: VK_AMDGPU_GOTPCREL32_LO) |
513 | .Case(S: "gotpcrel32@hi" , Value: VK_AMDGPU_GOTPCREL32_HI) |
514 | .Case(S: "rel32@lo" , Value: VK_AMDGPU_REL32_LO) |
515 | .Case(S: "rel32@hi" , Value: VK_AMDGPU_REL32_HI) |
516 | .Case(S: "rel64" , Value: VK_AMDGPU_REL64) |
517 | .Case(S: "abs32@lo" , Value: VK_AMDGPU_ABS32_LO) |
518 | .Case(S: "abs32@hi" , Value: VK_AMDGPU_ABS32_HI) |
519 | .Case(S: "hi" , Value: VK_VE_HI32) |
520 | .Case(S: "lo" , Value: VK_VE_LO32) |
521 | .Case(S: "pc_hi" , Value: VK_VE_PC_HI32) |
522 | .Case(S: "pc_lo" , Value: VK_VE_PC_LO32) |
523 | .Case(S: "got_hi" , Value: VK_VE_GOT_HI32) |
524 | .Case(S: "got_lo" , Value: VK_VE_GOT_LO32) |
525 | .Case(S: "gotoff_hi" , Value: VK_VE_GOTOFF_HI32) |
526 | .Case(S: "gotoff_lo" , Value: VK_VE_GOTOFF_LO32) |
527 | .Case(S: "plt_hi" , Value: VK_VE_PLT_HI32) |
528 | .Case(S: "plt_lo" , Value: VK_VE_PLT_LO32) |
529 | .Case(S: "tls_gd_hi" , Value: VK_VE_TLS_GD_HI32) |
530 | .Case(S: "tls_gd_lo" , Value: VK_VE_TLS_GD_LO32) |
531 | .Case(S: "tpoff_hi" , Value: VK_VE_TPOFF_HI32) |
532 | .Case(S: "tpoff_lo" , Value: VK_VE_TPOFF_LO32) |
533 | .Default(Value: VK_Invalid); |
534 | } |
535 | |
536 | /* *** */ |
537 | |
538 | void MCTargetExpr::anchor() {} |
539 | |
540 | /* *** */ |
541 | |
542 | bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { |
543 | return evaluateAsAbsolute(Res, Asm: nullptr, Layout: nullptr, Addrs: nullptr, InSet: false); |
544 | } |
545 | |
546 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, |
547 | const MCAsmLayout &Layout) const { |
548 | return evaluateAsAbsolute(Res, Asm: &Layout.getAssembler(), Layout: &Layout, Addrs: nullptr, InSet: false); |
549 | } |
550 | |
551 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, |
552 | const MCAsmLayout &Layout, |
553 | const SectionAddrMap &Addrs) const { |
554 | // Setting InSet causes us to absolutize differences across sections and that |
555 | // is what the MachO writer uses Addrs for. |
556 | return evaluateAsAbsolute(Res, Asm: &Layout.getAssembler(), Layout: &Layout, Addrs: &Addrs, InSet: true); |
557 | } |
558 | |
559 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { |
560 | return evaluateAsAbsolute(Res, Asm: &Asm, Layout: nullptr, Addrs: nullptr, InSet: false); |
561 | } |
562 | |
563 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { |
564 | return evaluateAsAbsolute(Res, Asm, Layout: nullptr, Addrs: nullptr, InSet: false); |
565 | } |
566 | |
567 | bool MCExpr::evaluateKnownAbsolute(int64_t &Res, |
568 | const MCAsmLayout &Layout) const { |
569 | return evaluateAsAbsolute(Res, Asm: &Layout.getAssembler(), Layout: &Layout, Addrs: nullptr, |
570 | InSet: true); |
571 | } |
572 | |
573 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, |
574 | const MCAsmLayout *Layout, |
575 | const SectionAddrMap *Addrs, bool InSet) const { |
576 | MCValue Value; |
577 | |
578 | // Fast path constants. |
579 | if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: this)) { |
580 | Res = CE->getValue(); |
581 | return true; |
582 | } |
583 | |
584 | bool IsRelocatable = |
585 | evaluateAsRelocatableImpl(Res&: Value, Asm, Layout, Fixup: nullptr, Addrs, InSet); |
586 | |
587 | // Record the current value. |
588 | Res = Value.getConstant(); |
589 | |
590 | return IsRelocatable && Value.isAbsolute(); |
591 | } |
592 | |
593 | /// Helper method for \see EvaluateSymbolAdd(). |
594 | static void AttemptToFoldSymbolOffsetDifference( |
595 | const MCAssembler *Asm, const MCAsmLayout *Layout, |
596 | const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, |
597 | const MCSymbolRefExpr *&B, int64_t &Addend) { |
598 | if (!A || !B) |
599 | return; |
600 | |
601 | const MCSymbol &SA = A->getSymbol(); |
602 | const MCSymbol &SB = B->getSymbol(); |
603 | |
604 | if (SA.isUndefined() || SB.isUndefined()) |
605 | return; |
606 | |
607 | if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(Asm: *Asm, A, B, InSet)) |
608 | return; |
609 | |
610 | auto FinalizeFolding = [&]() { |
611 | // Pointers to Thumb symbols need to have their low-bit set to allow |
612 | // for interworking. |
613 | if (Asm->isThumbFunc(Func: &SA)) |
614 | Addend |= 1; |
615 | |
616 | // Clear the symbol expr pointers to indicate we have folded these |
617 | // operands. |
618 | A = B = nullptr; |
619 | }; |
620 | |
621 | const MCFragment *FA = SA.getFragment(); |
622 | const MCFragment *FB = SB.getFragment(); |
623 | const MCSection &SecA = *FA->getParent(); |
624 | const MCSection &SecB = *FB->getParent(); |
625 | if ((&SecA != &SecB) && !Addrs) |
626 | return; |
627 | |
628 | // When layout is available, we can generally compute the difference using the |
629 | // getSymbolOffset path, which also avoids the possible slow fragment walk. |
630 | // However, linker relaxation may cause incorrect fold of A-B if A and B are |
631 | // separated by a linker-relaxable instruction. If the section contains |
632 | // instructions and InSet is false (not expressions in directive like |
633 | // .size/.fill), disable the fast path. |
634 | if (Layout && (InSet || !SecA.hasInstructions() || |
635 | !(Asm->getContext().getTargetTriple().isRISCV() || |
636 | Asm->getContext().getTargetTriple().isLoongArch()))) { |
637 | // If both symbols are in the same fragment, return the difference of their |
638 | // offsets. canGetFragmentOffset(FA) may be false. |
639 | if (FA == FB && !SA.isVariable() && !SB.isVariable()) { |
640 | Addend += SA.getOffset() - SB.getOffset(); |
641 | return FinalizeFolding(); |
642 | } |
643 | // One of the symbol involved is part of a fragment being laid out. Quit now |
644 | // to avoid a self loop. |
645 | if (!Layout->canGetFragmentOffset(F: FA) || !Layout->canGetFragmentOffset(F: FB)) |
646 | return; |
647 | |
648 | // Eagerly evaluate when layout is finalized. |
649 | Addend += Layout->getSymbolOffset(S: A->getSymbol()) - |
650 | Layout->getSymbolOffset(S: B->getSymbol()); |
651 | if (Addrs && (&SecA != &SecB)) |
652 | Addend += (Addrs->lookup(Val: &SecA) - Addrs->lookup(Val: &SecB)); |
653 | |
654 | FinalizeFolding(); |
655 | } else { |
656 | // When layout is not finalized, our ability to resolve differences between |
657 | // symbols is limited to specific cases where the fragments between two |
658 | // symbols (including the fragments the symbols are defined in) are |
659 | // fixed-size fragments so the difference can be calculated. For example, |
660 | // this is important when the Subtarget is changed and a new MCDataFragment |
661 | // is created in the case of foo: instr; .arch_extension ext; instr .if . - |
662 | // foo. |
663 | if (SA.isVariable() || SB.isVariable() || |
664 | FA->getSubsectionNumber() != FB->getSubsectionNumber()) |
665 | return; |
666 | |
667 | // Try to find a constant displacement from FA to FB, add the displacement |
668 | // between the offset in FA of SA and the offset in FB of SB. |
669 | bool Reverse = false; |
670 | if (FA == FB) { |
671 | Reverse = SA.getOffset() < SB.getOffset(); |
672 | } else if (!isa<MCDummyFragment>(Val: FA)) { |
673 | Reverse = std::find_if(first: std::next(x: FA->getIterator()), last: SecA.end(), |
674 | pred: [&](auto &I) { return &I == FB; }) != SecA.end(); |
675 | } |
676 | |
677 | uint64_t SAOffset = SA.getOffset(), SBOffset = SB.getOffset(); |
678 | int64_t Displacement = SA.getOffset() - SB.getOffset(); |
679 | if (Reverse) { |
680 | std::swap(a&: FA, b&: FB); |
681 | std::swap(a&: SAOffset, b&: SBOffset); |
682 | Displacement *= -1; |
683 | } |
684 | |
685 | [[maybe_unused]] bool Found = false; |
686 | // Track whether B is before a relaxable instruction and whether A is after |
687 | // a relaxable instruction. If SA and SB are separated by a linker-relaxable |
688 | // instruction, the difference cannot be resolved as it may be changed by |
689 | // the linker. |
690 | bool BBeforeRelax = false, AAfterRelax = false; |
691 | for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) { |
692 | auto DF = dyn_cast<MCDataFragment>(Val&: FI); |
693 | if (DF && DF->isLinkerRelaxable()) { |
694 | if (&*FI != FB || SBOffset != DF->getContents().size()) |
695 | BBeforeRelax = true; |
696 | if (&*FI != FA || SAOffset == DF->getContents().size()) |
697 | AAfterRelax = true; |
698 | if (BBeforeRelax && AAfterRelax) |
699 | return; |
700 | } |
701 | if (&*FI == FA) { |
702 | Found = true; |
703 | break; |
704 | } |
705 | |
706 | int64_t Num; |
707 | unsigned Count; |
708 | if (DF) { |
709 | Displacement += DF->getContents().size(); |
710 | } else if (auto *AF = dyn_cast<MCAlignFragment>(Val&: FI); |
711 | AF && Layout && AF->hasEmitNops() && |
712 | !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( |
713 | AF: *AF, Size&: Count)) { |
714 | Displacement += Asm->computeFragmentSize(Layout: *Layout, F: *AF); |
715 | } else if (auto *FF = dyn_cast<MCFillFragment>(Val&: FI); |
716 | FF && FF->getNumValues().evaluateAsAbsolute(Res&: Num)) { |
717 | Displacement += Num * FF->getValueSize(); |
718 | } else { |
719 | return; |
720 | } |
721 | } |
722 | // If the previous loop does not find FA, FA must be a dummy fragment not in |
723 | // the fragment list (which means SA is a pending label (see |
724 | // flushPendingLabels)). In either case, we can resolve the difference. |
725 | assert(Found || isa<MCDummyFragment>(FA)); |
726 | Addend += Reverse ? -Displacement : Displacement; |
727 | FinalizeFolding(); |
728 | } |
729 | } |
730 | |
731 | /// Evaluate the result of an add between (conceptually) two MCValues. |
732 | /// |
733 | /// This routine conceptually attempts to construct an MCValue: |
734 | /// Result = (Result_A - Result_B + Result_Cst) |
735 | /// from two MCValue's LHS and RHS where |
736 | /// Result = LHS + RHS |
737 | /// and |
738 | /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). |
739 | /// |
740 | /// This routine attempts to aggressively fold the operands such that the result |
741 | /// is representable in an MCValue, but may not always succeed. |
742 | /// |
743 | /// \returns True on success, false if the result is not representable in an |
744 | /// MCValue. |
745 | |
746 | /// NOTE: It is really important to have both the Asm and Layout arguments. |
747 | /// They might look redundant, but this function can be used before layout |
748 | /// is done (see the object streamer for example) and having the Asm argument |
749 | /// lets us avoid relaxations early. |
750 | static bool EvaluateSymbolicAdd(const MCAssembler *Asm, |
751 | const MCAsmLayout *Layout, |
752 | const SectionAddrMap *Addrs, bool InSet, |
753 | const MCValue &LHS, const MCValue &RHS, |
754 | MCValue &Res) { |
755 | // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy |
756 | // about dealing with modifiers. This will ultimately bite us, one day. |
757 | const MCSymbolRefExpr *LHS_A = LHS.getSymA(); |
758 | const MCSymbolRefExpr *LHS_B = LHS.getSymB(); |
759 | int64_t LHS_Cst = LHS.getConstant(); |
760 | |
761 | const MCSymbolRefExpr *RHS_A = RHS.getSymA(); |
762 | const MCSymbolRefExpr *RHS_B = RHS.getSymB(); |
763 | int64_t RHS_Cst = RHS.getConstant(); |
764 | |
765 | if (LHS.getRefKind() != RHS.getRefKind()) |
766 | return false; |
767 | |
768 | // Fold the result constant immediately. |
769 | int64_t Result_Cst = LHS_Cst + RHS_Cst; |
770 | |
771 | assert((!Layout || Asm) && |
772 | "Must have an assembler object if layout is given!" ); |
773 | |
774 | // If we have a layout, we can fold resolved differences. |
775 | if (Asm) { |
776 | // First, fold out any differences which are fully resolved. By |
777 | // reassociating terms in |
778 | // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). |
779 | // we have the four possible differences: |
780 | // (LHS_A - LHS_B), |
781 | // (LHS_A - RHS_B), |
782 | // (RHS_A - LHS_B), |
783 | // (RHS_A - RHS_B). |
784 | // Since we are attempting to be as aggressive as possible about folding, we |
785 | // attempt to evaluate each possible alternative. |
786 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, A&: LHS_A, B&: LHS_B, |
787 | Addend&: Result_Cst); |
788 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, A&: LHS_A, B&: RHS_B, |
789 | Addend&: Result_Cst); |
790 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, A&: RHS_A, B&: LHS_B, |
791 | Addend&: Result_Cst); |
792 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, A&: RHS_A, B&: RHS_B, |
793 | Addend&: Result_Cst); |
794 | } |
795 | |
796 | // We can't represent the addition or subtraction of two symbols. |
797 | if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) |
798 | return false; |
799 | |
800 | // At this point, we have at most one additive symbol and one subtractive |
801 | // symbol -- find them. |
802 | const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; |
803 | const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; |
804 | |
805 | Res = MCValue::get(SymA: A, SymB: B, Val: Result_Cst); |
806 | return true; |
807 | } |
808 | |
809 | bool MCExpr::evaluateAsRelocatable(MCValue &Res, |
810 | const MCAsmLayout *Layout, |
811 | const MCFixup *Fixup) const { |
812 | MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; |
813 | return evaluateAsRelocatableImpl(Res, Asm: Assembler, Layout, Fixup, Addrs: nullptr, |
814 | InSet: false); |
815 | } |
816 | |
817 | bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { |
818 | MCAssembler *Assembler = &Layout.getAssembler(); |
819 | return evaluateAsRelocatableImpl(Res, Asm: Assembler, Layout: &Layout, Fixup: nullptr, Addrs: nullptr, |
820 | InSet: true); |
821 | } |
822 | |
823 | static bool canExpand(const MCSymbol &Sym, bool InSet) { |
824 | if (Sym.isWeakExternal()) |
825 | return false; |
826 | |
827 | const MCExpr *Expr = Sym.getVariableValue(); |
828 | const auto *Inner = dyn_cast<MCSymbolRefExpr>(Val: Expr); |
829 | if (Inner) { |
830 | if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) |
831 | return false; |
832 | } |
833 | |
834 | if (InSet) |
835 | return true; |
836 | return !Sym.isInSection(); |
837 | } |
838 | |
839 | bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, |
840 | const MCAsmLayout *Layout, |
841 | const MCFixup *Fixup, |
842 | const SectionAddrMap *Addrs, |
843 | bool InSet) const { |
844 | ++stats::MCExprEvaluate; |
845 | |
846 | switch (getKind()) { |
847 | case Target: |
848 | return cast<MCTargetExpr>(Val: this)->evaluateAsRelocatableImpl(Res, Layout, |
849 | Fixup); |
850 | |
851 | case Constant: |
852 | Res = MCValue::get(Val: cast<MCConstantExpr>(Val: this)->getValue()); |
853 | return true; |
854 | |
855 | case SymbolRef: { |
856 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: this); |
857 | const MCSymbol &Sym = SRE->getSymbol(); |
858 | const auto Kind = SRE->getKind(); |
859 | |
860 | // Evaluate recursively if this is a variable. |
861 | if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && |
862 | canExpand(Sym, InSet)) { |
863 | bool IsMachO = SRE->hasSubsectionsViaSymbols(); |
864 | if (Sym.getVariableValue()->evaluateAsRelocatableImpl( |
865 | Res, Asm, Layout, Fixup, Addrs, InSet: InSet || IsMachO)) { |
866 | if (Kind != MCSymbolRefExpr::VK_None) { |
867 | if (Res.isAbsolute()) { |
868 | Res = MCValue::get(SymA: SRE, SymB: nullptr, Val: 0); |
869 | return true; |
870 | } |
871 | // If the reference has a variant kind, we can only handle expressions |
872 | // which evaluate exactly to a single unadorned symbol. Attach the |
873 | // original VariantKind to SymA of the result. |
874 | if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() || |
875 | Res.getSymB() || Res.getConstant()) |
876 | return false; |
877 | Res = |
878 | MCValue::get(SymA: MCSymbolRefExpr::create(Sym: &Res.getSymA()->getSymbol(), |
879 | Kind, Ctx&: Asm->getContext()), |
880 | SymB: Res.getSymB(), Val: Res.getConstant(), RefKind: Res.getRefKind()); |
881 | } |
882 | if (!IsMachO) |
883 | return true; |
884 | |
885 | const MCSymbolRefExpr *A = Res.getSymA(); |
886 | const MCSymbolRefExpr *B = Res.getSymB(); |
887 | // FIXME: This is small hack. Given |
888 | // a = b + 4 |
889 | // .long a |
890 | // the OS X assembler will completely drop the 4. We should probably |
891 | // include it in the relocation or produce an error if that is not |
892 | // possible. |
893 | // Allow constant expressions. |
894 | if (!A && !B) |
895 | return true; |
896 | // Allows aliases with zero offset. |
897 | if (Res.getConstant() == 0 && (!A || !B)) |
898 | return true; |
899 | } |
900 | } |
901 | |
902 | Res = MCValue::get(SymA: SRE, SymB: nullptr, Val: 0); |
903 | return true; |
904 | } |
905 | |
906 | case Unary: { |
907 | const MCUnaryExpr *AUE = cast<MCUnaryExpr>(Val: this); |
908 | MCValue Value; |
909 | |
910 | if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Res&: Value, Asm, Layout, Fixup, |
911 | Addrs, InSet)) |
912 | return false; |
913 | |
914 | switch (AUE->getOpcode()) { |
915 | case MCUnaryExpr::LNot: |
916 | if (!Value.isAbsolute()) |
917 | return false; |
918 | Res = MCValue::get(Val: !Value.getConstant()); |
919 | break; |
920 | case MCUnaryExpr::Minus: |
921 | /// -(a - b + const) ==> (b - a - const) |
922 | if (Value.getSymA() && !Value.getSymB()) |
923 | return false; |
924 | |
925 | // The cast avoids undefined behavior if the constant is INT64_MIN. |
926 | Res = MCValue::get(SymA: Value.getSymB(), SymB: Value.getSymA(), |
927 | Val: -(uint64_t)Value.getConstant()); |
928 | break; |
929 | case MCUnaryExpr::Not: |
930 | if (!Value.isAbsolute()) |
931 | return false; |
932 | Res = MCValue::get(Val: ~Value.getConstant()); |
933 | break; |
934 | case MCUnaryExpr::Plus: |
935 | Res = Value; |
936 | break; |
937 | } |
938 | |
939 | return true; |
940 | } |
941 | |
942 | case Binary: { |
943 | const MCBinaryExpr *ABE = cast<MCBinaryExpr>(Val: this); |
944 | MCValue LHSValue, RHSValue; |
945 | |
946 | if (!ABE->getLHS()->evaluateAsRelocatableImpl(Res&: LHSValue, Asm, Layout, Fixup, |
947 | Addrs, InSet) || |
948 | !ABE->getRHS()->evaluateAsRelocatableImpl(Res&: RHSValue, Asm, Layout, Fixup, |
949 | Addrs, InSet)) { |
950 | // Check if both are Target Expressions, see if we can compare them. |
951 | if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(Val: ABE->getLHS())) { |
952 | if (const MCTargetExpr *R = dyn_cast<MCTargetExpr>(Val: ABE->getRHS())) { |
953 | switch (ABE->getOpcode()) { |
954 | case MCBinaryExpr::EQ: |
955 | Res = MCValue::get(Val: L->isEqualTo(x: R) ? -1 : 0); |
956 | return true; |
957 | case MCBinaryExpr::NE: |
958 | Res = MCValue::get(Val: L->isEqualTo(x: R) ? 0 : -1); |
959 | return true; |
960 | default: |
961 | break; |
962 | } |
963 | } |
964 | } |
965 | return false; |
966 | } |
967 | |
968 | // We only support a few operations on non-constant expressions, handle |
969 | // those first. |
970 | if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { |
971 | switch (ABE->getOpcode()) { |
972 | default: |
973 | return false; |
974 | case MCBinaryExpr::Sub: |
975 | // Negate RHS and add. |
976 | // The cast avoids undefined behavior if the constant is INT64_MIN. |
977 | return EvaluateSymbolicAdd( |
978 | Asm, Layout, Addrs, InSet, LHS: LHSValue, |
979 | RHS: MCValue::get(SymA: RHSValue.getSymB(), SymB: RHSValue.getSymA(), |
980 | Val: -(uint64_t)RHSValue.getConstant(), |
981 | RefKind: RHSValue.getRefKind()), |
982 | Res); |
983 | |
984 | case MCBinaryExpr::Add: |
985 | return EvaluateSymbolicAdd( |
986 | Asm, Layout, Addrs, InSet, LHS: LHSValue, |
987 | RHS: MCValue::get(SymA: RHSValue.getSymA(), SymB: RHSValue.getSymB(), |
988 | Val: RHSValue.getConstant(), RefKind: RHSValue.getRefKind()), |
989 | Res); |
990 | } |
991 | } |
992 | |
993 | // FIXME: We need target hooks for the evaluation. It may be limited in |
994 | // width, and gas defines the result of comparisons differently from |
995 | // Apple as. |
996 | int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); |
997 | int64_t Result = 0; |
998 | auto Op = ABE->getOpcode(); |
999 | switch (Op) { |
1000 | case MCBinaryExpr::AShr: Result = LHS >> RHS; break; |
1001 | case MCBinaryExpr::Add: Result = LHS + RHS; break; |
1002 | case MCBinaryExpr::And: Result = LHS & RHS; break; |
1003 | case MCBinaryExpr::Div: |
1004 | case MCBinaryExpr::Mod: |
1005 | // Handle division by zero. gas just emits a warning and keeps going, |
1006 | // we try to be stricter. |
1007 | // FIXME: Currently the caller of this function has no way to understand |
1008 | // we're bailing out because of 'division by zero'. Therefore, it will |
1009 | // emit a 'expected relocatable expression' error. It would be nice to |
1010 | // change this code to emit a better diagnostic. |
1011 | if (RHS == 0) |
1012 | return false; |
1013 | if (ABE->getOpcode() == MCBinaryExpr::Div) |
1014 | Result = LHS / RHS; |
1015 | else |
1016 | Result = LHS % RHS; |
1017 | break; |
1018 | case MCBinaryExpr::EQ: Result = LHS == RHS; break; |
1019 | case MCBinaryExpr::GT: Result = LHS > RHS; break; |
1020 | case MCBinaryExpr::GTE: Result = LHS >= RHS; break; |
1021 | case MCBinaryExpr::LAnd: Result = LHS && RHS; break; |
1022 | case MCBinaryExpr::LOr: Result = LHS || RHS; break; |
1023 | case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; |
1024 | case MCBinaryExpr::LT: Result = LHS < RHS; break; |
1025 | case MCBinaryExpr::LTE: Result = LHS <= RHS; break; |
1026 | case MCBinaryExpr::Mul: Result = LHS * RHS; break; |
1027 | case MCBinaryExpr::NE: Result = LHS != RHS; break; |
1028 | case MCBinaryExpr::Or: Result = LHS | RHS; break; |
1029 | case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break; |
1030 | case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; |
1031 | case MCBinaryExpr::Sub: Result = LHS - RHS; break; |
1032 | case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; |
1033 | } |
1034 | |
1035 | switch (Op) { |
1036 | default: |
1037 | Res = MCValue::get(Val: Result); |
1038 | break; |
1039 | case MCBinaryExpr::EQ: |
1040 | case MCBinaryExpr::GT: |
1041 | case MCBinaryExpr::GTE: |
1042 | case MCBinaryExpr::LT: |
1043 | case MCBinaryExpr::LTE: |
1044 | case MCBinaryExpr::NE: |
1045 | // A comparison operator returns a -1 if true and 0 if false. |
1046 | Res = MCValue::get(Val: Result ? -1 : 0); |
1047 | break; |
1048 | } |
1049 | |
1050 | return true; |
1051 | } |
1052 | } |
1053 | |
1054 | llvm_unreachable("Invalid assembly expression kind!" ); |
1055 | } |
1056 | |
1057 | MCFragment *MCExpr::findAssociatedFragment() const { |
1058 | switch (getKind()) { |
1059 | case Target: |
1060 | // We never look through target specific expressions. |
1061 | return cast<MCTargetExpr>(Val: this)->findAssociatedFragment(); |
1062 | |
1063 | case Constant: |
1064 | return MCSymbol::AbsolutePseudoFragment; |
1065 | |
1066 | case SymbolRef: { |
1067 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: this); |
1068 | const MCSymbol &Sym = SRE->getSymbol(); |
1069 | return Sym.getFragment(); |
1070 | } |
1071 | |
1072 | case Unary: |
1073 | return cast<MCUnaryExpr>(Val: this)->getSubExpr()->findAssociatedFragment(); |
1074 | |
1075 | case Binary: { |
1076 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: this); |
1077 | MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); |
1078 | MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); |
1079 | |
1080 | // If either is absolute, return the other. |
1081 | if (LHS_F == MCSymbol::AbsolutePseudoFragment) |
1082 | return RHS_F; |
1083 | if (RHS_F == MCSymbol::AbsolutePseudoFragment) |
1084 | return LHS_F; |
1085 | |
1086 | // Not always correct, but probably the best we can do without more context. |
1087 | if (BE->getOpcode() == MCBinaryExpr::Sub) |
1088 | return MCSymbol::AbsolutePseudoFragment; |
1089 | |
1090 | // Otherwise, return the first non-null fragment. |
1091 | return LHS_F ? LHS_F : RHS_F; |
1092 | } |
1093 | } |
1094 | |
1095 | llvm_unreachable("Invalid assembly expression kind!" ); |
1096 | } |
1097 | |