MCObjectWriter.h revision 285b3e5b61af15f11e59a7700375aefa2a326bd8
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
18namespace llvm {
19class MCAsmLayout;
20class MCAssembler;
21class MCFixup;
22class MCFragment;
23class MCSymbolRefExpr;
24class MCValue;
25class 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.
38class MCObjectWriter {
39  MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
40  void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
41
42protected:
43  raw_ostream &OS;
44
45  unsigned IsLittleEndian : 1;
46
47protected: // Can only create subclasses.
48  MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
49    : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
50
51public:
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
193MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
194
195} // End llvm namespace
196
197#endif
198