Sorry for such a large commit. The summary is that only MachO cares about the
[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/ADT/Triple.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/Support/DataTypes.h"
16 #include <cassert>
17
18 namespace llvm {
19 class MCAsmLayout;
20 class MCAssembler;
21 class MCFixup;
22 class MCFragment;
23 class MCValue;
24 class raw_ostream;
25
26 /// MCObjectWriter - Defines the object file and target independent interfaces
27 /// used by the assembler backend to write native file format object files.
28 ///
29 /// The object writer contains a few callbacks used by the assembler to allow
30 /// the object writer to modify the assembler data structures at appropriate
31 /// points. Once assembly is complete, the object writer is given the
32 /// MCAssembler instance, which contains all the symbol and section data which
33 /// should be emitted as part of WriteObject().
34 ///
35 /// The object writer also contains a number of helper methods for writing
36 /// binary data to the output stream.
37 class MCObjectWriter {
38   MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
39   void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
40
41 protected:
42   raw_ostream &OS;
43
44   unsigned IsLittleEndian : 1;
45
46 protected: // Can only create subclasses.
47   MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
48     : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
49
50 public:
51   virtual ~MCObjectWriter();
52
53   bool isLittleEndian() const { return IsLittleEndian; }
54
55   raw_ostream &getStream() { return OS; }
56
57   /// @name High-Level API
58   /// @{
59
60   /// Perform any late binding of symbols (for example, to assign symbol indices
61   /// for use when generating relocations).
62   ///
63   /// This routine is called by the assembler after layout and relaxation is
64   /// complete.
65   virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
66                                         const MCAsmLayout &Layout) = 0;
67
68   /// Record a relocation entry.
69   ///
70   /// This routine is called by the assembler after layout and relaxation, and
71   /// post layout binding. The implementation is responsible for storing
72   /// information about the relocation so that it can be emitted during
73   /// WriteObject().
74   virtual void RecordRelocation(const MCAssembler &Asm,
75                                 const MCAsmLayout &Layout,
76                                 const MCFragment *Fragment,
77                                 const MCFixup &Fixup, MCValue Target,
78                                 uint64_t &FixedValue) = 0;
79
80   /// Check if a fixup is fully resolved.
81   ///
82   /// This routine is used by the assembler to let the file format decide
83   /// if a fixup is not fully resolved. For example, one that crosses
84   /// two sections on ELF.
85   virtual bool IsFixupFullyResolved(const MCAssembler &Asm,
86                                     const MCValue Target,
87                                     bool IsPCRel,
88                                     const MCFragment *DF) const = 0;
89
90   /// Write the object file.
91   ///
92   /// This routine is called by the assembler after layout and relaxation is
93   /// complete, fixups have been evaluated and applied, and relocations
94   /// generated.
95   virtual void WriteObject(MCAssembler &Asm,
96                            const MCAsmLayout &Layout) = 0;
97
98   /// @}
99   /// @name Binary Output
100   /// @{
101
102   void Write8(uint8_t Value) {
103     OS << char(Value);
104   }
105
106   void WriteLE16(uint16_t Value) {
107     Write8(uint8_t(Value >> 0));
108     Write8(uint8_t(Value >> 8));
109   }
110
111   void WriteLE32(uint32_t Value) {
112     WriteLE16(uint16_t(Value >> 0));
113     WriteLE16(uint16_t(Value >> 16));
114   }
115
116   void WriteLE64(uint64_t Value) {
117     WriteLE32(uint32_t(Value >> 0));
118     WriteLE32(uint32_t(Value >> 32));
119   }
120
121   void WriteBE16(uint16_t Value) {
122     Write8(uint8_t(Value >> 8));
123     Write8(uint8_t(Value >> 0));
124   }
125
126   void WriteBE32(uint32_t Value) {
127     WriteBE16(uint16_t(Value >> 16));
128     WriteBE16(uint16_t(Value >> 0));
129   }
130
131   void WriteBE64(uint64_t Value) {
132     WriteBE32(uint32_t(Value >> 32));
133     WriteBE32(uint32_t(Value >> 0));
134   }
135
136   void Write16(uint16_t Value) {
137     if (IsLittleEndian)
138       WriteLE16(Value);
139     else
140       WriteBE16(Value);
141   }
142
143   void Write32(uint32_t Value) {
144     if (IsLittleEndian)
145       WriteLE32(Value);
146     else
147       WriteBE32(Value);
148   }
149
150   void Write64(uint64_t Value) {
151     if (IsLittleEndian)
152       WriteLE64(Value);
153     else
154       WriteBE64(Value);
155   }
156
157   void WriteZeros(unsigned N) {
158     const char Zeros[16] = { 0 };
159
160     for (unsigned i = 0, e = N / 16; i != e; ++i)
161       OS << StringRef(Zeros, 16);
162
163     OS << StringRef(Zeros, N % 16);
164   }
165
166   void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
167     assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
168       "data size greater than fill size, unexpected large write will occur");
169     OS << Str;
170     if (ZeroFillSize)
171       WriteZeros(ZeroFillSize - Str.size());
172   }
173
174   /// @}
175
176   /// Utility function to encode a SLEB128 value.
177   static void EncodeSLEB128(int64_t Value, raw_ostream &OS);
178   /// Utility function to encode a ULEB128 value.
179   static void EncodeULEB128(uint64_t Value, raw_ostream &OS);
180 };
181
182 MCObjectWriter *createMachObjectWriter(raw_ostream &OS, bool is64Bit,
183                                        uint32_t CPUType, uint32_t CPUSubtype,
184                                        bool IsLittleEndian);
185 MCObjectWriter *createELFObjectWriter(raw_ostream &OS, bool is64Bit,
186                                       Triple::OSType OSType, uint16_t EMachine,
187                                       bool IsLittleEndian,
188                                       bool HasRelocationAddend);
189 MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
190
191 } // End llvm namespace
192
193 #endif