MC: Move assembler-backend's fixup list into the fragment.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95926 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Dunbar 2010-02-11 21:29:46 +00:00
parent 27ade18431
commit cb7d743b42
2 changed files with 74 additions and 85 deletions

View File

@ -31,9 +31,6 @@ class MCSymbol;
/// which needs to be rewritten. This region will either be rewritten by the
/// assembler or cause a relocation entry to be generated.
struct MCAsmFixup {
/// Fragment - The fragment containing the fixup.
MCFragment *Fragment;
/// Offset - The offset inside the fragment which needs to be rewritten.
uint64_t Offset;
@ -49,16 +46,18 @@ struct MCAsmFixup {
uint64_t FixedValue;
public:
MCAsmFixup(MCFragment &_Fragment, uint64_t _Offset, const MCExpr &_Value,
unsigned _Size)
: Fragment(&_Fragment), Offset(_Offset), Value(&_Value), Size(_Size),
FixedValue(0) {}
MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, unsigned _Size)
: Offset(_Offset), Value(&_Value), Size(_Size), FixedValue(0) {}
};
class MCFragment : public ilist_node<MCFragment> {
MCFragment(const MCFragment&); // DO NOT IMPLEMENT
void operator=(const MCFragment&); // DO NOT IMPLEMENT
public:
typedef std::vector<MCAsmFixup>::const_iterator const_fixup_iterator;
typedef std::vector<MCAsmFixup>::iterator fixup_iterator;
public:
enum FragmentType {
FT_Data,
@ -86,6 +85,11 @@ private:
/// FileSize - The file size of this section. This is ~0 until initialized.
uint64_t FileSize;
/// Fixups - The list of fixups in this fragment.
//
// FIXME: This should be sunk into MCDataFragment.
std::vector<MCAsmFixup> Fixups;
/// @}
protected:
@ -107,6 +111,39 @@ public:
return 0;
}
/// @name Fixup Access
/// @{
/// LookupFixup - Look up the fixup for the given \arg Fragment and \arg
/// Offset.
///
/// If multiple fixups exist for the same fragment and offset it is undefined
/// which one is returned.
//
// FIXME: This isn't horribly slow in practice, but there are much nicer
// solutions to applying the fixups. This will be fixed by sinking fixups into
// data fragments exclusively.
const MCAsmFixup *LookupFixup(uint64_t Offset) const {
for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
if (Fixups[i].Offset == Offset)
return &Fixups[i];
return 0;
}
std::vector<MCAsmFixup> &getFixups() {
return Fixups;
}
fixup_iterator fixup_begin() {
return Fixups.begin();
}
fixup_iterator fixup_end() {
return Fixups.end();
}
size_t fixup_size() const { return Fixups.size(); }
/// @name Assembler Backend Support
/// @{
//
@ -313,14 +350,13 @@ class MCSectionData : public ilist_node<MCSectionData> {
void operator=(const MCSectionData&); // DO NOT IMPLEMENT
public:
typedef iplist<MCFragment> FragmentListType;
typedef FragmentListType::const_iterator const_iterator;
typedef FragmentListType::iterator iterator;
typedef std::vector<MCAsmFixup>::const_iterator const_fixup_iterator;
typedef std::vector<MCAsmFixup>::iterator fixup_iterator;
typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
typedef FragmentListType::reverse_iterator reverse_iterator;
private:
iplist<MCFragment> Fragments;
@ -345,12 +381,6 @@ private:
/// initialized.
uint64_t FileSize;
/// LastFixupLookup - Cache for the last looked up fixup.
mutable unsigned LastFixupLookup;
/// Fixups - The list of fixups in this section.
std::vector<MCAsmFixup> Fixups;
/// HasInstructions - Whether this section has had instructions emitted into
/// it.
unsigned HasInstructions : 1;
@ -379,45 +409,22 @@ public:
iterator end() { return Fragments.end(); }
const_iterator end() const { return Fragments.end(); }
reverse_iterator rbegin() { return Fragments.rbegin(); }
const_reverse_iterator rbegin() const { return Fragments.rbegin(); }
reverse_iterator rend() { return Fragments.rend(); }
const_reverse_iterator rend() const { return Fragments.rend(); }
size_t size() const { return Fragments.size(); }
bool empty() const { return Fragments.empty(); }
/// @}
/// @name Fixup Access
/// @{
std::vector<MCAsmFixup> &getFixups() {
return Fixups;
}
fixup_iterator fixup_begin() {
return Fixups.begin();
}
fixup_iterator fixup_end() {
return Fixups.end();
}
size_t fixup_size() const { return Fixups.size(); }
/// @}
/// @name Assembler Backend Support
/// @{
//
// FIXME: This could all be kept private to the assembler implementation.
/// LookupFixup - Look up the fixup for the given \arg Fragment and \arg
/// Offset.
///
/// If multiple fixups exist for the same fragment and offset it is undefined
/// which one is returned.
//
// FIXME: This isn't horribly slow in practice, but there are much nicer
// solutions to applying the fixups.
const MCAsmFixup *LookupFixup(const MCFragment *Fragment,
uint64_t Offset) const;
uint64_t getAddress() const {
assert(Address != ~UINT64_C(0) && "Address not set!");
return Address;

View File

@ -402,12 +402,12 @@ public:
uint32_t Word0;
uint32_t Word1;
};
void ComputeScatteredRelocationInfo(MCAssembler &Asm,
void ComputeScatteredRelocationInfo(MCAssembler &Asm, MCFragment &Fragment,
MCAsmFixup &Fixup,
const MCValue &Target,
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
std::vector<MachRelocationEntry> &Relocs) {
uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
unsigned IsPCRel = 0;
unsigned Type = RIT_Vanilla;
@ -453,7 +453,7 @@ public:
}
}
void ComputeRelocationInfo(MCAssembler &Asm,
void ComputeRelocationInfo(MCAssembler &Asm, MCFragment &Fragment,
MCAsmFixup &Fixup,
DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
std::vector<MachRelocationEntry> &Relocs) {
@ -466,11 +466,11 @@ public:
if (Target.getSymB() ||
(Target.getSymA() && !Target.getSymA()->isUndefined() &&
Target.getConstant()))
return ComputeScatteredRelocationInfo(Asm, Fixup, Target,
return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target,
SymbolMap, Relocs);
// See <reloc.h>.
uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
uint32_t Address = Fragment.getOffset() + Fixup.Offset;
uint32_t Value = 0;
unsigned Index = 0;
unsigned IsPCRel = 0;
@ -766,17 +766,19 @@ public:
// is written.
std::vector<MachRelocationEntry> RelocInfos;
uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
++it) {
for (MCAssembler::iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
MCSectionData &SD = *it;
// The assembler writes relocations in the reverse order they were seen.
//
// FIXME: It is probably more complicated than this.
unsigned NumRelocsStart = RelocInfos.size();
for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i)
ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap,
RelocInfos);
for (MCSectionData::reverse_iterator it2 = SD.rbegin(),
ie2 = SD.rend(); it2 != ie2; ++it2)
for (unsigned i = 0, e = it2->fixup_size(); i != e; ++i)
ComputeRelocationInfo(Asm, *it2, it2->getFixups()[e - i - 1],
SymbolMap, RelocInfos);
unsigned NumRelocs = RelocInfos.size() - NumRelocsStart;
uint64_t SectionStart = SectionDataStart + SD.getAddress();
@ -905,35 +907,12 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
Address(~UINT64_C(0)),
Size(~UINT64_C(0)),
FileSize(~UINT64_C(0)),
LastFixupLookup(~0),
HasInstructions(false)
{
if (A)
A->getSectionList().push_back(this);
}
const MCAsmFixup *MCSectionData::LookupFixup(const MCFragment *Fragment,
uint64_t Offset) const {
// Use a one level cache to turn the common case of accessing the fixups in
// order into O(1) instead of O(N).
unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size();
if (i >= End)
i = 0;
while (Count--) {
const MCAsmFixup &F = Fixups[i];
if (F.Fragment == Fragment && F.Offset == Offset) {
LastFixupLookup = i;
return &F;
}
++i;
if (i == End)
i = 0;
}
return 0;
}
/* *** */
MCSymbolData::MCSymbolData() : Symbol(0) {}
@ -997,10 +976,13 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
break;
// Otherwise, add fixups for the values.
for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
MCAsmFixup Fix(F, i*FF.getValueSize(), FF.getValue(),FF.getValueSize());
SD.getFixups().push_back(Fix);
}
//
// FIXME: What we want to do here is lower this to a data fragment once we
// realize it will need relocations. This means that the only place we
// need to worry about relocations and fixing is on data fragments.
for (uint64_t i = 0, e = FF.getCount(); i != e; ++i)
FF.getFixups().push_back(MCAsmFixup(i*FF.getValueSize(), FF.getValue(),
FF.getValueSize()));
break;
}
@ -1105,9 +1087,9 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
if (!Target.isAbsolute()) {
// Find the fixup.
//
// FIXME: Find a better way to write in the fixes.
const MCAsmFixup *Fixup =
F.getParent()->LookupFixup(&F, i * FF.getValueSize());
// FIXME: Find a better way to write in the fixes (move to
// MCDataFragment).
const MCAsmFixup *Fixup = FF.LookupFixup(i * FF.getValueSize());
assert(Fixup && "Missing fixup for fill value!");
Value = Fixup->FixedValue;
}