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
/// @{
/// @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
// 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();
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()) {
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();
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;
}
}
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()) {
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
// 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: }