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/ScopeExit.h" |
11 | #include "llvm/ADT/Statistic.h" |
12 | #include "llvm/Config/llvm-config.h" |
13 | #include "llvm/MC/MCAsmBackend.h" |
14 | #include "llvm/MC/MCAsmInfo.h" |
15 | #include "llvm/MC/MCAssembler.h" |
16 | #include "llvm/MC/MCContext.h" |
17 | #include "llvm/MC/MCObjectWriter.h" |
18 | #include "llvm/MC/MCStreamer.h" |
19 | #include "llvm/MC/MCSymbol.h" |
20 | #include "llvm/MC/MCValue.h" |
21 | #include "llvm/Support/Casting.h" |
22 | #include "llvm/Support/Compiler.h" |
23 | #include "llvm/Support/Debug.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | #include <cassert> |
27 | #include <cstdint> |
28 | |
29 | using namespace llvm; |
30 | |
31 | #define DEBUG_TYPE "mcexpr" |
32 | |
33 | namespace { |
34 | namespace stats { |
35 | |
36 | STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations" ); |
37 | |
38 | } // end namespace stats |
39 | } // end anonymous namespace |
40 | |
41 | static int getPrecedence(MCBinaryExpr::Opcode Op) { |
42 | switch (Op) { |
43 | case MCBinaryExpr::Add: |
44 | case MCBinaryExpr::Sub: |
45 | return 1; |
46 | default: |
47 | return 0; |
48 | } |
49 | } |
50 | |
51 | // VariantKind printing and formatting utilize MAI. operator<< (dump and some |
52 | // target code) specifies MAI as nullptr and should be avoided when MAI is |
53 | // needed. |
54 | void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, |
55 | int SurroundingPrec) const { |
56 | constexpr int MaxPrec = 9; |
57 | switch (getKind()) { |
58 | case MCExpr::Target: |
59 | return cast<MCTargetExpr>(Val: this)->printImpl(OS, MAI); |
60 | case MCExpr::Constant: { |
61 | auto Value = cast<MCConstantExpr>(Val: *this).getValue(); |
62 | auto PrintInHex = cast<MCConstantExpr>(Val: *this).useHexFormat(); |
63 | auto SizeInBytes = cast<MCConstantExpr>(Val: *this).getSizeInBytes(); |
64 | if (Value < 0 && MAI && !MAI->supportsSignedData()) |
65 | PrintInHex = true; |
66 | if (PrintInHex) |
67 | switch (SizeInBytes) { |
68 | default: |
69 | OS << "0x" << Twine::utohexstr(Val: Value); |
70 | break; |
71 | case 1: |
72 | OS << format(Fmt: "0x%02" PRIx64, Vals: Value); |
73 | break; |
74 | case 2: |
75 | OS << format(Fmt: "0x%04" PRIx64, Vals: Value); |
76 | break; |
77 | case 4: |
78 | OS << format(Fmt: "0x%08" PRIx64, Vals: Value); |
79 | break; |
80 | case 8: |
81 | OS << format(Fmt: "0x%016" PRIx64, Vals: Value); |
82 | break; |
83 | } |
84 | else |
85 | OS << Value; |
86 | return; |
87 | } |
88 | case MCExpr::SymbolRef: { |
89 | const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Val: *this); |
90 | const MCSymbol &Sym = SRE.getSymbol(); |
91 | Sym.print(OS, MAI); |
92 | |
93 | const MCSymbolRefExpr::VariantKind Kind = SRE.getKind(); |
94 | if (Kind) { |
95 | if (!MAI) // should only be used by dump() |
96 | OS << "@<variant " << Kind << '>'; |
97 | else if (MAI->useParensForSpecifier()) // ARM |
98 | OS << '(' << MAI->getSpecifierName(S: Kind) << ')'; |
99 | else |
100 | OS << '@' << MAI->getSpecifierName(S: Kind); |
101 | } |
102 | |
103 | return; |
104 | } |
105 | |
106 | case MCExpr::Unary: { |
107 | const MCUnaryExpr &UE = cast<MCUnaryExpr>(Val: *this); |
108 | switch (UE.getOpcode()) { |
109 | case MCUnaryExpr::LNot: OS << '!'; break; |
110 | case MCUnaryExpr::Minus: OS << '-'; break; |
111 | case MCUnaryExpr::Not: OS << '~'; break; |
112 | case MCUnaryExpr::Plus: OS << '+'; break; |
113 | } |
114 | UE.getSubExpr()->print(OS, MAI, SurroundingPrec: MaxPrec); |
115 | return; |
116 | } |
117 | |
118 | case MCExpr::Binary: { |
119 | const MCBinaryExpr &BE = cast<MCBinaryExpr>(Val: *this); |
120 | // We want to avoid redundant parentheses for relocatable expressions like |
121 | // a-b+c. |
122 | // |
123 | // Print '(' if the current operator has lower precedence than the |
124 | // surrounding operator, or if the surrounding operator's precedence is |
125 | // unknown (set to HighPrecedence). |
126 | int Prec = getPrecedence(Op: BE.getOpcode()); |
127 | bool Paren = Prec < SurroundingPrec; |
128 | if (Paren) |
129 | OS << '('; |
130 | // Many operators' precedence is different from C. Set the precedence to |
131 | // HighPrecedence for unknown operators. |
132 | int SubPrec = Prec ? Prec : MaxPrec; |
133 | BE.getLHS()->print(OS, MAI, SurroundingPrec: SubPrec); |
134 | |
135 | switch (BE.getOpcode()) { |
136 | case MCBinaryExpr::Add: |
137 | // Print "X-42" instead of "X+-42". |
138 | if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(Val: BE.getRHS())) { |
139 | if (RHSC->getValue() < 0) { |
140 | OS << RHSC->getValue(); |
141 | if (Paren) |
142 | OS << ')'; |
143 | return; |
144 | } |
145 | } |
146 | |
147 | OS << '+'; |
148 | break; |
149 | case MCBinaryExpr::AShr: OS << ">>" ; break; |
150 | case MCBinaryExpr::And: OS << '&'; break; |
151 | case MCBinaryExpr::Div: OS << '/'; break; |
152 | case MCBinaryExpr::EQ: OS << "==" ; break; |
153 | case MCBinaryExpr::GT: OS << '>'; break; |
154 | case MCBinaryExpr::GTE: OS << ">=" ; break; |
155 | case MCBinaryExpr::LAnd: OS << "&&" ; break; |
156 | case MCBinaryExpr::LOr: OS << "||" ; break; |
157 | case MCBinaryExpr::LShr: OS << ">>" ; break; |
158 | case MCBinaryExpr::LT: OS << '<'; break; |
159 | case MCBinaryExpr::LTE: OS << "<=" ; break; |
160 | case MCBinaryExpr::Mod: OS << '%'; break; |
161 | case MCBinaryExpr::Mul: OS << '*'; break; |
162 | case MCBinaryExpr::NE: OS << "!=" ; break; |
163 | case MCBinaryExpr::Or: OS << '|'; break; |
164 | case MCBinaryExpr::OrNot: OS << '!'; break; |
165 | case MCBinaryExpr::Shl: OS << "<<" ; break; |
166 | case MCBinaryExpr::Sub: OS << '-'; break; |
167 | case MCBinaryExpr::Xor: OS << '^'; break; |
168 | } |
169 | |
170 | BE.getRHS()->print(OS, MAI, SurroundingPrec: SubPrec + 1); |
171 | if (Paren) |
172 | OS << ')'; |
173 | return; |
174 | } |
175 | |
176 | case MCExpr::Specifier: { |
177 | auto &SE = cast<MCSpecifierExpr>(Val: *this); |
178 | if (MAI) |
179 | return MAI->printSpecifierExpr(OS, SE); |
180 | // Used by dump features like -show-inst. Regular MCAsmStreamer output must |
181 | // set MAI. |
182 | OS << "specifier(" << SE.getSpecifier() << ','; |
183 | SE.getSubExpr()->print(OS, MAI: nullptr); |
184 | OS << ')'; |
185 | return; |
186 | } |
187 | } |
188 | |
189 | llvm_unreachable("Invalid expression kind!" ); |
190 | } |
191 | |
192 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
193 | LLVM_DUMP_METHOD void MCExpr::dump() const { |
194 | print(dbgs(), nullptr); |
195 | dbgs() << '\n'; |
196 | } |
197 | #endif |
198 | |
199 | /* *** */ |
200 | |
201 | const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS, |
202 | const MCExpr *RHS, MCContext &Ctx, |
203 | SMLoc Loc) { |
204 | return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc); |
205 | } |
206 | |
207 | const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr, |
208 | MCContext &Ctx, SMLoc Loc) { |
209 | return new (Ctx) MCUnaryExpr(Opc, Expr, Loc); |
210 | } |
211 | |
212 | const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx, |
213 | bool PrintInHex, |
214 | unsigned SizeInBytes) { |
215 | return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes); |
216 | } |
217 | |
218 | /* *** */ |
219 | |
220 | MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, Spec specifier, |
221 | const MCAsmInfo *MAI, SMLoc Loc) |
222 | : MCExpr(MCExpr::SymbolRef, Loc, specifier), Symbol(Symbol) { |
223 | assert(Symbol); |
224 | } |
225 | |
226 | const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym, |
227 | uint16_t specifier, |
228 | MCContext &Ctx, SMLoc Loc) { |
229 | return new (Ctx) MCSymbolRefExpr(Sym, specifier, Ctx.getAsmInfo(), Loc); |
230 | } |
231 | |
232 | /* *** */ |
233 | |
234 | void MCTargetExpr::anchor() {} |
235 | |
236 | /* *** */ |
237 | |
238 | bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { |
239 | return evaluateAsAbsolute(Res, Asm: nullptr, InSet: false); |
240 | } |
241 | |
242 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { |
243 | return evaluateAsAbsolute(Res, Asm: &Asm, InSet: false); |
244 | } |
245 | |
246 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { |
247 | return evaluateAsAbsolute(Res, Asm, InSet: false); |
248 | } |
249 | |
250 | bool MCExpr::evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const { |
251 | return evaluateAsAbsolute(Res, Asm: &Asm, InSet: true); |
252 | } |
253 | |
254 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, |
255 | bool InSet) const { |
256 | MCValue Value; |
257 | |
258 | // Fast path constants. |
259 | if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: this)) { |
260 | Res = CE->getValue(); |
261 | return true; |
262 | } |
263 | |
264 | bool IsRelocatable = evaluateAsRelocatableImpl(Res&: Value, Asm, InSet); |
265 | Res = Value.getConstant(); |
266 | // Value with RefKind (e.g. %hi(0xdeadbeef) in MIPS) is not considered |
267 | // absolute (the value is unknown at parse time), even if it might be resolved |
268 | // by evaluateFixup. |
269 | return IsRelocatable && Value.isAbsolute() && Value.getSpecifier() == 0; |
270 | } |
271 | |
272 | /// Helper method for \see EvaluateSymbolAdd(). |
273 | static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, |
274 | bool InSet, const MCSymbol *&A, |
275 | const MCSymbol *&B, |
276 | int64_t &Addend) { |
277 | if (!A || !B) |
278 | return; |
279 | |
280 | const MCSymbol &SA = *A, &SB = *B; |
281 | if (SA.isUndefined() || SB.isUndefined()) |
282 | return; |
283 | if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(A: SA, B: SB, InSet)) |
284 | return; |
285 | |
286 | auto FinalizeFolding = [&]() { |
287 | // Pointers to Thumb symbols need to have their low-bit set to allow |
288 | // for interworking. |
289 | if (Asm->isThumbFunc(Func: &SA)) |
290 | Addend |= 1; |
291 | |
292 | // Clear the symbol expr pointers to indicate we have folded these |
293 | // operands. |
294 | A = B = nullptr; |
295 | }; |
296 | |
297 | const MCFragment *FA = SA.getFragment(); |
298 | const MCFragment *FB = SB.getFragment(); |
299 | const MCSection &SecA = *FA->getParent(); |
300 | const MCSection &SecB = *FB->getParent(); |
301 | if (&SecA != &SecB) |
302 | return; |
303 | |
304 | // When layout is available, we can generally compute the difference using the |
305 | // getSymbolOffset path, which also avoids the possible slow fragment walk. |
306 | // However, linker relaxation may cause incorrect fold of A-B if A and B are |
307 | // separated by a linker-relaxable fragment. If the section contains |
308 | // linker-relaxable instruction and InSet is false (not expressions in |
309 | // directive like .size/.fill), disable the fast path. |
310 | bool Layout = Asm->hasLayout(); |
311 | if (Layout && (InSet || !SecA.isLinkerRelaxable())) { |
312 | // If both symbols are in the same fragment, return the difference of their |
313 | // offsets. canGetFragmentOffset(FA) may be false. |
314 | if (FA == FB && !SA.isVariable() && !SB.isVariable()) { |
315 | Addend += SA.getOffset() - SB.getOffset(); |
316 | return FinalizeFolding(); |
317 | } |
318 | |
319 | // Eagerly evaluate when layout is finalized. |
320 | Addend += Asm->getSymbolOffset(S: SA) - Asm->getSymbolOffset(S: SB); |
321 | FinalizeFolding(); |
322 | } else { |
323 | // When layout is not finalized, our ability to resolve differences between |
324 | // symbols is limited to specific cases where the fragments between two |
325 | // symbols (including the fragments the symbols are defined in) are |
326 | // fixed-size fragments so the difference can be calculated. For example, |
327 | // this is important when the Subtarget is changed and a new MCDataFragment |
328 | // is created in the case of foo: instr; .arch_extension ext; instr .if . - |
329 | // foo. |
330 | if (SA.isVariable() || SB.isVariable()) |
331 | return; |
332 | |
333 | // Try to find a constant displacement from FA to FB, add the displacement |
334 | // between the offset in FA of SA and the offset in FB of SB. |
335 | bool Reverse = false; |
336 | if (FA == FB) |
337 | Reverse = SA.getOffset() < SB.getOffset(); |
338 | else |
339 | Reverse = FA->getLayoutOrder() < FB->getLayoutOrder(); |
340 | |
341 | uint64_t SAOffset = SA.getOffset(), SBOffset = SB.getOffset(); |
342 | int64_t Displacement = SA.getOffset() - SB.getOffset(); |
343 | if (Reverse) { |
344 | std::swap(a&: FA, b&: FB); |
345 | std::swap(a&: SAOffset, b&: SBOffset); |
346 | Displacement *= -1; |
347 | } |
348 | |
349 | // Track whether B is before a relaxable instruction and whether A is after |
350 | // a relaxable instruction. If SA and SB are separated by a linker-relaxable |
351 | // instruction, the difference cannot be resolved as it may be changed by |
352 | // the linker. |
353 | bool BBeforeRelax = false, AAfterRelax = false; |
354 | for (auto FI = FB; FI; FI = FI->getNext()) { |
355 | auto DF = dyn_cast<MCDataFragment>(Val: FI); |
356 | if (DF && DF->isLinkerRelaxable()) { |
357 | if (&*FI != FB || SBOffset != DF->getContents().size()) |
358 | BBeforeRelax = true; |
359 | if (&*FI != FA || SAOffset == DF->getContents().size()) |
360 | AAfterRelax = true; |
361 | if (BBeforeRelax && AAfterRelax) |
362 | return; |
363 | } |
364 | if (&*FI == FA) { |
365 | // If FA and FB belong to the same subsection, the loop will find FA and |
366 | // we can resolve the difference. |
367 | Addend += Reverse ? -Displacement : Displacement; |
368 | FinalizeFolding(); |
369 | return; |
370 | } |
371 | |
372 | int64_t Num; |
373 | unsigned Count; |
374 | if (DF) { |
375 | Displacement += DF->getContents().size(); |
376 | } else if (auto *RF = dyn_cast<MCRelaxableFragment>(Val: FI); |
377 | RF && Asm->hasFinalLayout()) { |
378 | // Before finishLayout, a relaxable fragment's size is indeterminate. |
379 | // After layout, during relocation generation, it can be treated as a |
380 | // data fragment. |
381 | Displacement += RF->getContents().size(); |
382 | } else if (auto *AF = dyn_cast<MCAlignFragment>(Val: FI); |
383 | AF && Layout && AF->hasEmitNops() && |
384 | !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( |
385 | AF: *AF, Size&: Count)) { |
386 | Displacement += Asm->computeFragmentSize(F: *AF); |
387 | } else if (auto *FF = dyn_cast<MCFillFragment>(Val: FI); |
388 | FF && FF->getNumValues().evaluateAsAbsolute(Res&: Num)) { |
389 | Displacement += Num * FF->getValueSize(); |
390 | } else { |
391 | return; |
392 | } |
393 | } |
394 | } |
395 | } |
396 | |
397 | // Evaluate the sum of two relocatable expressions. |
398 | // |
399 | // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). |
400 | // |
401 | // This routine attempts to aggressively fold the operands such that the result |
402 | // is representable in an MCValue, but may not always succeed. |
403 | // |
404 | // LHS_A and RHS_A might have relocation specifiers while LHS_B and RHS_B |
405 | // cannot have specifiers. |
406 | // |
407 | // \returns True on success, false if the result is not representable in an |
408 | // MCValue. |
409 | |
410 | // NOTE: This function can be used before layout is done (see the object |
411 | // streamer for example) and having the Asm argument lets us avoid relaxations |
412 | // early. |
413 | bool MCExpr::evaluateSymbolicAdd(const MCAssembler *Asm, bool InSet, |
414 | const MCValue &LHS, const MCValue &RHS, |
415 | MCValue &Res) { |
416 | const MCSymbol *LHS_A = LHS.getAddSym(); |
417 | const MCSymbol *LHS_B = LHS.getSubSym(); |
418 | int64_t LHS_Cst = LHS.getConstant(); |
419 | |
420 | const MCSymbol *RHS_A = RHS.getAddSym(); |
421 | const MCSymbol *RHS_B = RHS.getSubSym(); |
422 | int64_t RHS_Cst = RHS.getConstant(); |
423 | |
424 | // Fold the result constant immediately. |
425 | int64_t Result_Cst = LHS_Cst + RHS_Cst; |
426 | |
427 | // If we have a layout, we can fold resolved differences. |
428 | if (Asm && !LHS.getSpecifier() && !RHS.getSpecifier()) { |
429 | // While LHS_A-LHS_B and RHS_A-RHS_B from recursive calls have already been |
430 | // folded, reassociating terms in |
431 | // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). |
432 | // might bring more opportunities. |
433 | if (LHS_A && RHS_B) { |
434 | attemptToFoldSymbolOffsetDifference(Asm, InSet, A&: LHS_A, B&: RHS_B, Addend&: Result_Cst); |
435 | } |
436 | if (RHS_A && LHS_B) { |
437 | attemptToFoldSymbolOffsetDifference(Asm, InSet, A&: RHS_A, B&: LHS_B, Addend&: Result_Cst); |
438 | } |
439 | } |
440 | |
441 | // We can't represent the addition or subtraction of two symbols. |
442 | if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) |
443 | return false; |
444 | |
445 | // At this point, we have at most one additive symbol and one subtractive |
446 | // symbol -- find them. |
447 | auto *A = LHS_A ? LHS_A : RHS_A; |
448 | auto *B = LHS_B ? LHS_B : RHS_B; |
449 | auto Spec = LHS.getSpecifier(); |
450 | if (!Spec) |
451 | Spec = RHS.getSpecifier(); |
452 | Res = MCValue::get(SymA: A, SymB: B, Val: Result_Cst, Specifier: Spec); |
453 | return true; |
454 | } |
455 | |
456 | bool MCExpr::evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const { |
457 | return evaluateAsRelocatableImpl(Res, Asm, InSet: false); |
458 | } |
459 | bool MCExpr::evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const { |
460 | return evaluateAsRelocatableImpl(Res, Asm: &Asm, InSet: true); |
461 | } |
462 | |
463 | bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, |
464 | bool InSet) const { |
465 | ++stats::MCExprEvaluate; |
466 | switch (getKind()) { |
467 | case Target: |
468 | return cast<MCTargetExpr>(Val: this)->evaluateAsRelocatableImpl(Res, Asm); |
469 | case Constant: |
470 | Res = MCValue::get(Val: cast<MCConstantExpr>(Val: this)->getValue()); |
471 | return true; |
472 | |
473 | case SymbolRef: { |
474 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Val: this); |
475 | MCSymbol &Sym = const_cast<MCSymbol &>(SRE->getSymbol()); |
476 | const auto Kind = SRE->getKind(); |
477 | bool Layout = Asm && Asm->hasLayout(); |
478 | |
479 | // If the symbol is equated, resolve the inner expression. |
480 | // However, when two IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY symbols reference |
481 | // each other, we retain the equated symbol to avoid a cyclic definition |
482 | // error. |
483 | if (Sym.isResolving()) { |
484 | if (Asm && Asm->hasFinalLayout()) { |
485 | Asm->getContext().reportError( |
486 | L: Sym.getVariableValue()->getLoc(), |
487 | Msg: "cyclic dependency detected for symbol '" + Sym.getName() + "'" ); |
488 | Sym.setVariableValue(MCConstantExpr::create(Value: 0, Ctx&: Asm->getContext())); |
489 | } |
490 | return false; |
491 | } |
492 | if (Sym.isVariable() && (Kind == 0 || Layout) && !Sym.isWeakExternal()) { |
493 | Sym.setIsResolving(true); |
494 | auto _ = make_scope_exit(F: [&] { Sym.setIsResolving(false); }); |
495 | bool IsMachO = |
496 | Asm && Asm->getContext().getAsmInfo()->hasSubsectionsViaSymbols(); |
497 | if (!Sym.getVariableValue()->evaluateAsRelocatableImpl(Res, Asm, |
498 | InSet: InSet || IsMachO)) |
499 | return false; |
500 | // When generating relocations, if Sym resolves to a symbol relative to a |
501 | // section, relocations are generated against Sym. Treat label differences |
502 | // as constants. |
503 | auto *A = Res.getAddSym(); |
504 | auto *B = Res.getSubSym(); |
505 | if (InSet || !(A && !B && A->isInSection())) { |
506 | if (Kind) { |
507 | if (Res.isAbsolute()) { |
508 | Res = MCValue::get(SymA: &Sym, SymB: nullptr, Val: 0, Specifier: Kind); |
509 | return true; |
510 | } |
511 | // If the reference has a variant kind, we can only handle expressions |
512 | // which evaluate exactly to a single unadorned symbol. Attach the |
513 | // original VariantKind to SymA of the result. |
514 | if (Res.getSpecifier() || !Res.getAddSym() || Res.getSubSym() || |
515 | Res.getConstant()) |
516 | return false; |
517 | Res.Specifier = Kind; |
518 | } |
519 | if (!IsMachO) |
520 | return true; |
521 | |
522 | // FIXME: This is small hack. Given |
523 | // a = b + 4 |
524 | // .long a |
525 | // the OS X assembler will completely drop the 4. We should probably |
526 | // include it in the relocation or produce an error if that is not |
527 | // possible. |
528 | // Allow constant expressions. |
529 | if (!A && !B) |
530 | return true; |
531 | // Allows aliases with zero offset. |
532 | if (Res.getConstant() == 0 && (!A || !B)) |
533 | return true; |
534 | } |
535 | } |
536 | |
537 | Res = MCValue::get(SymA: &Sym, SymB: nullptr, Val: 0, Specifier: Kind); |
538 | return true; |
539 | } |
540 | |
541 | case Unary: { |
542 | const MCUnaryExpr *AUE = cast<MCUnaryExpr>(Val: this); |
543 | MCValue Value; |
544 | |
545 | if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Res&: Value, Asm, InSet)) |
546 | return false; |
547 | switch (AUE->getOpcode()) { |
548 | case MCUnaryExpr::LNot: |
549 | if (!Value.isAbsolute()) |
550 | return false; |
551 | Res = MCValue::get(Val: !Value.getConstant()); |
552 | break; |
553 | case MCUnaryExpr::Minus: |
554 | /// -(a - b + const) ==> (b - a - const) |
555 | if (Value.getAddSym() && !Value.getSubSym()) |
556 | return false; |
557 | |
558 | // The cast avoids undefined behavior if the constant is INT64_MIN. |
559 | Res = MCValue::get(SymA: Value.getSubSym(), SymB: Value.getAddSym(), |
560 | Val: -(uint64_t)Value.getConstant()); |
561 | break; |
562 | case MCUnaryExpr::Not: |
563 | if (!Value.isAbsolute()) |
564 | return false; |
565 | Res = MCValue::get(Val: ~Value.getConstant()); |
566 | break; |
567 | case MCUnaryExpr::Plus: |
568 | Res = Value; |
569 | break; |
570 | } |
571 | |
572 | return true; |
573 | } |
574 | |
575 | case Binary: { |
576 | const MCBinaryExpr *ABE = cast<MCBinaryExpr>(Val: this); |
577 | MCValue LHSValue, RHSValue; |
578 | |
579 | if (!ABE->getLHS()->evaluateAsRelocatableImpl(Res&: LHSValue, Asm, InSet) || |
580 | !ABE->getRHS()->evaluateAsRelocatableImpl(Res&: RHSValue, Asm, InSet)) { |
581 | // Check if both are Target Expressions, see if we can compare them. |
582 | if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(Val: ABE->getLHS())) { |
583 | if (const MCTargetExpr *R = dyn_cast<MCTargetExpr>(Val: ABE->getRHS())) { |
584 | switch (ABE->getOpcode()) { |
585 | case MCBinaryExpr::EQ: |
586 | Res = MCValue::get(Val: L->isEqualTo(x: R) ? -1 : 0); |
587 | return true; |
588 | case MCBinaryExpr::NE: |
589 | Res = MCValue::get(Val: L->isEqualTo(x: R) ? 0 : -1); |
590 | return true; |
591 | default: |
592 | break; |
593 | } |
594 | } |
595 | } |
596 | return false; |
597 | } |
598 | |
599 | // We only support a few operations on non-constant expressions, handle |
600 | // those first. |
601 | auto Op = ABE->getOpcode(); |
602 | int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); |
603 | if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { |
604 | switch (Op) { |
605 | default: |
606 | return false; |
607 | case MCBinaryExpr::Add: |
608 | case MCBinaryExpr::Sub: |
609 | if (Op == MCBinaryExpr::Sub) { |
610 | std::swap(a&: RHSValue.SymA, b&: RHSValue.SymB); |
611 | RHSValue.Cst = -(uint64_t)RHSValue.Cst; |
612 | } |
613 | if (RHSValue.isAbsolute()) { |
614 | LHSValue.Cst += RHSValue.Cst; |
615 | Res = LHSValue; |
616 | return true; |
617 | } |
618 | if (LHSValue.isAbsolute()) { |
619 | RHSValue.Cst += LHSValue.Cst; |
620 | Res = RHSValue; |
621 | return true; |
622 | } |
623 | if (LHSValue.SymB && LHSValue.Specifier) |
624 | return false; |
625 | if (RHSValue.SymB && RHSValue.Specifier) |
626 | return false; |
627 | return evaluateSymbolicAdd(Asm, InSet, LHS: LHSValue, RHS: RHSValue, Res); |
628 | } |
629 | } |
630 | |
631 | // FIXME: We need target hooks for the evaluation. It may be limited in |
632 | // width, and gas defines the result of comparisons differently from |
633 | // Apple as. |
634 | int64_t Result = 0; |
635 | switch (Op) { |
636 | case MCBinaryExpr::AShr: Result = LHS >> RHS; break; |
637 | case MCBinaryExpr::Add: Result = LHS + RHS; break; |
638 | case MCBinaryExpr::And: Result = LHS & RHS; break; |
639 | case MCBinaryExpr::Div: |
640 | case MCBinaryExpr::Mod: |
641 | // Handle division by zero. gas just emits a warning and keeps going, |
642 | // we try to be stricter. |
643 | // FIXME: Currently the caller of this function has no way to understand |
644 | // we're bailing out because of 'division by zero'. Therefore, it will |
645 | // emit a 'expected relocatable expression' error. It would be nice to |
646 | // change this code to emit a better diagnostic. |
647 | if (RHS == 0) |
648 | return false; |
649 | if (ABE->getOpcode() == MCBinaryExpr::Div) |
650 | Result = LHS / RHS; |
651 | else |
652 | Result = LHS % RHS; |
653 | break; |
654 | case MCBinaryExpr::EQ: Result = LHS == RHS; break; |
655 | case MCBinaryExpr::GT: Result = LHS > RHS; break; |
656 | case MCBinaryExpr::GTE: Result = LHS >= RHS; break; |
657 | case MCBinaryExpr::LAnd: Result = LHS && RHS; break; |
658 | case MCBinaryExpr::LOr: Result = LHS || RHS; break; |
659 | case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; |
660 | case MCBinaryExpr::LT: Result = LHS < RHS; break; |
661 | case MCBinaryExpr::LTE: Result = LHS <= RHS; break; |
662 | case MCBinaryExpr::Mul: Result = LHS * RHS; break; |
663 | case MCBinaryExpr::NE: Result = LHS != RHS; break; |
664 | case MCBinaryExpr::Or: Result = LHS | RHS; break; |
665 | case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break; |
666 | case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; |
667 | case MCBinaryExpr::Sub: Result = LHS - RHS; break; |
668 | case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; |
669 | } |
670 | |
671 | switch (Op) { |
672 | default: |
673 | Res = MCValue::get(Val: Result); |
674 | break; |
675 | case MCBinaryExpr::EQ: |
676 | case MCBinaryExpr::GT: |
677 | case MCBinaryExpr::GTE: |
678 | case MCBinaryExpr::LT: |
679 | case MCBinaryExpr::LTE: |
680 | case MCBinaryExpr::NE: |
681 | // A comparison operator returns a -1 if true and 0 if false. |
682 | Res = MCValue::get(Val: Result ? -1 : 0); |
683 | break; |
684 | } |
685 | |
686 | return true; |
687 | } |
688 | case Specifier: |
689 | // Fold the expression during relocation generation. As parse time Asm might |
690 | // be null, and targets should not rely on the folding. |
691 | return Asm && Asm->getContext().getAsmInfo()->evaluateAsRelocatableImpl( |
692 | cast<MCSpecifierExpr>(Val: *this), Res, Asm); |
693 | } |
694 | |
695 | llvm_unreachable("Invalid assembly expression kind!" ); |
696 | } |
697 | |
698 | MCFragment *MCExpr::findAssociatedFragment() const { |
699 | switch (getKind()) { |
700 | case Target: |
701 | // We never look through target specific expressions. |
702 | return cast<MCTargetExpr>(Val: this)->findAssociatedFragment(); |
703 | |
704 | case Constant: |
705 | return MCSymbol::AbsolutePseudoFragment; |
706 | |
707 | case SymbolRef: { |
708 | auto &Sym = |
709 | const_cast<MCSymbol &>(cast<MCSymbolRefExpr>(Val: this)->getSymbol()); |
710 | if (Sym.Fragment) |
711 | return Sym.Fragment; |
712 | if (Sym.isResolving()) |
713 | return MCSymbol::AbsolutePseudoFragment; |
714 | Sym.setIsResolving(true); |
715 | auto *F = Sym.getFragment(); |
716 | Sym.setIsResolving(false); |
717 | return F; |
718 | } |
719 | |
720 | case Unary: |
721 | return cast<MCUnaryExpr>(Val: this)->getSubExpr()->findAssociatedFragment(); |
722 | |
723 | case Binary: { |
724 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(Val: this); |
725 | MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); |
726 | MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); |
727 | |
728 | // If either is absolute, return the other. |
729 | if (LHS_F == MCSymbol::AbsolutePseudoFragment) |
730 | return RHS_F; |
731 | if (RHS_F == MCSymbol::AbsolutePseudoFragment) |
732 | return LHS_F; |
733 | |
734 | // Not always correct, but probably the best we can do without more context. |
735 | if (BE->getOpcode() == MCBinaryExpr::Sub) |
736 | return MCSymbol::AbsolutePseudoFragment; |
737 | |
738 | // Otherwise, return the first non-null fragment. |
739 | return LHS_F ? LHS_F : RHS_F; |
740 | } |
741 | |
742 | case Specifier: |
743 | return cast<MCSpecifierExpr>(Val: this)->getSubExpr()->findAssociatedFragment(); |
744 | } |
745 | |
746 | llvm_unreachable("Invalid assembly expression kind!" ); |
747 | } |
748 | |
749 | const MCSpecifierExpr *MCSpecifierExpr::create(const MCExpr *Expr, Spec S, |
750 | MCContext &Ctx, SMLoc Loc) { |
751 | return new (Ctx) MCSpecifierExpr(Expr, S, Loc); |
752 | } |
753 | |
754 | const MCSpecifierExpr *MCSpecifierExpr::create(const MCSymbol *Sym, Spec S, |
755 | MCContext &Ctx, SMLoc Loc) { |
756 | return new (Ctx) MCSpecifierExpr(MCSymbolRefExpr::create(Symbol: Sym, Ctx), S, Loc); |
757 | } |
758 | |