mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
MC: Route access to Fragment offset and effective size through MCAsmLayout.
llvm-svn: 99473
This commit is contained in:
parent
0978fc47b3
commit
4b6b2a1a1f
@ -35,6 +35,12 @@ public:
|
||||
|
||||
uint64_t getFragmentAddress(const MCFragment *F) const;
|
||||
|
||||
uint64_t getFragmentEffectiveSize(const MCFragment *F) const;
|
||||
void setFragmentEffectiveSize(MCFragment *F, uint64_t Value);
|
||||
|
||||
uint64_t getFragmentOffset(const MCFragment *F) const;
|
||||
void setFragmentOffset(MCFragment *F, uint64_t Value);
|
||||
|
||||
uint64_t getSectionAddress(const MCSectionData *SD) const;
|
||||
|
||||
uint64_t getSymbolAddress(const MCSymbolData *SD) const;
|
||||
|
@ -87,8 +87,9 @@ private:
|
||||
/// initialized.
|
||||
uint64_t Offset;
|
||||
|
||||
/// FileSize - The file size of this section. This is ~0 until initialized.
|
||||
uint64_t FileSize;
|
||||
/// EffectiveSize - The compute size of this section. This is ~0 until
|
||||
/// initialized.
|
||||
uint64_t EffectiveSize;
|
||||
|
||||
/// @}
|
||||
|
||||
@ -105,25 +106,6 @@ public:
|
||||
MCSectionData *getParent() const { return Parent; }
|
||||
void setParent(MCSectionData *Value) { Parent = Value; }
|
||||
|
||||
/// @name Assembler Backend Support
|
||||
/// @{
|
||||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
uint64_t getFileSize() const {
|
||||
assert(FileSize != ~UINT64_C(0) && "File size not set!");
|
||||
return FileSize;
|
||||
}
|
||||
void setFileSize(uint64_t Value) { FileSize = Value; }
|
||||
|
||||
uint64_t getOffset() const {
|
||||
assert(Offset != ~UINT64_C(0) && "File offset not set!");
|
||||
return Offset;
|
||||
}
|
||||
void setOffset(uint64_t Value) { Offset = Value; }
|
||||
|
||||
/// @}
|
||||
|
||||
static bool classof(const MCFragment *O) { return true; }
|
||||
|
||||
virtual void dump();
|
||||
@ -711,7 +693,8 @@ public:
|
||||
/// Emit the section contents using the given object writer.
|
||||
//
|
||||
// FIXME: Should MCAssembler always have a reference to the object writer?
|
||||
void WriteSectionData(const MCSectionData *Section, MCObjectWriter *OW) const;
|
||||
void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout,
|
||||
MCObjectWriter *OW) const;
|
||||
|
||||
public:
|
||||
/// Construct a new assembler instance.
|
||||
|
@ -47,7 +47,25 @@ STATISTIC(ObjectBytes, "Number of emitted object file bytes");
|
||||
|
||||
uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
|
||||
assert(F->getParent() && "Missing section()!");
|
||||
return getSectionAddress(F->getParent()) + F->getOffset();
|
||||
return getSectionAddress(F->getParent()) + getFragmentOffset(F);
|
||||
}
|
||||
|
||||
uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const {
|
||||
assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!");
|
||||
return F->EffectiveSize;
|
||||
}
|
||||
|
||||
void MCAsmLayout::setFragmentEffectiveSize(MCFragment *F, uint64_t Value) {
|
||||
F->EffectiveSize = Value;
|
||||
}
|
||||
|
||||
uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
|
||||
assert(F->Offset != ~UINT64_C(0) && "Address not set!");
|
||||
return F->Offset;
|
||||
}
|
||||
|
||||
void MCAsmLayout::setFragmentOffset(MCFragment *F, uint64_t Value) {
|
||||
F->Offset = Value;
|
||||
}
|
||||
|
||||
uint64_t MCAsmLayout::getSymbolAddress(const MCSymbolData *SD) const {
|
||||
@ -72,7 +90,7 @@ MCFragment::MCFragment() : Kind(FragmentType(~0)) {
|
||||
MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
|
||||
: Kind(_Kind),
|
||||
Parent(_Parent),
|
||||
FileSize(~UINT64_C(0))
|
||||
EffectiveSize(~UINT64_C(0))
|
||||
{
|
||||
if (Parent)
|
||||
Parent->getFragmentList().push_back(this);
|
||||
@ -335,33 +353,33 @@ void MCAssembler::LayoutSection(MCSectionData &SD,
|
||||
for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
|
||||
MCFragment &F = *it;
|
||||
|
||||
F.setOffset(Address - StartAddress);
|
||||
uint64_t FragmentOffset = Address - StartAddress;
|
||||
Layout.setFragmentOffset(&F, FragmentOffset);
|
||||
|
||||
// Evaluate fragment size.
|
||||
uint64_t EffectiveSize = 0;
|
||||
switch (F.getKind()) {
|
||||
case MCFragment::FT_Align: {
|
||||
MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
||||
|
||||
uint64_t Size = OffsetToAlignment(Address, AF.getAlignment());
|
||||
if (Size > AF.getMaxBytesToEmit())
|
||||
AF.setFileSize(0);
|
||||
else
|
||||
AF.setFileSize(Size);
|
||||
EffectiveSize = OffsetToAlignment(Address, AF.getAlignment());
|
||||
if (EffectiveSize > AF.getMaxBytesToEmit())
|
||||
EffectiveSize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case MCFragment::FT_Data:
|
||||
F.setFileSize(cast<MCDataFragment>(F).getContents().size());
|
||||
EffectiveSize = cast<MCDataFragment>(F).getContents().size();
|
||||
break;
|
||||
|
||||
case MCFragment::FT_Fill: {
|
||||
MCFillFragment &FF = cast<MCFillFragment>(F);
|
||||
F.setFileSize(FF.getValueSize() * FF.getCount());
|
||||
EffectiveSize = FF.getValueSize() * FF.getCount();
|
||||
break;
|
||||
}
|
||||
|
||||
case MCFragment::FT_Inst:
|
||||
F.setFileSize(cast<MCInstFragment>(F).getInstSize());
|
||||
EffectiveSize = cast<MCInstFragment>(F).getInstSize();
|
||||
break;
|
||||
|
||||
case MCFragment::FT_Org: {
|
||||
@ -372,12 +390,12 @@ void MCAssembler::LayoutSection(MCSectionData &SD,
|
||||
llvm_report_error("expected assembly-time absolute expression");
|
||||
|
||||
// FIXME: We need a way to communicate this error.
|
||||
int64_t Offset = TargetLocation - F.getOffset();
|
||||
int64_t Offset = TargetLocation - FragmentOffset;
|
||||
if (Offset < 0)
|
||||
llvm_report_error("invalid .org offset '" + Twine(TargetLocation) +
|
||||
"' (at offset '" + Twine(F.getOffset()) + "'");
|
||||
"' (at offset '" + Twine(FragmentOffset) + "'");
|
||||
|
||||
F.setFileSize(Offset);
|
||||
EffectiveSize = Offset;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -386,16 +404,18 @@ void MCAssembler::LayoutSection(MCSectionData &SD,
|
||||
|
||||
// Align the fragment offset; it is safe to adjust the offset freely since
|
||||
// this is only in virtual sections.
|
||||
//
|
||||
// FIXME: We shouldn't be doing this here.
|
||||
Address = RoundUpToAlignment(Address, ZFF.getAlignment());
|
||||
F.setOffset(Address - StartAddress);
|
||||
Layout.setFragmentOffset(&F, Address - StartAddress);
|
||||
|
||||
// FIXME: This is misnamed.
|
||||
F.setFileSize(ZFF.getSize());
|
||||
EffectiveSize = ZFF.getSize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Address += F.getFileSize();
|
||||
Layout.setFragmentEffectiveSize(&F, EffectiveSize);
|
||||
Address += EffectiveSize;
|
||||
}
|
||||
|
||||
// Set the section sizes.
|
||||
@ -407,27 +427,28 @@ void MCAssembler::LayoutSection(MCSectionData &SD,
|
||||
}
|
||||
|
||||
/// WriteFragmentData - Write the \arg F data to the output file.
|
||||
static void WriteFragmentData(const MCAssembler &Asm, const MCFragment &F,
|
||||
MCObjectWriter *OW) {
|
||||
static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment &F, MCObjectWriter *OW) {
|
||||
uint64_t Start = OW->getStream().tell();
|
||||
(void) Start;
|
||||
|
||||
++stats::EmittedFragments;
|
||||
|
||||
// FIXME: Embed in fragments instead?
|
||||
uint64_t FragmentSize = Layout.getFragmentEffectiveSize(&F);
|
||||
switch (F.getKind()) {
|
||||
case MCFragment::FT_Align: {
|
||||
MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
||||
uint64_t Count = AF.getFileSize() / AF.getValueSize();
|
||||
uint64_t Count = FragmentSize / AF.getValueSize();
|
||||
|
||||
// FIXME: This error shouldn't actually occur (the front end should emit
|
||||
// multiple .align directives to enforce the semantics it wants), but is
|
||||
// severe enough that we want to report it. How to handle this?
|
||||
if (Count * AF.getValueSize() != AF.getFileSize())
|
||||
if (Count * AF.getValueSize() != FragmentSize)
|
||||
llvm_report_error("undefined .align directive, value size '" +
|
||||
Twine(AF.getValueSize()) +
|
||||
"' is not a divisor of padding size '" +
|
||||
Twine(AF.getFileSize()) + "'");
|
||||
Twine(FragmentSize) + "'");
|
||||
|
||||
// See if we are aligning with nops, and if so do that first to try to fill
|
||||
// the Count bytes. Then if that did not fill any bytes or there are any
|
||||
@ -456,7 +477,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCFragment &F,
|
||||
|
||||
case MCFragment::FT_Data: {
|
||||
MCDataFragment &DF = cast<MCDataFragment>(F);
|
||||
assert(DF.getFileSize() == DF.getContents().size() && "Invalid size!");
|
||||
assert(FragmentSize == DF.getContents().size() && "Invalid size!");
|
||||
OW->WriteBytes(DF.getContents().str());
|
||||
break;
|
||||
}
|
||||
@ -483,7 +504,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCFragment &F,
|
||||
case MCFragment::FT_Org: {
|
||||
MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
||||
|
||||
for (uint64_t i = 0, e = OF.getFileSize(); i != e; ++i)
|
||||
for (uint64_t i = 0, e = FragmentSize; i != e; ++i)
|
||||
OW->Write8(uint8_t(OF.getValue()));
|
||||
|
||||
break;
|
||||
@ -495,10 +516,11 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCFragment &F,
|
||||
}
|
||||
}
|
||||
|
||||
assert(OW->getStream().tell() - Start == F.getFileSize());
|
||||
assert(OW->getStream().tell() - Start == FragmentSize);
|
||||
}
|
||||
|
||||
void MCAssembler::WriteSectionData(const MCSectionData *SD,
|
||||
const MCAsmLayout &Layout,
|
||||
MCObjectWriter *OW) const {
|
||||
// Ignore virtual sections.
|
||||
if (getBackend().isVirtualSection(SD->getSection())) {
|
||||
@ -511,7 +533,7 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD,
|
||||
|
||||
for (MCSectionData::const_iterator it = SD->begin(),
|
||||
ie = SD->end(); it != ie; ++it)
|
||||
WriteFragmentData(*this, *it, OW);
|
||||
WriteFragmentData(*this, Layout, *it, OW);
|
||||
|
||||
// Add section padding.
|
||||
assert(SD->getFileSize() >= SD->getSize() && "Invalid section sizes!");
|
||||
@ -735,9 +757,11 @@ void MCAssembler::FinishLayout(MCAsmLayout &Layout) {
|
||||
SD.getFragmentList().insert(it2, DF);
|
||||
|
||||
// Update the data fragments layout data.
|
||||
//
|
||||
// FIXME: Add MCAsmLayout utility for this.
|
||||
DF->setParent(IF->getParent());
|
||||
DF->setOffset(IF->getOffset());
|
||||
DF->setFileSize(IF->getInstSize());
|
||||
Layout.setFragmentOffset(DF, Layout.getFragmentOffset(IF));
|
||||
Layout.setFragmentEffectiveSize(DF, Layout.getFragmentEffectiveSize(IF));
|
||||
|
||||
// Copy in the data and the fixups.
|
||||
DF->getContents().append(IF->getCode().begin(), IF->getCode().end());
|
||||
@ -767,7 +791,7 @@ void MCFragment::dump() {
|
||||
raw_ostream &OS = llvm::errs();
|
||||
|
||||
OS << "<MCFragment " << (void*) this << " Offset:" << Offset
|
||||
<< " FileSize:" << FileSize;
|
||||
<< " EffectiveSize:" << EffectiveSize;
|
||||
|
||||
OS << ">";
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ public:
|
||||
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
|
||||
|
||||
// See <reloc.h>.
|
||||
uint32_t Address = Fragment->getOffset() + Fixup.Offset;
|
||||
uint32_t Address = Layout.getFragmentOffset(Fragment) + Fixup.Offset;
|
||||
int64_t Value = 0;
|
||||
unsigned Index = 0;
|
||||
unsigned IsExtern = 0;
|
||||
@ -645,7 +645,7 @@ public:
|
||||
const MCFragment *Fragment,
|
||||
const MCAsmFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) {
|
||||
uint32_t Address = Fragment->getOffset() + Fixup.Offset;
|
||||
uint32_t Address = Layout.getFragmentOffset(Fragment) + Fixup.Offset;
|
||||
unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
|
||||
unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
|
||||
unsigned Type = RIT_Vanilla;
|
||||
@ -723,7 +723,7 @@ public:
|
||||
}
|
||||
|
||||
// See <reloc.h>.
|
||||
uint32_t Address = Fragment->getOffset() + Fixup.Offset;
|
||||
uint32_t Address = Layout.getFragmentOffset(Fragment) + Fixup.Offset;
|
||||
uint32_t Value = 0;
|
||||
unsigned Index = 0;
|
||||
unsigned IsExtern = 0;
|
||||
@ -1036,7 +1036,7 @@ public:
|
||||
// Write the actual section data.
|
||||
for (MCAssembler::const_iterator it = Asm.begin(),
|
||||
ie = Asm.end(); it != ie; ++it)
|
||||
Asm.WriteSectionData(it, Writer);
|
||||
Asm.WriteSectionData(it, Layout, Writer);
|
||||
|
||||
// Write the extra padding.
|
||||
WriteZeros(SectionDataPadding);
|
||||
|
Loading…
Reference in New Issue
Block a user