MCObjectWriter.h revision f12b379448a9f2131feba15c01714e44bedda120
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//                     The LLVM Compiler Infrastructure
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This file is distributed under the University of Illinois Open Source
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// License. See LICENSE.TXT for details.
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===----------------------------------------------------------------------===//
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef LLVM_MC_MCOBJECTWRITER_H
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define LLVM_MC_MCOBJECTWRITER_H
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/ADT/SmallVector.h"
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Support/Compiler.h"
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Support/DataTypes.h"
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Support/raw_ostream.h"
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <cassert>
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace llvm {
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCAsmLayout;
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCAssembler;
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCFixup;
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCFragment;
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCSymbolData;
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCSymbolRefExpr;
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCValue;
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// MCObjectWriter - Defines the object file and target independent interfaces
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// used by the assembler backend to write native file format object files.
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org///
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// The object writer contains a few callbacks used by the assembler to allow
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// the object writer to modify the assembler data structures at appropriate
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// points. Once assembly is complete, the object writer is given the
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// MCAssembler instance, which contains all the symbol and section data which
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// should be emitted as part of WriteObject().
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org///
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// The object writer also contains a number of helper methods for writing
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// binary data to the output stream.
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MCObjectWriter {
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprotected:
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  raw_ostream &OS;
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  unsigned IsLittleEndian : 1;
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprotected: // Can only create subclasses.
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual ~MCObjectWriter();
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// lifetime management
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual void reset() { }
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isLittleEndian() const { return IsLittleEndian; }
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  raw_ostream &getStream() { return OS; }
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// @name High-Level API
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// @{
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// \brief Perform any late binding of symbols (for example, to assign symbol
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// indices for use when generating relocations).
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ///
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// This routine is called by the assembler after layout and relaxation is
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// complete.
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                        const MCAsmLayout &Layout) = 0;
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// \brief Record a relocation entry.
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ///
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// This routine is called by the assembler after layout and relaxation, and
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// post layout binding. The implementation is responsible for storing
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// information about the relocation so that it can be emitted during
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// WriteObject().
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual void RecordRelocation(const MCAssembler &Asm,
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                const MCAsmLayout &Layout,
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                const MCFragment *Fragment,
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                const MCFixup &Fixup, MCValue Target,
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                uint64_t &FixedValue) = 0;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// \brief Check whether the difference (A - B) between two symbol
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// references is fully resolved.
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ///
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// Clients are not required to answer precisely and may conservatively return
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// false, even when a difference is fully resolved.
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     const MCSymbolRefExpr *A,
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     const MCSymbolRefExpr *B,
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     bool InSet) const;
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual bool
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         const MCSymbolData &DataA,
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         const MCFragment &FB,
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         bool InSet,
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         bool IsPCRel) const;
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// \brief Write the object file.
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ///
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// This routine is called by the assembler after layout and relaxation is
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// complete, fixups have been evaluated and applied, and relocations
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// generated.
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  virtual void WriteObject(MCAssembler &Asm,
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           const MCAsmLayout &Layout) = 0;
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// @}
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// @name Binary Output
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// @{
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void Write8(uint8_t Value) {
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    OS << char(Value);
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteLE16(uint16_t Value) {
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Write8(uint8_t(Value >> 0));
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Write8(uint8_t(Value >> 8));
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteLE32(uint32_t Value) {
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteLE16(uint16_t(Value >> 0));
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteLE16(uint16_t(Value >> 16));
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteLE64(uint64_t Value) {
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteLE32(uint32_t(Value >> 0));
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteLE32(uint32_t(Value >> 32));
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteBE16(uint16_t Value) {
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Write8(uint8_t(Value >> 8));
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Write8(uint8_t(Value >> 0));
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteBE32(uint32_t Value) {
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteBE16(uint16_t(Value >> 16));
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteBE16(uint16_t(Value >> 0));
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteBE64(uint64_t Value) {
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteBE32(uint32_t(Value >> 32));
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteBE32(uint32_t(Value >> 0));
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void Write16(uint16_t Value) {
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (IsLittleEndian)
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      WriteLE16(Value);
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      WriteBE16(Value);
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void Write32(uint32_t Value) {
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (IsLittleEndian)
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      WriteLE32(Value);
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      WriteBE32(Value);
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void Write64(uint64_t Value) {
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (IsLittleEndian)
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      WriteLE64(Value);
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      WriteBE64(Value);
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteZeros(unsigned N) {
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    const char Zeros[16] = { 0 };
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for (unsigned i = 0, e = N / 16; i != e; ++i)
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      OS << StringRef(Zeros, 16);
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    OS << StringRef(Zeros, N % 16);
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // TODO: this version may need to go away once all fragment contents are
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // converted to SmallVector<char, N>
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      "data size greater than fill size, unexpected large write will occur");
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    OS << Str;
189    if (ZeroFillSize)
190      WriteZeros(ZeroFillSize - Str.size());
191  }
192
193  /// @}
194
195};
196
197} // End llvm namespace
198
199#endif
200