Skip to content

Commit f275ad8

Browse files
committed
Fix fixup evaluation when deciding what to relocate with.
The previous logic was to first try without relocations at all and failing that stop on the first defined symbol. That was inefficient and incorrect in the case part of the expression could be simplified and another part could not (see included test). We now stop the evaluation when we get to a variable whose value can change (i.e. is weak). llvm-svn: 233187
1 parent 235838e commit f275ad8

File tree

7 files changed

+61
-66
lines changed

7 files changed

+61
-66
lines changed

llvm/include/llvm/MC/MCExpr.h

+1-11
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ class MCExpr {
6161
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
6262
const MCAsmLayout *Layout,
6363
const MCFixup *Fixup,
64-
const SectionAddrMap *Addrs, bool InSet,
65-
bool ForceVarExpansion) const;
64+
const SectionAddrMap *Addrs, bool InSet) const;
6665

6766
public:
6867
/// @name Accessors
@@ -106,15 +105,6 @@ class MCExpr {
106105
bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
107106
const MCFixup *Fixup) const;
108107

109-
/// \brief Try to evaluate the expression to the form (a - b + constant) where
110-
/// neither a nor b are variables.
111-
///
112-
/// This is a more aggressive variant of EvaluateAsRelocatable. The intended
113-
/// use is for when relocations are not available, like the symbol value in
114-
/// the symbol table.
115-
bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout,
116-
const MCFixup *Fixup) const;
117-
118108
/// FindAssociatedSection - Find the "associated section" for this expression,
119109
/// which is currently defined as the absolute section for constants, or
120110
/// otherwise the section associated with the first defined symbol in the

llvm/include/llvm/MC/MCObjectWriter.h

+5
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ class MCObjectWriter {
9999
bool InSet,
100100
bool IsPCRel) const;
101101

102+
/// \brief True if this symbol (which is a variable) is weak. This is not
103+
/// just STB_WEAK, but more generally whether or not we can evaluate
104+
/// past it.
105+
virtual bool isWeak(const MCSymbolData &SD) const;
106+
102107
/// \brief Write the object file.
103108
///
104109
/// This routine is called by the assembler after layout and relaxation is

llvm/lib/MC/ELFObjectWriter.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ class ELFObjectWriter : public MCObjectWriter {
312312
bool InSet,
313313
bool IsPCRel) const override;
314314

315+
bool isWeak(const MCSymbolData &SD) const override;
316+
315317
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
316318
void writeSection(MCAssembler &Asm,
317319
const SectionIndexMapTy &SectionIndexMap,
@@ -847,7 +849,7 @@ void ELFObjectWriter::RecordRelocation(MCAssembler &Asm,
847849
Fixup.getLoc(), "Cannot represent a difference across sections");
848850

849851
const MCSymbolData &SymBD = Asm.getSymbolData(SymB);
850-
if (isWeak(SymBD))
852+
if (::isWeak(SymBD))
851853
Asm.getContext().FatalError(
852854
Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol");
853855

@@ -1817,12 +1819,16 @@ ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
18171819
const MCFragment &FB,
18181820
bool InSet,
18191821
bool IsPCRel) const {
1820-
if (isWeak(DataA))
1822+
if (::isWeak(DataA))
18211823
return false;
18221824
return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
18231825
Asm, DataA, FB,InSet, IsPCRel);
18241826
}
18251827

1828+
bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const {
1829+
return ::isWeak(SD);
1830+
}
1831+
18261832
MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
18271833
raw_ostream &OS,
18281834
bool IsLittleEndian) {

llvm/lib/MC/MCAssembler.cpp

+3-15
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static bool getSymbolOffsetImpl(const MCAsmLayout &Layout,
142142

143143
// If SD is a variable, evaluate it.
144144
MCValue Target;
145-
if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout, nullptr))
145+
if (!S.getVariableValue()->EvaluateAsRelocatable(Target, &Layout, nullptr))
146146
report_fatal_error("unable to evaluate offset for variable '" +
147147
S.getName() + "'");
148148

@@ -188,7 +188,7 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const {
188188

189189
const MCExpr *Expr = Symbol.getVariableValue();
190190
MCValue Value;
191-
if (!Expr->EvaluateAsValue(Value, this, nullptr))
191+
if (!Expr->EvaluateAsRelocatable(Value, this, nullptr))
192192
llvm_unreachable("Invalid Expression");
193193

194194
const MCSymbolRefExpr *RefB = Value.getSymB();
@@ -473,18 +473,6 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const {
473473
return SD->getFragment()->getAtom();
474474
}
475475

476-
// Try to fully compute Expr to an absolute value and if that fails produce
477-
// a relocatable expr.
478-
// FIXME: Should this be the behavior of EvaluateAsRelocatable itself?
479-
static bool evaluate(const MCExpr &Expr, const MCAsmLayout &Layout,
480-
const MCFixup &Fixup, MCValue &Target) {
481-
if (Expr.EvaluateAsValue(Target, &Layout, &Fixup)) {
482-
if (Target.isAbsolute())
483-
return true;
484-
}
485-
return Expr.EvaluateAsRelocatable(Target, &Layout, &Fixup);
486-
}
487-
488476
bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
489477
const MCFixup &Fixup, const MCFragment *DF,
490478
MCValue &Target, uint64_t &Value) const {
@@ -494,7 +482,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
494482
// probably merge the two into a single callback that tries to evaluate a
495483
// fixup and records a relocation if one is needed.
496484
const MCExpr *Expr = Fixup.getValue();
497-
if (!evaluate(*Expr, Layout, Fixup, Target))
485+
if (!Expr->EvaluateAsRelocatable(Target, &Layout, &Fixup))
498486
getContext().FatalError(Fixup.getLoc(), "expected relocatable expression");
499487

500488
bool IsPCRel = Backend.getFixupKindInfo(

llvm/lib/MC/MCExpr.cpp

+30-38
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,8 @@ bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
432432
return true;
433433
}
434434

435-
bool IsRelocatable = EvaluateAsRelocatableImpl(
436-
Value, Asm, Layout, nullptr, Addrs, InSet, /*ForceVarExpansion*/ true);
435+
bool IsRelocatable =
436+
EvaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet);
437437

438438
// Record the current value.
439439
Res = Value.getConstant();
@@ -586,21 +586,21 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
586586
const MCFixup *Fixup) const {
587587
MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
588588
return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
589-
false, /*ForceVarExpansion*/ false);
589+
false);
590590
}
591591

592-
bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout,
593-
const MCFixup *Fixup) const {
594-
MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
595-
return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
596-
false, /*ForceVarExpansion*/ true);
592+
static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm) {
593+
if (!Asm)
594+
return false;
595+
const MCSymbolData &SD = Asm->getSymbolData(Sym);
596+
return !Asm->getWriter().isWeak(SD);
597597
}
598598

599599
bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
600600
const MCAsmLayout *Layout,
601601
const MCFixup *Fixup,
602-
const SectionAddrMap *Addrs, bool InSet,
603-
bool ForceVarExpansion) const {
602+
const SectionAddrMap *Addrs,
603+
bool InSet) const {
604604
++stats::MCExprEvaluate;
605605

606606
switch (getKind()) {
@@ -617,28 +617,23 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
617617
const MCSymbol &Sym = SRE->getSymbol();
618618

619619
// Evaluate recursively if this is a variable.
620-
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
620+
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
621+
canExpand(Sym, Asm)) {
621622
if (Sym.getVariableValue()->EvaluateAsRelocatableImpl(
622-
Res, Asm, Layout, Fixup, Addrs, true, ForceVarExpansion)) {
623+
Res, Asm, Layout, Fixup, Addrs, true)) {
624+
if (!SRE->hasSubsectionsViaSymbols())
625+
return true;
626+
623627
const MCSymbolRefExpr *A = Res.getSymA();
624628
const MCSymbolRefExpr *B = Res.getSymB();
625-
626-
if (SRE->hasSubsectionsViaSymbols()) {
627-
// FIXME: This is small hack. Given
628-
// a = b + 4
629-
// .long a
630-
// the OS X assembler will completely drop the 4. We should probably
631-
// include it in the relocation or produce an error if that is not
632-
// possible.
633-
if (!A && !B)
634-
return true;
635-
} else {
636-
if (ForceVarExpansion)
637-
return true;
638-
bool IsSymbol = A && A->getSymbol().isDefined();
639-
if (!IsSymbol)
640-
return true;
641-
}
629+
// FIXME: This is small hack. Given
630+
// a = b + 4
631+
// .long a
632+
// the OS X assembler will completely drop the 4. We should probably
633+
// include it in the relocation or produce an error if that is not
634+
// possible.
635+
if (!A && !B)
636+
return true;
642637
}
643638
}
644639

@@ -650,9 +645,8 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
650645
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
651646
MCValue Value;
652647

653-
if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
654-
Fixup, Addrs, InSet,
655-
ForceVarExpansion))
648+
if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, Fixup,
649+
Addrs, InSet))
656650
return false;
657651

658652
switch (AUE->getOpcode()) {
@@ -685,12 +679,10 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
685679
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
686680
MCValue LHSValue, RHSValue;
687681

688-
if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
689-
Fixup, Addrs, InSet,
690-
ForceVarExpansion) ||
691-
!ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
692-
Fixup, Addrs, InSet,
693-
ForceVarExpansion))
682+
if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup,
683+
Addrs, InSet) ||
684+
!ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup,
685+
Addrs, InSet))
694686
return false;
695687

696688
// We only support a few operations on non-constant expressions, handle

llvm/lib/MC/MCObjectWriter.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,5 @@ MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
5454
// On ELF and COFF A - B is absolute if A and B are in the same section.
5555
return &SecA == &SecB;
5656
}
57+
58+
bool MCObjectWriter::isWeak(const MCSymbolData &SD) const { return false; }

llvm/test/MC/X86/expand-var.s

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux < %s | llvm-readobj -r | FileCheck %s
2+
3+
// CHECK: Section (2) .rela.text {
4+
// CHECK-NEXT: 0x0 R_X86_64_32 d 0x0
5+
// CHECK-NEXT: }
6+
7+
a:
8+
b = a
9+
c = a
10+
d = a
11+
.weak d
12+
.long d + (b - c)

0 commit comments

Comments
 (0)