mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-26 23:24:34 +00:00
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). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233187 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -61,8 +61,7 @@ protected:
|
|||||||
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
||||||
const MCAsmLayout *Layout,
|
const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup,
|
const MCFixup *Fixup,
|
||||||
const SectionAddrMap *Addrs, bool InSet,
|
const SectionAddrMap *Addrs, bool InSet) const;
|
||||||
bool ForceVarExpansion) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @name Accessors
|
/// @name Accessors
|
||||||
@ -106,15 +105,6 @@ public:
|
|||||||
bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
|
bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup) const;
|
const MCFixup *Fixup) 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 MCFixup *Fixup) const;
|
|
||||||
|
|
||||||
/// FindAssociatedSection - Find the "associated section" for this expression,
|
/// FindAssociatedSection - Find the "associated section" for this expression,
|
||||||
/// which is currently defined as the absolute section for constants, or
|
/// which is currently defined as the absolute section for constants, or
|
||||||
/// otherwise the section associated with the first defined symbol in the
|
/// otherwise the section associated with the first defined symbol in the
|
||||||
|
@ -99,6 +99,11 @@ public:
|
|||||||
bool InSet,
|
bool InSet,
|
||||||
bool IsPCRel) const;
|
bool IsPCRel) const;
|
||||||
|
|
||||||
|
/// \brief True if this symbol (which is a variable) is weak. This is not
|
||||||
|
/// just STB_WEAK, but more generally whether or not we can evaluate
|
||||||
|
/// past it.
|
||||||
|
virtual bool isWeak(const MCSymbolData &SD) const;
|
||||||
|
|
||||||
/// \brief Write the object file.
|
/// \brief Write the object file.
|
||||||
///
|
///
|
||||||
/// This routine is called by the assembler after layout and relaxation is
|
/// This routine is called by the assembler after layout and relaxation is
|
||||||
|
@ -312,6 +312,8 @@ class ELFObjectWriter : public MCObjectWriter {
|
|||||||
bool InSet,
|
bool InSet,
|
||||||
bool IsPCRel) const override;
|
bool IsPCRel) const override;
|
||||||
|
|
||||||
|
bool isWeak(const MCSymbolData &SD) const override;
|
||||||
|
|
||||||
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||||
void writeSection(MCAssembler &Asm,
|
void writeSection(MCAssembler &Asm,
|
||||||
const SectionIndexMapTy &SectionIndexMap,
|
const SectionIndexMapTy &SectionIndexMap,
|
||||||
@ -847,7 +849,7 @@ void ELFObjectWriter::RecordRelocation(MCAssembler &Asm,
|
|||||||
Fixup.getLoc(), "Cannot represent a difference across sections");
|
Fixup.getLoc(), "Cannot represent a difference across sections");
|
||||||
|
|
||||||
const MCSymbolData &SymBD = Asm.getSymbolData(SymB);
|
const MCSymbolData &SymBD = Asm.getSymbolData(SymB);
|
||||||
if (isWeak(SymBD))
|
if (::isWeak(SymBD))
|
||||||
Asm.getContext().FatalError(
|
Asm.getContext().FatalError(
|
||||||
Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol");
|
Fixup.getLoc(), "Cannot represent a subtraction with a weak symbol");
|
||||||
|
|
||||||
@ -1817,12 +1819,16 @@ ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
|||||||
const MCFragment &FB,
|
const MCFragment &FB,
|
||||||
bool InSet,
|
bool InSet,
|
||||||
bool IsPCRel) const {
|
bool IsPCRel) const {
|
||||||
if (isWeak(DataA))
|
if (::isWeak(DataA))
|
||||||
return false;
|
return false;
|
||||||
return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
|
return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
|
||||||
Asm, DataA, FB,InSet, IsPCRel);
|
Asm, DataA, FB,InSet, IsPCRel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const {
|
||||||
|
return ::isWeak(SD);
|
||||||
|
}
|
||||||
|
|
||||||
MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
|
MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
|
||||||
raw_ostream &OS,
|
raw_ostream &OS,
|
||||||
bool IsLittleEndian) {
|
bool IsLittleEndian) {
|
||||||
|
@ -142,7 +142,7 @@ static bool getSymbolOffsetImpl(const MCAsmLayout &Layout,
|
|||||||
|
|
||||||
// If SD is a variable, evaluate it.
|
// If SD is a variable, evaluate it.
|
||||||
MCValue Target;
|
MCValue Target;
|
||||||
if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout, nullptr))
|
if (!S.getVariableValue()->EvaluateAsRelocatable(Target, &Layout, nullptr))
|
||||||
report_fatal_error("unable to evaluate offset for variable '" +
|
report_fatal_error("unable to evaluate offset for variable '" +
|
||||||
S.getName() + "'");
|
S.getName() + "'");
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const {
|
|||||||
|
|
||||||
const MCExpr *Expr = Symbol.getVariableValue();
|
const MCExpr *Expr = Symbol.getVariableValue();
|
||||||
MCValue Value;
|
MCValue Value;
|
||||||
if (!Expr->EvaluateAsValue(Value, this, nullptr))
|
if (!Expr->EvaluateAsRelocatable(Value, this, nullptr))
|
||||||
llvm_unreachable("Invalid Expression");
|
llvm_unreachable("Invalid Expression");
|
||||||
|
|
||||||
const MCSymbolRefExpr *RefB = Value.getSymB();
|
const MCSymbolRefExpr *RefB = Value.getSymB();
|
||||||
@ -473,18 +473,6 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const {
|
|||||||
return SD->getFragment()->getAtom();
|
return SD->getFragment()->getAtom();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to fully compute Expr to an absolute value and if that fails produce
|
|
||||||
// a relocatable expr.
|
|
||||||
// FIXME: Should this be the behavior of EvaluateAsRelocatable itself?
|
|
||||||
static bool evaluate(const MCExpr &Expr, const MCAsmLayout &Layout,
|
|
||||||
const MCFixup &Fixup, MCValue &Target) {
|
|
||||||
if (Expr.EvaluateAsValue(Target, &Layout, &Fixup)) {
|
|
||||||
if (Target.isAbsolute())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return Expr.EvaluateAsRelocatable(Target, &Layout, &Fixup);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
|
bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
|
||||||
const MCFixup &Fixup, const MCFragment *DF,
|
const MCFixup &Fixup, const MCFragment *DF,
|
||||||
MCValue &Target, uint64_t &Value) const {
|
MCValue &Target, uint64_t &Value) const {
|
||||||
@ -494,7 +482,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
|
|||||||
// probably merge the two into a single callback that tries to evaluate a
|
// probably merge the two into a single callback that tries to evaluate a
|
||||||
// fixup and records a relocation if one is needed.
|
// fixup and records a relocation if one is needed.
|
||||||
const MCExpr *Expr = Fixup.getValue();
|
const MCExpr *Expr = Fixup.getValue();
|
||||||
if (!evaluate(*Expr, Layout, Fixup, Target))
|
if (!Expr->EvaluateAsRelocatable(Target, &Layout, &Fixup))
|
||||||
getContext().FatalError(Fixup.getLoc(), "expected relocatable expression");
|
getContext().FatalError(Fixup.getLoc(), "expected relocatable expression");
|
||||||
|
|
||||||
bool IsPCRel = Backend.getFixupKindInfo(
|
bool IsPCRel = Backend.getFixupKindInfo(
|
||||||
|
@ -432,8 +432,8 @@ bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsRelocatable = EvaluateAsRelocatableImpl(
|
bool IsRelocatable =
|
||||||
Value, Asm, Layout, nullptr, Addrs, InSet, /*ForceVarExpansion*/ true);
|
EvaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet);
|
||||||
|
|
||||||
// Record the current value.
|
// Record the current value.
|
||||||
Res = Value.getConstant();
|
Res = Value.getConstant();
|
||||||
@ -586,21 +586,21 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
|
|||||||
const MCFixup *Fixup) const {
|
const MCFixup *Fixup) const {
|
||||||
MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
|
MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
|
||||||
return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
|
return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
|
||||||
false, /*ForceVarExpansion*/ false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout,
|
static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm) {
|
||||||
const MCFixup *Fixup) const {
|
if (!Asm)
|
||||||
MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr;
|
return false;
|
||||||
return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr,
|
const MCSymbolData &SD = Asm->getSymbolData(Sym);
|
||||||
false, /*ForceVarExpansion*/ true);
|
return !Asm->getWriter().isWeak(SD);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
||||||
const MCAsmLayout *Layout,
|
const MCAsmLayout *Layout,
|
||||||
const MCFixup *Fixup,
|
const MCFixup *Fixup,
|
||||||
const SectionAddrMap *Addrs, bool InSet,
|
const SectionAddrMap *Addrs,
|
||||||
bool ForceVarExpansion) const {
|
bool InSet) const {
|
||||||
++stats::MCExprEvaluate;
|
++stats::MCExprEvaluate;
|
||||||
|
|
||||||
switch (getKind()) {
|
switch (getKind()) {
|
||||||
@ -617,13 +617,15 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
|||||||
const MCSymbol &Sym = SRE->getSymbol();
|
const MCSymbol &Sym = SRE->getSymbol();
|
||||||
|
|
||||||
// Evaluate recursively if this is a variable.
|
// Evaluate recursively if this is a variable.
|
||||||
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
|
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None &&
|
||||||
|
canExpand(Sym, Asm)) {
|
||||||
if (Sym.getVariableValue()->EvaluateAsRelocatableImpl(
|
if (Sym.getVariableValue()->EvaluateAsRelocatableImpl(
|
||||||
Res, Asm, Layout, Fixup, Addrs, true, ForceVarExpansion)) {
|
Res, Asm, Layout, Fixup, Addrs, true)) {
|
||||||
|
if (!SRE->hasSubsectionsViaSymbols())
|
||||||
|
return true;
|
||||||
|
|
||||||
const MCSymbolRefExpr *A = Res.getSymA();
|
const MCSymbolRefExpr *A = Res.getSymA();
|
||||||
const MCSymbolRefExpr *B = Res.getSymB();
|
const MCSymbolRefExpr *B = Res.getSymB();
|
||||||
|
|
||||||
if (SRE->hasSubsectionsViaSymbols()) {
|
|
||||||
// FIXME: This is small hack. Given
|
// FIXME: This is small hack. Given
|
||||||
// a = b + 4
|
// a = b + 4
|
||||||
// .long a
|
// .long a
|
||||||
@ -632,13 +634,6 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
|||||||
// possible.
|
// possible.
|
||||||
if (!A && !B)
|
if (!A && !B)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
if (ForceVarExpansion)
|
|
||||||
return true;
|
|
||||||
bool IsSymbol = A && A->getSymbol().isDefined();
|
|
||||||
if (!IsSymbol)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,9 +645,8 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
|||||||
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
|
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
|
||||||
MCValue Value;
|
MCValue Value;
|
||||||
|
|
||||||
if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
|
if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, Fixup,
|
||||||
Fixup, Addrs, InSet,
|
Addrs, InSet))
|
||||||
ForceVarExpansion))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (AUE->getOpcode()) {
|
switch (AUE->getOpcode()) {
|
||||||
@ -685,12 +679,10 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
|
|||||||
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
|
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
|
||||||
MCValue LHSValue, RHSValue;
|
MCValue LHSValue, RHSValue;
|
||||||
|
|
||||||
if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
|
if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup,
|
||||||
Fixup, Addrs, InSet,
|
Addrs, InSet) ||
|
||||||
ForceVarExpansion) ||
|
!ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup,
|
||||||
!ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
|
Addrs, InSet))
|
||||||
Fixup, Addrs, InSet,
|
|
||||||
ForceVarExpansion))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We only support a few operations on non-constant expressions, handle
|
// We only support a few operations on non-constant expressions, handle
|
||||||
|
@ -54,3 +54,5 @@ MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
|||||||
// On ELF and COFF A - B is absolute if A and B are in the same section.
|
// On ELF and COFF A - B is absolute if A and B are in the same section.
|
||||||
return &SecA == &SecB;
|
return &SecA == &SecB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MCObjectWriter::isWeak(const MCSymbolData &SD) const { return false; }
|
||||||
|
12
test/MC/X86/expand-var.s
Normal file
12
test/MC/X86/expand-var.s
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux < %s | llvm-readobj -r | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: Section (2) .rela.text {
|
||||||
|
// CHECK-NEXT: 0x0 R_X86_64_32 d 0x0
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
|
a:
|
||||||
|
b = a
|
||||||
|
c = a
|
||||||
|
d = a
|
||||||
|
.weak d
|
||||||
|
.long d + (b - c)
|
Reference in New Issue
Block a user