f0e86a7cc83dfe18f79496b70c51e9592c71f945
[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/SmallVector.h"
14 #include "llvm/Support/Compiler.h"
15 #include "llvm/Support/DataTypes.h"
16 #include "llvm/Support/EndianStream.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <cassert>
19
20 namespace llvm {
21 class MCAsmLayout;
22 class MCAssembler;
23 class MCFixup;
24 class MCFragment;
25 class MCSymbolData;
26 class MCSymbolRefExpr;
27 class MCValue;
28
29 /// MCObjectWriter - Defines the object file and target independent interfaces
30 /// used by the assembler backend to write native file format object files.
31 ///
32 /// The object writer contains a few callbacks used by the assembler to allow
33 /// the object writer to modify the assembler data structures at appropriate
34 /// points. Once assembly is complete, the object writer is given the
35 /// MCAssembler instance, which contains all the symbol and section data which
36 /// should be emitted as part of WriteObject().
37 ///
38 /// The object writer also contains a number of helper methods for writing
39 /// binary data to the output stream.
40 class MCObjectWriter {
41   MCObjectWriter(const MCObjectWriter &) = delete;
42   void operator=(const MCObjectWriter &) = delete;
43
44 protected:
45   raw_ostream &OS;
46
47   unsigned IsLittleEndian : 1;
48
49 protected: // Can only create subclasses.
50   MCObjectWriter(raw_ostream &OS, bool IsLittleEndian)
51       : OS(OS), IsLittleEndian(IsLittleEndian) {}
52
53 public:
54   virtual ~MCObjectWriter();
55
56   /// lifetime management
57   virtual void reset() { }
58
59   bool isLittleEndian() const { return IsLittleEndian; }
60
61   raw_ostream &getStream() { return OS; }
62
63   /// @name High-Level API
64   /// @{
65
66   /// \brief Perform any late binding of symbols (for example, to assign symbol
67   /// indices for use when generating relocations).
68   ///
69   /// This routine is called by the assembler after layout and relaxation is
70   /// complete.
71   virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
72                                         const MCAsmLayout &Layout) = 0;
73
74   /// \brief Record a relocation entry.
75   ///
76   /// This routine is called by the assembler after layout and relaxation, and
77   /// post layout binding. The implementation is responsible for storing
78   /// information about the relocation so that it can be emitted during
79   /// WriteObject().
80   virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
81                                 const MCFragment *Fragment,
82                                 const MCFixup &Fixup, MCValue Target,
83                                 bool &IsPCRel, uint64_t &FixedValue) = 0;
84
85   /// \brief Check whether the difference (A - B) between two symbol
86   /// references is fully resolved.
87   ///
88   /// Clients are not required to answer precisely and may conservatively return
89   /// false, even when a difference is fully resolved.
90   bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
91                                           const MCSymbolRefExpr *A,
92                                           const MCSymbolRefExpr *B,
93                                           bool InSet) const;
94
95   virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
96                                                       const MCSymbolData &DataA,
97                                                       const MCSymbolData *DataB,
98                                                       const MCFragment &FB,
99                                                       bool InSet,
100                                                       bool IsPCRel) const;
101
102   /// \brief True if this symbol (which is a variable) is weak. This is not
103   /// just STB_WEAK, but more generally whether or not we can evaluate
104   /// past it.
105   virtual bool isWeak(const MCSymbolData &SD) const;
106
107   /// \brief Write the object file.
108   ///
109   /// This routine is called by the assembler after layout and relaxation is
110   /// complete, fixups have been evaluated and applied, and relocations
111   /// generated.
112   virtual void WriteObject(MCAssembler &Asm,
113                            const MCAsmLayout &Layout) = 0;
114
115   /// @}
116   /// @name Binary Output
117   /// @{
118
119   void Write8(uint8_t Value) {
120     OS << char(Value);
121   }
122
123   void WriteLE16(uint16_t Value) {
124     support::endian::Writer<support::little>(OS).write(Value);
125   }
126
127   void WriteLE32(uint32_t Value) {
128     support::endian::Writer<support::little>(OS).write(Value);
129   }
130
131   void WriteLE64(uint64_t Value) {
132     support::endian::Writer<support::little>(OS).write(Value);
133   }
134
135   void WriteBE16(uint16_t Value) {
136     support::endian::Writer<support::big>(OS).write(Value);
137   }
138
139   void WriteBE32(uint32_t Value) {
140     support::endian::Writer<support::big>(OS).write(Value);
141   }
142
143   void WriteBE64(uint64_t Value) {
144     support::endian::Writer<support::big>(OS).write(Value);
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(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
178     WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
179   }
180
181   void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
182     // TODO: this version may need to go away once all fragment contents are
183     // converted to SmallVector<char, N>
184     assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
185       "data size greater than fill size, unexpected large write will occur");
186     OS << Str;
187     if (ZeroFillSize)
188       WriteZeros(ZeroFillSize - Str.size());
189   }
190
191   /// @}
192
193 };
194
195 } // End llvm namespace
196
197 #endif