From d6f761e0eb610936a6b8495360b62696dcd85164 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 21 Aug 2009 23:07:38 +0000 Subject: llvm-mc/Mach-O: Support .o emission for .org and .align. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79684 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCAssembler.h | 28 +++++------- lib/MC/MCAssembler.cpp | 104 +++++++++++++++++++++++++++++++++++------- lib/MC/MCMachOStreamer.cpp | 4 +- test/MC/MachO/data.s | 15 ++++-- 4 files changed, 113 insertions(+), 38 deletions(-) diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index a5739f2bc9..17de0b68b4 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -64,7 +64,7 @@ public: FragmentType getKind() const { return Kind; } // FIXME: This should be abstract, fix sentinel. - virtual unsigned getMaxFileSize() const { + virtual uint64_t getMaxFileSize() const { assert(0 && "Invalid getMaxFileSize call !"); }; @@ -102,7 +102,7 @@ public: /// @name Accessors /// @{ - unsigned getMaxFileSize() const { + uint64_t getMaxFileSize() const { return Contents.size(); } @@ -141,7 +141,7 @@ public: /// @name Accessors /// @{ - unsigned getMaxFileSize() const { + uint64_t getMaxFileSize() const { return std::max(Alignment - 1, MaxBytesToEmit); } @@ -180,7 +180,7 @@ public: /// @name Accessors /// @{ - unsigned getMaxFileSize() const { + uint64_t getMaxFileSize() const { return ValueSize * Count; } @@ -203,29 +203,23 @@ class MCOrgFragment : public MCFragment { MCValue Offset; /// Value - Value to use for filling bytes. - int64_t Value; - - /// ValueSize - The size (in bytes) of \arg Value to use when filling. - unsigned ValueSize; + int8_t Value; public: - MCOrgFragment(MCValue _Offset, int64_t _Value, unsigned _ValueSize, - MCSectionData *SD = 0) + MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0) : MCFragment(FT_Org, SD), - Offset(_Offset), Value(_Value), ValueSize(_ValueSize) {} + Offset(_Offset), Value(_Value) {} /// @name Accessors /// @{ - unsigned getMaxFileSize() const { - // FIXME - return 0; + uint64_t getMaxFileSize() const { + // FIXME: This doesn't make much sense. + return ~UINT64_C(0); } MCValue getOffset() const { return Offset; } - int64_t getValue() const { return Value; } - - unsigned getValueSize() const { return ValueSize; } + uint8_t getValue() const { return Value; } /// @} diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 883cabe45c..9d8c3c5600 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAssembler.h" + +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -232,17 +234,58 @@ MCAssembler::~MCAssembler() { } void MCAssembler::LayoutSection(MCSectionData &SD) { - uint64_t Offset = SD.getFileOffset(); + uint64_t FileOffset = SD.getFileOffset(); + uint64_t SectionOffset = 0; 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(); + + F.setFileOffset(FileOffset); + + // Evaluate fragment size. + switch (F.getKind()) { + case MCFragment::FT_Align: { + MCAlignFragment &AF = cast(F); + + uint64_t AlignedOffset = + RoundUpToAlignment(SectionOffset, AF.getAlignment()); + uint64_t PaddingBytes = AlignedOffset - SectionOffset; + + 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(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. + if (OrgOffset < SectionOffset) + llvm_report_error("invalid .org offset '" + Twine(OrgOffset) + + "' (section offset '" + Twine(SectionOffset) + "'"); + + F.setFileSize(OrgOffset - SectionOffset); + break; + } + } + + FileOffset += F.getFileSize(); + SectionOffset += F.getFileSize(); } // FIXME: Pad section? - SD.setFileSize(Offset - SD.getFileOffset()); + SD.setFileSize(FileOffset - SD.getFileOffset()); } /// WriteFileData - Write the \arg F data to the output file. @@ -251,39 +294,68 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F, uint64_t Start = OS.tell(); (void) Start; + assert(F.getFileOffset() == Start && "Invalid file offset!"); + // FIXME: Embed in fragments instead? switch (F.getKind()) { - default: - assert(0 && "Invalid section kind!"); + case MCFragment::FT_Align: { + MCAlignFragment &AF = cast(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; + } case MCFragment::FT_Data: OS << cast(F).getContents().str(); break; - case MCFragment::FT_Align: - llvm_unreachable("FIXME: Not yet implemented!"); - case MCFragment::FT_Fill: { MCFillFragment &FF = cast(F); if (!FF.getValue().isAbsolute()) llvm_unreachable("FIXME: Not yet implemented!"); + int64_t Value = FF.getValue().getConstant(); 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; + 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; } } break; } - case MCFragment::FT_Org: - llvm_unreachable("FIXME: Not yet implemented!"); + case MCFragment::FT_Org: { + MCOrgFragment &OF = cast(F); + + for (uint64_t i = 0, e = OF.getFileSize(); i != e; ++i) + MOW.Write8(uint8_t(OF.getValue())); + + break; + } } assert(OS.tell() - Start == F.getFileSize()); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 0ad03273cf..316051ce01 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -150,6 +150,8 @@ void MCMachOStreamer::EmitValue(const MCValue &Value, unsigned Size) { void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, unsigned ValueSize, unsigned MaxBytesToEmit) { + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, CurSectionData); @@ -160,7 +162,7 @@ void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, void MCMachOStreamer::EmitValueToOffset(const MCValue &Offset, unsigned char Value) { - new MCOrgFragment(Offset, Value, 1, CurSectionData); + new MCOrgFragment(Offset, Value, CurSectionData); } void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { diff --git a/test/MC/MachO/data.s b/test/MC/MachO/data.s index 3d39b53593..56979b61f2 100644 --- a/test/MC/MachO/data.s +++ b/test/MC/MachO/data.s @@ -6,6 +6,13 @@ .short 0xABCD .long 0xABCDABCD .quad 0xABCDABCDABCDABCD +.org 30 + .long 0xF000 // 34 + .p2align 3, 0xAB // 40 (0xAB * 6) + .short 0 // 42 + .p2alignw 3, 0xABCD // 48 (0xABCD * 2) + .short 0 // 50 + .p2alignw 3, 0xABCD, 5 // 50 // CHECK: ('cputype', 7) // CHECK: ('cpusubtype', 3) @@ -19,9 +26,9 @@ // CHECK: ('size', 192) // CHECK: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') // CHECK: ('vm_addr', 0) -// CHECK: ('vm_size', 20) +// CHECK: ('vm_size', 50) // CHECK: ('file_offset', 220) -// CHECK: ('file_size', 20) +// CHECK: ('file_size', 50) // CHECK: ('maxprot', 7) // CHECK: ('initprot', 7) // CHECK: ('num_sections', 2) @@ -44,9 +51,9 @@ // CHECK: (('section_name', '__data\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') // CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') // CHECK: ('address', 0) -// CHECK: ('size', 20) +// CHECK: ('size', 50) // CHECK: ('offset', 220) -// CHECK: ('alignment', 0) +// CHECK: ('alignment', 3) // CHECK: ('reloc_offset', 0) // CHECK: ('num_reloc', 0) // CHECK: ('flags', 0x0) -- cgit v1.2.3