MCObjectWriter.h revision 53b2338a1d061ad15a858ff0d641431f4d4ac101
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/System/DataTypes.h"
15#include <cassert>
16
17namespace llvm {
18class MCAsmFixup;
19class MCAssembler;
20class MCDataFragment;
21class MCValue;
22class raw_ostream;
23
24/// MCObjectWriter - Defines the object file and target independent interfaces
25/// used by the assembler backend to write native file format object files.
26///
27/// The object writer contains a few callbacks used by the assembler to allow
28/// the object writer to modify the assembler data structures at appropriate
29/// points. Once assembly is complete, the object writer is given the
30/// MCAssembler instance, which contains all the symbol and section data which
31/// should be emitted as part of WriteObject().
32///
33/// The object writer also contains a number of helper methods for writing
34/// binary data to the output stream.
35class MCObjectWriter {
36  MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
37  void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
38
39protected:
40  raw_ostream &OS;
41
42  unsigned IsLittleEndian : 1;
43
44protected: // Can only create subclasses.
45  MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
46    : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
47
48public:
49  virtual ~MCObjectWriter();
50
51  bool isLittleEndian() { return IsLittleEndian; }
52
53  raw_ostream &getStream() { return OS; }
54
55  /// @name High-Level API
56  /// @{
57
58  /// Perform any late binding of symbols (for example, to assign symbol indices
59  /// for use when generating relocations).
60  ///
61  /// This routine is called by the assembler after layout and relaxation is
62  /// complete.
63  virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0;
64
65  /// Record a relocation entry.
66  ///
67  /// This routine is called by the assembler after layout and relaxation, and
68  /// post layout binding. The implementation is responsible for storing
69  /// information about the relocation so that it can be emitted during
70  /// WriteObject().
71  virtual void RecordRelocation(const MCAssembler &Asm,
72                                const MCDataFragment &Fragment,
73                                const MCAsmFixup &Fixup, MCValue Target,
74                                uint64_t &FixedValue) = 0;
75
76  /// Write the object file.
77  ///
78  /// This routine is called by the assembler after layout and relaxation is
79  /// complete, fixups have been evaluate and applied, and relocations
80  /// generated.
81  virtual void WriteObject(const MCAssembler &Asm) = 0;
82
83  /// @}
84  /// @name Binary Output
85  /// @{
86
87  void Write8(uint8_t Value) {
88    OS << char(Value);
89  }
90
91  void WriteLE16(uint16_t Value) {
92    Write8(uint8_t(Value >> 0));
93    Write8(uint8_t(Value >> 8));
94  }
95
96  void WriteLE32(uint32_t Value) {
97    WriteLE16(uint16_t(Value >> 0));
98    WriteLE16(uint16_t(Value >> 16));
99  }
100
101  void WriteLE64(uint64_t Value) {
102    WriteLE32(uint32_t(Value >> 0));
103    WriteLE32(uint32_t(Value >> 32));
104  }
105
106  void WriteBE16(uint16_t Value) {
107    Write8(uint8_t(Value >> 8));
108    Write8(uint8_t(Value >> 0));
109  }
110
111  void WriteBE32(uint32_t Value) {
112    WriteBE16(uint16_t(Value >> 16));
113    WriteBE16(uint16_t(Value >> 0));
114  }
115
116  void WriteBE64(uint64_t Value) {
117    WriteBE32(uint32_t(Value >> 32));
118    WriteBE32(uint32_t(Value >> 0));
119  }
120
121  void Write16(uint16_t Value) {
122    if (IsLittleEndian)
123      WriteLE16(Value);
124    else
125      WriteBE16(Value);
126  }
127
128  void Write32(uint32_t Value) {
129    if (IsLittleEndian)
130      WriteLE32(Value);
131    else
132      WriteBE32(Value);
133  }
134
135  void Write64(uint64_t Value) {
136    if (IsLittleEndian)
137      WriteLE64(Value);
138    else
139      WriteBE64(Value);
140  }
141
142  void WriteZeros(unsigned N) {
143    const char Zeros[16] = { 0 };
144
145    for (unsigned i = 0, e = N / 16; i != e; ++i)
146      OS << StringRef(Zeros, 16);
147
148    OS << StringRef(Zeros, N % 16);
149  }
150
151  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
152    OS << Str;
153    if (ZeroFillSize)
154      WriteZeros(ZeroFillSize - Str.size());
155  }
156
157  /// @}
158};
159
160} // End llvm namespace
161
162#endif
163