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