aboutsummaryrefslogtreecommitdiff
path: root/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-08-21 18:29:01 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-08-21 18:29:01 +0000
commit0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4 (patch)
tree6a94c62766d730622c20c3a2ab24da931415e57e /lib/MC/MCAssembler.cpp
parent7178010a168a378df5d9be95956093a3e5f963fd (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.cpp153
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();
}