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 /include | |
parent | 7178010a168a378df5d9be95956093a3e5f963fd (diff) | |
download | external_llvm-0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4.zip external_llvm-0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4.tar.gz external_llvm-0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4.tar.bz2 |
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 'include')
-rw-r--r-- | include/llvm/MC/MCAssembler.h | 256 |
1 files changed, 246 insertions, 10 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index b2a2415..a5739f2 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -10,8 +10,11 @@ #ifndef LLVM_MC_MCASSEMBLER_H #define LLVM_MC_MCASSEMBLER_H +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -25,7 +28,211 @@ class MCFragment : public ilist_node<MCFragment> { void operator=(const MCFragment&); // DO NOT IMPLEMENT public: - MCFragment(MCSectionData *SD = 0); + enum FragmentType { + FT_Data, + FT_Align, + FT_Fill, + FT_Org + }; + +private: + FragmentType Kind; + + /// @name Assembler Backend Data + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// FileOffset - The offset of this section in the object file. This is ~0 + /// until initialized. + uint64_t FileOffset; + + /// FileSize - The size of this section in the object file. This is ~0 until + /// initialized. + uint64_t FileSize; + + /// @} + +protected: + MCFragment(FragmentType _Kind, MCSectionData *SD = 0); + +public: + // Only for sentinel. + MCFragment(); + virtual ~MCFragment(); + + FragmentType getKind() const { return Kind; } + + // FIXME: This should be abstract, fix sentinel. + virtual unsigned getMaxFileSize() const { + assert(0 && "Invalid getMaxFileSize call !"); + }; + + /// @name Assembler Backend Support + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + unsigned getFileSize() const { + assert(FileSize != ~UINT64_C(0) && "File size not set!"); + return FileSize; + } + void setFileSize(uint64_t Value) { + assert(Value <= getMaxFileSize() && "Invalid file size!"); + FileSize = Value; + } + + uint64_t getFileOffset() const { + assert(FileOffset != ~UINT64_C(0) && "File offset not set!"); + return FileOffset; + } + void setFileOffset(uint64_t Value) { FileOffset = Value; } + + /// @} + + static bool classof(const MCFragment *O) { return true; } +}; + +class MCDataFragment : public MCFragment { + SmallString<32> Contents; + +public: + MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} + + /// @name Accessors + /// @{ + + unsigned getMaxFileSize() const { + return Contents.size(); + } + + SmallString<32> &getContents() { return Contents; } + const SmallString<32> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Data; + } + static bool classof(const MCDataFragment *) { return true; } +}; + +class MCAlignFragment : public MCFragment { + /// Alignment - The alignment to ensure, in bytes. + unsigned Alignment; + + /// Value - Value to use for filling padding bytes. + int64_t Value; + + /// ValueSize - The size of the integer (in bytes) of \arg Value. + unsigned ValueSize; + + /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment + /// cannot be satisfied in this width then this fragment is ignored. + unsigned MaxBytesToEmit; + +public: + MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, + unsigned _MaxBytesToEmit, MCSectionData *SD = 0) + : MCFragment(FT_Align, SD), Alignment(_Alignment), + Value(_Value),ValueSize(_ValueSize), + MaxBytesToEmit(_MaxBytesToEmit) {} + + /// @name Accessors + /// @{ + + unsigned getMaxFileSize() const { + return std::max(Alignment - 1, MaxBytesToEmit); + } + + unsigned getAlignment() const { return Alignment; } + + int64_t getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Align; + } + static bool classof(const MCAlignFragment *) { return true; } +}; + +class MCFillFragment : public MCFragment { + /// Value - Value to use for filling bytes. + MCValue Value; + + /// ValueSize - The size (in bytes) of \arg Value to use when filling. + unsigned ValueSize; + + /// Count - The number of copies of \arg Value to insert. + uint64_t Count; + +public: + MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count, + MCSectionData *SD = 0) + : MCFragment(FT_Fill, SD), + Value(_Value), ValueSize(_ValueSize), Count(_Count) {} + + /// @name Accessors + /// @{ + + unsigned getMaxFileSize() const { + return ValueSize * Count; + } + + MCValue getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + uint64_t getCount() const { return Count; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Fill; + } + static bool classof(const MCFillFragment *) { return true; } +}; + +class MCOrgFragment : public MCFragment { + /// Offset - The offset this fragment should start at. + 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; + +public: + MCOrgFragment(MCValue _Offset, int64_t _Value, unsigned _ValueSize, + MCSectionData *SD = 0) + : MCFragment(FT_Org, SD), + Offset(_Offset), Value(_Value), ValueSize(_ValueSize) {} + /// @name Accessors + /// @{ + + unsigned getMaxFileSize() const { + // FIXME + return 0; + } + + MCValue getOffset() const { return Offset; } + + int64_t getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Org; + } + static bool classof(const MCOrgFragment *) { return true; } }; // FIXME: Should this be a separate class, or just merged into MCSection? Since @@ -38,6 +245,9 @@ class MCSectionData : public ilist_node<MCSectionData> { public: typedef iplist<MCFragment> FragmentListType; + typedef FragmentListType::const_iterator const_iterator; + typedef FragmentListType::iterator iterator; + private: iplist<MCFragment> Fragments; const MCSection &Section; @@ -50,10 +260,12 @@ private: // // FIXME: This could all be kept private to the assembler implementation. - /// FileOffset - The offset of this section in the object file. + /// FileOffset - The offset of this section in the object file. This is ~0 + /// until initialized. uint64_t FileOffset; - /// FileSize - The size of this section in the object file. + /// FileSize - The size of this section in the object file. This is ~0 until + /// initialized. uint64_t FileSize; /// @} @@ -63,26 +275,44 @@ public: MCSectionData(); MCSectionData(const MCSection &Section, MCAssembler *A = 0); - const FragmentListType &getFragmentList() const { return Fragments; } - FragmentListType &getFragmentList() { return Fragments; } - const MCSection &getSection() const { return Section; } unsigned getAlignment() const { return Alignment; } void setAlignment(unsigned Value) { Alignment = Value; } + + /// @name Section List Access + /// @{ + + const FragmentListType &getFragmentList() const { return Fragments; } + FragmentListType &getFragmentList() { return Fragments; } + + iterator begin() { return Fragments.begin(); } + const_iterator begin() const { return Fragments.begin(); } + + iterator end() { return Fragments.end(); } + const_iterator end() const { return Fragments.end(); } + + size_t size() const { return Fragments.size(); } + + /// @} /// @name Assembler Backend Support /// @{ // // FIXME: This could all be kept private to the assembler implementation. - unsigned getFileSize() const { return FileSize; } + unsigned getFileSize() const { + assert(FileSize != ~UINT64_C(0) && "File size not set!"); + return FileSize; + } + void setFileSize(uint64_t Value) { FileSize = Value; } - uint64_t getFileOffset() const { return FileOffset; } + uint64_t getFileOffset() const { + assert(FileOffset != ~UINT64_C(0) && "File offset not set!"); + return FileOffset; + } void setFileOffset(uint64_t Value) { FileOffset = Value; } - void WriteFileData(raw_ostream &OS) const; - /// @} }; @@ -101,6 +331,12 @@ private: iplist<MCSectionData> Sections; +private: + /// LayoutSection - Assign offsets and sizes to the fragments in the section + /// \arg SD, and update the section size. The section file offset should + /// already have been computed. + void LayoutSection(MCSectionData &SD); + public: /// Construct a new assembler instance. /// |