1205407Srdivacky//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
2205407Srdivacky//
3205407Srdivacky//                     The LLVM Compiler Infrastructure
4205407Srdivacky//
5205407Srdivacky// This file is distributed under the University of Illinois Open Source
6205407Srdivacky// License. See LICENSE.TXT for details.
7205407Srdivacky//
8205407Srdivacky//===----------------------------------------------------------------------===//
9205407Srdivacky
10205407Srdivacky#ifndef LLVM_MC_MCOBJECTWRITER_H
11205407Srdivacky#define LLVM_MC_MCOBJECTWRITER_H
12205407Srdivacky
13249423Sdim#include "llvm/ADT/SmallVector.h"
14243830Sdim#include "llvm/Support/Compiler.h"
15218893Sdim#include "llvm/Support/DataTypes.h"
16249423Sdim#include "llvm/Support/raw_ostream.h"
17205407Srdivacky#include <cassert>
18205407Srdivacky
19205407Srdivackynamespace llvm {
20206083Srdivackyclass MCAsmLayout;
21205407Srdivackyclass MCAssembler;
22208599Srdivackyclass MCFixup;
23206083Srdivackyclass MCFragment;
24218893Sdimclass MCSymbolData;
25218893Sdimclass MCSymbolRefExpr;
26205407Srdivackyclass MCValue;
27205407Srdivacky
28205407Srdivacky/// MCObjectWriter - Defines the object file and target independent interfaces
29205407Srdivacky/// used by the assembler backend to write native file format object files.
30205407Srdivacky///
31205407Srdivacky/// The object writer contains a few callbacks used by the assembler to allow
32205407Srdivacky/// the object writer to modify the assembler data structures at appropriate
33205407Srdivacky/// points. Once assembly is complete, the object writer is given the
34205407Srdivacky/// MCAssembler instance, which contains all the symbol and section data which
35205407Srdivacky/// should be emitted as part of WriteObject().
36205407Srdivacky///
37205407Srdivacky/// The object writer also contains a number of helper methods for writing
38205407Srdivacky/// binary data to the output stream.
39205407Srdivackyclass MCObjectWriter {
40243830Sdim  MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
41243830Sdim  void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
42205407Srdivacky
43205407Srdivackyprotected:
44205407Srdivacky  raw_ostream &OS;
45205407Srdivacky
46205407Srdivacky  unsigned IsLittleEndian : 1;
47205407Srdivacky
48205407Srdivackyprotected: // Can only create subclasses.
49205407Srdivacky  MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
50205407Srdivacky    : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
51205407Srdivacky
52205407Srdivackypublic:
53205407Srdivacky  virtual ~MCObjectWriter();
54205407Srdivacky
55249423Sdim  /// lifetime management
56249423Sdim  virtual void reset() { }
57249423Sdim
58207618Srdivacky  bool isLittleEndian() const { return IsLittleEndian; }
59205407Srdivacky
60205407Srdivacky  raw_ostream &getStream() { return OS; }
61205407Srdivacky
62205407Srdivacky  /// @name High-Level API
63205407Srdivacky  /// @{
64205407Srdivacky
65249423Sdim  /// \brief Perform any late binding of symbols (for example, to assign symbol
66249423Sdim  /// indices for use when generating relocations).
67205407Srdivacky  ///
68205407Srdivacky  /// This routine is called by the assembler after layout and relaxation is
69205407Srdivacky  /// complete.
70218893Sdim  virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
71218893Sdim                                        const MCAsmLayout &Layout) = 0;
72205407Srdivacky
73249423Sdim  /// \brief Record a relocation entry.
74205407Srdivacky  ///
75205407Srdivacky  /// This routine is called by the assembler after layout and relaxation, and
76205407Srdivacky  /// post layout binding. The implementation is responsible for storing
77205407Srdivacky  /// information about the relocation so that it can be emitted during
78205407Srdivacky  /// WriteObject().
79205407Srdivacky  virtual void RecordRelocation(const MCAssembler &Asm,
80206083Srdivacky                                const MCAsmLayout &Layout,
81206083Srdivacky                                const MCFragment *Fragment,
82208599Srdivacky                                const MCFixup &Fixup, MCValue Target,
83205407Srdivacky                                uint64_t &FixedValue) = 0;
84205407Srdivacky
85218893Sdim  /// \brief Check whether the difference (A - B) between two symbol
86218893Sdim  /// references is fully resolved.
87218893Sdim  ///
88218893Sdim  /// Clients are not required to answer precisely and may conservatively return
89218893Sdim  /// false, even when a difference is fully resolved.
90218893Sdim  bool
91218893Sdim  IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
92218893Sdim                                     const MCSymbolRefExpr *A,
93218893Sdim                                     const MCSymbolRefExpr *B,
94218893Sdim                                     bool InSet) const;
95218893Sdim
96218893Sdim  virtual bool
97218893Sdim  IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
98218893Sdim                                         const MCSymbolData &DataA,
99218893Sdim                                         const MCFragment &FB,
100218893Sdim                                         bool InSet,
101218893Sdim                                         bool IsPCRel) const;
102218893Sdim
103249423Sdim  /// \brief Write the object file.
104205407Srdivacky  ///
105205407Srdivacky  /// This routine is called by the assembler after layout and relaxation is
106208599Srdivacky  /// complete, fixups have been evaluated and applied, and relocations
107205407Srdivacky  /// generated.
108218893Sdim  virtual void WriteObject(MCAssembler &Asm,
109206083Srdivacky                           const MCAsmLayout &Layout) = 0;
110205407Srdivacky
111205407Srdivacky  /// @}
112205407Srdivacky  /// @name Binary Output
113205407Srdivacky  /// @{
114205407Srdivacky
115205407Srdivacky  void Write8(uint8_t Value) {
116205407Srdivacky    OS << char(Value);
117205407Srdivacky  }
118205407Srdivacky
119205407Srdivacky  void WriteLE16(uint16_t Value) {
120205407Srdivacky    Write8(uint8_t(Value >> 0));
121205407Srdivacky    Write8(uint8_t(Value >> 8));
122205407Srdivacky  }
123205407Srdivacky
124205407Srdivacky  void WriteLE32(uint32_t Value) {
125205407Srdivacky    WriteLE16(uint16_t(Value >> 0));
126205407Srdivacky    WriteLE16(uint16_t(Value >> 16));
127205407Srdivacky  }
128205407Srdivacky
129205407Srdivacky  void WriteLE64(uint64_t Value) {
130205407Srdivacky    WriteLE32(uint32_t(Value >> 0));
131205407Srdivacky    WriteLE32(uint32_t(Value >> 32));
132205407Srdivacky  }
133205407Srdivacky
134205407Srdivacky  void WriteBE16(uint16_t Value) {
135205407Srdivacky    Write8(uint8_t(Value >> 8));
136205407Srdivacky    Write8(uint8_t(Value >> 0));
137205407Srdivacky  }
138205407Srdivacky
139205407Srdivacky  void WriteBE32(uint32_t Value) {
140205407Srdivacky    WriteBE16(uint16_t(Value >> 16));
141205407Srdivacky    WriteBE16(uint16_t(Value >> 0));
142205407Srdivacky  }
143205407Srdivacky
144205407Srdivacky  void WriteBE64(uint64_t Value) {
145205407Srdivacky    WriteBE32(uint32_t(Value >> 32));
146205407Srdivacky    WriteBE32(uint32_t(Value >> 0));
147205407Srdivacky  }
148205407Srdivacky
149205407Srdivacky  void Write16(uint16_t Value) {
150205407Srdivacky    if (IsLittleEndian)
151205407Srdivacky      WriteLE16(Value);
152205407Srdivacky    else
153205407Srdivacky      WriteBE16(Value);
154205407Srdivacky  }
155205407Srdivacky
156205407Srdivacky  void Write32(uint32_t Value) {
157205407Srdivacky    if (IsLittleEndian)
158205407Srdivacky      WriteLE32(Value);
159205407Srdivacky    else
160205407Srdivacky      WriteBE32(Value);
161205407Srdivacky  }
162205407Srdivacky
163205407Srdivacky  void Write64(uint64_t Value) {
164205407Srdivacky    if (IsLittleEndian)
165205407Srdivacky      WriteLE64(Value);
166205407Srdivacky    else
167205407Srdivacky      WriteBE64(Value);
168205407Srdivacky  }
169205407Srdivacky
170205407Srdivacky  void WriteZeros(unsigned N) {
171205407Srdivacky    const char Zeros[16] = { 0 };
172205407Srdivacky
173205407Srdivacky    for (unsigned i = 0, e = N / 16; i != e; ++i)
174205407Srdivacky      OS << StringRef(Zeros, 16);
175205407Srdivacky
176205407Srdivacky    OS << StringRef(Zeros, N % 16);
177205407Srdivacky  }
178205407Srdivacky
179249423Sdim  void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
180249423Sdim    WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
181249423Sdim  }
182249423Sdim
183205407Srdivacky  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
184249423Sdim    // TODO: this version may need to go away once all fragment contents are
185249423Sdim    // converted to SmallVector<char, N>
186208599Srdivacky    assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
187208599Srdivacky      "data size greater than fill size, unexpected large write will occur");
188205407Srdivacky    OS << Str;
189205407Srdivacky    if (ZeroFillSize)
190205407Srdivacky      WriteZeros(ZeroFillSize - Str.size());
191205407Srdivacky  }
192205407Srdivacky
193205407Srdivacky  /// @}
194218893Sdim
195205407Srdivacky};
196205407Srdivacky
197205407Srdivacky} // End llvm namespace
198205407Srdivacky
199205407Srdivacky#endif
200