LLVM: lib/MC/MCExpr.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12#include "llvm/Config/llvm-config.h"
26#include
27#include
28
29using namespace llvm;
30
31#define DEBUG_TYPE "mcexpr"
32
33namespace {
35
36STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");
37
38}
39}
40
42 switch (Op) {
45 return 1;
46 default:
47 return 0;
48 }
49}
50
51
52
53
55 int SurroundingPrec) const {
56 constexpr int MaxPrec = 9;
65 PrintInHex = true;
66 if (PrintInHex)
67 switch (SizeInBytes) {
68 default:
70 break;
71 case 1:
73 break;
74 case 2:
76 break;
77 case 4:
79 break;
80 case 8:
82 break;
83 }
84 else
86 return;
87 }
91 Sym.print(OS, MAI);
92
94 if (Kind) {
95 if (!MAI)
96 OS << "@<variant " << Kind << '>';
99 else
101 }
102
103 return;
104 }
105
113 }
114 UE.getSubExpr()->print(OS, MAI, MaxPrec);
115 return;
116 }
117
120
121
122
123
124
125
127 bool Paren = Prec < SurroundingPrec;
128 if (Paren)
129 OS << '(';
130
131
132 int SubPrec = Prec ? Prec : MaxPrec;
133 BE.getLHS()->print(OS, MAI, SubPrec);
134
137
139 if (RHSC->getValue() < 0) {
140 OS << RHSC->getValue();
141 if (Paren)
142 OS << ')';
143 return;
144 }
145 }
146
147 OS << '+';
148 break;
168 }
169
170 BE.getRHS()->print(OS, MAI, SubPrec + 1);
171 if (Paren)
172 OS << ')';
173 return;
174 }
175
178 if (MAI)
180
181
182 OS << "specifier(" << SE.getSpecifier() << ',';
183 SE.getSubExpr()->print(OS, nullptr);
184 OS << ')';
185 return;
186 }
187 }
188
190}
191
192#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
194 print(dbgs(), nullptr);
195 dbgs() << '\n';
196}
197#endif
198
199
200
204 return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc);
205}
206
209 return new (Ctx) MCUnaryExpr(Opc, Expr, Loc);
210}
211
213 bool PrintInHex,
214 unsigned SizeInBytes) {
215 return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes);
216}
217
218
219
220MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, Spec specifier,
222 : MCExpr(MCExpr::SymbolRef, Loc, specifier), Symbol(Symbol) {
224}
225
229 return new (Ctx) MCSymbolRefExpr(Sym, specifier, Ctx.getAsmInfo(), Loc);
230}
231
232
233
234void MCTargetExpr::anchor() {}
235
236
237
238bool MCExpr::evaluateAsAbsolute(int64_t &Res) const {
239 return evaluateAsAbsolute(Res, nullptr, false);
240}
241
242bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
243 return evaluateAsAbsolute(Res, &Asm, false);
244}
245
246bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {
247 return evaluateAsAbsolute(Res, Asm, false);
248}
249
251 return evaluateAsAbsolute(Res, &Asm, true);
252}
253
254bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
255 bool InSet) const {
257
258
260 Res = CE->getValue();
261 return true;
262 }
263
265 Res = Value.getConstant();
266
267
268
269 return IsRelocatable && Value.isAbsolute() && Value.getSpecifier() == 0;
270}
271
272
276 int64_t &Addend) {
277 if ( ||
)
278 return;
279
281 if (SA.isUndefined() || SB.isUndefined())
282 return;
283 if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(SA, SB, InSet))
284 return;
285
286 auto FinalizeFolding = [&]() {
287
288
289 if (Asm->isThumbFunc(&SA))
290 Addend |= 1;
291
292
293
295 };
296
298 const MCFragment *FB = SB.getFragment();
301 if (&SecA != &SecB)
302 return;
303
304
305
306
307
308
309
310 bool Layout = Asm->hasLayout();
312
313
314 if (FA == FB && !SA.isVariable() && !SB.isVariable()) {
315 Addend += SA.getOffset() - SB.getOffset();
316 return FinalizeFolding();
317 }
318
319
320 Addend += Asm->getSymbolOffset(SA) - Asm->getSymbolOffset(SB);
321 FinalizeFolding();
322 } else {
323
324
325
326
327
328
329
330 if (SA.isVariable() || SB.isVariable())
331 return;
332
333
334
336 if (FA == FB)
338 else
340
342 int64_t Displacement = SA.getOffset() - SB.getOffset();
346 Displacement *= -1;
347 }
348
349
350
351
352
353 bool BBeforeRelax = false, AAfterRelax = false;
354 for (auto F = FB; F; F = F->getNext()) {
355 if (F && F->isLinkerRelaxable()) {
356 if (&*F != FB || SBOffset != F->getSize())
357 BBeforeRelax = true;
358 if (&*F != FA || SAOffset == F->getSize())
359 AAfterRelax = true;
360 if (BBeforeRelax && AAfterRelax)
361 return;
362 }
363 if (&*F == FA) {
364
365
366 Addend += Reverse ? -Displacement : Displacement;
367 FinalizeFolding();
368 return;
369 }
370
371 int64_t Num;
373 Displacement += F->getFixedSize();
376 Asm->hasFinalLayout()) {
377
378
379
380 Displacement += F->getSize();
382 FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
383 Displacement += Num * FF->getValueSize();
384 } else {
385 return;
386 }
387 }
388 }
389}
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
410 const MCSymbol *LHS_A = LHS.getAddSym();
411 const MCSymbol *LHS_B = LHS.getSubSym();
412 int64_t LHS_Cst = LHS.getConstant();
413
414 const MCSymbol *RHS_A = RHS.getAddSym();
415 const MCSymbol *RHS_B = RHS.getSubSym();
416 int64_t RHS_Cst = RHS.getConstant();
417
418
419 int64_t Result_Cst = LHS_Cst + RHS_Cst;
420
421
422 if (Asm && !LHS.getSpecifier() && !RHS.getSpecifier()) {
423
424
425
426
427 if (LHS_A && RHS_B) {
429 }
430 if (RHS_A && LHS_B) {
432 }
433 }
434
435
436 if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
437 return false;
438
439
440
441 auto *A = LHS_A ? LHS_A : RHS_A;
442 auto *B = LHS_B ? LHS_B : RHS_B;
443 auto Spec = LHS.getSpecifier();
445 Spec = RHS.getSpecifier();
447 return true;
448}
449
456
458 bool InSet) const {
459 ++stats::MCExprEvaluate;
462 return cast(this)->evaluateAsRelocatableImpl(Res, Asm);
465 return true;
466
470 const auto Kind = SRE->getKind();
471 bool Layout = Asm && Asm->hasLayout();
472
473
474
475
476
478 if (Asm && Asm->hasFinalLayout()) {
479 Asm->getContext().reportError(
481 "cyclic dependency detected for symbol '" + Sym.getName() + "'");
483 }
484 return false;
485 }
489 bool IsMachO =
490 Asm && Asm->getContext().getAsmInfo()->hasSubsectionsViaSymbols();
492 InSet || IsMachO))
493 return false;
494
495
496
499 if (InSet || !(A && && A->isInSection())) {
500 if (Kind) {
503 return true;
504 }
505
506
507
510 return false;
511 Res.Specifier = Kind;
512 }
513 if (!IsMachO)
514 return true;
515
516
517
518
519
520
521
522
523 if ( &&
)
524 return true;
525
527 return true;
528 }
529 }
530
532 return true;
533 }
534
538
540 return false;
543 if (.isAbsolute())
544 return false;
546 break;
548
549 if (Value.getAddSym() && .getSubSym())
550 return false;
551
552
555 break;
557 if (.isAbsolute())
558 return false;
560 break;
563 break;
564 }
565
566 return true;
567 }
568
571 MCValue LHSValue, RHSValue;
572
575
580 Res = MCValue::get(L->isEqualTo(R) ? -1 : 0);
581 return true;
583 Res = MCValue::get(L->isEqualTo(R) ? 0 : -1);
584 return true;
585 default:
586 break;
587 }
588 }
589 }
590 return false;
591 }
592
593
594
598 switch (Op) {
599 default:
600 return false;
604 std::swap(RHSValue.SymA, RHSValue.SymB);
605 RHSValue.Cst = -(uint64_t)RHSValue.Cst;
606 }
608 LHSValue.Cst += RHSValue.Cst;
609 Res = LHSValue;
610 return true;
611 }
613 RHSValue.Cst += LHSValue.Cst;
614 Res = RHSValue;
615 return true;
616 }
617 if (LHSValue.SymB && LHSValue.Specifier)
618 return false;
619 if (RHSValue.SymB && RHSValue.Specifier)
620 return false;
622 }
623 }
624
625
626
627
628 int64_t Result = 0;
629 switch (Op) {
635
636
637
638
639
640
641 if (RHS == 0)
642 return false;
644 Result = LHS / RHS;
645 else
646 Result = LHS % RHS;
647 break;
663 }
664
665 switch (Op) {
666 default:
668 break;
675
677 break;
678 }
679
680 return true;
681 }
683
684
685 return Asm && Asm->getContext().getAsmInfo()->evaluateAsRelocatableImpl(
687 }
688
690}
691
695
697
700
702 auto &Sym =
711 return F;
712 }
713
715 return cast(this)->getSubExpr()->findAssociatedFragment();
716
721
722
724 return RHS_F;
726 return LHS_F;
727
728
731
732
733 return LHS_F ? LHS_F : RHS_F;
734 }
735
738 }
739
741}
742
747
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, bool InSet, const MCSymbol *&A, const MCSymbol *&B, int64_t &Addend)
Helper method for.
Definition MCExpr.cpp:273
static int getPrecedence(MCBinaryExpr::Opcode Op)
Definition MCExpr.cpp:41
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This class is intended to be used as a base class for asm properties and features specific to the tar...
virtual void printSpecifierExpr(raw_ostream &, const MCSpecifierExpr &) const
StringRef getSpecifierName(uint32_t S) const
bool useParensForSpecifier() const
Binary assembler expressions.
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Opcode getOpcode() const
Get the kind of this binary expression.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:201
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const
Try to evaluate the expression to the form (a - b + constant) where neither a nor b are variables.
Definition MCExpr.cpp:453
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
Definition MCExpr.cpp:450
MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData=0)
@ Unary
Unary expressions.
@ Constant
Constant expressions.
@ SymbolRef
References to labels and assigned expressions.
@ Target
Target specific expression.
@ Specifier
Expression with a relocation specifier.
@ Binary
Binary expressions.
static LLVM_ABI bool evaluateSymbolicAdd(const MCAssembler *, bool, const MCValue &, const MCValue &, MCValue &)
Definition MCExpr.cpp:407
LLVM_ABI bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const
Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.
Definition MCExpr.cpp:250
LLVM_ABI MCFragment * findAssociatedFragment() const
Find the "associated section" for this expression, which is currently defined as the absolute section...
Definition MCExpr.cpp:692
LLVM_ABI bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, bool InSet) const
Definition MCExpr.cpp:457
LLVM_ABI void dump() const
Definition MCExpr.cpp:193
unsigned getLayoutOrder() const
MCSection * getParent() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
bool isLinkerRelaxable() const
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
MCSpecifierExpr(const MCExpr *Expr, Spec S, SMLoc Loc=SMLoc())
Represent a reference to a symbol from inside an expression.
const MCSymbol & getSymbol() const
VariantKind getKind() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
void setIsResolving(bool V)
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
StringRef getName() const
getName - Get the symbol name.
bool isWeakExternal() const
bool isVariable() const
isVariable - Check if this is a variable symbol.
LLVM_ABI void setVariableValue(const MCExpr *Value)
MCFragment * Fragment
If a symbol has a Fragment, the section is implied, so we only need one pointer.
static LLVM_ABI MCFragment * AbsolutePseudoFragment
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
MCFragment * getFragment() const
uint64_t getOffset() const
Extension point for target-specific MCExpr subclasses to implement.
Unary assembler expressions.
Opcode getOpcode() const
Get the kind of this unary expression.
static LLVM_ABI const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:207
const MCExpr * getSubExpr() const
Get the child of this unary expression.
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
const MCSymbol * getAddSym() const
int64_t getConstant() const
uint32_t getSpecifier() const
const MCSymbol * getSubSym() const
bool isAbsolute() const
Is this an absolute (as opposed to relocatable) value.
Represents a location in source code.
static Twine utohexstr(uint64_t Val)
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.