llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/MC/MCAssembler.h"
|
2009-08-22 07:07:38 +08:00
|
|
|
|
|
|
|
#include "llvm/ADT/Twine.h"
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
#include "llvm/MC/MCSectionMachO.h"
|
|
|
|
#include "llvm/Support/DataTypes.h"
|
2009-08-22 02:29:01 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/Target/TargetMachOWriterInfo.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class MachObjectWriter {
|
|
|
|
// See <mach-o/loader.h>.
|
|
|
|
enum {
|
|
|
|
Header_Magic32 = 0xFEEDFACE,
|
|
|
|
Header_Magic64 = 0xFEEDFACF
|
|
|
|
};
|
|
|
|
|
|
|
|
static const unsigned Header32Size = 28;
|
|
|
|
static const unsigned Header64Size = 32;
|
|
|
|
static const unsigned SegmentLoadCommand32Size = 56;
|
|
|
|
static const unsigned Section32Size = 68;
|
|
|
|
|
|
|
|
enum HeaderFileType {
|
|
|
|
HFT_Object = 0x1
|
|
|
|
};
|
|
|
|
|
|
|
|
enum LoadCommandType {
|
|
|
|
LCT_Segment = 0x1
|
|
|
|
};
|
|
|
|
|
|
|
|
raw_ostream &OS;
|
|
|
|
bool IsLSB;
|
|
|
|
|
|
|
|
public:
|
|
|
|
MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true)
|
|
|
|
: OS(_OS), IsLSB(_IsLSB) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @name Helper Methods
|
|
|
|
/// @{
|
|
|
|
|
2009-08-22 02:29:01 +08:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
void Write32(uint32_t Value) {
|
|
|
|
if (IsLSB) {
|
2009-08-22 02:29:01 +08:00
|
|
|
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));
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
} else {
|
2009-08-22 02:29:01 +08:00
|
|
|
Write32(uint32_t(Value >> 32));
|
|
|
|
Write32(uint32_t(Value >> 0));
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteZeros(unsigned N) {
|
|
|
|
const char Zeros[16] = { 0 };
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = N / 16; i != e; ++i)
|
|
|
|
OS << StringRef(Zeros, 16);
|
|
|
|
|
|
|
|
OS << StringRef(Zeros, N % 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteString(const StringRef &Str, unsigned ZeroFillSize = 0) {
|
|
|
|
OS << Str;
|
|
|
|
if (ZeroFillSize)
|
|
|
|
WriteZeros(ZeroFillSize - Str.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
|
|
|
|
void WriteHeader32(unsigned NumSections) {
|
|
|
|
// struct mach_header (28 bytes)
|
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
|
|
|
Write32(Header_Magic32);
|
|
|
|
|
|
|
|
// FIXME: Support cputype.
|
|
|
|
Write32(TargetMachOWriterInfo::HDR_CPU_TYPE_I386);
|
|
|
|
|
|
|
|
// FIXME: Support cpusubtype.
|
|
|
|
Write32(TargetMachOWriterInfo::HDR_CPU_SUBTYPE_I386_ALL);
|
|
|
|
|
|
|
|
Write32(HFT_Object);
|
|
|
|
|
|
|
|
// Object files have a single load command, the segment.
|
|
|
|
Write32(1);
|
|
|
|
Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
|
|
|
|
Write32(0); // Flags
|
|
|
|
|
|
|
|
assert(OS.tell() - Start == Header32Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLoadCommandHeader(uint32_t Cmd, uint32_t CmdSize) {
|
|
|
|
assert((CmdSize & 0x3) == 0 && "Invalid size!");
|
|
|
|
|
|
|
|
Write32(Cmd);
|
|
|
|
Write32(CmdSize);
|
|
|
|
}
|
|
|
|
|
2009-08-22 02:29:01 +08:00
|
|
|
/// 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) {
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
// struct segment_command (56 bytes)
|
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
|
|
|
Write32(LCT_Segment);
|
|
|
|
Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
|
|
|
|
|
|
|
|
WriteString("", 16);
|
|
|
|
Write32(0); // vmaddr
|
2009-08-22 02:29:01 +08:00
|
|
|
Write32(SectionDataSize); // vmsize
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
Write32(Header32Size + SegmentLoadCommand32Size +
|
|
|
|
NumSections * Section32Size); // file offset
|
2009-08-22 02:29:01 +08:00
|
|
|
Write32(SectionDataSize); // file size
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
Write32(0x7); // maxprot
|
|
|
|
Write32(0x7); // initprot
|
|
|
|
Write32(NumSections);
|
|
|
|
Write32(0); // flags
|
|
|
|
|
|
|
|
assert(OS.tell() - Start == SegmentLoadCommand32Size);
|
|
|
|
}
|
|
|
|
|
2009-08-22 16:28:27 +08:00
|
|
|
void WriteSection32(const MCSectionData &SD, uint64_t FileOffset) {
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
// struct section (68 bytes)
|
|
|
|
|
|
|
|
uint64_t Start = OS.tell();
|
|
|
|
(void) Start;
|
|
|
|
|
|
|
|
// FIXME: cast<> support!
|
|
|
|
const MCSectionMachO &Section =
|
|
|
|
static_cast<const MCSectionMachO&>(SD.getSection());
|
|
|
|
WriteString(Section.getSectionName(), 16);
|
|
|
|
WriteString(Section.getSegmentName(), 16);
|
|
|
|
Write32(0); // address
|
|
|
|
Write32(SD.getFileSize()); // size
|
2009-08-22 16:28:27 +08:00
|
|
|
Write32(FileOffset);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
|
|
|
|
assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
|
|
|
|
Write32(Log2_32(SD.getAlignment()));
|
|
|
|
Write32(0); // file offset of relocation entries
|
|
|
|
Write32(0); // number of relocation entrions
|
|
|
|
Write32(Section.getTypeAndAttributes());
|
|
|
|
Write32(0); // reserved1
|
|
|
|
Write32(Section.getStubSize()); // reserved2
|
|
|
|
|
|
|
|
assert(OS.tell() - Start == Section32Size);
|
|
|
|
}
|
2009-08-22 16:28:27 +08:00
|
|
|
|
|
|
|
void WriteProlog(MCAssembler &Asm) {
|
|
|
|
unsigned NumSections = Asm.size();
|
|
|
|
|
|
|
|
// Compute the file offsets for all the sections in advance, so that we can
|
|
|
|
// write things out in order.
|
|
|
|
SmallVector<uint64_t, 16> SectionFileOffsets;
|
|
|
|
SectionFileOffsets.resize(NumSections);
|
|
|
|
|
|
|
|
// The section data starts after the header, the segment load command, and
|
|
|
|
// the section headers.
|
|
|
|
uint64_t FileOffset = Header32Size + SegmentLoadCommand32Size +
|
|
|
|
NumSections * Section32Size;
|
|
|
|
uint64_t SectionDataSize = 0;
|
|
|
|
unsigned Index = 0;
|
|
|
|
for (MCAssembler::iterator it = Asm.begin(),
|
|
|
|
ie = Asm.end(); it != ie; ++it, ++Index) {
|
|
|
|
SectionFileOffsets[Index] = FileOffset;
|
|
|
|
FileOffset += it->getFileSize();
|
|
|
|
SectionDataSize += it->getFileSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the prolog, starting with the header and load command...
|
|
|
|
WriteHeader32(NumSections);
|
|
|
|
WriteSegmentLoadCommand32(NumSections, SectionDataSize);
|
|
|
|
|
|
|
|
// ... and then the section headers.
|
|
|
|
Index = 0;
|
|
|
|
for (MCAssembler::iterator it = Asm.begin(),
|
|
|
|
ie = Asm.end(); it != ie; ++it, ++Index)
|
|
|
|
WriteSection32(*it, SectionFileOffsets[Index]);
|
|
|
|
}
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *** */
|
|
|
|
|
2009-08-22 02:29:01 +08:00
|
|
|
MCFragment::MCFragment() : Kind(FragmentType(~0)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
MCFragment::MCFragment(FragmentType _Kind, MCSectionData *SD)
|
|
|
|
: Kind(_Kind),
|
|
|
|
FileSize(~UINT64_C(0))
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
{
|
|
|
|
if (SD)
|
|
|
|
SD->getFragmentList().push_back(this);
|
|
|
|
}
|
|
|
|
|
2009-08-22 02:29:01 +08:00
|
|
|
MCFragment::~MCFragment() {
|
|
|
|
}
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
/* *** */
|
|
|
|
|
|
|
|
MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
|
|
|
|
|
|
|
|
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
|
|
|
: Section(_Section),
|
|
|
|
Alignment(1),
|
2009-08-22 02:29:01 +08:00
|
|
|
FileSize(~UINT64_C(0))
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
{
|
|
|
|
if (A)
|
|
|
|
A->getSectionList().push_back(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *** */
|
|
|
|
|
|
|
|
MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {}
|
|
|
|
|
|
|
|
MCAssembler::~MCAssembler() {
|
|
|
|
}
|
|
|
|
|
2009-08-22 02:29:01 +08:00
|
|
|
void MCAssembler::LayoutSection(MCSectionData &SD) {
|
2009-08-22 16:27:54 +08:00
|
|
|
uint64_t Offset = 0;
|
2009-08-22 02:29:01 +08:00
|
|
|
|
|
|
|
for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
|
|
|
|
MCFragment &F = *it;
|
2009-08-22 07:07:38 +08:00
|
|
|
|
2009-08-22 16:27:54 +08:00
|
|
|
F.setOffset(Offset);
|
2009-08-22 07:07:38 +08:00
|
|
|
|
|
|
|
// Evaluate fragment size.
|
|
|
|
switch (F.getKind()) {
|
|
|
|
case MCFragment::FT_Align: {
|
|
|
|
MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
|
|
|
|
2009-08-22 16:27:54 +08:00
|
|
|
uint64_t AlignedOffset = RoundUpToAlignment(Offset, AF.getAlignment());
|
|
|
|
uint64_t PaddingBytes = AlignedOffset - Offset;
|
2009-08-22 07:07:38 +08:00
|
|
|
|
|
|
|
if (PaddingBytes > AF.getMaxBytesToEmit())
|
|
|
|
AF.setFileSize(0);
|
|
|
|
else
|
|
|
|
AF.setFileSize(PaddingBytes);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case MCFragment::FT_Data:
|
|
|
|
case MCFragment::FT_Fill:
|
|
|
|
F.setFileSize(F.getMaxFileSize());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MCFragment::FT_Org: {
|
|
|
|
MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
|
|
|
|
|
|
|
if (!OF.getOffset().isAbsolute())
|
|
|
|
llvm_unreachable("FIXME: Not yet implemented!");
|
|
|
|
uint64_t OrgOffset = OF.getOffset().getConstant();
|
|
|
|
|
|
|
|
// FIXME: We need a way to communicate this error.
|
2009-08-22 16:27:54 +08:00
|
|
|
if (OrgOffset < Offset)
|
2009-08-22 07:07:38 +08:00
|
|
|
llvm_report_error("invalid .org offset '" + Twine(OrgOffset) +
|
2009-08-22 16:27:54 +08:00
|
|
|
"' (section offset '" + Twine(Offset) + "'");
|
2009-08-22 07:07:38 +08:00
|
|
|
|
2009-08-22 16:27:54 +08:00
|
|
|
F.setFileSize(OrgOffset - Offset);
|
2009-08-22 07:07:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-22 16:27:54 +08:00
|
|
|
Offset += F.getFileSize();
|
2009-08-22 02:29:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Pad section?
|
2009-08-22 16:27:54 +08:00
|
|
|
SD.setFileSize(Offset);
|
2009-08-22 02:29:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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()) {
|
2009-08-22 07:07:38 +08:00
|
|
|
case MCFragment::FT_Align: {
|
|
|
|
MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
|
|
|
uint64_t Count = AF.getFileSize() / 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())
|
|
|
|
llvm_report_error("undefined .align directive, value size '" +
|
|
|
|
Twine(AF.getValueSize()) +
|
|
|
|
"' is not a divisor of padding size '" +
|
|
|
|
Twine(AF.getFileSize()) + "'");
|
|
|
|
|
|
|
|
for (uint64_t i = 0; i != Count; ++i) {
|
|
|
|
switch (AF.getValueSize()) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid size!");
|
|
|
|
case 1: MOW.Write8 (uint8_t (AF.getValue())); break;
|
|
|
|
case 2: MOW.Write16(uint16_t(AF.getValue())); break;
|
|
|
|
case 4: MOW.Write32(uint32_t(AF.getValue())); break;
|
|
|
|
case 8: MOW.Write64(uint64_t(AF.getValue())); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-08-22 02:29:01 +08:00
|
|
|
|
|
|
|
case MCFragment::FT_Data:
|
|
|
|
OS << cast<MCDataFragment>(F).getContents().str();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MCFragment::FT_Fill: {
|
|
|
|
MCFillFragment &FF = cast<MCFillFragment>(F);
|
|
|
|
|
|
|
|
if (!FF.getValue().isAbsolute())
|
|
|
|
llvm_unreachable("FIXME: Not yet implemented!");
|
2009-08-22 07:07:38 +08:00
|
|
|
int64_t Value = FF.getValue().getConstant();
|
2009-08-22 02:29:01 +08:00
|
|
|
|
|
|
|
for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
|
|
|
|
switch (FF.getValueSize()) {
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid size!");
|
2009-08-22 07:07:38 +08:00
|
|
|
case 1: MOW.Write8 (uint8_t (Value)); break;
|
|
|
|
case 2: MOW.Write16(uint16_t(Value)); break;
|
|
|
|
case 4: MOW.Write32(uint32_t(Value)); break;
|
|
|
|
case 8: MOW.Write64(uint64_t(Value)); break;
|
2009-08-22 02:29:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-08-22 07:07:38 +08:00
|
|
|
case MCFragment::FT_Org: {
|
|
|
|
MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
|
|
|
|
|
|
|
for (uint64_t i = 0, e = OF.getFileSize(); i != e; ++i)
|
|
|
|
MOW.Write8(uint8_t(OF.getValue()));
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2009-08-22 02:29:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
void MCAssembler::Finish() {
|
2009-08-22 02:29:01 +08:00
|
|
|
// Layout the sections and fragments.
|
2009-08-22 16:28:27 +08:00
|
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it)
|
2009-08-22 02:29:01 +08:00
|
|
|
LayoutSection(*it);
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
MachObjectWriter MOW(OS);
|
|
|
|
|
2009-08-22 16:28:27 +08:00
|
|
|
// Write the prolog, followed by the data for all the sections & fragments.
|
|
|
|
MOW.WriteProlog(*this);
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
|
2009-08-22 16:28:27 +08:00
|
|
|
// FIXME: This should move into the Mach-O writer, it should have control over
|
|
|
|
// what goes where.
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it)
|
2009-08-22 02:29:01 +08:00
|
|
|
WriteFileData(OS, *it, MOW);
|
|
|
|
|
llvm-mc: Start MCAssembler and MCMachOStreamer.
- Together these form the (Mach-O) back end of the assembler.
- MCAssembler is the actual assembler backend, which is designed to have a
reasonable API. This will eventually grow to support multiple object file
implementations, but for now its Mach-O/i386 only.
- MCMachOStreamer adapts the MCStreamer "actions" API to the MCAssembler API,
e.g. converting the various directives into fragments, managing state like
the current section, and so on.
- llvm-mc will use the new backend via '-filetype=obj', which may eventually
be, but is not yet, since I hear that people like assemblers which actually
assemble.
- The only thing that works at the moment is changing sections. For the time
being I have a Python Mach-O dumping tool in test/scripts so this stuff can
be easily tested, eventually I expect to replace this with a real LLVM tool.
- More doxyments to come.
I assume that since this stuff doesn't touch any of the things which are part of
2.6 that it is ok to put this in not so long before the freeze, but if someone
objects let me know, I can pull it.
llvm-svn: 79612
2009-08-21 17:11:24 +08:00
|
|
|
OS.flush();
|
|
|
|
}
|