diff options
-rw-r--r-- | include/llvm/MC/MCExpr.h | 13 | ||||
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCExpr.cpp | 43 | ||||
-rw-r--r-- | test/MC/ELF/offset.s | 59 |
4 files changed, 98 insertions, 21 deletions
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 0033a54e42..f28adfa865 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -53,8 +53,9 @@ protected: bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, - const SectionAddrMap *Addrs, - bool InSet) const; + const SectionAddrMap *Addrs, bool InSet, + bool ForceVarExpansion) const; + public: /// @name Accessors /// @{ @@ -93,6 +94,14 @@ public: /// @result - True on success. bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout) const; + /// \brief Try to evaluate the expression to the form (a - b + constant) where + /// neither a nor b are variables. + /// + /// This is a more aggressive variant of EvaluateAsRelocatable. The intended + /// use is for when relocations are not available, like the symbol value in + /// the symbol table. + bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const; + /// FindAssociatedSection - Find the "associated section" for this expression, /// which is currently defined as the absolute section for constants, or /// otherwise the section associated with the first defined symbol in the diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 68e28cf4d4..1b7ac64258 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -496,7 +496,7 @@ uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData, if (Symbol->isVariable()) { const MCExpr *Expr = Symbol->getVariableValue(); MCValue Value; - if (!Expr->EvaluateAsRelocatable(Value, &Layout)) + if (!Expr->EvaluateAsValue(Value, &Layout)) llvm_unreachable("Invalid expression"); assert(!Value.getSymB()); @@ -606,7 +606,7 @@ static const MCSymbol *getBaseSymbol(const MCAsmLayout &Layout, const MCExpr *Expr = Symbol.getVariableValue(); MCValue Value; - if (!Expr->EvaluateAsRelocatable(Value, &Layout)) + if (!Expr->EvaluateAsValue(Value, &Layout)) llvm_unreachable("Invalid Expression"); const MCSymbolRefExpr *RefB = Value.getSymB(); if (RefB) { diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 300613530a..5a45c65266 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -478,7 +478,8 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, // absolutize differences across sections and that is what the MachO writer // uses Addrs for. bool IsRelocatable = - EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs); + EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs, + /*ForceVarExpansion*/ false); // Record the current value. Res = Value.getConstant(); @@ -629,14 +630,20 @@ static bool EvaluateSymbolicAdd(const MCAssembler *Asm, bool MCExpr::EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout) const { MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; - return EvaluateAsRelocatableImpl(Res, Assembler, Layout, nullptr, false); + return EvaluateAsRelocatableImpl(Res, Assembler, Layout, nullptr, false, + /*ForceVarExpansion*/ false); } -bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, - const MCAssembler *Asm, +bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const { + MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; + return EvaluateAsRelocatableImpl(Res, Assembler, Layout, nullptr, false, + /*ForceVarExpansion*/ true); +} + +bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, - const SectionAddrMap *Addrs, - bool InSet) const { + const SectionAddrMap *Addrs, bool InSet, + bool ForceVarExpansion) const { ++stats::MCExprEvaluate; switch (getKind()) { @@ -649,13 +656,14 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, case SymbolRef: { const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); + bool IsWeakRef = SRE->getKind() == MCSymbolRefExpr::VK_WEAKREF; const MCSymbol &Sym = SRE->getSymbol(); const MCAsmInfo &MCAsmInfo = SRE->getMCAsmInfo(); // Evaluate recursively if this is a variable. - if (Sym.isVariable()) { - if (Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, Layout, - Addrs, true)) { + if (Sym.isVariable() && !IsWeakRef) { + if (Sym.getVariableValue()->EvaluateAsRelocatableImpl( + Res, Asm, Layout, Addrs, true, ForceVarExpansion)) { const MCSymbolRefExpr *A = Res.getSymA(); const MCSymbolRefExpr *B = Res.getSymB(); @@ -669,9 +677,10 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, if (!A && !B) return true; } else { + if (ForceVarExpansion) + return true; bool IsSymbol = A && A->getSymbol().isDefined(); - bool IsWeakRef = SRE->getKind() == MCSymbolRefExpr::VK_WEAKREF; - if (!IsSymbol && !IsWeakRef) + if (!IsSymbol) return true; } } @@ -685,8 +694,8 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); MCValue Value; - if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, - Addrs, InSet)) + if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, + InSet, ForceVarExpansion)) return false; switch (AUE->getOpcode()) { @@ -719,10 +728,10 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); MCValue LHSValue, RHSValue; - if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, - Addrs, InSet) || - !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, - Addrs, InSet)) + if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, Addrs, + InSet, ForceVarExpansion) || + !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, Addrs, + InSet, ForceVarExpansion)) return false; // We only support a few operations on non-constant expressions, handle diff --git a/test/MC/ELF/offset.s b/test/MC/ELF/offset.s index a412619143..f448332994 100644 --- a/test/MC/ELF/offset.s +++ b/test/MC/ELF/offset.s @@ -71,3 +71,62 @@ sym_f = sym_a + (1 - 1) // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: .data // CHECK-NEXT: } + + + .globl test2_a + .globl test2_b + .globl test2_c + .globl test2_d + .globl test2_e +test2_a: + .long 0 +test2_b = test2_a +test2_c: + .long 0 +test2_d = test2_c +test2_e = test2_d - test2_b +// CHECK: Symbol { +// CHECK: Name: test2_a +// CHECK-NEXT: Value: 0x5 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .data +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: test2_b +// CHECK-NEXT: Value: 0x5 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .data +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: test2_c +// CHECK-NEXT: Value: 0x9 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .data +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: test2_d +// CHECK-NEXT: Value: 0x9 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .data +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: test2_e +// CHECK-NEXT: Value: 0x4 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Absolute +// CHECK-NEXT: } |