Sorry for such a large commit. The summary is that only MachO cares about the

actuall addresses in a .o file, so it is better to let the MachO writer compute
it.

This is good for two reasons. First, areas that shouldn't care about
addresses now don't have access to it. Second, the layout of each section
is independent. I should use this in a subsequent commit to speed it up.

Most of the patch is just removing the section address computation. The two
interesting parts are the change on how we handle padding in the end
of sections and how MachO can get the address of a-b when a and b are in
different sections.

Since now the expression evaluation normally doesn't know the section address,
it will think that a-b needs relocation and let the MachO writer know. Once
it has computed the section addresses, it calls back the expression evaluation
with the section addresses to resolve these expressions.

The remaining problem is the handling of padding. Currently it will create
a special alignment fragment at the end. Since that fragment doesn't update
the alignment of the section, it needs the real address to be computed.

Since now the layout will not compute a-b with a and b in different sections,
the only effect that the special alignment fragment has is update the
address size of the section. This can also be done by the MachO writer.

llvm-svn: 121076
This commit is contained in:
Rafael Espindola 2010-12-07 00:27:36 +00:00
parent cad25fc6bc
commit 93e3cf0ebd
15 changed files with 169 additions and 206 deletions

View File

@ -66,11 +66,6 @@ public:
/// been initialized.
void LayoutFragment(MCFragment *Fragment);
/// \brief Performs initial layout for a single section, assuming that the
/// previous section (including its fragments) has already been layed out
/// correctly.
void LayoutSection(MCSectionData *SD);
/// @name Section Access (in layout order)
/// @{
@ -92,21 +87,10 @@ public:
/// \brief Get the offset of the given fragment inside its containing section.
uint64_t getFragmentOffset(const MCFragment *F) const;
/// @}
/// @name Section Layout Data
/// @{
/// \brief Get the computed address of the given section.
uint64_t getSectionAddress(const MCSectionData *SD) const;
/// @}
/// @name Utility Functions
/// @{
/// \brief Get the address of the given fragment, as computed in the current
/// layout.
uint64_t getFragmentAddress(const MCFragment *F) const;
/// \brief Get the address space size of the given section, as it effects
/// layout. This may differ from the size reported by \see getSectionSize() by
/// not including section tail padding.
@ -116,13 +100,6 @@ public:
/// file. This may include additional padding, or be 0 for virtual sections.
uint64_t getSectionFileSize(const MCSectionData *SD) const;
/// \brief Get the logical data size of the given section.
uint64_t getSectionSize(const MCSectionData *SD) const;
/// \brief Get the address of the given symbol, as computed in the current
/// layout.
uint64_t getSymbolAddress(const MCSymbolData *SD) const;
/// \brief Get the offset of the given symbol, as computed in the current
/// layout.
uint64_t getSymbolOffset(const MCSymbolData *SD) const;

View File

@ -236,19 +236,12 @@ class MCAlignFragment : public MCFragment {
/// target dependent.
bool EmitNops : 1;
/// OnlyAlignAddress - Flag to indicate that this align is only used to adjust
/// the address space size of a section and that it should not be included as
/// part of the section size. This flag can only be used on the last fragment
/// in a section.
bool OnlyAlignAddress : 1;
public:
MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
: MCFragment(FT_Align, SD), Alignment(_Alignment),
Value(_Value),ValueSize(_ValueSize),
MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false),
OnlyAlignAddress(false) {}
MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {}
/// @name Accessors
/// @{
@ -264,9 +257,6 @@ public:
bool hasEmitNops() const { return EmitNops; }
void setEmitNops(bool Value) { EmitNops = Value; }
bool hasOnlyAlignAddress() const { return OnlyAlignAddress; }
void setOnlyAlignAddress(bool Value) { OnlyAlignAddress = Value; }
/// @}
static bool classof(const MCFragment *F) {
@ -447,10 +437,6 @@ private:
//
// FIXME: This could all be kept private to the assembler implementation.
/// Address - The computed address of this section. This is ~0 until
/// initialized.
uint64_t Address;
/// HasInstructions - Whether this section has had instructions emitted into
/// it.
unsigned HasInstructions : 1;
@ -679,7 +665,6 @@ private:
unsigned RelaxAll : 1;
unsigned SubsectionsViaSymbols : 1;
unsigned PadSectionToAlignment : 1;
private:
/// Evaluate a fixup to a relocatable expression and the value which should be
@ -713,7 +698,6 @@ private:
/// Compute the effective fragment size assuming it is layed out at the given
/// \arg SectionAddress and \arg FragmentOffset.
uint64_t ComputeFragmentSize(const MCFragment &F,
uint64_t SectionAddress,
uint64_t FragmentOffset) const;
/// LayoutOnce - Perform one layout iteration and return true if any offsets
@ -765,8 +749,7 @@ public:
// option is to make this abstract, and have targets provide concrete
// implementations as we do with AsmParser.
MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
MCCodeEmitter &_Emitter, bool _PadSectionToAlignment,
raw_ostream &OS);
MCCodeEmitter &_Emitter, raw_ostream &OS);
~MCAssembler();
MCContext &getContext() const { return Context; }

View File

@ -10,6 +10,7 @@
#ifndef LLVM_MC_MCEXPR_H
#define LLVM_MC_MCEXPR_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
@ -18,10 +19,12 @@ class MCAsmInfo;
class MCAsmLayout;
class MCAssembler;
class MCContext;
class MCSectionData;
class MCSymbol;
class MCValue;
class raw_ostream;
class StringRef;
typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap;
/// MCExpr - Base class for the full range of assembler expressions which are
/// needed for parsing.
@ -42,12 +45,14 @@ private:
void operator=(const MCExpr&); // DO NOT IMPLEMENT
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout) const;
const MCAsmLayout *Layout,
const SectionAddrMap *Addrs) const;
protected:
explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {}
bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
const SectionAddrMap *Addrs,
bool InSet) const;
public:
/// @name Accessors
@ -76,6 +81,8 @@ public:
bool EvaluateAsAbsolute(int64_t &Res) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout,
const SectionAddrMap &Addrs) const;
/// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable
/// value, i.e. an expression of the fixed form (a - b + constant).

View File

@ -37,8 +37,7 @@ class MCObjectStreamer : public MCStreamer {
protected:
MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &_OS, MCCodeEmitter *_Emitter,
bool _PadSectionToAlignment);
raw_ostream &_OS, MCCodeEmitter *_Emitter);
~MCObjectStreamer();
MCSectionData *getCurrentSectionData() const {

View File

@ -62,7 +62,8 @@ public:
///
/// This routine is called by the assembler after layout and relaxation is
/// complete.
virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0;
virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) = 0;
/// Record a relocation entry.
///

View File

@ -325,7 +325,8 @@ namespace {
virtual void CreateGroupSections(MCAssembler &Asm, MCAsmLayout &Layout,
GroupMapTy &GroupMap, RevGroupMapTy &RevGroupMap);
virtual void ExecutePostLayoutBinding(MCAssembler &Asm);
virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout);
virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
uint64_t Address, uint64_t Offset,
@ -557,7 +558,8 @@ static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) {
return 0;
}
void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
// The presence of symbol versions causes undefined symbols and
// versions declared with @@@ to be renamed.
@ -1365,11 +1367,11 @@ static uint64_t GetSectionFileSize(const MCAsmLayout &Layout,
return Layout.getSectionFileSize(&SD);
}
static uint64_t GetSectionSize(const MCAsmLayout &Layout,
const MCSectionData &SD) {
static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout,
const MCSectionData &SD) {
if (IsELFMetaDataSection(SD))
return DataSectionSize(SD);
return Layout.getSectionSize(&SD);
return Layout.getSectionAddressSize(&SD);
}
static void WriteDataSectionData(ELFObjectWriter *W, const MCSectionData &SD) {
@ -1479,7 +1481,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
else
GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]);
uint64_t Size = GetSectionSize(Layout, SD);
uint64_t Size = GetSectionAddressSize(Layout, SD);
WriteSection(Asm, SectionIndexMap, GroupSymbolIndex,
SectionOffsetMap[&Section], Size,

View File

@ -38,7 +38,6 @@ STATISTIC(FragmentLayouts, "Number of fragment layouts");
STATISTIC(ObjectBytes, "Number of emitted object file bytes");
STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
STATISTIC(SectionLayouts, "Number of section layouts");
}
}
@ -113,11 +112,6 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const {
}
}
uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
assert(F->getParent() && "Missing section()!");
return getSectionAddress(F->getParent()) + getFragmentOffset(F);
}
uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const {
EnsureValid(F);
assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!");
@ -135,17 +129,6 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
return getFragmentOffset(SD->getFragment()) + SD->getOffset();
}
uint64_t MCAsmLayout::getSymbolAddress(const MCSymbolData *SD) const {
assert(SD->getFragment() && "Invalid getAddress() on undefined symbol!");
return getFragmentAddress(SD->getFragment()) + SD->getOffset();
}
uint64_t MCAsmLayout::getSectionAddress(const MCSectionData *SD) const {
EnsureValid(SD->begin());
assert(SD->Address != ~UINT64_C(0) && "Address not set!");
return SD->Address;
}
uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {
// The size is the last fragment's end offset.
const MCFragment &F = SD->getFragmentList().back();
@ -161,17 +144,6 @@ uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
return getSectionAddressSize(SD);
}
uint64_t MCAsmLayout::getSectionSize(const MCSectionData *SD) const {
// The logical size is the address space size minus any tail padding.
uint64_t Size = getSectionAddressSize(SD);
const MCAlignFragment *AF =
dyn_cast<MCAlignFragment>(&(SD->getFragmentList().back()));
if (AF && AF->hasOnlyAlignAddress())
Size -= getFragmentEffectiveSize(AF);
return Size;
}
/* *** */
MCFragment::MCFragment() : Kind(FragmentType(~0)) {
@ -196,7 +168,6 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
: Section(&_Section),
Ordinal(~UINT32_C(0)),
Alignment(1),
Address(~UINT64_C(0)),
HasInstructions(false)
{
if (A)
@ -221,11 +192,9 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment,
/* *** */
MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
MCCodeEmitter &_Emitter, bool _PadSectionToAlignment,
raw_ostream &_OS)
MCCodeEmitter &_Emitter, raw_ostream &_OS)
: Context(_Context), Backend(_Backend), Emitter(_Emitter),
OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false),
PadSectionToAlignment(_PadSectionToAlignment)
OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false)
{
}
@ -285,14 +254,14 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
if (const MCSymbolRefExpr *A = Target.getSymA()) {
const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
if (Sym.isDefined())
Value += Layout.getSymbolAddress(&getSymbolData(Sym));
Value += Layout.getSymbolOffset(&getSymbolData(Sym));
else
IsResolved = false;
}
if (const MCSymbolRefExpr *B = Target.getSymB()) {
const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
if (Sym.isDefined())
Value -= Layout.getSymbolAddress(&getSymbolData(Sym));
Value -= Layout.getSymbolOffset(&getSymbolData(Sym));
else
IsResolved = false;
}
@ -301,13 +270,12 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF);
if (IsPCRel)
Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset();
Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset();
return IsResolved;
}
uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
uint64_t SectionAddress,
uint64_t FragmentOffset) const {
switch (F.getKind()) {
case MCFragment::FT_Data:
@ -323,11 +291,7 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
assert((!AF.hasOnlyAlignAddress() || !AF.getNextNode()) &&
"Invalid OnlyAlignAddress bit, not the last fragment!");
uint64_t Size = OffsetToAlignment(SectionAddress + FragmentOffset,
AF.getAlignment());
uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment());
// Honor MaxBytesToEmit.
if (Size > AF.getMaxBytesToEmit())
@ -351,8 +315,6 @@ void MCAsmLayout::LayoutFile() {
// Initialize the first section and set the valid fragment layout point. All
// actual layout computations are done lazily.
LastValidFragment = 0;
if (!getSectionOrder().empty())
getSectionOrder().front()->Address = 0;
}
void MCAsmLayout::LayoutFragment(MCFragment *F) {
@ -371,43 +333,14 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) {
++stats::FragmentLayouts;
// Compute the fragment start address.
uint64_t StartAddress = F->getParent()->Address;
uint64_t Address = StartAddress;
if (Prev)
Address += Prev->Offset + Prev->EffectiveSize;
// Compute fragment offset and size.
F->Offset = Address - StartAddress;
F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, StartAddress,
F->Offset);
uint64_t Offset = 0;
if (Prev)
Offset += Prev->Offset + Prev->EffectiveSize;
F->Offset = Offset;
F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset);
LastValidFragment = F;
// If this is the last fragment in a section, update the next section address.
if (!F->getNextNode()) {
unsigned NextIndex = F->getParent()->getLayoutOrder() + 1;
if (NextIndex != getSectionOrder().size())
LayoutSection(getSectionOrder()[NextIndex]);
}
}
void MCAsmLayout::LayoutSection(MCSectionData *SD) {
unsigned SectionOrderIndex = SD->getLayoutOrder();
++stats::SectionLayouts;
// Compute the section start address.
uint64_t StartAddress = 0;
if (SectionOrderIndex) {
MCSectionData *Prev = getSectionOrder()[SectionOrderIndex - 1];
StartAddress = getSectionAddress(Prev) + getSectionAddressSize(Prev);
}
// Honor the section alignment requirements.
StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
// Set the section address.
SD->Address = StartAddress;
}
/// WriteFragmentData - Write the \arg F data to the output file.
@ -566,7 +499,7 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD,
ie = SD->end(); it != ie; ++it)
WriteFragmentData(*this, Layout, *it, OW);
assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD));
assert(OW->getStream().tell() - Start == Layout.getSectionAddressSize(SD));
}
@ -594,29 +527,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
// Create the layout object.
MCAsmLayout Layout(*this);
// Insert additional align fragments for concrete sections to explicitly pad
// the previous section to match their alignment requirements. This is for
// 'gas' compatibility, it shouldn't strictly be necessary.
if (PadSectionToAlignment) {
for (unsigned i = 1, e = Layout.getSectionOrder().size(); i < e; ++i) {
MCSectionData *SD = Layout.getSectionOrder()[i];
// Ignore sections without alignment requirements.
unsigned Align = SD->getAlignment();
if (Align <= 1)
continue;
// Ignore virtual sections, they don't cause file size modifications.
if (SD->getSection().isVirtualSection())
continue;
// Otherwise, create a new align fragment at the end of the previous
// section.
MCAlignFragment *AF = new MCAlignFragment(Align, 0, 1, Align,
Layout.getSectionOrder()[i - 1]);
AF->setOnlyAlignAddress(true);
}
}
// Create dummy fragments and assign section ordinals.
unsigned SectionIndex = 0;
@ -668,7 +579,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) {
// Allow the object writer a chance to perform post-layout binding (for
// example, to set the index fields in the symbol data).
Writer->ExecutePostLayoutBinding(*this);
Writer->ExecutePostLayoutBinding(*this, Layout);
// Evaluate and apply the fixups, generating relocation entries as necessary.
for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
@ -920,8 +831,6 @@ void MCFragment::dump() {
const MCAlignFragment *AF = cast<MCAlignFragment>(this);
if (AF->hasEmitNops())
OS << " (emit nops)";
if (AF->hasOnlyAlignAddress())
OS << " (only align section)";
OS << "\n ";
OS << " Alignment:" << AF->getAlignment()
<< " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize()
@ -991,8 +900,7 @@ void MCSectionData::dump() {
raw_ostream &OS = llvm::errs();
OS << "<MCSectionData";
OS << " Alignment:" << getAlignment() << " Address:" << Address
<< " Fragments:[\n ";
OS << " Alignment:" << getAlignment() << " Fragments:[\n ";
for (iterator it = begin(), ie = end(); it != ie; ++it) {
if (it != begin()) OS << ",\n ";
it->dump();

View File

@ -71,7 +71,7 @@ class MCELFStreamer : public MCObjectStreamer {
public:
MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
: MCObjectStreamer(Context, TAB, OS, Emitter, false) {}
: MCObjectStreamer(Context, TAB, OS, Emitter) {}
~MCELFStreamer() {}

View File

@ -238,20 +238,27 @@ void MCTargetExpr::Anchor() {}
/* *** */
bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
return EvaluateAsAbsolute(Res, 0, 0);
return EvaluateAsAbsolute(Res, 0, 0, 0);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
const MCAsmLayout &Layout) const {
return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout);
return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
const MCAsmLayout &Layout,
const SectionAddrMap &Addrs) const {
return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
return EvaluateAsAbsolute(Res, &Asm, 0);
return EvaluateAsAbsolute(Res, &Asm, 0, 0);
}
bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout) const {
const MCAsmLayout *Layout,
const SectionAddrMap *Addrs) const {
MCValue Value;
// Fast path constants.
@ -260,7 +267,7 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
return true;
}
if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, false) ||
if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, Addrs) ||
!Value.isAbsolute()) {
// EvaluateAsAbsolute is defined to return the "current value" of
// the expression if we are given a Layout object, even in cases
@ -268,11 +275,11 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
if (Layout) {
Res = Value.getConstant();
if (Value.getSymA()) {
Res += Layout->getSymbolAddress(
Res += Layout->getSymbolOffset(
&Layout->getAssembler().getSymbolData(Value.getSymA()->getSymbol()));
}
if (Value.getSymB()) {
Res -= Layout->getSymbolAddress(
Res -= Layout->getSymbolOffset(
&Layout->getAssembler().getSymbolData(Value.getSymB()->getSymbol()));
}
}
@ -283,8 +290,9 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
return true;
}
static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
const MCAssembler *Asm,
static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
const MCAsmLayout *Layout,
const SectionAddrMap *Addrs,
bool InSet,
const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
@ -327,10 +335,19 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
}
if (Layout) {
Res = MCValue::get(+ Layout->getSymbolAddress(&AD)
- Layout->getSymbolAddress(&BD)
+ LHS.getConstant()
+ RHS_Cst);
const MCSectionData &SecA = *AD.getFragment()->getParent();
const MCSectionData &SecB = *BD.getFragment()->getParent();
int64_t Val = + Layout->getSymbolOffset(&AD)
- Layout->getSymbolOffset(&BD)
+ LHS.getConstant()
+ RHS_Cst;
if (&SecA != &SecB) {
if (!Addrs)
return false;
Val += Addrs->lookup(&SecA);
Val -= Addrs->lookup(&SecB);
}
Res = MCValue::get(Val);
return true;
}
}
@ -344,14 +361,15 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
const MCAsmLayout *Layout) const {
if (Layout)
return EvaluateAsRelocatableImpl(Res, &Layout->getAssembler(), Layout,
false);
0, false);
else
return EvaluateAsRelocatableImpl(Res, 0, 0, false);
return EvaluateAsRelocatableImpl(Res, 0, 0, 0, false);
}
bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
const MCAssembler *Asm,
const MCAsmLayout *Layout,
const SectionAddrMap *Addrs,
bool InSet) const {
++stats::MCExprEvaluate;
@ -371,6 +389,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm,
Layout,
Addrs,
true);
// If we failed to simplify this to a constant, let the target
// handle it.
@ -387,7 +406,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
MCValue Value;
if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
InSet))
Addrs, InSet))
return false;
switch (AUE->getOpcode()) {
@ -421,9 +440,9 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
MCValue LHSValue, RHSValue;
if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
InSet) ||
Addrs, InSet) ||
!ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
InSet))
Addrs, InSet))
return false;
// We only support a few operations on non-constant expressions, handle
@ -434,13 +453,13 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
return false;
case MCBinaryExpr::Sub:
// Negate RHS and add.
return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
RHSValue.getSymB(), RHSValue.getSymA(),
-RHSValue.getConstant(),
Res);
case MCBinaryExpr::Add:
return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
RHSValue.getSymA(), RHSValue.getSymB(),
RHSValue.getConstant(),
Res);

View File

@ -36,7 +36,7 @@ private:
public:
MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
: MCObjectStreamer(Context, TAB, OS, Emitter, true) {}
: MCObjectStreamer(Context, TAB, OS, Emitter) {}
/// @name MCStreamer Interface
/// @{

View File

@ -19,11 +19,9 @@
using namespace llvm;
MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &_OS, MCCodeEmitter *_Emitter,
bool _PadSectionToAlignment)
raw_ostream &_OS, MCCodeEmitter *_Emitter)
: MCStreamer(Context), Assembler(new MCAssembler(Context, TAB,
*_Emitter,
_PadSectionToAlignment,
_OS)),
CurSectionData(0)
{

View File

@ -30,8 +30,7 @@ private:
public:
MCPureStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
: MCObjectStreamer(Context, TAB, OS, Emitter,
/*PadSectionToAlignment=*/true) {}
: MCObjectStreamer(Context, TAB, OS, Emitter) {}
/// @name MCStreamer Interface
/// @{

View File

@ -197,6 +197,34 @@ class MachObjectWriter : public MCObjectWriter {
/// @}
SectionAddrMap SectionAddress;
uint64_t getSectionAddress(const MCSectionData* SD) const {
return SectionAddress.lookup(SD);
}
uint64_t getSymbolAddress(const MCSymbolData* SD,
const MCAsmLayout &Layout) const {
return getSectionAddress(SD->getFragment()->getParent()) +
Layout.getSymbolOffset(SD);
}
uint64_t getFragmentAddress(const MCFragment *Fragment,
const MCAsmLayout &Layout) const {
return getSectionAddress(Fragment->getParent()) +
Layout.getFragmentOffset(Fragment);
}
uint64_t getPaddingSize(const MCSectionData *SD,
const MCAsmLayout &Layout) const {
uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD);
unsigned Next = SD->getLayoutOrder() + 1;
if (Next >= Layout.getSectionOrder().size())
return 0;
const MCSectionData &NextSD = *Layout.getSectionOrder()[Next];
if (NextSD.getSection().isVirtualSection())
return 0;
return OffsetToAlignment(EndAddr, NextSD.getAlignment());
}
unsigned Is64Bit : 1;
uint32_t CPUType;
@ -283,7 +311,7 @@ public:
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCSectionData &SD, uint64_t FileOffset,
uint64_t RelocationsStart, unsigned NumRelocations) {
uint64_t SectionSize = Layout.getSectionSize(&SD);
uint64_t SectionSize = Layout.getSectionAddressSize(&SD);
// The offset is unused for virtual sections.
if (SD.getSection().isVirtualSection()) {
@ -301,10 +329,10 @@ public:
WriteBytes(Section.getSectionName(), 16);
WriteBytes(Section.getSegmentName(), 16);
if (Is64Bit) {
Write64(Layout.getSectionAddress(&SD)); // address
Write64(getSectionAddress(&SD)); // address
Write64(SectionSize); // size
} else {
Write32(Layout.getSectionAddress(&SD)); // address
Write32(getSectionAddress(&SD)); // address
Write32(SectionSize); // size
}
Write32(FileOffset);
@ -413,7 +441,7 @@ public:
if (Symbol.isAbsolute()) {
Address = cast<MCConstantExpr>(Symbol.getVariableValue())->getValue();
} else {
Address = Layout.getSymbolAddress(&Data);
Address = getSymbolAddress(&Data, Layout);
}
} else if (Data.isCommon()) {
// Common symbols are encoded with the size in the address
@ -473,7 +501,7 @@ public:
uint32_t FixupOffset =
Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
uint32_t FixupAddress =
Layout.getFragmentAddress(Fragment) + Fixup.getOffset();
getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
int64_t Value = 0;
unsigned Index = 0;
unsigned IsExtern = 0;
@ -603,10 +631,21 @@ public:
// The index is the section ordinal (1-based).
Index = SD.getFragment()->getParent()->getOrdinal() + 1;
IsExtern = 0;
Value += Layout.getSymbolAddress(&SD);
Value += getSymbolAddress(&SD, Layout);
if (IsPCRel)
Value -= FixupAddress + (1 << Log2Size);
} else if (Symbol->isVariable()) {
const MCExpr *Value = Symbol->getVariableValue();
int64_t Res;
bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress);
if (isAbs) {
FixedValue = Res;
return;
} else {
report_fatal_error("unsupported relocation of variable '" +
Symbol->getName() + "'");
}
} else {
report_fatal_error("unsupported relocation of undefined symbol '" +
Symbol->getName() + "'");
@ -708,7 +747,9 @@ public:
report_fatal_error("symbol '" + A->getName() +
"' can not be undefined in a subtraction expression");
uint32_t Value = Layout.getSymbolAddress(A_SD);
uint32_t Value = getSymbolAddress(A_SD, Layout);
uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
FixedValue += SecAddr;
uint32_t Value2 = 0;
if (const MCSymbolRefExpr *B = Target.getSymB()) {
@ -725,7 +766,8 @@ public:
// for pedantic compatibility with 'as'.
Type = A_SD->isExternal() ? macho::RIT_Difference :
macho::RIT_LocalDifference;
Value2 = Layout.getSymbolAddress(B_SD);
Value2 = getSymbolAddress(B_SD, Layout);
FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
}
// Relocations are written out in reverse order, so the PAIR comes first.
@ -774,10 +816,10 @@ public:
if (Target.getSymB()) {
// If this is a subtraction then we're pcrel.
uint32_t FixupAddress =
Layout.getFragmentAddress(Fragment) + Fixup.getOffset();
getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol());
IsPCRel = 1;
FixedValue = (FixupAddress - Layout.getSymbolAddress(SD_B) +
FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) +
Target.getConstant());
FixedValue += 1ULL << Log2Size;
} else {
@ -855,10 +897,13 @@ public:
// compensate for the addend of the symbol address, if it was
// undefined. This occurs with weak definitions, for example.
if (!SD->Symbol->isUndefined())
FixedValue -= Layout.getSymbolAddress(SD);
FixedValue -= getSymbolAddress(SD, Layout);
} else {
// The index is the section ordinal (1-based).
Index = SD->getFragment()->getParent()->getOrdinal() + 1;
FixedValue += getSectionAddress(SD->getFragment()->getParent());
if (IsPCRel)
FixedValue -= getSectionAddress(Fragment->getParent());
}
Type = macho::RIT_Vanilla;
@ -1039,7 +1084,25 @@ public:
StringTable += '\x00';
}
void ExecutePostLayoutBinding(MCAssembler &Asm) {
void computeSectionAddresses(const MCAssembler &Asm,
const MCAsmLayout &Layout) {
uint64_t StartAddress = 0;
const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder();
for (int i = 0, n = Order.size(); i != n ; ++i) {
const MCSectionData *SD = Order[i];
StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
SectionAddress[SD] = StartAddress;
StartAddress += Layout.getSectionAddressSize(SD);
// Explicitly pad the section to match the alignment requirements of the
// following one. This is for 'gas' compatibility, it shouldn't
/// strictly be necessary.
StartAddress += getPaddingSize(SD, Layout);
}
}
void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
computeSectionAddresses(Asm, Layout);
// Create symbol data for any indirect symbols.
BindIndirectSymbols(Asm);
@ -1113,9 +1176,10 @@ public:
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
const MCSectionData &SD = *it;
uint64_t Address = Layout.getSectionAddress(&SD);
uint64_t Size = Layout.getSectionSize(&SD);
uint64_t Address = getSectionAddress(&SD);
uint64_t Size = Layout.getSectionAddressSize(&SD);
uint64_t FileSize = Layout.getSectionFileSize(&SD);
FileSize += getPaddingSize(&SD, Layout);
VMSize = std::max(VMSize, Address + Size);
@ -1144,7 +1208,7 @@ public:
ie = Asm.end(); it != ie; ++it) {
std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
unsigned NumRelocs = Relocs.size();
uint64_t SectionStart = SectionDataStart + Layout.getSectionAddress(it);
uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
}
@ -1185,9 +1249,14 @@ public:
// Write the actual section data.
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it)
ie = Asm.end(); it != ie; ++it) {
Asm.WriteSectionData(it, Layout, this);
uint64_t Pad = getPaddingSize(it, Layout);
for (unsigned int i = 0; i < Pad; ++i)
Write8(0);
}
// Write the extra padding.
WriteZeros(SectionDataPadding);

View File

@ -170,7 +170,7 @@ public:
// MCObjectWriter interface implementation.
void ExecutePostLayoutBinding(MCAssembler &Asm);
void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout);
void RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
@ -616,7 +616,8 @@ void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
////////////////////////////////////////////////////////////////////////////////
// MCObjectWriter interface implementations
void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
// "Define" each section & symbol. This creates section & symbol
// entries in the staging area.
@ -753,7 +754,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
for (sections::iterator i = Sections.begin(),
e = Sections.end(); i != e; i++) {
if (Layout.getSectionSize((*i)->MCData) > 0) {
if (Layout.getSectionAddressSize((*i)->MCData) > 0) {
MakeSectionReal(**i, ++Header.NumberOfSections);
} else {
(*i)->Number = -1;

View File

@ -124,7 +124,7 @@ WinCOFFStreamer::WinCOFFStreamer(MCContext &Context,
TargetAsmBackend &TAB,
MCCodeEmitter &CE,
raw_ostream &OS)
: MCObjectStreamer(Context, TAB, OS, &CE, false)
: MCObjectStreamer(Context, TAB, OS, &CE)
, CurSymbol(NULL) {
}