File: | llvm/lib/MC/MCExpr.cpp |
Warning: | line 626, column 28 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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/StringExtras.h" | ||||||
12 | #include "llvm/ADT/StringSwitch.h" | ||||||
13 | #include "llvm/Config/llvm-config.h" | ||||||
14 | #include "llvm/MC/MCAsmBackend.h" | ||||||
15 | #include "llvm/MC/MCAsmInfo.h" | ||||||
16 | #include "llvm/MC/MCAsmLayout.h" | ||||||
17 | #include "llvm/MC/MCAssembler.h" | ||||||
18 | #include "llvm/MC/MCContext.h" | ||||||
19 | #include "llvm/MC/MCObjectWriter.h" | ||||||
20 | #include "llvm/MC/MCSymbol.h" | ||||||
21 | #include "llvm/MC/MCValue.h" | ||||||
22 | #include "llvm/Support/Casting.h" | ||||||
23 | #include "llvm/Support/Compiler.h" | ||||||
24 | #include "llvm/Support/Debug.h" | ||||||
25 | #include "llvm/Support/ErrorHandling.h" | ||||||
26 | #include "llvm/Support/raw_ostream.h" | ||||||
27 | #include <cassert> | ||||||
28 | #include <cstdint> | ||||||
29 | |||||||
30 | using namespace llvm; | ||||||
31 | |||||||
32 | #define DEBUG_TYPE"mcexpr" "mcexpr" | ||||||
33 | |||||||
34 | namespace { | ||||||
35 | namespace stats { | ||||||
36 | |||||||
37 | STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations")static llvm::Statistic MCExprEvaluate = {"mcexpr", "MCExprEvaluate" , "Number of MCExpr evaluations"}; | ||||||
38 | |||||||
39 | } // end namespace stats | ||||||
40 | } // end anonymous namespace | ||||||
41 | |||||||
42 | void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { | ||||||
43 | switch (getKind()) { | ||||||
44 | case MCExpr::Target: | ||||||
45 | return cast<MCTargetExpr>(this)->printImpl(OS, MAI); | ||||||
46 | case MCExpr::Constant: { | ||||||
47 | auto Value = cast<MCConstantExpr>(*this).getValue(); | ||||||
48 | auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat(); | ||||||
49 | auto SizeInBytes = cast<MCConstantExpr>(*this).getSizeInBytes(); | ||||||
50 | if (Value < 0 && MAI && !MAI->supportsSignedData()) | ||||||
51 | PrintInHex = true; | ||||||
52 | if (PrintInHex) | ||||||
53 | switch (SizeInBytes) { | ||||||
54 | default: | ||||||
55 | OS << "0x" << Twine::utohexstr(Value); | ||||||
56 | break; | ||||||
57 | case 1: | ||||||
58 | OS << format("0x%02" PRIx64"l" "x", Value); | ||||||
59 | break; | ||||||
60 | case 2: | ||||||
61 | OS << format("0x%04" PRIx64"l" "x", Value); | ||||||
62 | break; | ||||||
63 | case 4: | ||||||
64 | OS << format("0x%08" PRIx64"l" "x", Value); | ||||||
65 | break; | ||||||
66 | case 8: | ||||||
67 | OS << format("0x%016" PRIx64"l" "x", Value); | ||||||
68 | break; | ||||||
69 | } | ||||||
70 | else | ||||||
71 | OS << Value; | ||||||
72 | return; | ||||||
73 | } | ||||||
74 | case MCExpr::SymbolRef: { | ||||||
75 | const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); | ||||||
76 | const MCSymbol &Sym = SRE.getSymbol(); | ||||||
77 | // Parenthesize names that start with $ so that they don't look like | ||||||
78 | // absolute names. | ||||||
79 | bool UseParens = | ||||||
80 | !InParens && !Sym.getName().empty() && Sym.getName()[0] == '$'; | ||||||
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>(*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>(*this); | ||||||
116 | |||||||
117 | // Only print parens around the LHS if it is non-trivial. | ||||||
118 | if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(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>(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>(BE.getRHS()) || isa<MCSymbolRefExpr>(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!")::llvm::llvm_unreachable_internal("Invalid expression kind!", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/MC/MCExpr.cpp" , 171); | ||||||
172 | } | ||||||
173 | |||||||
174 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||
175 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) 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, MAI->hasSubsectionsViaSymbols())), | ||||||
206 | Symbol(Symbol) { | ||||||
207 | assert(Symbol)(static_cast <bool> (Symbol) ? void (0) : __assert_fail ("Symbol", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/MC/MCExpr.cpp" , 207, __extension__ __PRETTY_FUNCTION__)); | ||||||
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(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_GOTTPOFF: return "GOTTPOFF"; | ||||||
234 | case VK_INDNTPOFF: return "INDNTPOFF"; | ||||||
235 | case VK_NTPOFF: return "NTPOFF"; | ||||||
236 | case VK_GOTNTPOFF: return "GOTNTPOFF"; | ||||||
237 | case VK_PLT: return "PLT"; | ||||||
238 | case VK_TLSGD: return "TLSGD"; | ||||||
239 | case VK_TLSLD: return "TLSLD"; | ||||||
240 | case VK_TLSLDM: return "TLSLDM"; | ||||||
241 | case VK_TPOFF: return "TPOFF"; | ||||||
242 | case VK_TPREL: return "TPREL"; | ||||||
243 | case VK_TLSCALL: return "tlscall"; | ||||||
244 | case VK_TLSDESC: return "tlsdesc"; | ||||||
245 | case VK_TLVP: return "TLVP"; | ||||||
246 | case VK_TLVPPAGE: return "TLVPPAGE"; | ||||||
247 | case VK_TLVPPAGEOFF: return "TLVPPAGEOFF"; | ||||||
248 | case VK_PAGE: return "PAGE"; | ||||||
249 | case VK_PAGEOFF: return "PAGEOFF"; | ||||||
250 | case VK_GOTPAGE: return "GOTPAGE"; | ||||||
251 | case VK_GOTPAGEOFF: return "GOTPAGEOFF"; | ||||||
252 | case VK_SECREL: return "SECREL32"; | ||||||
253 | case VK_SIZE: return "SIZE"; | ||||||
254 | case VK_WEAKREF: return "WEAKREF"; | ||||||
255 | case VK_X86_ABS8: return "ABS8"; | ||||||
256 | case VK_X86_PLTOFF: return "PLTOFF"; | ||||||
257 | case VK_ARM_NONE: return "none"; | ||||||
258 | case VK_ARM_GOT_PREL: return "GOT_PREL"; | ||||||
259 | case VK_ARM_TARGET1: return "target1"; | ||||||
260 | case VK_ARM_TARGET2: return "target2"; | ||||||
261 | case VK_ARM_PREL31: return "prel31"; | ||||||
262 | case VK_ARM_SBREL: return "sbrel"; | ||||||
263 | case VK_ARM_TLSLDO: return "tlsldo"; | ||||||
264 | case VK_ARM_TLSDESCSEQ: return "tlsdescseq"; | ||||||
265 | case VK_AVR_NONE: return "none"; | ||||||
266 | case VK_AVR_LO8: return "lo8"; | ||||||
267 | case VK_AVR_HI8: return "hi8"; | ||||||
268 | case VK_AVR_HLO8: return "hlo8"; | ||||||
269 | case VK_AVR_DIFF8: return "diff8"; | ||||||
270 | case VK_AVR_DIFF16: return "diff16"; | ||||||
271 | case VK_AVR_DIFF32: return "diff32"; | ||||||
272 | case VK_AVR_PM: return "pm"; | ||||||
273 | case VK_PPC_LO: return "l"; | ||||||
274 | case VK_PPC_HI: return "h"; | ||||||
275 | case VK_PPC_HA: return "ha"; | ||||||
276 | case VK_PPC_HIGH: return "high"; | ||||||
277 | case VK_PPC_HIGHA: return "higha"; | ||||||
278 | case VK_PPC_HIGHER: return "higher"; | ||||||
279 | case VK_PPC_HIGHERA: return "highera"; | ||||||
280 | case VK_PPC_HIGHEST: return "highest"; | ||||||
281 | case VK_PPC_HIGHESTA: return "highesta"; | ||||||
282 | case VK_PPC_GOT_LO: return "got@l"; | ||||||
283 | case VK_PPC_GOT_HI: return "got@h"; | ||||||
284 | case VK_PPC_GOT_HA: return "got@ha"; | ||||||
285 | case VK_PPC_TOCBASE: return "tocbase"; | ||||||
286 | case VK_PPC_TOC: return "toc"; | ||||||
287 | case VK_PPC_TOC_LO: return "toc@l"; | ||||||
288 | case VK_PPC_TOC_HI: return "toc@h"; | ||||||
289 | case VK_PPC_TOC_HA: return "toc@ha"; | ||||||
290 | case VK_PPC_U: return "u"; | ||||||
291 | case VK_PPC_L: return "l"; | ||||||
292 | case VK_PPC_DTPMOD: return "dtpmod"; | ||||||
293 | case VK_PPC_TPREL_LO: return "tprel@l"; | ||||||
294 | case VK_PPC_TPREL_HI: return "tprel@h"; | ||||||
295 | case VK_PPC_TPREL_HA: return "tprel@ha"; | ||||||
296 | case VK_PPC_TPREL_HIGH: return "tprel@high"; | ||||||
297 | case VK_PPC_TPREL_HIGHA: return "tprel@higha"; | ||||||
298 | case VK_PPC_TPREL_HIGHER: return "tprel@higher"; | ||||||
299 | case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; | ||||||
300 | case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; | ||||||
301 | case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; | ||||||
302 | case VK_PPC_DTPREL_LO: return "dtprel@l"; | ||||||
303 | case VK_PPC_DTPREL_HI: return "dtprel@h"; | ||||||
304 | case VK_PPC_DTPREL_HA: return "dtprel@ha"; | ||||||
305 | case VK_PPC_DTPREL_HIGH: return "dtprel@high"; | ||||||
306 | case VK_PPC_DTPREL_HIGHA: return "dtprel@higha"; | ||||||
307 | case VK_PPC_DTPREL_HIGHER: return "dtprel@higher"; | ||||||
308 | case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera"; | ||||||
309 | case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest"; | ||||||
310 | case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta"; | ||||||
311 | case VK_PPC_GOT_TPREL: return "got@tprel"; | ||||||
312 | case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; | ||||||
313 | case VK_PPC_GOT_TPREL_HI: return "got@tprel@h"; | ||||||
314 | case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; | ||||||
315 | case VK_PPC_GOT_DTPREL: return "got@dtprel"; | ||||||
316 | case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l"; | ||||||
317 | case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h"; | ||||||
318 | case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha"; | ||||||
319 | case VK_PPC_TLS: return "tls"; | ||||||
320 | case VK_PPC_GOT_TLSGD: return "got@tlsgd"; | ||||||
321 | case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; | ||||||
322 | case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h"; | ||||||
323 | case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; | ||||||
324 | case VK_PPC_TLSGD: return "tlsgd"; | ||||||
325 | case VK_PPC_AIX_TLSGD: | ||||||
326 | return "gd"; | ||||||
327 | case VK_PPC_AIX_TLSGDM: | ||||||
328 | return "m"; | ||||||
329 | case VK_PPC_GOT_TLSLD: return "got@tlsld"; | ||||||
330 | case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; | ||||||
331 | case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; | ||||||
332 | case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; | ||||||
333 | case VK_PPC_GOT_PCREL: | ||||||
334 | return "got@pcrel"; | ||||||
335 | case VK_PPC_GOT_TLSGD_PCREL: | ||||||
336 | return "got@tlsgd@pcrel"; | ||||||
337 | case VK_PPC_GOT_TLSLD_PCREL: | ||||||
338 | return "got@tlsld@pcrel"; | ||||||
339 | case VK_PPC_GOT_TPREL_PCREL: | ||||||
340 | return "got@tprel@pcrel"; | ||||||
341 | case VK_PPC_TLS_PCREL: | ||||||
342 | return "tls@pcrel"; | ||||||
343 | case VK_PPC_TLSLD: return "tlsld"; | ||||||
344 | case VK_PPC_LOCAL: return "local"; | ||||||
345 | case VK_PPC_NOTOC: return "notoc"; | ||||||
346 | case VK_PPC_PCREL_OPT: return "<<invalid>>"; | ||||||
347 | case VK_COFF_IMGREL32: return "IMGREL"; | ||||||
348 | case VK_Hexagon_LO16: return "LO16"; | ||||||
349 | case VK_Hexagon_HI16: return "HI16"; | ||||||
350 | case VK_Hexagon_GPREL: return "GPREL"; | ||||||
351 | case VK_Hexagon_GD_GOT: return "GDGOT"; | ||||||
352 | case VK_Hexagon_LD_GOT: return "LDGOT"; | ||||||
353 | case VK_Hexagon_GD_PLT: return "GDPLT"; | ||||||
354 | case VK_Hexagon_LD_PLT: return "LDPLT"; | ||||||
355 | case VK_Hexagon_IE: return "IE"; | ||||||
356 | case VK_Hexagon_IE_GOT: return "IEGOT"; | ||||||
357 | case VK_WASM_TYPEINDEX: return "TYPEINDEX"; | ||||||
358 | case VK_WASM_MBREL: return "MBREL"; | ||||||
359 | case VK_WASM_TLSREL: return "TLSREL"; | ||||||
360 | case VK_WASM_TBREL: return "TBREL"; | ||||||
361 | case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; | ||||||
362 | case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; | ||||||
363 | case VK_AMDGPU_REL32_LO: return "rel32@lo"; | ||||||
364 | case VK_AMDGPU_REL32_HI: return "rel32@hi"; | ||||||
365 | case VK_AMDGPU_REL64: return "rel64"; | ||||||
366 | case VK_AMDGPU_ABS32_LO: return "abs32@lo"; | ||||||
367 | case VK_AMDGPU_ABS32_HI: return "abs32@hi"; | ||||||
368 | case VK_VE_HI32: return "hi"; | ||||||
369 | case VK_VE_LO32: return "lo"; | ||||||
370 | case VK_VE_PC_HI32: return "pc_hi"; | ||||||
371 | case VK_VE_PC_LO32: return "pc_lo"; | ||||||
372 | case VK_VE_GOT_HI32: return "got_hi"; | ||||||
373 | case VK_VE_GOT_LO32: return "got_lo"; | ||||||
374 | case VK_VE_GOTOFF_HI32: return "gotoff_hi"; | ||||||
375 | case VK_VE_GOTOFF_LO32: return "gotoff_lo"; | ||||||
376 | case VK_VE_PLT_HI32: return "plt_hi"; | ||||||
377 | case VK_VE_PLT_LO32: return "plt_lo"; | ||||||
378 | case VK_VE_TLS_GD_HI32: return "tls_gd_hi"; | ||||||
379 | case VK_VE_TLS_GD_LO32: return "tls_gd_lo"; | ||||||
380 | case VK_VE_TPOFF_HI32: return "tpoff_hi"; | ||||||
381 | case VK_VE_TPOFF_LO32: return "tpoff_lo"; | ||||||
382 | } | ||||||
383 | llvm_unreachable("Invalid variant kind")::llvm::llvm_unreachable_internal("Invalid variant kind", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/MC/MCExpr.cpp" , 383); | ||||||
384 | } | ||||||
385 | |||||||
386 | MCSymbolRefExpr::VariantKind | ||||||
387 | MCSymbolRefExpr::getVariantKindForName(StringRef Name) { | ||||||
388 | return StringSwitch<VariantKind>(Name.lower()) | ||||||
389 | .Case("dtprel", VK_DTPREL) | ||||||
390 | .Case("dtpoff", VK_DTPOFF) | ||||||
391 | .Case("got", VK_GOT) | ||||||
392 | .Case("gotoff", VK_GOTOFF) | ||||||
393 | .Case("gotrel", VK_GOTREL) | ||||||
394 | .Case("pcrel", VK_PCREL) | ||||||
395 | .Case("gotpcrel", VK_GOTPCREL) | ||||||
396 | .Case("gottpoff", VK_GOTTPOFF) | ||||||
397 | .Case("indntpoff", VK_INDNTPOFF) | ||||||
398 | .Case("ntpoff", VK_NTPOFF) | ||||||
399 | .Case("gotntpoff", VK_GOTNTPOFF) | ||||||
400 | .Case("plt", VK_PLT) | ||||||
401 | .Case("tlscall", VK_TLSCALL) | ||||||
402 | .Case("tlsdesc", VK_TLSDESC) | ||||||
403 | .Case("tlsgd", VK_TLSGD) | ||||||
404 | .Case("tlsld", VK_TLSLD) | ||||||
405 | .Case("tlsldm", VK_TLSLDM) | ||||||
406 | .Case("tpoff", VK_TPOFF) | ||||||
407 | .Case("tprel", VK_TPREL) | ||||||
408 | .Case("tlvp", VK_TLVP) | ||||||
409 | .Case("tlvppage", VK_TLVPPAGE) | ||||||
410 | .Case("tlvppageoff", VK_TLVPPAGEOFF) | ||||||
411 | .Case("page", VK_PAGE) | ||||||
412 | .Case("pageoff", VK_PAGEOFF) | ||||||
413 | .Case("gotpage", VK_GOTPAGE) | ||||||
414 | .Case("gotpageoff", VK_GOTPAGEOFF) | ||||||
415 | .Case("imgrel", VK_COFF_IMGREL32) | ||||||
416 | .Case("secrel32", VK_SECREL) | ||||||
417 | .Case("size", VK_SIZE) | ||||||
418 | .Case("abs8", VK_X86_ABS8) | ||||||
419 | .Case("pltoff", VK_X86_PLTOFF) | ||||||
420 | .Case("l", VK_PPC_LO) | ||||||
421 | .Case("h", VK_PPC_HI) | ||||||
422 | .Case("ha", VK_PPC_HA) | ||||||
423 | .Case("high", VK_PPC_HIGH) | ||||||
424 | .Case("higha", VK_PPC_HIGHA) | ||||||
425 | .Case("higher", VK_PPC_HIGHER) | ||||||
426 | .Case("highera", VK_PPC_HIGHERA) | ||||||
427 | .Case("highest", VK_PPC_HIGHEST) | ||||||
428 | .Case("highesta", VK_PPC_HIGHESTA) | ||||||
429 | .Case("got@l", VK_PPC_GOT_LO) | ||||||
430 | .Case("got@h", VK_PPC_GOT_HI) | ||||||
431 | .Case("got@ha", VK_PPC_GOT_HA) | ||||||
432 | .Case("local", VK_PPC_LOCAL) | ||||||
433 | .Case("tocbase", VK_PPC_TOCBASE) | ||||||
434 | .Case("toc", VK_PPC_TOC) | ||||||
435 | .Case("toc@l", VK_PPC_TOC_LO) | ||||||
436 | .Case("toc@h", VK_PPC_TOC_HI) | ||||||
437 | .Case("toc@ha", VK_PPC_TOC_HA) | ||||||
438 | .Case("u", VK_PPC_U) | ||||||
439 | .Case("l", VK_PPC_L) | ||||||
440 | .Case("tls", VK_PPC_TLS) | ||||||
441 | .Case("dtpmod", VK_PPC_DTPMOD) | ||||||
442 | .Case("tprel@l", VK_PPC_TPREL_LO) | ||||||
443 | .Case("tprel@h", VK_PPC_TPREL_HI) | ||||||
444 | .Case("tprel@ha", VK_PPC_TPREL_HA) | ||||||
445 | .Case("tprel@high", VK_PPC_TPREL_HIGH) | ||||||
446 | .Case("tprel@higha", VK_PPC_TPREL_HIGHA) | ||||||
447 | .Case("tprel@higher", VK_PPC_TPREL_HIGHER) | ||||||
448 | .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) | ||||||
449 | .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) | ||||||
450 | .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) | ||||||
451 | .Case("dtprel@l", VK_PPC_DTPREL_LO) | ||||||
452 | .Case("dtprel@h", VK_PPC_DTPREL_HI) | ||||||
453 | .Case("dtprel@ha", VK_PPC_DTPREL_HA) | ||||||
454 | .Case("dtprel@high", VK_PPC_DTPREL_HIGH) | ||||||
455 | .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA) | ||||||
456 | .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) | ||||||
457 | .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) | ||||||
458 | .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) | ||||||
459 | .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) | ||||||
460 | .Case("got@tprel", VK_PPC_GOT_TPREL) | ||||||
461 | .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) | ||||||
462 | .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) | ||||||
463 | .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) | ||||||
464 | .Case("got@dtprel", VK_PPC_GOT_DTPREL) | ||||||
465 | .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) | ||||||
466 | .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) | ||||||
467 | .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) | ||||||
468 | .Case("got@tlsgd", VK_PPC_GOT_TLSGD) | ||||||
469 | .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) | ||||||
470 | .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) | ||||||
471 | .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) | ||||||
472 | .Case("got@tlsld", VK_PPC_GOT_TLSLD) | ||||||
473 | .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) | ||||||
474 | .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) | ||||||
475 | .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) | ||||||
476 | .Case("got@pcrel", VK_PPC_GOT_PCREL) | ||||||
477 | .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL) | ||||||
478 | .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL) | ||||||
479 | .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL) | ||||||
480 | .Case("tls@pcrel", VK_PPC_TLS_PCREL) | ||||||
481 | .Case("notoc", VK_PPC_NOTOC) | ||||||
482 | .Case("gdgot", VK_Hexagon_GD_GOT) | ||||||
483 | .Case("gdplt", VK_Hexagon_GD_PLT) | ||||||
484 | .Case("iegot", VK_Hexagon_IE_GOT) | ||||||
485 | .Case("ie", VK_Hexagon_IE) | ||||||
486 | .Case("ldgot", VK_Hexagon_LD_GOT) | ||||||
487 | .Case("ldplt", VK_Hexagon_LD_PLT) | ||||||
488 | .Case("none", VK_ARM_NONE) | ||||||
489 | .Case("got_prel", VK_ARM_GOT_PREL) | ||||||
490 | .Case("target1", VK_ARM_TARGET1) | ||||||
491 | .Case("target2", VK_ARM_TARGET2) | ||||||
492 | .Case("prel31", VK_ARM_PREL31) | ||||||
493 | .Case("sbrel", VK_ARM_SBREL) | ||||||
494 | .Case("tlsldo", VK_ARM_TLSLDO) | ||||||
495 | .Case("lo8", VK_AVR_LO8) | ||||||
496 | .Case("hi8", VK_AVR_HI8) | ||||||
497 | .Case("hlo8", VK_AVR_HLO8) | ||||||
498 | .Case("typeindex", VK_WASM_TYPEINDEX) | ||||||
499 | .Case("tbrel", VK_WASM_TBREL) | ||||||
500 | .Case("mbrel", VK_WASM_MBREL) | ||||||
501 | .Case("tlsrel", VK_WASM_TLSREL) | ||||||
502 | .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) | ||||||
503 | .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) | ||||||
504 | .Case("rel32@lo", VK_AMDGPU_REL32_LO) | ||||||
505 | .Case("rel32@hi", VK_AMDGPU_REL32_HI) | ||||||
506 | .Case("rel64", VK_AMDGPU_REL64) | ||||||
507 | .Case("abs32@lo", VK_AMDGPU_ABS32_LO) | ||||||
508 | .Case("abs32@hi", VK_AMDGPU_ABS32_HI) | ||||||
509 | .Case("hi", VK_VE_HI32) | ||||||
510 | .Case("lo", VK_VE_LO32) | ||||||
511 | .Case("pc_hi", VK_VE_PC_HI32) | ||||||
512 | .Case("pc_lo", VK_VE_PC_LO32) | ||||||
513 | .Case("got_hi", VK_VE_GOT_HI32) | ||||||
514 | .Case("got_lo", VK_VE_GOT_LO32) | ||||||
515 | .Case("gotoff_hi", VK_VE_GOTOFF_HI32) | ||||||
516 | .Case("gotoff_lo", VK_VE_GOTOFF_LO32) | ||||||
517 | .Case("plt_hi", VK_VE_PLT_HI32) | ||||||
518 | .Case("plt_lo", VK_VE_PLT_LO32) | ||||||
519 | .Case("tls_gd_hi", VK_VE_TLS_GD_HI32) | ||||||
520 | .Case("tls_gd_lo", VK_VE_TLS_GD_LO32) | ||||||
521 | .Case("tpoff_hi", VK_VE_TPOFF_HI32) | ||||||
522 | .Case("tpoff_lo", VK_VE_TPOFF_LO32) | ||||||
523 | .Default(VK_Invalid); | ||||||
524 | } | ||||||
525 | |||||||
526 | /* *** */ | ||||||
527 | |||||||
528 | void MCTargetExpr::anchor() {} | ||||||
529 | |||||||
530 | /* *** */ | ||||||
531 | |||||||
532 | bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { | ||||||
533 | return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr, false); | ||||||
534 | } | ||||||
535 | |||||||
536 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, | ||||||
537 | const MCAsmLayout &Layout) const { | ||||||
538 | return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, false); | ||||||
539 | } | ||||||
540 | |||||||
541 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, | ||||||
542 | const MCAsmLayout &Layout, | ||||||
543 | const SectionAddrMap &Addrs) const { | ||||||
544 | // Setting InSet causes us to absolutize differences across sections and that | ||||||
545 | // is what the MachO writer uses Addrs for. | ||||||
546 | return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs, true); | ||||||
547 | } | ||||||
548 | |||||||
549 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { | ||||||
550 | return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr, false); | ||||||
551 | } | ||||||
552 | |||||||
553 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { | ||||||
554 | return evaluateAsAbsolute(Res, Asm, nullptr, nullptr, false); | ||||||
555 | } | ||||||
556 | |||||||
557 | bool MCExpr::evaluateKnownAbsolute(int64_t &Res, | ||||||
558 | const MCAsmLayout &Layout) const { | ||||||
559 | return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, | ||||||
560 | true); | ||||||
561 | } | ||||||
562 | |||||||
563 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, | ||||||
564 | const MCAsmLayout *Layout, | ||||||
565 | const SectionAddrMap *Addrs, bool InSet) const { | ||||||
566 | MCValue Value; | ||||||
567 | |||||||
568 | // Fast path constants. | ||||||
569 | if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { | ||||||
570 | Res = CE->getValue(); | ||||||
571 | return true; | ||||||
572 | } | ||||||
573 | |||||||
574 | bool IsRelocatable = | ||||||
575 | evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); | ||||||
576 | |||||||
577 | // Record the current value. | ||||||
578 | Res = Value.getConstant(); | ||||||
579 | |||||||
580 | return IsRelocatable && Value.isAbsolute(); | ||||||
581 | } | ||||||
582 | |||||||
583 | /// Helper method for \see EvaluateSymbolAdd(). | ||||||
584 | static void AttemptToFoldSymbolOffsetDifference( | ||||||
585 | const MCAssembler *Asm, const MCAsmLayout *Layout, | ||||||
586 | const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, | ||||||
587 | const MCSymbolRefExpr *&B, int64_t &Addend) { | ||||||
588 | if (!A
| ||||||
589 | return; | ||||||
590 | |||||||
591 | const MCSymbol &SA = A->getSymbol(); | ||||||
592 | const MCSymbol &SB = B->getSymbol(); | ||||||
593 | |||||||
594 | if (SA.isUndefined() || SB.isUndefined()) | ||||||
595 | return; | ||||||
596 | |||||||
597 | if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) | ||||||
598 | return; | ||||||
599 | |||||||
600 | auto FinalizeFolding = [&]() { | ||||||
601 | // Pointers to Thumb symbols need to have their low-bit set to allow | ||||||
602 | // for interworking. | ||||||
603 | if (Asm->isThumbFunc(&SA)) | ||||||
604 | Addend |= 1; | ||||||
605 | |||||||
606 | // If symbol is labeled as micromips, we set low-bit to ensure | ||||||
607 | // correct offset in .gcc_except_table | ||||||
608 | if (Asm->getBackend().isMicroMips(&SA)) | ||||||
609 | Addend |= 1; | ||||||
610 | |||||||
611 | // Clear the symbol expr pointers to indicate we have folded these | ||||||
612 | // operands. | ||||||
613 | A = B = nullptr; | ||||||
614 | }; | ||||||
615 | |||||||
616 | const MCFragment *FA = SA.getFragment(); | ||||||
617 | const MCFragment *FB = SB.getFragment(); | ||||||
618 | // If both symbols are in the same fragment, return the difference of their | ||||||
619 | // offsets | ||||||
620 | if (FA == FB && !SA.isVariable() && !SA.isUnset() && !SB.isVariable() && | ||||||
621 | !SB.isUnset()) { | ||||||
622 | Addend += SA.getOffset() - SB.getOffset(); | ||||||
623 | return FinalizeFolding(); | ||||||
624 | } | ||||||
625 | |||||||
626 | const MCSection &SecA = *FA->getParent(); | ||||||
| |||||||
627 | const MCSection &SecB = *FB->getParent(); | ||||||
628 | |||||||
629 | if ((&SecA != &SecB) && !Addrs) | ||||||
630 | return; | ||||||
631 | |||||||
632 | if (Layout) { | ||||||
633 | // One of the symbol involved is part of a fragment being laid out. Quit now | ||||||
634 | // to avoid a self loop. | ||||||
635 | if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB)) | ||||||
636 | return; | ||||||
637 | |||||||
638 | // Eagerly evaluate when layout is finalized. | ||||||
639 | Addend += Layout->getSymbolOffset(A->getSymbol()) - | ||||||
640 | Layout->getSymbolOffset(B->getSymbol()); | ||||||
641 | if (Addrs && (&SecA != &SecB)) | ||||||
642 | Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); | ||||||
643 | |||||||
644 | FinalizeFolding(); | ||||||
645 | } else { | ||||||
646 | // When layout is not finalized, our ability to resolve differences between | ||||||
647 | // symbols is limited to specific cases where the fragments between two | ||||||
648 | // symbols (including the fragments the symbols are defined in) are | ||||||
649 | // fixed-size fragments so the difference can be calculated. For example, | ||||||
650 | // this is important when the Subtarget is changed and a new MCDataFragment | ||||||
651 | // is created in the case of foo: instr; .arch_extension ext; instr .if . - | ||||||
652 | // foo. | ||||||
653 | if (SA.isVariable() || SA.isUnset() || SB.isVariable() || SB.isUnset() || | ||||||
654 | FA->getKind() != MCFragment::FT_Data || | ||||||
655 | FB->getKind() != MCFragment::FT_Data || | ||||||
656 | FA->getSubsectionNumber() != FB->getSubsectionNumber()) | ||||||
657 | return; | ||||||
658 | // Try to find a constant displacement from FA to FB, add the displacement | ||||||
659 | // between the offset in FA of SA and the offset in FB of SB. | ||||||
660 | int64_t Displacement = SA.getOffset() - SB.getOffset(); | ||||||
661 | for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) { | ||||||
662 | if (&*FI == FA) { | ||||||
663 | Addend += Displacement; | ||||||
664 | return FinalizeFolding(); | ||||||
665 | } | ||||||
666 | |||||||
667 | if (FI->getKind() != MCFragment::FT_Data) | ||||||
668 | return; | ||||||
669 | Displacement += cast<MCDataFragment>(FI)->getContents().size(); | ||||||
670 | } | ||||||
671 | } | ||||||
672 | } | ||||||
673 | |||||||
674 | /// Evaluate the result of an add between (conceptually) two MCValues. | ||||||
675 | /// | ||||||
676 | /// This routine conceptually attempts to construct an MCValue: | ||||||
677 | /// Result = (Result_A - Result_B + Result_Cst) | ||||||
678 | /// from two MCValue's LHS and RHS where | ||||||
679 | /// Result = LHS + RHS | ||||||
680 | /// and | ||||||
681 | /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). | ||||||
682 | /// | ||||||
683 | /// This routine attempts to aggressively fold the operands such that the result | ||||||
684 | /// is representable in an MCValue, but may not always succeed. | ||||||
685 | /// | ||||||
686 | /// \returns True on success, false if the result is not representable in an | ||||||
687 | /// MCValue. | ||||||
688 | |||||||
689 | /// NOTE: It is really important to have both the Asm and Layout arguments. | ||||||
690 | /// They might look redundant, but this function can be used before layout | ||||||
691 | /// is done (see the object streamer for example) and having the Asm argument | ||||||
692 | /// lets us avoid relaxations early. | ||||||
693 | static bool | ||||||
694 | EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout, | ||||||
695 | const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS, | ||||||
696 | const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B, | ||||||
697 | int64_t RHS_Cst, MCValue &Res) { | ||||||
698 | // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy | ||||||
699 | // about dealing with modifiers. This will ultimately bite us, one day. | ||||||
700 | const MCSymbolRefExpr *LHS_A = LHS.getSymA(); | ||||||
701 | const MCSymbolRefExpr *LHS_B = LHS.getSymB(); | ||||||
702 | int64_t LHS_Cst = LHS.getConstant(); | ||||||
703 | |||||||
704 | // Fold the result constant immediately. | ||||||
705 | int64_t Result_Cst = LHS_Cst + RHS_Cst; | ||||||
706 | |||||||
707 | assert((!Layout || Asm) &&(static_cast <bool> ((!Layout || Asm) && "Must have an assembler object if layout is given!" ) ? void (0) : __assert_fail ("(!Layout || Asm) && \"Must have an assembler object if layout is given!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/MC/MCExpr.cpp" , 708, __extension__ __PRETTY_FUNCTION__)) | ||||||
708 | "Must have an assembler object if layout is given!")(static_cast <bool> ((!Layout || Asm) && "Must have an assembler object if layout is given!" ) ? void (0) : __assert_fail ("(!Layout || Asm) && \"Must have an assembler object if layout is given!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/MC/MCExpr.cpp" , 708, __extension__ __PRETTY_FUNCTION__)); | ||||||
709 | |||||||
710 | // If we have a layout, we can fold resolved differences. | ||||||
711 | if (Asm
| ||||||
712 | // First, fold out any differences which are fully resolved. By | ||||||
713 | // reassociating terms in | ||||||
714 | // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). | ||||||
715 | // we have the four possible differences: | ||||||
716 | // (LHS_A - LHS_B), | ||||||
717 | // (LHS_A - RHS_B), | ||||||
718 | // (RHS_A - LHS_B), | ||||||
719 | // (RHS_A - RHS_B). | ||||||
720 | // Since we are attempting to be as aggressive as possible about folding, we | ||||||
721 | // attempt to evaluate each possible alternative. | ||||||
722 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, | ||||||
723 | Result_Cst); | ||||||
724 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, | ||||||
725 | Result_Cst); | ||||||
726 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, | ||||||
727 | Result_Cst); | ||||||
728 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, | ||||||
729 | Result_Cst); | ||||||
730 | } | ||||||
731 | |||||||
732 | // We can't represent the addition or subtraction of two symbols. | ||||||
733 | if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) | ||||||
734 | return false; | ||||||
735 | |||||||
736 | // At this point, we have at most one additive symbol and one subtractive | ||||||
737 | // symbol -- find them. | ||||||
738 | const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; | ||||||
739 | const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; | ||||||
740 | |||||||
741 | Res = MCValue::get(A, B, Result_Cst); | ||||||
742 | return true; | ||||||
743 | } | ||||||
744 | |||||||
745 | bool MCExpr::evaluateAsRelocatable(MCValue &Res, | ||||||
746 | const MCAsmLayout *Layout, | ||||||
747 | const MCFixup *Fixup) const { | ||||||
748 | MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; | ||||||
749 | return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, | ||||||
750 | false); | ||||||
751 | } | ||||||
752 | |||||||
753 | bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { | ||||||
754 | MCAssembler *Assembler = &Layout.getAssembler(); | ||||||
755 | return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, | ||||||
756 | true); | ||||||
757 | } | ||||||
758 | |||||||
759 | static bool canExpand(const MCSymbol &Sym, bool InSet) { | ||||||
760 | const MCExpr *Expr = Sym.getVariableValue(); | ||||||
761 | const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); | ||||||
762 | if (Inner) { | ||||||
763 | if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) | ||||||
764 | return false; | ||||||
765 | } | ||||||
766 | |||||||
767 | if (InSet) | ||||||
768 | return true; | ||||||
769 | return !Sym.isInSection(); | ||||||
770 | } | ||||||
771 | |||||||
772 | bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, | ||||||
773 | const MCAsmLayout *Layout, | ||||||
774 | const MCFixup *Fixup, | ||||||
775 | const SectionAddrMap *Addrs, | ||||||
776 | bool InSet) const { | ||||||
777 | ++stats::MCExprEvaluate; | ||||||
778 | |||||||
779 | switch (getKind()) { | ||||||
| |||||||
780 | case Target: | ||||||
781 | return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout, | ||||||
782 | Fixup); | ||||||
783 | |||||||
784 | case Constant: | ||||||
785 | Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); | ||||||
786 | return true; | ||||||
787 | |||||||
788 | case SymbolRef: { | ||||||
789 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); | ||||||
790 | const MCSymbol &Sym = SRE->getSymbol(); | ||||||
791 | const auto Kind = SRE->getKind(); | ||||||
792 | |||||||
793 | // Evaluate recursively if this is a variable. | ||||||
794 | if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && | ||||||
795 | canExpand(Sym, InSet)) { | ||||||
796 | bool IsMachO = SRE->hasSubsectionsViaSymbols(); | ||||||
797 | if (Sym.getVariableValue()->evaluateAsRelocatableImpl( | ||||||
798 | Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { | ||||||
799 | if (Kind != MCSymbolRefExpr::VK_None) { | ||||||
800 | if (Res.isAbsolute()) { | ||||||
801 | Res = MCValue::get(SRE, nullptr, 0); | ||||||
802 | return true; | ||||||
803 | } | ||||||
804 | // If the reference has a variant kind, we can only handle expressions | ||||||
805 | // which evaluate exactly to a single unadorned symbol. Attach the | ||||||
806 | // original VariantKind to SymA of the result. | ||||||
807 | if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() || | ||||||
808 | Res.getSymB() || Res.getConstant()) | ||||||
809 | return false; | ||||||
810 | Res = | ||||||
811 | MCValue::get(MCSymbolRefExpr::create(&Res.getSymA()->getSymbol(), | ||||||
812 | Kind, Asm->getContext()), | ||||||
813 | Res.getSymB(), Res.getConstant(), Res.getRefKind()); | ||||||
814 | } | ||||||
815 | if (!IsMachO) | ||||||
816 | return true; | ||||||
817 | |||||||
818 | const MCSymbolRefExpr *A = Res.getSymA(); | ||||||
819 | const MCSymbolRefExpr *B = Res.getSymB(); | ||||||
820 | // FIXME: This is small hack. Given | ||||||
821 | // a = b + 4 | ||||||
822 | // .long a | ||||||
823 | // the OS X assembler will completely drop the 4. We should probably | ||||||
824 | // include it in the relocation or produce an error if that is not | ||||||
825 | // possible. | ||||||
826 | // Allow constant expressions. | ||||||
827 | if (!A && !B) | ||||||
828 | return true; | ||||||
829 | // Allows aliases with zero offset. | ||||||
830 | if (Res.getConstant() == 0 && (!A || !B)) | ||||||
831 | return true; | ||||||
832 | } | ||||||
833 | } | ||||||
834 | |||||||
835 | Res = MCValue::get(SRE, nullptr, 0); | ||||||
836 | return true; | ||||||
837 | } | ||||||
838 | |||||||
839 | case Unary: { | ||||||
840 | const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); | ||||||
841 | MCValue Value; | ||||||
842 | |||||||
843 | if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, | ||||||
844 | Addrs, InSet)) | ||||||
845 | return false; | ||||||
846 | |||||||
847 | switch (AUE->getOpcode()) { | ||||||
848 | case MCUnaryExpr::LNot: | ||||||
849 | if (!Value.isAbsolute()) | ||||||
850 | return false; | ||||||
851 | Res = MCValue::get(!Value.getConstant()); | ||||||
852 | break; | ||||||
853 | case MCUnaryExpr::Minus: | ||||||
854 | /// -(a - b + const) ==> (b - a - const) | ||||||
855 | if (Value.getSymA() && !Value.getSymB()) | ||||||
856 | return false; | ||||||
857 | |||||||
858 | // The cast avoids undefined behavior if the constant is INT64_MIN. | ||||||
859 | Res = MCValue::get(Value.getSymB(), Value.getSymA(), | ||||||
860 | -(uint64_t)Value.getConstant()); | ||||||
861 | break; | ||||||
862 | case MCUnaryExpr::Not: | ||||||
863 | if (!Value.isAbsolute()) | ||||||
864 | return false; | ||||||
865 | Res = MCValue::get(~Value.getConstant()); | ||||||
866 | break; | ||||||
867 | case MCUnaryExpr::Plus: | ||||||
868 | Res = Value; | ||||||
869 | break; | ||||||
870 | } | ||||||
871 | |||||||
872 | return true; | ||||||
873 | } | ||||||
874 | |||||||
875 | case Binary: { | ||||||
876 | const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); | ||||||
877 | MCValue LHSValue, RHSValue; | ||||||
878 | |||||||
879 | if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, | ||||||
880 | Addrs, InSet) || | ||||||
881 | !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, | ||||||
882 | Addrs, InSet)) { | ||||||
883 | // Check if both are Target Expressions, see if we can compare them. | ||||||
884 | if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) | ||||||
885 | if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) { | ||||||
886 | switch (ABE->getOpcode()) { | ||||||
887 | case MCBinaryExpr::EQ: | ||||||
888 | Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0); | ||||||
889 | return true; | ||||||
890 | case MCBinaryExpr::NE: | ||||||
891 | Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1); | ||||||
892 | return true; | ||||||
893 | default: break; | ||||||
894 | } | ||||||
895 | } | ||||||
896 | return false; | ||||||
897 | } | ||||||
898 | |||||||
899 | // We only support a few operations on non-constant expressions, handle | ||||||
900 | // those first. | ||||||
901 | if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { | ||||||
902 | switch (ABE->getOpcode()) { | ||||||
903 | default: | ||||||
904 | return false; | ||||||
905 | case MCBinaryExpr::Sub: | ||||||
906 | // Negate RHS and add. | ||||||
907 | // The cast avoids undefined behavior if the constant is INT64_MIN. | ||||||
908 | return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, | ||||||
909 | RHSValue.getSymB(), RHSValue.getSymA(), | ||||||
910 | -(uint64_t)RHSValue.getConstant(), Res); | ||||||
911 | |||||||
912 | case MCBinaryExpr::Add: | ||||||
913 | return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, | ||||||
914 | RHSValue.getSymA(), RHSValue.getSymB(), | ||||||
915 | RHSValue.getConstant(), Res); | ||||||
916 | } | ||||||
917 | } | ||||||
918 | |||||||
919 | // FIXME: We need target hooks for the evaluation. It may be limited in | ||||||
920 | // width, and gas defines the result of comparisons differently from | ||||||
921 | // Apple as. | ||||||
922 | int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); | ||||||
923 | int64_t Result = 0; | ||||||
924 | auto Op = ABE->getOpcode(); | ||||||
925 | switch (Op) { | ||||||
926 | case MCBinaryExpr::AShr: Result = LHS >> RHS; break; | ||||||
927 | case MCBinaryExpr::Add: Result = LHS + RHS; break; | ||||||
928 | case MCBinaryExpr::And: Result = LHS & RHS; break; | ||||||
929 | case MCBinaryExpr::Div: | ||||||
930 | case MCBinaryExpr::Mod: | ||||||
931 | // Handle division by zero. gas just emits a warning and keeps going, | ||||||
932 | // we try to be stricter. | ||||||
933 | // FIXME: Currently the caller of this function has no way to understand | ||||||
934 | // we're bailing out because of 'division by zero'. Therefore, it will | ||||||
935 | // emit a 'expected relocatable expression' error. It would be nice to | ||||||
936 | // change this code to emit a better diagnostic. | ||||||
937 | if (RHS == 0) | ||||||
938 | return false; | ||||||
939 | if (ABE->getOpcode() == MCBinaryExpr::Div) | ||||||
940 | Result = LHS / RHS; | ||||||
941 | else | ||||||
942 | Result = LHS % RHS; | ||||||
943 | break; | ||||||
944 | case MCBinaryExpr::EQ: Result = LHS == RHS; break; | ||||||
945 | case MCBinaryExpr::GT: Result = LHS > RHS; break; | ||||||
946 | case MCBinaryExpr::GTE: Result = LHS >= RHS; break; | ||||||
947 | case MCBinaryExpr::LAnd: Result = LHS && RHS; break; | ||||||
948 | case MCBinaryExpr::LOr: Result = LHS || RHS; break; | ||||||
949 | case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; | ||||||
950 | case MCBinaryExpr::LT: Result = LHS < RHS; break; | ||||||
951 | case MCBinaryExpr::LTE: Result = LHS <= RHS; break; | ||||||
952 | case MCBinaryExpr::Mul: Result = LHS * RHS; break; | ||||||
953 | case MCBinaryExpr::NE: Result = LHS != RHS; break; | ||||||
954 | case MCBinaryExpr::Or: Result = LHS | RHS; break; | ||||||
955 | case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break; | ||||||
956 | case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; | ||||||
957 | case MCBinaryExpr::Sub: Result = LHS - RHS; break; | ||||||
958 | case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; | ||||||
959 | } | ||||||
960 | |||||||
961 | switch (Op) { | ||||||
962 | default: | ||||||
963 | Res = MCValue::get(Result); | ||||||
964 | break; | ||||||
965 | case MCBinaryExpr::EQ: | ||||||
966 | case MCBinaryExpr::GT: | ||||||
967 | case MCBinaryExpr::GTE: | ||||||
968 | case MCBinaryExpr::LT: | ||||||
969 | case MCBinaryExpr::LTE: | ||||||
970 | case MCBinaryExpr::NE: | ||||||
971 | // A comparison operator returns a -1 if true and 0 if false. | ||||||
972 | Res = MCValue::get(Result ? -1 : 0); | ||||||
973 | break; | ||||||
974 | } | ||||||
975 | |||||||
976 | return true; | ||||||
977 | } | ||||||
978 | } | ||||||
979 | |||||||
980 | llvm_unreachable("Invalid assembly expression kind!")::llvm::llvm_unreachable_internal("Invalid assembly expression kind!" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/MC/MCExpr.cpp" , 980); | ||||||
981 | } | ||||||
982 | |||||||
983 | MCFragment *MCExpr::findAssociatedFragment() const { | ||||||
984 | switch (getKind()) { | ||||||
985 | case Target: | ||||||
986 | // We never look through target specific expressions. | ||||||
987 | return cast<MCTargetExpr>(this)->findAssociatedFragment(); | ||||||
988 | |||||||
989 | case Constant: | ||||||
990 | return MCSymbol::AbsolutePseudoFragment; | ||||||
991 | |||||||
992 | case SymbolRef: { | ||||||
993 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); | ||||||
994 | const MCSymbol &Sym = SRE->getSymbol(); | ||||||
995 | return Sym.getFragment(); | ||||||
996 | } | ||||||
997 | |||||||
998 | case Unary: | ||||||
999 | return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment(); | ||||||
1000 | |||||||
1001 | case Binary: { | ||||||
1002 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); | ||||||
1003 | MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); | ||||||
1004 | MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); | ||||||
1005 | |||||||
1006 | // If either is absolute, return the other. | ||||||
1007 | if (LHS_F == MCSymbol::AbsolutePseudoFragment) | ||||||
1008 | return RHS_F; | ||||||
1009 | if (RHS_F == MCSymbol::AbsolutePseudoFragment) | ||||||
1010 | return LHS_F; | ||||||
1011 | |||||||
1012 | // Not always correct, but probably the best we can do without more context. | ||||||
1013 | if (BE->getOpcode() == MCBinaryExpr::Sub) | ||||||
1014 | return MCSymbol::AbsolutePseudoFragment; | ||||||
1015 | |||||||
1016 | // Otherwise, return the first non-null fragment. | ||||||
1017 | return LHS_F ? LHS_F : RHS_F; | ||||||
1018 | } | ||||||
1019 | } | ||||||
1020 | |||||||
1021 | llvm_unreachable("Invalid assembly expression kind!")::llvm::llvm_unreachable_internal("Invalid assembly expression kind!" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/MC/MCExpr.cpp" , 1021); | ||||||
1022 | } |
1 | //===-- llvm/MC/MCValue.h - MCValue class -----------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains the declaration of the MCValue class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_MC_MCVALUE_H |
14 | #define LLVM_MC_MCVALUE_H |
15 | |
16 | #include "llvm/MC/MCExpr.h" |
17 | #include "llvm/Support/DataTypes.h" |
18 | #include <cassert> |
19 | |
20 | namespace llvm { |
21 | class raw_ostream; |
22 | |
23 | /// This represents an "assembler immediate". |
24 | /// |
25 | /// In its most general form, this can hold ":Kind:(SymbolA - SymbolB + |
26 | /// imm64)". Not all targets supports relocations of this general form, but we |
27 | /// need to represent this anyway. |
28 | /// |
29 | /// In general both SymbolA and SymbolB will also have a modifier |
30 | /// analogous to the top-level Kind. Current targets are not expected |
31 | /// to make use of both though. The choice comes down to whether |
32 | /// relocation modifiers apply to the closest symbol or the whole |
33 | /// expression. |
34 | /// |
35 | /// Note that this class must remain a simple POD value class, because we need |
36 | /// it to live in unions etc. |
37 | class MCValue { |
38 | const MCSymbolRefExpr *SymA = nullptr, *SymB = nullptr; |
39 | int64_t Cst = 0; |
40 | uint32_t RefKind = 0; |
41 | |
42 | public: |
43 | MCValue() = default; |
44 | int64_t getConstant() const { return Cst; } |
45 | const MCSymbolRefExpr *getSymA() const { return SymA; } |
46 | const MCSymbolRefExpr *getSymB() const { return SymB; } |
47 | uint32_t getRefKind() const { return RefKind; } |
48 | |
49 | /// Is this an absolute (as opposed to relocatable) value. |
50 | bool isAbsolute() const { return !SymA && !SymB; } |
51 | |
52 | /// Print the value to the stream \p OS. |
53 | void print(raw_ostream &OS) const; |
54 | |
55 | /// Print the value to stderr. |
56 | void dump() const; |
57 | |
58 | MCSymbolRefExpr::VariantKind getAccessVariant() const; |
59 | |
60 | static MCValue get(const MCSymbolRefExpr *SymA, |
61 | const MCSymbolRefExpr *SymB = nullptr, |
62 | int64_t Val = 0, uint32_t RefKind = 0) { |
63 | MCValue R; |
64 | R.Cst = Val; |
65 | R.SymA = SymA; |
66 | R.SymB = SymB; |
67 | R.RefKind = RefKind; |
68 | return R; |
69 | } |
70 | |
71 | static MCValue get(int64_t Val) { |
72 | MCValue R; |
73 | R.Cst = Val; |
74 | R.SymA = nullptr; |
75 | R.SymB = nullptr; |
76 | R.RefKind = 0; |
77 | return R; |
78 | } |
79 | |
80 | }; |
81 | |
82 | } // end namespace llvm |
83 | |
84 | #endif |
1 | //===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains the declaration of the MCSymbol class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_MC_MCSYMBOL_H |
14 | #define LLVM_MC_MCSYMBOL_H |
15 | |
16 | #include "llvm/ADT/PointerIntPair.h" |
17 | #include "llvm/ADT/StringMap.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/MC/MCExpr.h" |
20 | #include "llvm/MC/MCFragment.h" |
21 | #include "llvm/Support/ErrorHandling.h" |
22 | #include "llvm/Support/MathExtras.h" |
23 | #include <cassert> |
24 | #include <cstddef> |
25 | #include <cstdint> |
26 | |
27 | namespace llvm { |
28 | |
29 | class MCAsmInfo; |
30 | class MCContext; |
31 | class MCSection; |
32 | class raw_ostream; |
33 | |
34 | /// MCSymbol - Instances of this class represent a symbol name in the MC file, |
35 | /// and MCSymbols are created and uniqued by the MCContext class. MCSymbols |
36 | /// should only be constructed with valid names for the object file. |
37 | /// |
38 | /// If the symbol is defined/emitted into the current translation unit, the |
39 | /// Section member is set to indicate what section it lives in. Otherwise, if |
40 | /// it is a reference to an external entity, it has a null section. |
41 | class MCSymbol { |
42 | protected: |
43 | /// The kind of the symbol. If it is any value other than unset then this |
44 | /// class is actually one of the appropriate subclasses of MCSymbol. |
45 | enum SymbolKind { |
46 | SymbolKindUnset, |
47 | SymbolKindCOFF, |
48 | SymbolKindELF, |
49 | SymbolKindGOFF, |
50 | SymbolKindMachO, |
51 | SymbolKindWasm, |
52 | SymbolKindXCOFF, |
53 | }; |
54 | |
55 | /// A symbol can contain an Offset, or Value, or be Common, but never more |
56 | /// than one of these. |
57 | enum Contents : uint8_t { |
58 | SymContentsUnset, |
59 | SymContentsOffset, |
60 | SymContentsVariable, |
61 | SymContentsCommon, |
62 | SymContentsTargetCommon, // Index stores the section index |
63 | }; |
64 | |
65 | // Special sentinal value for the absolute pseudo fragment. |
66 | static MCFragment *AbsolutePseudoFragment; |
67 | |
68 | /// If a symbol has a Fragment, the section is implied, so we only need |
69 | /// one pointer. |
70 | /// The special AbsolutePseudoFragment value is for absolute symbols. |
71 | /// If this is a variable symbol, this caches the variable value's fragment. |
72 | /// FIXME: We might be able to simplify this by having the asm streamer create |
73 | /// dummy fragments. |
74 | /// If this is a section, then it gives the symbol is defined in. This is null |
75 | /// for undefined symbols. |
76 | /// |
77 | /// If this is a fragment, then it gives the fragment this symbol's value is |
78 | /// relative to, if any. |
79 | /// |
80 | /// For the 'HasName' integer, this is true if this symbol is named. |
81 | /// A named symbol will have a pointer to the name allocated in the bytes |
82 | /// immediately prior to the MCSymbol. |
83 | mutable PointerIntPair<MCFragment *, 1> FragmentAndHasName; |
84 | |
85 | /// IsTemporary - True if this is an assembler temporary label, which |
86 | /// typically does not survive in the .o file's symbol table. Usually |
87 | /// "Lfoo" or ".foo". |
88 | unsigned IsTemporary : 1; |
89 | |
90 | /// True if this symbol can be redefined. |
91 | unsigned IsRedefinable : 1; |
92 | |
93 | /// IsUsed - True if this symbol has been used. |
94 | mutable unsigned IsUsed : 1; |
95 | |
96 | mutable unsigned IsRegistered : 1; |
97 | |
98 | /// True if this symbol is visible outside this translation unit. Note: ELF |
99 | /// uses binding instead of this bit. |
100 | mutable unsigned IsExternal : 1; |
101 | |
102 | /// This symbol is private extern. |
103 | mutable unsigned IsPrivateExtern : 1; |
104 | |
105 | /// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is |
106 | /// unsigned to avoid sign extension and achieve better bitpacking with MSVC. |
107 | unsigned Kind : 3; |
108 | |
109 | /// True if we have created a relocation that uses this symbol. |
110 | mutable unsigned IsUsedInReloc : 1; |
111 | |
112 | /// This is actually a Contents enumerator, but is unsigned to avoid sign |
113 | /// extension and achieve better bitpacking with MSVC. |
114 | unsigned SymbolContents : 3; |
115 | |
116 | /// The alignment of the symbol, if it is 'common', or -1. |
117 | /// |
118 | /// The alignment is stored as log2(align) + 1. This allows all values from |
119 | /// 0 to 2^31 to be stored which is every power of 2 representable by an |
120 | /// unsigned. |
121 | enum : unsigned { NumCommonAlignmentBits = 5 }; |
122 | unsigned CommonAlignLog2 : NumCommonAlignmentBits; |
123 | |
124 | /// The Flags field is used by object file implementations to store |
125 | /// additional per symbol information which is not easily classified. |
126 | enum : unsigned { NumFlagsBits = 16 }; |
127 | mutable uint32_t Flags : NumFlagsBits; |
128 | |
129 | /// Index field, for use by the object file implementation. |
130 | mutable uint32_t Index = 0; |
131 | |
132 | union { |
133 | /// The offset to apply to the fragment address to form this symbol's value. |
134 | uint64_t Offset; |
135 | |
136 | /// The size of the symbol, if it is 'common'. |
137 | uint64_t CommonSize; |
138 | |
139 | /// If non-null, the value for a variable symbol. |
140 | const MCExpr *Value; |
141 | }; |
142 | |
143 | // MCContext creates and uniques these. |
144 | friend class MCExpr; |
145 | friend class MCContext; |
146 | |
147 | /// The name for a symbol. |
148 | /// MCSymbol contains a uint64_t so is probably aligned to 8. On a 32-bit |
149 | /// system, the name is a pointer so isn't going to satisfy the 8 byte |
150 | /// alignment of uint64_t. Account for that here. |
151 | using NameEntryStorageTy = union { |
152 | const StringMapEntry<bool> *NameEntry; |
153 | uint64_t AlignmentPadding; |
154 | }; |
155 | |
156 | MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary) |
157 | : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false), |
158 | IsRegistered(false), IsExternal(false), IsPrivateExtern(false), |
159 | Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset), |
160 | CommonAlignLog2(0), Flags(0) { |
161 | Offset = 0; |
162 | FragmentAndHasName.setInt(!!Name); |
163 | if (Name) |
164 | getNameEntryPtr() = Name; |
165 | } |
166 | |
167 | // Provide custom new/delete as we will only allocate space for a name |
168 | // if we need one. |
169 | void *operator new(size_t s, const StringMapEntry<bool> *Name, |
170 | MCContext &Ctx); |
171 | |
172 | private: |
173 | void operator delete(void *); |
174 | /// Placement delete - required by std, but never called. |
175 | void operator delete(void*, unsigned) { |
176 | llvm_unreachable("Constructor throws?")::llvm::llvm_unreachable_internal("Constructor throws?", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 176); |
177 | } |
178 | /// Placement delete - required by std, but never called. |
179 | void operator delete(void*, unsigned, bool) { |
180 | llvm_unreachable("Constructor throws?")::llvm::llvm_unreachable_internal("Constructor throws?", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 180); |
181 | } |
182 | |
183 | /// Get a reference to the name field. Requires that we have a name |
184 | const StringMapEntry<bool> *&getNameEntryPtr() { |
185 | assert(FragmentAndHasName.getInt() && "Name is required")(static_cast <bool> (FragmentAndHasName.getInt() && "Name is required") ? void (0) : __assert_fail ("FragmentAndHasName.getInt() && \"Name is required\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 185, __extension__ __PRETTY_FUNCTION__)); |
186 | NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this); |
187 | return (*(Name - 1)).NameEntry; |
188 | } |
189 | const StringMapEntry<bool> *&getNameEntryPtr() const { |
190 | return const_cast<MCSymbol*>(this)->getNameEntryPtr(); |
191 | } |
192 | |
193 | public: |
194 | MCSymbol(const MCSymbol &) = delete; |
195 | MCSymbol &operator=(const MCSymbol &) = delete; |
196 | |
197 | /// getName - Get the symbol name. |
198 | StringRef getName() const { |
199 | if (!FragmentAndHasName.getInt()) |
200 | return StringRef(); |
201 | |
202 | return getNameEntryPtr()->first(); |
203 | } |
204 | |
205 | bool isRegistered() const { return IsRegistered; } |
206 | void setIsRegistered(bool Value) const { IsRegistered = Value; } |
207 | |
208 | void setUsedInReloc() const { IsUsedInReloc = true; } |
209 | bool isUsedInReloc() const { return IsUsedInReloc; } |
210 | |
211 | /// \name Accessors |
212 | /// @{ |
213 | |
214 | /// isTemporary - Check if this is an assembler temporary symbol. |
215 | bool isTemporary() const { return IsTemporary; } |
216 | |
217 | /// isUsed - Check if this is used. |
218 | bool isUsed() const { return IsUsed; } |
219 | |
220 | /// Check if this symbol is redefinable. |
221 | bool isRedefinable() const { return IsRedefinable; } |
222 | /// Mark this symbol as redefinable. |
223 | void setRedefinable(bool Value) { IsRedefinable = Value; } |
224 | /// Prepare this symbol to be redefined. |
225 | void redefineIfPossible() { |
226 | if (IsRedefinable) { |
227 | if (SymbolContents == SymContentsVariable) { |
228 | Value = nullptr; |
229 | SymbolContents = SymContentsUnset; |
230 | } |
231 | setUndefined(); |
232 | IsRedefinable = false; |
233 | } |
234 | } |
235 | |
236 | /// @} |
237 | /// \name Associated Sections |
238 | /// @{ |
239 | |
240 | /// isDefined - Check if this symbol is defined (i.e., it has an address). |
241 | /// |
242 | /// Defined symbols are either absolute or in some section. |
243 | bool isDefined() const { return !isUndefined(); } |
244 | |
245 | /// isInSection - Check if this symbol is defined in some section (i.e., it |
246 | /// is defined but not absolute). |
247 | bool isInSection() const { |
248 | return isDefined() && !isAbsolute(); |
249 | } |
250 | |
251 | /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). |
252 | bool isUndefined(bool SetUsed = true) const { |
253 | return getFragment(SetUsed) == nullptr; |
254 | } |
255 | |
256 | /// isAbsolute - Check if this is an absolute symbol. |
257 | bool isAbsolute() const { |
258 | return getFragment() == AbsolutePseudoFragment; |
259 | } |
260 | |
261 | /// Get the section associated with a defined, non-absolute symbol. |
262 | MCSection &getSection() const { |
263 | assert(isInSection() && "Invalid accessor!")(static_cast <bool> (isInSection() && "Invalid accessor!" ) ? void (0) : __assert_fail ("isInSection() && \"Invalid accessor!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 263, __extension__ __PRETTY_FUNCTION__)); |
264 | return *getFragment()->getParent(); |
265 | } |
266 | |
267 | /// Mark the symbol as defined in the fragment \p F. |
268 | void setFragment(MCFragment *F) const { |
269 | assert(!isVariable() && "Cannot set fragment of variable")(static_cast <bool> (!isVariable() && "Cannot set fragment of variable" ) ? void (0) : __assert_fail ("!isVariable() && \"Cannot set fragment of variable\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 269, __extension__ __PRETTY_FUNCTION__)); |
270 | FragmentAndHasName.setPointer(F); |
271 | } |
272 | |
273 | /// Mark the symbol as undefined. |
274 | void setUndefined() { FragmentAndHasName.setPointer(nullptr); } |
275 | |
276 | bool isELF() const { return Kind == SymbolKindELF; } |
277 | |
278 | bool isCOFF() const { return Kind == SymbolKindCOFF; } |
279 | |
280 | bool isGOFF() const { return Kind == SymbolKindGOFF; } |
281 | |
282 | bool isMachO() const { return Kind == SymbolKindMachO; } |
283 | |
284 | bool isWasm() const { return Kind == SymbolKindWasm; } |
285 | |
286 | bool isXCOFF() const { return Kind == SymbolKindXCOFF; } |
287 | |
288 | /// @} |
289 | /// \name Variable Symbols |
290 | /// @{ |
291 | |
292 | /// isVariable - Check if this is a variable symbol. |
293 | bool isVariable() const { |
294 | return SymbolContents == SymContentsVariable; |
295 | } |
296 | |
297 | /// getVariableValue - Get the value for variable symbols. |
298 | const MCExpr *getVariableValue(bool SetUsed = true) const { |
299 | assert(isVariable() && "Invalid accessor!")(static_cast <bool> (isVariable() && "Invalid accessor!" ) ? void (0) : __assert_fail ("isVariable() && \"Invalid accessor!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 299, __extension__ __PRETTY_FUNCTION__)); |
300 | IsUsed |= SetUsed; |
301 | return Value; |
302 | } |
303 | |
304 | void setVariableValue(const MCExpr *Value); |
305 | |
306 | /// @} |
307 | |
308 | /// Get the (implementation defined) index. |
309 | uint32_t getIndex() const { |
310 | return Index; |
311 | } |
312 | |
313 | /// Set the (implementation defined) index. |
314 | void setIndex(uint32_t Value) const { |
315 | Index = Value; |
316 | } |
317 | |
318 | bool isUnset() const { return SymbolContents == SymContentsUnset; } |
319 | |
320 | uint64_t getOffset() const { |
321 | assert((SymbolContents == SymContentsUnset ||(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot get offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot get offset for a common/variable symbol\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 323, __extension__ __PRETTY_FUNCTION__)) |
322 | SymbolContents == SymContentsOffset) &&(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot get offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot get offset for a common/variable symbol\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 323, __extension__ __PRETTY_FUNCTION__)) |
323 | "Cannot get offset for a common/variable symbol")(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot get offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot get offset for a common/variable symbol\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 323, __extension__ __PRETTY_FUNCTION__)); |
324 | return Offset; |
325 | } |
326 | void setOffset(uint64_t Value) { |
327 | assert((SymbolContents == SymContentsUnset ||(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot set offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot set offset for a common/variable symbol\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 329, __extension__ __PRETTY_FUNCTION__)) |
328 | SymbolContents == SymContentsOffset) &&(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot set offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot set offset for a common/variable symbol\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 329, __extension__ __PRETTY_FUNCTION__)) |
329 | "Cannot set offset for a common/variable symbol")(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot set offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot set offset for a common/variable symbol\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 329, __extension__ __PRETTY_FUNCTION__)); |
330 | Offset = Value; |
331 | SymbolContents = SymContentsOffset; |
332 | } |
333 | |
334 | /// Return the size of a 'common' symbol. |
335 | uint64_t getCommonSize() const { |
336 | assert(isCommon() && "Not a 'common' symbol!")(static_cast <bool> (isCommon() && "Not a 'common' symbol!" ) ? void (0) : __assert_fail ("isCommon() && \"Not a 'common' symbol!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 336, __extension__ __PRETTY_FUNCTION__)); |
337 | return CommonSize; |
338 | } |
339 | |
340 | /// Mark this symbol as being 'common'. |
341 | /// |
342 | /// \param Size - The size of the symbol. |
343 | /// \param Align - The alignment of the symbol. |
344 | /// \param Target - Is the symbol a target-specific common-like symbol. |
345 | void setCommon(uint64_t Size, unsigned Align, bool Target = false) { |
346 | assert(getOffset() == 0)(static_cast <bool> (getOffset() == 0) ? void (0) : __assert_fail ("getOffset() == 0", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 346, __extension__ __PRETTY_FUNCTION__)); |
347 | CommonSize = Size; |
348 | SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon; |
349 | |
350 | assert((!Align || isPowerOf2_32(Align)) &&(static_cast <bool> ((!Align || isPowerOf2_32(Align)) && "Alignment must be a power of 2") ? void (0) : __assert_fail ("(!Align || isPowerOf2_32(Align)) && \"Alignment must be a power of 2\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 351, __extension__ __PRETTY_FUNCTION__)) |
351 | "Alignment must be a power of 2")(static_cast <bool> ((!Align || isPowerOf2_32(Align)) && "Alignment must be a power of 2") ? void (0) : __assert_fail ("(!Align || isPowerOf2_32(Align)) && \"Alignment must be a power of 2\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 351, __extension__ __PRETTY_FUNCTION__)); |
352 | unsigned Log2Align = Log2_32(Align) + 1; |
353 | assert(Log2Align < (1U << NumCommonAlignmentBits) &&(static_cast <bool> (Log2Align < (1U << NumCommonAlignmentBits ) && "Out of range alignment") ? void (0) : __assert_fail ("Log2Align < (1U << NumCommonAlignmentBits) && \"Out of range alignment\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 354, __extension__ __PRETTY_FUNCTION__)) |
354 | "Out of range alignment")(static_cast <bool> (Log2Align < (1U << NumCommonAlignmentBits ) && "Out of range alignment") ? void (0) : __assert_fail ("Log2Align < (1U << NumCommonAlignmentBits) && \"Out of range alignment\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 354, __extension__ __PRETTY_FUNCTION__)); |
355 | CommonAlignLog2 = Log2Align; |
356 | } |
357 | |
358 | /// Return the alignment of a 'common' symbol. |
359 | unsigned getCommonAlignment() const { |
360 | assert(isCommon() && "Not a 'common' symbol!")(static_cast <bool> (isCommon() && "Not a 'common' symbol!" ) ? void (0) : __assert_fail ("isCommon() && \"Not a 'common' symbol!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 360, __extension__ __PRETTY_FUNCTION__)); |
361 | return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0; |
362 | } |
363 | |
364 | /// Declare this symbol as being 'common'. |
365 | /// |
366 | /// \param Size - The size of the symbol. |
367 | /// \param Align - The alignment of the symbol. |
368 | /// \param Target - Is the symbol a target-specific common-like symbol. |
369 | /// \return True if symbol was already declared as a different type |
370 | bool declareCommon(uint64_t Size, unsigned Align, bool Target = false) { |
371 | assert(isCommon() || getOffset() == 0)(static_cast <bool> (isCommon() || getOffset() == 0) ? void (0) : __assert_fail ("isCommon() || getOffset() == 0", "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 371, __extension__ __PRETTY_FUNCTION__)); |
372 | if(isCommon()) { |
373 | if (CommonSize != Size || getCommonAlignment() != Align || |
374 | isTargetCommon() != Target) |
375 | return true; |
376 | } else |
377 | setCommon(Size, Align, Target); |
378 | return false; |
379 | } |
380 | |
381 | /// Is this a 'common' symbol. |
382 | bool isCommon() const { |
383 | return SymbolContents == SymContentsCommon || |
384 | SymbolContents == SymContentsTargetCommon; |
385 | } |
386 | |
387 | /// Is this a target-specific common-like symbol. |
388 | bool isTargetCommon() const { |
389 | return SymbolContents == SymContentsTargetCommon; |
390 | } |
391 | |
392 | MCFragment *getFragment(bool SetUsed = true) const { |
393 | MCFragment *Fragment = FragmentAndHasName.getPointer(); |
394 | if (Fragment || !isVariable()) |
395 | return Fragment; |
396 | Fragment = getVariableValue(SetUsed)->findAssociatedFragment(); |
397 | FragmentAndHasName.setPointer(Fragment); |
398 | return Fragment; |
399 | } |
400 | |
401 | bool isExternal() const { return IsExternal; } |
402 | void setExternal(bool Value) const { IsExternal = Value; } |
403 | |
404 | bool isPrivateExtern() const { return IsPrivateExtern; } |
405 | void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } |
406 | |
407 | /// print - Print the value to the stream \p OS. |
408 | void print(raw_ostream &OS, const MCAsmInfo *MAI) const; |
409 | |
410 | /// dump - Print the value to stderr. |
411 | void dump() const; |
412 | |
413 | protected: |
414 | /// Get the (implementation defined) symbol flags. |
415 | uint32_t getFlags() const { return Flags; } |
416 | |
417 | /// Set the (implementation defined) symbol flags. |
418 | void setFlags(uint32_t Value) const { |
419 | assert(Value < (1U << NumFlagsBits) && "Out of range flags")(static_cast <bool> (Value < (1U << NumFlagsBits ) && "Out of range flags") ? void (0) : __assert_fail ("Value < (1U << NumFlagsBits) && \"Out of range flags\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 419, __extension__ __PRETTY_FUNCTION__)); |
420 | Flags = Value; |
421 | } |
422 | |
423 | /// Modify the flags via a mask |
424 | void modifyFlags(uint32_t Value, uint32_t Mask) const { |
425 | assert(Value < (1U << NumFlagsBits) && "Out of range flags")(static_cast <bool> (Value < (1U << NumFlagsBits ) && "Out of range flags") ? void (0) : __assert_fail ("Value < (1U << NumFlagsBits) && \"Out of range flags\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/MC/MCSymbol.h" , 425, __extension__ __PRETTY_FUNCTION__)); |
426 | Flags = (Flags & ~Mask) | Value; |
427 | } |
428 | }; |
429 | |
430 | inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { |
431 | Sym.print(OS, nullptr); |
432 | return OS; |
433 | } |
434 | |
435 | } // end namespace llvm |
436 | |
437 | #endif // LLVM_MC_MCSYMBOL_H |