MCObjectWriter.h revision 1f6efa3996dd1929fbc129203ce5009b620e6969
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 MCValue;
24class raw_ostream;
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) = 0;
66
67  /// Record a relocation entry.
68  ///
69  /// This routine is called by the assembler after layout and relaxation, and
70  /// post layout binding. The implementation is responsible for storing
71  /// information about the relocation so that it can be emitted during
72  /// WriteObject().
73  virtual void RecordRelocation(const MCAssembler &Asm,
74                                const MCAsmLayout &Layout,
75                                const MCFragment *Fragment,
76                                const MCFixup &Fixup, MCValue Target,
77                                uint64_t &FixedValue) = 0;
78
79  /// Check if a fixup is fully resolved.
80  ///
81  /// This routine is used by the assembler to let the file format decide
82  /// if a fixup is not fully resolved. For example, one that crosses
83  /// two sections on ELF.
84  virtual bool IsFixupFullyResolved(const MCAssembler &Asm,
85                                    const MCValue Target,
86                                    bool IsPCRel,
87                                    const MCFragment *DF) const = 0;
88
89  /// Write the object file.
90  ///
91  /// This routine is called by the assembler after layout and relaxation is
92  /// complete, fixups have been evaluated and applied, and relocations
93  /// generated.
94  virtual void WriteObject(MCAssembler &Asm,
95                           const MCAsmLayout &Layout) = 0;
96
97  /// @}
98  /// @name Binary Output
99  /// @{
100
101  void Write8(uint8_t Value) {
102    OS << char(Value);
103  }
104
105  void WriteLE16(uint16_t Value) {
106    Write8(uint8_t(Value >> 0));
107    Write8(uint8_t(Value >> 8));
108  }
109
110  void WriteLE32(uint32_t Value) {
111    WriteLE16(uint16_t(Value >> 0));
112    WriteLE16(uint16_t(Value >> 16));
113  }
114
115  void WriteLE64(uint64_t Value) {
116    WriteLE32(uint32_t(Value >> 0));
117    WriteLE32(uint32_t(Value >> 32));
118  }
119
120  void WriteBE16(uint16_t Value) {
121    Write8(uint8_t(Value >> 8));
122    Write8(uint8_t(Value >> 0));
123  }
124
125  void WriteBE32(uint32_t Value) {
126    WriteBE16(uint16_t(Value >> 16));
127    WriteBE16(uint16_t(Value >> 0));
128  }
129
130  void WriteBE64(uint64_t Value) {
131    WriteBE32(uint32_t(Value >> 32));
132    WriteBE32(uint32_t(Value >> 0));
133  }
134
135  void Write16(uint16_t Value) {
136    if (IsLittleEndian)
137      WriteLE16(Value);
138    else
139      WriteBE16(Value);
140  }
141
142  void Write32(uint32_t Value) {
143    if (IsLittleEndian)
144      WriteLE32(Value);
145    else
146      WriteBE32(Value);
147  }
148
149  void Write64(uint64_t Value) {
150    if (IsLittleEndian)
151      WriteLE64(Value);
152    else
153      WriteBE64(Value);
154  }
155
156  void WriteZeros(unsigned N) {
157    const char Zeros[16] = { 0 };
158
159    for (unsigned i = 0, e = N / 16; i != e; ++i)
160      OS << StringRef(Zeros, 16);
161
162    OS << StringRef(Zeros, N % 16);
163  }
164
165  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
166    assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
167      "data size greater than fill size, unexpected large write will occur");
168    OS << Str;
169    if (ZeroFillSize)
170      WriteZeros(ZeroFillSize - Str.size());
171  }
172
173  /// @}
174
175  /// Utility function to encode a SLEB128 value.
176  static void EncodeSLEB128(int64_t Value, raw_ostream &OS);
177  /// Utility function to encode a ULEB128 value.
178  static void EncodeULEB128(uint64_t Value, raw_ostream &OS);
179};
180
181MCObjectWriter *createMachObjectWriter(raw_ostream &OS, bool is64Bit,
182                                       uint32_t CPUType, uint32_t CPUSubtype,
183                                       bool IsLittleEndian);
184MCObjectWriter *createELFObjectWriter(raw_ostream &OS, bool is64Bit,
185                                      Triple::OSType OSType, uint16_t EMachine,
186                                      bool IsLittleEndian,
187                                      bool HasRelocationAddend);
188MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
189
190} // End llvm namespace
191
192#endif
193