summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCExpr.h13
-rw-r--r--lib/MC/ELFObjectWriter.cpp4
-rw-r--r--lib/MC/MCExpr.cpp43
-rw-r--r--test/MC/ELF/offset.s59
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: }