diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-08-21 18:29:01 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-08-21 18:29:01 +0000 |
commit | 0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4 (patch) | |
tree | 6a94c62766d730622c20c3a2ab24da931415e57e /lib/MC/MCAssembler.cpp | |
parent | 7178010a168a378df5d9be95956093a3e5f963fd (diff) |
llvm-mc/Mach-O: Support byte and fill value emission.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79652 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCAssembler.cpp')
-rw-r--r-- | lib/MC/MCAssembler.cpp | 153 |
1 files changed, 130 insertions, 23 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 7a1e935af4..883cabe45c 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachOWriterInfo.h" @@ -48,17 +49,37 @@ public: /// @name Helper Methods /// @{ + void Write8(uint8_t Value) { + OS << char(Value); + } + + void Write16(uint16_t Value) { + if (IsLSB) { + Write8(uint8_t(Value >> 0)); + Write8(uint8_t(Value >> 8)); + } else { + Write8(uint8_t(Value >> 8)); + Write8(uint8_t(Value >> 0)); + } + } + void Write32(uint32_t Value) { if (IsLSB) { - OS << char(Value >> 0); - OS << char(Value >> 8); - OS << char(Value >> 16); - OS << char(Value >> 24); + Write16(uint16_t(Value >> 0)); + Write16(uint16_t(Value >> 16)); + } else { + Write16(uint16_t(Value >> 16)); + Write16(uint16_t(Value >> 0)); + } + } + + void Write64(uint64_t Value) { + if (IsLSB) { + Write32(uint32_t(Value >> 0)); + Write32(uint32_t(Value >> 32)); } else { - OS << char(Value >> 24); - OS << char(Value >> 16); - OS << char(Value >> 8); - OS << char(Value >> 0); + Write32(uint32_t(Value >> 32)); + Write32(uint32_t(Value >> 0)); } } @@ -115,7 +136,12 @@ public: Write32(CmdSize); } - void WriteSegmentLoadCommand32(unsigned NumSections) { + /// WriteSegmentLoadCommand32 - Write a 32-bit segment load command. + /// + /// \arg NumSections - The number of sections in this segment. + /// \arg SectionDataSize - The total size of the sections. + void WriteSegmentLoadCommand32(unsigned NumSections, + uint64_t SectionDataSize) { // struct segment_command (56 bytes) uint64_t Start = OS.tell(); @@ -126,10 +152,10 @@ public: WriteString("", 16); Write32(0); // vmaddr - Write32(0); // vmsize + Write32(SectionDataSize); // vmsize Write32(Header32Size + SegmentLoadCommand32Size + NumSections * Section32Size); // file offset - Write32(0); // file size + Write32(SectionDataSize); // file size Write32(0x7); // maxprot Write32(0x7); // initprot Write32(NumSections); @@ -169,12 +195,21 @@ public: /* *** */ -MCFragment::MCFragment(MCSectionData *SD) +MCFragment::MCFragment() : Kind(FragmentType(~0)) { +} + +MCFragment::MCFragment(FragmentType _Kind, MCSectionData *SD) + : Kind(_Kind), + FileOffset(~UINT64_C(0)), + FileSize(~UINT64_C(0)) { if (SD) SD->getFragmentList().push_back(this); } +MCFragment::~MCFragment() { +} + /* *** */ MCSectionData::MCSectionData() : Section(*(MCSection*)0) {} @@ -182,17 +217,13 @@ MCSectionData::MCSectionData() : Section(*(MCSection*)0) {} MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) : Section(_Section), Alignment(1), - FileOffset(0), - FileSize(0) + FileOffset(~UINT64_C(0)), + FileSize(~UINT64_C(0)) { if (A) A->getSectionList().push_back(this); } -void MCSectionData::WriteFileData(raw_ostream &OS) const { - -} - /* *** */ MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {} @@ -200,21 +231,97 @@ MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {} MCAssembler::~MCAssembler() { } +void MCAssembler::LayoutSection(MCSectionData &SD) { + uint64_t Offset = SD.getFileOffset(); + + for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) { + MCFragment &F = *it; + F.setFileOffset(Offset); + F.setFileSize(F.getMaxFileSize()); + Offset += F.getFileSize(); + } + + // FIXME: Pad section? + SD.setFileSize(Offset - SD.getFileOffset()); +} + +/// WriteFileData - Write the \arg F data to the output file. +static void WriteFileData(raw_ostream &OS, const MCFragment &F, + MachObjectWriter &MOW) { + uint64_t Start = OS.tell(); + (void) Start; + + // FIXME: Embed in fragments instead? + switch (F.getKind()) { + default: + assert(0 && "Invalid section kind!"); + + case MCFragment::FT_Data: + OS << cast<MCDataFragment>(F).getContents().str(); + break; + + case MCFragment::FT_Align: + llvm_unreachable("FIXME: Not yet implemented!"); + + case MCFragment::FT_Fill: { + MCFillFragment &FF = cast<MCFillFragment>(F); + + if (!FF.getValue().isAbsolute()) + llvm_unreachable("FIXME: Not yet implemented!"); + + for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) { + switch (FF.getValueSize()) { + default: + assert(0 && "Invalid size!"); + case 1: MOW.Write8 (uint8_t (FF.getValue().getConstant())); break; + case 2: MOW.Write16(uint16_t(FF.getValue().getConstant())); break; + case 4: MOW.Write32(uint32_t(FF.getValue().getConstant())); break; + case 8: MOW.Write64(uint64_t(FF.getValue().getConstant())); break; + } + } + break; + } + + case MCFragment::FT_Org: + llvm_unreachable("FIXME: Not yet implemented!"); + } + + assert(OS.tell() - Start == F.getFileSize()); +} + +/// WriteFileData - Write the \arg SD data to the output file. +static void WriteFileData(raw_ostream &OS, const MCSectionData &SD, + MachObjectWriter &MOW) { + uint64_t Start = OS.tell(); + (void) Start; + + for (MCSectionData::const_iterator it = SD.begin(), + ie = SD.end(); it != ie; ++it) + WriteFileData(OS, *it, MOW); + + assert(OS.tell() - Start == SD.getFileSize()); +} + void MCAssembler::Finish() { unsigned NumSections = Sections.size(); - - // Compute the file offsets so we can write in a single pass. + + // Layout the sections and fragments. uint64_t Offset = MachObjectWriter::getPrologSize32(NumSections); + uint64_t SectionDataSize = 0; for (iterator it = begin(), ie = end(); it != ie; ++it) { it->setFileOffset(Offset); + + LayoutSection(*it); + Offset += it->getFileSize(); + SectionDataSize += it->getFileSize(); } MachObjectWriter MOW(OS); // Write the prolog, starting with the header and load command... MOW.WriteHeader32(NumSections); - MOW.WriteSegmentLoadCommand32(NumSections); + MOW.WriteSegmentLoadCommand32(NumSections, SectionDataSize); // ... and then the section headers. for (iterator it = begin(), ie = end(); it != ie; ++it) @@ -222,7 +329,7 @@ void MCAssembler::Finish() { // Finally, write the section data. for (iterator it = begin(), ie = end(); it != ie; ++it) - it->WriteFileData(OS); - + WriteFileData(OS, *it, MOW); + OS.flush(); } |