MCObjectWriter.h revision 550f0ade457c3b042fa099ecff2c022c7ab58b1e
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/Compiler.h"
14#include "llvm/Support/DataTypes.h"
15#include "llvm/Support/raw_ostream.h"
16#include <cassert>
17
18namespace llvm {
19class MCAsmLayout;
20class MCAssembler;
21class MCFixup;
22class MCFragment;
23class MCSymbolData;
24class MCSymbolRefExpr;
25class MCValue;
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 &) LLVM_DELETED_FUNCTION;
40  void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
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  bool
87  IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
88                                     const MCSymbolRefExpr *A,
89                                     const MCSymbolRefExpr *B,
90                                     bool InSet) const;
91
92  virtual bool
93  IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
94                                         const MCSymbolData &DataA,
95                                         const MCFragment &FB,
96                                         bool InSet,
97                                         bool IsPCRel) const;
98
99
100  /// Write the object file.
101  ///
102  /// This routine is called by the assembler after layout and relaxation is
103  /// complete, fixups have been evaluated and applied, and relocations
104  /// generated.
105  virtual void WriteObject(MCAssembler &Asm,
106                           const MCAsmLayout &Layout) = 0;
107
108  /// @}
109  /// @name Binary Output
110  /// @{
111
112  void Write8(uint8_t Value) {
113    OS << char(Value);
114  }
115
116  void WriteLE16(uint16_t Value) {
117    Write8(uint8_t(Value >> 0));
118    Write8(uint8_t(Value >> 8));
119  }
120
121  void WriteLE32(uint32_t Value) {
122    WriteLE16(uint16_t(Value >> 0));
123    WriteLE16(uint16_t(Value >> 16));
124  }
125
126  void WriteLE64(uint64_t Value) {
127    WriteLE32(uint32_t(Value >> 0));
128    WriteLE32(uint32_t(Value >> 32));
129  }
130
131  void WriteBE16(uint16_t Value) {
132    Write8(uint8_t(Value >> 8));
133    Write8(uint8_t(Value >> 0));
134  }
135
136  void WriteBE32(uint32_t Value) {
137    WriteBE16(uint16_t(Value >> 16));
138    WriteBE16(uint16_t(Value >> 0));
139  }
140
141  void WriteBE64(uint64_t Value) {
142    WriteBE32(uint32_t(Value >> 32));
143    WriteBE32(uint32_t(Value >> 0));
144  }
145
146  void Write16(uint16_t Value) {
147    if (IsLittleEndian)
148      WriteLE16(Value);
149    else
150      WriteBE16(Value);
151  }
152
153  void Write32(uint32_t Value) {
154    if (IsLittleEndian)
155      WriteLE32(Value);
156    else
157      WriteBE32(Value);
158  }
159
160  void Write64(uint64_t Value) {
161    if (IsLittleEndian)
162      WriteLE64(Value);
163    else
164      WriteBE64(Value);
165  }
166
167  void WriteZeros(unsigned N) {
168    const char Zeros[16] = { 0 };
169
170    for (unsigned i = 0, e = N / 16; i != e; ++i)
171      OS << StringRef(Zeros, 16);
172
173    OS << StringRef(Zeros, N % 16);
174  }
175
176  void WriteBytes(SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
177    WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
178  }
179
180  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
181    // TODO: this version may need to go away once all fragment contents are
182    // converted to SmallVector<char, N>
183    assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
184      "data size greater than fill size, unexpected large write will occur");
185    OS << Str;
186    if (ZeroFillSize)
187      WriteZeros(ZeroFillSize - Str.size());
188  }
189
190  /// @}
191
192};
193
194} // End llvm namespace
195
196#endif
197