diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-08-28 05:49:21 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-08-28 05:49:21 +0000 |
commit | d5a8e98ef627a35284c9b5989664514f8f163968 (patch) | |
tree | 4f45d76a4e219a3c4c5cdcf3e4f22d65653b0273 /lib/MC | |
parent | edc670f3f2ba629b6803a1a7ed4aa47061afd276 (diff) | |
download | external_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.cpp | 67 | ||||
-rw-r--r-- | lib/MC/MCMachOStreamer.cpp | 22 |
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) { |