Merge IsFixupFullyResolved and IsSymbolRefDifferenceFullyResolved. We now

have a single point where targets test if a relocation is needed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122549 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2010-12-24 21:22:02 +00:00
parent a112087e42
commit fea753b397
6 changed files with 108 additions and 223 deletions

View File

@ -21,6 +21,7 @@ class MCAssembler;
class MCFixup; class MCFixup;
class MCFragment; class MCFragment;
class MCSymbol; class MCSymbol;
class MCSymbolData;
class MCSymbolRefExpr; class MCSymbolRefExpr;
class MCValue; class MCValue;
class raw_ostream; class raw_ostream;
@ -84,21 +85,19 @@ public:
/// ///
/// Clients are not required to answer precisely and may conservatively return /// Clients are not required to answer precisely and may conservatively return
/// false, even when a difference is fully resolved. /// false, even when a difference is fully resolved.
virtual bool bool
IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
const MCSymbolRefExpr *A, const MCSymbolRefExpr *A,
const MCSymbolRefExpr *B, const MCSymbolRefExpr *B,
bool InSet) const; bool InSet) const;
/// Check if a fixup is fully resolved. virtual bool
/// IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
/// This routine is used by the assembler to let the file format decide const MCSymbolData &DataA,
/// if a fixup is not fully resolved. For example, one that crosses const MCFragment &FB,
/// two sections on ELF. bool InSet,
virtual bool IsFixupFullyResolved(const MCAssembler &Asm, bool IsPCRel) const = 0;
const MCValue Target,
bool IsPCRel,
const MCFragment *DF) const = 0;
/// Write the object file. /// Write the object file.
/// ///

View File

@ -344,10 +344,12 @@ namespace {
MCDataFragment *F, MCDataFragment *F,
const MCSectionData *SD); const MCSectionData *SD);
virtual bool IsFixupFullyResolved(const MCAssembler &Asm, virtual bool
const MCValue Target, IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
bool IsPCRel, const MCSymbolData &DataA,
const MCFragment *DF) const; const MCFragment &FB,
bool InSet,
bool IsPCRel) const;
virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
virtual void WriteSection(MCAssembler &Asm, virtual void WriteSection(MCAssembler &Asm,
@ -1154,50 +1156,22 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm,
} }
} }
bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, bool
const MCValue Target, ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
bool IsPCRel, const MCSymbolData &DataA,
const MCFragment *DF) const { const MCFragment &FB,
// If this is a PCrel relocation, find the section this fixup value is bool InSet,
// relative to. bool IsPCRel) const {
const MCSection *BaseSection = 0;
if (IsPCRel) {
BaseSection = &DF->getParent()->getSection();
assert(BaseSection);
}
const MCSection *SectionA = 0;
const MCSymbol *SymbolA = 0;
if (const MCSymbolRefExpr *A = Target.getSymA()) {
SymbolA = &A->getSymbol();
SectionA = &SymbolA->AliasedSymbol().getSection();
}
const MCSection *SectionB = 0;
const MCSymbol *SymbolB = 0;
if (const MCSymbolRefExpr *B = Target.getSymB()) {
SymbolB = &B->getSymbol();
SectionB = &SymbolB->AliasedSymbol().getSection();
}
if (!BaseSection)
return SectionA == SectionB;
if (SymbolB)
return false;
// Absolute address but PCrel instruction, so we need a relocation.
if (!SymbolA)
return false;
// FIXME: This is in here just to match gnu as output. If the two ends // FIXME: This is in here just to match gnu as output. If the two ends
// are in the same section, there is nothing that the linker can do to // are in the same section, there is nothing that the linker can do to
// break it. // break it.
const MCSymbolData &DataA = Asm.getSymbolData(*SymbolA);
if (DataA.isExternal()) if (DataA.isExternal())
return false; return false;
return BaseSection == SectionA; const MCSection &SecA = DataA.getSymbol().AliasedSymbol().getSection();
const MCSection &SecB = FB.getParent()->getSection();
// On ELF A - B is absolute if A and B are in the same section.
return &SecA == &SecB;
} }
void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm, void ELFObjectWriter::CreateGroupSections(MCAssembler &Asm,

View File

@ -11,6 +11,7 @@
#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSection.h"
@ -218,22 +219,37 @@ bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout,
if (!Fixup.getValue()->EvaluateAsRelocatable(Target, Layout)) if (!Fixup.getValue()->EvaluateAsRelocatable(Target, Layout))
report_fatal_error("expected relocatable expression"); report_fatal_error("expected relocatable expression");
// FIXME: How do non-scattered symbols work in ELF? I presume the linker bool IsPCRel = Backend.getFixupKindInfo(
// doesn't support small relocations, but then under what criteria does the Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
// assembler allow symbol differences?
bool IsResolved;
if (IsPCRel) {
if (Target.getSymB()) {
IsResolved = false;
} else if (!Target.getSymA()) {
IsResolved = false;
} else {
const MCSymbol &SA = Target.getSymA()->getSymbol();
if (SA.AliasedSymbol().isUndefined()) {
IsResolved = false;
} else {
const MCSymbolData &DataA = getSymbolData(SA);
IsResolved =
getWriter().IsSymbolRefDifferenceFullyResolvedImpl(*this, DataA,
*DF, false, true);
}
}
} else {
IsResolved = Target.isAbsolute();
}
Value = Target.getConstant(); Value = Target.getConstant();
bool IsPCRel = Backend.getFixupKindInfo(
Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
bool IsResolved = true;
bool IsThumb = false; bool IsThumb = false;
if (const MCSymbolRefExpr *A = Target.getSymA()) { if (const MCSymbolRefExpr *A = Target.getSymA()) {
const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
if (Sym.isDefined()) if (Sym.isDefined())
Value += Layout.getSymbolOffset(&getSymbolData(Sym)); Value += Layout.getSymbolOffset(&getSymbolData(Sym));
else
IsResolved = false;
if (isThumbFunc(&Sym)) if (isThumbFunc(&Sym))
IsThumb = true; IsThumb = true;
} }
@ -241,12 +257,8 @@ bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout,
const MCSymbol &Sym = B->getSymbol().AliasedSymbol(); const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
if (Sym.isDefined()) if (Sym.isDefined())
Value -= Layout.getSymbolOffset(&getSymbolData(Sym)); Value -= Layout.getSymbolOffset(&getSymbolData(Sym));
else
IsResolved = false;
} }
if (IsResolved)
IsResolved = getWriter().IsFixupFullyResolved(*this, Target, IsPCRel, DF);
bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags & bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits; MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;

View File

@ -7,6 +7,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbol.h"
@ -54,9 +55,14 @@ MCObjectWriter::IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
const MCSymbol &SA = A->getSymbol(); const MCSymbol &SA = A->getSymbol();
const MCSymbol &SB = B->getSymbol(); const MCSymbol &SB = B->getSymbol();
if (SA.isUndefined() || SB.isUndefined()) if (SA.AliasedSymbol().isUndefined() || SB.AliasedSymbol().isUndefined())
return false; return false;
// On ELF and COFF A - B is absolute if A and B are in the same section. const MCSymbolData &DataA = Asm.getSymbolData(SA);
return &SA.getSection() == &SB.getSection(); const MCSymbolData &DataB = Asm.getSymbolData(SB);
return IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA,
*DataB.getFragment(),
InSet,
false);
} }

View File

@ -64,86 +64,6 @@ static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) {
return false; return false;
} }
static bool isScatteredFixupFullyResolved(const MCAssembler &Asm,
const MCValue Target,
const MCSymbolData *BaseSymbol) {
// The effective fixup address is
// addr(atom(A)) + offset(A)
// - addr(atom(B)) - offset(B)
// - addr(BaseSymbol) + <fixup offset from base symbol>
// and the offsets are not relocatable, so the fixup is fully resolved when
// addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0.
//
// Note that "false" is almost always conservatively correct (it means we emit
// a relocation which is unnecessary), except when it would force us to emit a
// relocation which the target cannot encode.
const MCSymbolData *A_Base = 0, *B_Base = 0;
if (const MCSymbolRefExpr *A = Target.getSymA()) {
// Modified symbol references cannot be resolved.
if (A->getKind() != MCSymbolRefExpr::VK_None)
return false;
A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol()));
if (!A_Base)
return false;
}
if (const MCSymbolRefExpr *B = Target.getSymB()) {
// Modified symbol references cannot be resolved.
if (B->getKind() != MCSymbolRefExpr::VK_None)
return false;
B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol()));
if (!B_Base)
return false;
}
// If there is no base, A and B have to be the same atom for this fixup to be
// fully resolved.
if (!BaseSymbol)
return A_Base == B_Base;
// Otherwise, B must be missing and A must be the base.
return !B_Base && BaseSymbol == A_Base;
}
static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm,
const MCValue Target,
const MCSection *BaseSection) {
// The effective fixup address is
// addr(atom(A)) + offset(A)
// - addr(atom(B)) - offset(B)
// - addr(<base symbol>) + <fixup offset from base symbol>
// and the offsets are not relocatable, so the fixup is fully resolved when
// addr(atom(A)) - addr(atom(B)) - addr(<base symbol>)) == 0.
//
// The simple (Darwin, except on x86_64) way of dealing with this was to
// assume that any reference to a temporary symbol *must* be a temporary
// symbol in the same atom, unless the sections differ. Therefore, any PCrel
// relocation to a temporary symbol (in the same section) is fully
// resolved. This also works in conjunction with absolutized .set, which
// requires the compiler to use .set to absolutize the differences between
// symbols which the compiler knows to be assembly time constants, so we don't
// need to worry about considering symbol differences fully resolved.
// Non-relative fixups are only resolved if constant.
if (!BaseSection)
return Target.isAbsolute();
// Otherwise, relative fixups are only resolved if not a difference and the
// target is a temporary in the same section.
if (Target.isAbsolute() || Target.getSymB())
return false;
const MCSymbol *A = &Target.getSymA()->getSymbol();
if (!A->isTemporary() || !A->isInSection() ||
&A->getSection() != BaseSection)
return false;
return true;
}
namespace { namespace {
class MachObjectWriter : public MCObjectWriter { class MachObjectWriter : public MCObjectWriter {
@ -1325,16 +1245,14 @@ public:
UndefinedSymbolData); UndefinedSymbolData);
} }
bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbolRefExpr *A, const MCSymbolData &DataA,
const MCSymbolRefExpr *B, const MCFragment &FB,
bool InSet) const { bool InSet,
bool IsPCRel) const {
if (InSet) if (InSet)
return true; return true;
if (!TargetObjectWriter->useAggressiveSymbolFolding())
return false;
// The effective address is // The effective address is
// addr(atom(A)) + offset(A) // addr(atom(A)) + offset(A)
// - addr(atom(B)) - offset(B) // - addr(atom(B)) - offset(B)
@ -1342,16 +1260,38 @@ public:
// addr(atom(A)) - addr(atom(B)) == 0. // addr(atom(A)) - addr(atom(B)) == 0.
const MCSymbolData *A_Base = 0, *B_Base = 0; const MCSymbolData *A_Base = 0, *B_Base = 0;
// Modified symbol references cannot be resolved. const MCSymbol &SA = DataA.getSymbol().AliasedSymbol();
if (A->getKind() != MCSymbolRefExpr::VK_None || const MCSection &SecA = SA.getSection();
B->getKind() != MCSymbolRefExpr::VK_None) const MCSection &SecB = FB.getParent()->getSection();
return false;
A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol())); if (IsPCRel) {
// The simple (Darwin, except on x86_64) way of dealing with this was to
// assume that any reference to a temporary symbol *must* be a temporary
// symbol in the same atom, unless the sections differ. Therefore, any
// PCrel relocation to a temporary symbol (in the same section) is fully
// resolved. This also works in conjunction with absolutized .set, which
// requires the compiler to use .set to absolutize the differences between
// symbols which the compiler knows to be assembly time constants, so we
// don't need to worry about considering symbol differences fully
// resolved.
if (!Asm.getBackend().hasReliableSymbolDifference()) {
if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB)
return false;
return true;
}
} else {
if (!TargetObjectWriter->useAggressiveSymbolFolding())
return false;
}
const MCFragment &FA = *Asm.getSymbolData(SA).getFragment();
A_Base = FA.getAtom();
if (!A_Base) if (!A_Base)
return false; return false;
B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol())); B_Base = FB.getAtom();
if (!B_Base) if (!B_Base)
return false; return false;
@ -1363,37 +1303,6 @@ public:
return false; return false;
} }
bool IsFixupFullyResolved(const MCAssembler &Asm,
const MCValue Target,
bool IsPCRel,
const MCFragment *DF) const {
// Otherwise, determine whether this value is actually resolved; scattering
// may cause atoms to move.
// Check if we are using the "simple" resolution algorithm (e.g.,
// i386).
if (!Asm.getBackend().hasReliableSymbolDifference()) {
const MCSection *BaseSection = 0;
if (IsPCRel)
BaseSection = &DF->getParent()->getSection();
return isScatteredFixupFullyResolvedSimple(Asm, Target, BaseSection);
}
// Otherwise, compute the proper answer as reliably as possible.
// If this is a PCrel relocation, find the base atom (identified by its
// symbol) that the fixup value is relative to.
const MCSymbolData *BaseSymbol = 0;
if (IsPCRel) {
BaseSymbol = DF->getAtom();
if (!BaseSymbol)
return false;
}
return isScatteredFixupFullyResolved(Asm, Target, BaseSymbol);
}
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
unsigned NumSections = Asm.size(); unsigned NumSections = Asm.size();

View File

@ -179,10 +179,12 @@ public:
MCValue Target, MCValue Target,
uint64_t &FixedValue); uint64_t &FixedValue);
virtual bool IsFixupFullyResolved(const MCAssembler &Asm, virtual bool
const MCValue Target, IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
bool IsPCRel, const MCSymbolData &DataA,
const MCFragment *DF) const; const MCFragment &FB,
bool InSet,
bool IsPCRel) const;
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
}; };
@ -717,34 +719,17 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
coff_section->Relocations.push_back(Reloc); coff_section->Relocations.push_back(Reloc);
} }
bool WinCOFFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, bool
const MCValue Target, WinCOFFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
bool IsPCRel, const MCAssembler &Asm,
const MCFragment *DF) const { const MCSymbolData &DataA,
// If this is a PCrel relocation, find the section this fixup value is const MCFragment &FB,
// relative to. bool InSet,
const MCSection *BaseSection = 0; bool IsPCRel) const {
if (IsPCRel) { const MCSection &SecA = DataA.getSymbol().AliasedSymbol().getSection();
BaseSection = &DF->getParent()->getSection(); const MCSection &SecB = FB.getParent()->getSection();
assert(BaseSection); // On COFF A - B is absolute if A and B are in the same section.
} return &SecA == &SecB;
const MCSection *SectionA = 0;
const MCSymbol *SymbolA = 0;
if (const MCSymbolRefExpr *A = Target.getSymA()) {
SymbolA = &A->getSymbol();
SectionA = &SymbolA->getSection();
}
const MCSection *SectionB = 0;
if (const MCSymbolRefExpr *B = Target.getSymB()) {
SectionB = &B->getSymbol().getSection();
}
if (!BaseSection)
return SectionA == SectionB;
return !SectionB && BaseSection == SectionA;
} }
void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,