summaryrefslogtreecommitdiff
path: root/include/llvm/MC/MCObjectWriter.h
blob: 77ab6abed201cc828c8ccee0357dc69b3654c27e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_MC_MCOBJECTWRITER_H
#define LLVM_MC_MCOBJECTWRITER_H

#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/DataTypes.h"
#include <cassert>

namespace llvm {
class MCAsmLayout;
class MCAssembler;
class MCFixup;
class MCFragment;
class MCValue;
class raw_ostream;

/// MCObjectWriter - Defines the object file and target independent interfaces
/// used by the assembler backend to write native file format object files.
///
/// The object writer contains a few callbacks used by the assembler to allow
/// the object writer to modify the assembler data structures at appropriate
/// points. Once assembly is complete, the object writer is given the
/// MCAssembler instance, which contains all the symbol and section data which
/// should be emitted as part of WriteObject().
///
/// The object writer also contains a number of helper methods for writing
/// binary data to the output stream.
class MCObjectWriter {
  MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
  void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT

protected:
  raw_ostream &OS;

  unsigned IsLittleEndian : 1;

protected: // Can only create subclasses.
  MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
    : OS(_OS), IsLittleEndian(_IsLittleEndian) {}

public:
  virtual ~MCObjectWriter();

  bool isLittleEndian() const { return IsLittleEndian; }

  raw_ostream &getStream() { return OS; }

  /// @name High-Level API
  /// @{

  /// Perform any late binding of symbols (for example, to assign symbol indices
  /// for use when generating relocations).
  ///
  /// This routine is called by the assembler after layout and relaxation is
  /// complete.
  virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0;

  /// Record a relocation entry.
  ///
  /// This routine is called by the assembler after layout and relaxation, and
  /// post layout binding. The implementation is responsible for storing
  /// information about the relocation so that it can be emitted during
  /// WriteObject().
  virtual void RecordRelocation(const MCAssembler &Asm,
                                const MCAsmLayout &Layout,
                                const MCFragment *Fragment,
                                const MCFixup &Fixup, MCValue Target,
                                uint64_t &FixedValue) = 0;

  /// Check if a fixup is fully resolved.
  ///
  /// This routine is used by the assembler to let the file format decide
  /// if a fixup is not fully resolved. For example, one that crosses
  /// two sections on ELF.
  virtual bool IsFixupFullyResolved(const MCAssembler &Asm,
                                    const MCValue Target,
                                    bool IsPCRel,
                                    const MCFragment *DF) const = 0;

  /// Write the object file.
  ///
  /// This routine is called by the assembler after layout and relaxation is
  /// complete, fixups have been evaluated and applied, and relocations
  /// generated.
  virtual void WriteObject(MCAssembler &Asm,
                           const MCAsmLayout &Layout) = 0;

  /// @}
  /// @name Binary Output
  /// @{

  void Write8(uint8_t Value) {
    OS << char(Value);
  }

  void WriteLE16(uint16_t Value) {
    Write8(uint8_t(Value >> 0));
    Write8(uint8_t(Value >> 8));
  }

  void WriteLE32(uint32_t Value) {
    WriteLE16(uint16_t(Value >> 0));
    WriteLE16(uint16_t(Value >> 16));
  }

  void WriteLE64(uint64_t Value) {
    WriteLE32(uint32_t(Value >> 0));
    WriteLE32(uint32_t(Value >> 32));
  }

  void WriteBE16(uint16_t Value) {
    Write8(uint8_t(Value >> 8));
    Write8(uint8_t(Value >> 0));
  }

  void WriteBE32(uint32_t Value) {
    WriteBE16(uint16_t(Value >> 16));
    WriteBE16(uint16_t(Value >> 0));
  }

  void WriteBE64(uint64_t Value) {
    WriteBE32(uint32_t(Value >> 32));
    WriteBE32(uint32_t(Value >> 0));
  }

  void Write16(uint16_t Value) {
    if (IsLittleEndian)
      WriteLE16(Value);
    else
      WriteBE16(Value);
  }

  void Write32(uint32_t Value) {
    if (IsLittleEndian)
      WriteLE32(Value);
    else
      WriteBE32(Value);
  }

  void Write64(uint64_t Value) {
    if (IsLittleEndian)
      WriteLE64(Value);
    else
      WriteBE64(Value);
  }

  void WriteZeros(unsigned N) {
    const char Zeros[16] = { 0 };

    for (unsigned i = 0, e = N / 16; i != e; ++i)
      OS << StringRef(Zeros, 16);

    OS << StringRef(Zeros, N % 16);
  }

  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
    assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
      "data size greater than fill size, unexpected large write will occur");
    OS << Str;
    if (ZeroFillSize)
      WriteZeros(ZeroFillSize - Str.size());
  }

  /// @}

  /// Utility function to encode a SLEB128 value.
  static void EncodeSLEB128(int64_t Value, raw_ostream &OS);
  /// Utility function to encode a ULEB128 value.
  static void EncodeULEB128(uint64_t Value, raw_ostream &OS);
};

MCObjectWriter *createMachObjectWriter(raw_ostream &OS, bool is64Bit,
                                       uint32_t CPUType, uint32_t CPUSubtype,
                                       bool IsLittleEndian);
MCObjectWriter *createELFObjectWriter(raw_ostream &OS, bool is64Bit,
                                      Triple::OSType OSType, uint16_t EMachine,
                                      bool IsLittleEndian,
                                      bool HasRelocationAddend);
MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);

} // End llvm namespace

#endif