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