MCObjectWriter.h revision f1d0f7781e766df878bec4e7977fa3204374f394
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/Support/raw_ostream.h"
14#include "llvm/Support/DataTypes.h"
15#include <cassert>
16
17namespace llvm {
18class MCAsmLayout;
19class MCAssembler;
20class MCFixup;
21class MCFragment;
22class MCSymbolData;
23class MCSymbolRefExpr;
24class MCValue;
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.
37class MCObjectWriter {
38  MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
39  void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
40
41protected:
42  raw_ostream &OS;
43
44  unsigned IsLittleEndian : 1;
45
46protected: // Can only create subclasses.
47  MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
48    : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
49
50public:
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  /// \brief Check whether the difference (A - B) between two symbol
81  /// references is fully resolved.
82  ///
83  /// Clients are not required to answer precisely and may conservatively return
84  /// false, even when a difference is fully resolved.
85  bool
86  IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
87                                     const MCSymbolRefExpr *A,
88                                     const MCSymbolRefExpr *B,
89                                     bool InSet) const;
90
91  virtual bool
92  IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
93                                         const MCSymbolData &DataA,
94                                         const MCFragment &FB,
95                                         bool InSet,
96                                         bool IsPCRel) const;
97
98
99  /// Write the object file.
100  ///
101  /// This routine is called by the assembler after layout and relaxation is
102  /// complete, fixups have been evaluated and applied, and relocations
103  /// generated.
104  virtual void WriteObject(MCAssembler &Asm,
105                           const MCAsmLayout &Layout) = 0;
106
107  /// @}
108  /// @name Binary Output
109  /// @{
110
111  void Write8(uint8_t Value) {
112    OS << char(Value);
113  }
114
115  void WriteLE16(uint16_t Value) {
116    Write8(uint8_t(Value >> 0));
117    Write8(uint8_t(Value >> 8));
118  }
119
120  void WriteLE32(uint32_t Value) {
121    WriteLE16(uint16_t(Value >> 0));
122    WriteLE16(uint16_t(Value >> 16));
123  }
124
125  void WriteLE64(uint64_t Value) {
126    WriteLE32(uint32_t(Value >> 0));
127    WriteLE32(uint32_t(Value >> 32));
128  }
129
130  void WriteBE16(uint16_t Value) {
131    Write8(uint8_t(Value >> 8));
132    Write8(uint8_t(Value >> 0));
133  }
134
135  void WriteBE32(uint32_t Value) {
136    WriteBE16(uint16_t(Value >> 16));
137    WriteBE16(uint16_t(Value >> 0));
138  }
139
140  void WriteBE64(uint64_t Value) {
141    WriteBE32(uint32_t(Value >> 32));
142    WriteBE32(uint32_t(Value >> 0));
143  }
144
145  void Write16(uint16_t Value) {
146    if (IsLittleEndian)
147      WriteLE16(Value);
148    else
149      WriteBE16(Value);
150  }
151
152  void Write32(uint32_t Value) {
153    if (IsLittleEndian)
154      WriteLE32(Value);
155    else
156      WriteBE32(Value);
157  }
158
159  void Write64(uint64_t Value) {
160    if (IsLittleEndian)
161      WriteLE64(Value);
162    else
163      WriteBE64(Value);
164  }
165
166  void WriteZeros(unsigned N) {
167    const char Zeros[16] = { 0 };
168
169    for (unsigned i = 0, e = N / 16; i != e; ++i)
170      OS << StringRef(Zeros, 16);
171
172    OS << StringRef(Zeros, N % 16);
173  }
174
175  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
176    assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
177      "data size greater than fill size, unexpected large write will occur");
178    OS << Str;
179    if (ZeroFillSize)
180      WriteZeros(ZeroFillSize - Str.size());
181  }
182
183  /// @}
184
185  /// Utility function to encode a SLEB128 value.
186  static void EncodeSLEB128(int64_t Value, raw_ostream &OS);
187  /// Utility function to encode a ULEB128 value.
188  static void EncodeULEB128(uint64_t Value, raw_ostream &OS,
189                            unsigned Padding = 0);
190};
191
192} // End llvm namespace
193
194#endif
195