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