MC: Direct all {fragment,section,symbol} address access through the MCAsmLayout object.
[oota-llvm.git] / include / llvm / MC / MCObjectWriter.h
1 //===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLVM_MC_MCOBJECTWRITER_H
11 #define LLVM_MC_MCOBJECTWRITER_H
12
13 #include "llvm/Support/raw_ostream.h"
14 #include "llvm/System/DataTypes.h"
15 #include <cassert>
16
17 namespace llvm {
18 class MCAsmFixup;
19 class MCAsmLayout;
20 class MCAssembler;
21 class MCFragment;
22 class MCValue;
23 class raw_ostream;
24
25 /// MCObjectWriter - Defines the object file and target independent interfaces
26 /// used by the assembler backend to write native file format object files.
27 ///
28 /// The object writer contains a few callbacks used by the assembler to allow
29 /// the object writer to modify the assembler data structures at appropriate
30 /// points. Once assembly is complete, the object writer is given the
31 /// MCAssembler instance, which contains all the symbol and section data which
32 /// should be emitted as part of WriteObject().
33 ///
34 /// The object writer also contains a number of helper methods for writing
35 /// binary data to the output stream.
36 class MCObjectWriter {
37   MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
38   void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
39
40 protected:
41   raw_ostream &OS;
42
43   unsigned IsLittleEndian : 1;
44
45 protected: // Can only create subclasses.
46   MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
47     : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
48
49 public:
50   virtual ~MCObjectWriter();
51
52   bool isLittleEndian() { return IsLittleEndian; }
53
54   raw_ostream &getStream() { return OS; }
55
56   /// @name High-Level API
57   /// @{
58
59   /// Perform any late binding of symbols (for example, to assign symbol indices
60   /// for use when generating relocations).
61   ///
62   /// This routine is called by the assembler after layout and relaxation is
63   /// complete.
64   virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0;
65
66   /// Record a relocation entry.
67   ///
68   /// This routine is called by the assembler after layout and relaxation, and
69   /// post layout binding. The implementation is responsible for storing
70   /// information about the relocation so that it can be emitted during
71   /// WriteObject().
72   virtual void RecordRelocation(const MCAssembler &Asm,
73                                 const MCAsmLayout &Layout,
74                                 const MCFragment *Fragment,
75                                 const MCAsmFixup &Fixup, MCValue Target,
76                                 uint64_t &FixedValue) = 0;
77
78   /// Write the object file.
79   ///
80   /// This routine is called by the assembler after layout and relaxation is
81   /// complete, fixups have been evaluate and applied, and relocations
82   /// generated.
83   virtual void WriteObject(const MCAssembler &Asm,
84                            const MCAsmLayout &Layout) = 0;
85
86   /// @}
87   /// @name Binary Output
88   /// @{
89
90   void Write8(uint8_t Value) {
91     OS << char(Value);
92   }
93
94   void WriteLE16(uint16_t Value) {
95     Write8(uint8_t(Value >> 0));
96     Write8(uint8_t(Value >> 8));
97   }
98
99   void WriteLE32(uint32_t Value) {
100     WriteLE16(uint16_t(Value >> 0));
101     WriteLE16(uint16_t(Value >> 16));
102   }
103
104   void WriteLE64(uint64_t Value) {
105     WriteLE32(uint32_t(Value >> 0));
106     WriteLE32(uint32_t(Value >> 32));
107   }
108
109   void WriteBE16(uint16_t Value) {
110     Write8(uint8_t(Value >> 8));
111     Write8(uint8_t(Value >> 0));
112   }
113
114   void WriteBE32(uint32_t Value) {
115     WriteBE16(uint16_t(Value >> 16));
116     WriteBE16(uint16_t(Value >> 0));
117   }
118
119   void WriteBE64(uint64_t Value) {
120     WriteBE32(uint32_t(Value >> 32));
121     WriteBE32(uint32_t(Value >> 0));
122   }
123
124   void Write16(uint16_t Value) {
125     if (IsLittleEndian)
126       WriteLE16(Value);
127     else
128       WriteBE16(Value);
129   }
130
131   void Write32(uint32_t Value) {
132     if (IsLittleEndian)
133       WriteLE32(Value);
134     else
135       WriteBE32(Value);
136   }
137
138   void Write64(uint64_t Value) {
139     if (IsLittleEndian)
140       WriteLE64(Value);
141     else
142       WriteBE64(Value);
143   }
144
145   void WriteZeros(unsigned N) {
146     const char Zeros[16] = { 0 };
147
148     for (unsigned i = 0, e = N / 16; i != e; ++i)
149       OS << StringRef(Zeros, 16);
150
151     OS << StringRef(Zeros, N % 16);
152   }
153
154   void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
155     OS << Str;
156     if (ZeroFillSize)
157       WriteZeros(ZeroFillSize - Str.size());
158   }
159
160   /// @}
161 };
162
163 } // End llvm namespace
164
165 #endif