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