mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
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
This commit is contained in:
@@ -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 {
|
||||
OS << char(Value >> 24);
|
||||
OS << char(Value >> 16);
|
||||
OS << char(Value >> 8);
|
||||
OS << char(Value >> 0);
|
||||
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 {
|
||||
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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user