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