summaryrefslogtreecommitdiffstats
path: root/lib/MC
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-08-28 05:49:21 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-08-28 05:49:21 +0000
commitd5a8e98ef627a35284c9b5989664514f8f163968 (patch)
tree4f45d76a4e219a3c4c5cdcf3e4f22d65653b0273 /lib/MC
parentedc670f3f2ba629b6803a1a7ed4aa47061afd276 (diff)
downloadexternal_llvm-d5a8e98ef627a35284c9b5989664514f8f163968.zip
external_llvm-d5a8e98ef627a35284c9b5989664514f8f163968.tar.gz
external_llvm-d5a8e98ef627a35284c9b5989664514f8f163968.tar.bz2
llvm-mc: Support .zerofill emission.
- I'm still trying to figure out the cleanest way to implement this and match the assembler, currently there are some substantial differences. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80347 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/MCAssembler.cpp67
-rw-r--r--lib/MC/MCMachOStreamer.cpp22
2 files changed, 85 insertions, 4 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 1375b77..8057fcb 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -28,6 +28,15 @@ STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
MachObjectWriter &MOW);
+/// isVirtualSection - Check if this is a section which does not actually exist
+/// in the object file.
+static bool isVirtualSection(const MCSection &Section) {
+ // FIXME: Lame.
+ const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
+ unsigned Type = SMO.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
+ return (Type == MCSectionMachO::S_ZEROFILL);
+}
+
class MachObjectWriter {
// See <mach-o/loader.h>.
enum {
@@ -229,6 +238,12 @@ public:
void WriteSection32(const MCSectionData &SD, uint64_t FileOffset,
uint64_t RelocationsStart, unsigned NumRelocations) {
+ // The offset is unused for virtual sections.
+ if (isVirtualSection(SD.getSection())) {
+ assert(SD.getFileSize() == 0 && "Invalid file size!");
+ FileOffset = 0;
+ }
+
// struct section (68 bytes)
uint64_t Start = OS.tell();
@@ -692,6 +707,9 @@ public:
VMSize = std::max(VMSize, SD.getAddress() + SD.getSize());
+ if (isVirtualSection(SD.getSection()))
+ continue;
+
SectionDataSize = std::max(SectionDataSize,
SD.getAddress() + SD.getSize());
SectionDataFileSize = std::max(SectionDataFileSize,
@@ -922,7 +940,7 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
case MCFragment::FT_Align: {
MCAlignFragment &AF = cast<MCAlignFragment>(F);
- uint64_t Size = RoundUpToAlignment(Address, AF.getAlignment()) - Address;
+ uint64_t Size = OffsetToAlignment(Address, AF.getAlignment());
if (Size > AF.getMaxBytesToEmit())
AF.setFileSize(0);
else
@@ -968,6 +986,19 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
F.setFileSize(OrgOffset - Offset);
break;
}
+
+ case MCFragment::FT_ZeroFill: {
+ MCZeroFillFragment &ZFF = cast<MCZeroFillFragment>(F);
+
+ // Align the fragment offset; it is safe to adjust the offset freely since
+ // this is only in virtual sections.
+ uint64_t Aligned = RoundUpToAlignment(Address, ZFF.getAlignment());
+ F.setOffset(Aligned - SD.getAddress());
+
+ // FIXME: This is misnamed.
+ F.setFileSize(ZFF.getSize());
+ break;
+ }
}
Address += F.getFileSize();
@@ -975,7 +1006,10 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
// Set the section sizes.
SD.setSize(Address - SD.getAddress());
- SD.setFileSize(Address - SD.getAddress());
+ if (isVirtualSection(SD.getSection()))
+ SD.setFileSize(0);
+ else
+ SD.setFileSize(Address - SD.getAddress());
}
/// WriteFileData - Write the \arg F data to the output file.
@@ -1055,6 +1089,11 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
break;
}
+
+ case MCFragment::FT_ZeroFill: {
+ assert(0 && "Invalid zero fill fragment in concrete section!");
+ break;
+ }
}
assert(OS.tell() - Start == F.getFileSize());
@@ -1063,6 +1102,12 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
/// WriteFileData - Write the \arg SD data to the output file.
static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
MachObjectWriter &MOW) {
+ // Ignore virtual sections.
+ if (isVirtualSection(SD.getSection())) {
+ assert(SD.getFileSize() == 0);
+ return;
+ }
+
uint64_t Start = OS.tell();
(void) Start;
@@ -1078,12 +1123,16 @@ static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
}
void MCAssembler::Finish() {
- // Layout the sections and fragments.
+ // Layout the concrete sections and fragments.
uint64_t Address = 0;
MCSectionData *Prev = 0;
for (iterator it = begin(), ie = end(); it != ie; ++it) {
MCSectionData &SD = *it;
+ // Skip virtual sections.
+ if (isVirtualSection(SD.getSection()))
+ continue;
+
// Align this section if necessary by adding padding bytes to the previous
// section.
if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment())) {
@@ -1100,6 +1149,18 @@ void MCAssembler::Finish() {
Prev = &SD;
}
+ // Layout the virtual sections.
+ for (iterator it = begin(), ie = end(); it != ie; ++it) {
+ MCSectionData &SD = *it;
+
+ if (!isVirtualSection(SD.getSection()))
+ continue;
+
+ SD.setAddress(Address);
+ LayoutSection(SD);
+ Address += SD.getSize();
+ }
+
// Write the object file.
MachObjectWriter MOW(OS);
MOW.WriteObject(*this);
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
index 9f813fd..b53a82e 100644
--- a/lib/MC/MCMachOStreamer.cpp
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -278,7 +278,27 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
unsigned Size, unsigned Pow2Alignment) {
- llvm_unreachable("FIXME: Not yet implemented!");
+ unsigned ByteAlignment = 1 << Pow2Alignment;
+ MCSectionData &SectData = getSectionData(*Section);
+
+ // The symbol may not be present, which only creates the section.
+ if (!Symbol)
+ return;
+
+ // FIXME: Assert that this section has the zerofill type.
+
+ assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
+
+ MCSymbolData &SD = getSymbolData(*Symbol);
+
+ MCFragment *F = new MCZeroFillFragment(Size, 1 << Pow2Alignment, &SectData);
+ SD.setFragment(F);
+
+ Symbol->setSection(*Section);
+
+ // Update the maximum alignment on the zero fill section if necessary.
+ if (ByteAlignment > SectData.getAlignment())
+ SectData.setAlignment(ByteAlignment);
}
void MCMachOStreamer::EmitBytes(const StringRef &Data) {