summaryrefslogtreecommitdiff
path: root/include
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 /include
parent7178010a168a378df5d9be95956093a3e5f963fd (diff)
downloadllvm-0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4.tar.gz
llvm-0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4.tar.bz2
llvm-0705fbf52fcaade0c6b9d5d33bec163ee4c2daf4.tar.xz
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.h256
1 files changed, 246 insertions, 10 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index b2a24159a7..a5739f2bc9 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.
///