MC: Use MCSymbol in MCObjectWriter::isWeak(), NFC
[oota-llvm.git] / include / llvm / MC / MCObjectWriter.h
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/ADT/SmallVector.h"
14 #include "llvm/Support/Compiler.h"
15 #include "llvm/Support/DataTypes.h"
16 #include "llvm/Support/EndianStream.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <cassert>
19
20 namespace llvm {
21 class MCAsmLayout;
22 class MCAssembler;
23 class MCFixup;
24 class MCFragment;
25 class MCSymbolData;
26 class MCSymbolRefExpr;
27 class MCValue;
28
29 /// MCObjectWriter - Defines the object file and target independent interfaces
30 /// used by the assembler backend to write native file format object files.
31 ///
32 /// The object writer contains a few callbacks used by the assembler to allow
33 /// the object writer to modify the assembler data structures at appropriate
34 /// points. Once assembly is complete, the object writer is given the
35 /// MCAssembler instance, which contains all the symbol and section data which
36 /// should be emitted as part of WriteObject().
37 ///
38 /// The object writer also contains a number of helper methods for writing
39 /// binary data to the output stream.
40 class MCObjectWriter {
41   MCObjectWriter(const MCObjectWriter &) = delete;
42   void operator=(const MCObjectWriter &) = delete;
43
44 protected:
45   raw_pwrite_stream &OS;
46
47   unsigned IsLittleEndian : 1;
48
49 protected: // Can only create subclasses.
50   MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian)
51       : OS(OS), IsLittleEndian(IsLittleEndian) {}
52
53 public:
54   virtual ~MCObjectWriter();
55
56   /// lifetime management
57   virtual void reset() { }
58
59   bool isLittleEndian() const { return IsLittleEndian; }
60
61   raw_ostream &getStream() { return OS; }
62
63   /// \name High-Level API
64   /// @{
65
66   /// \brief Perform any late binding of symbols (for example, to assign symbol
67   /// indices for use when generating relocations).
68   ///
69   /// This routine is called by the assembler after layout and relaxation is
70   /// complete.
71   virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
72                                         const MCAsmLayout &Layout) = 0;
73
74   /// \brief Record a relocation entry.
75   ///
76   /// This routine is called by the assembler after layout and relaxation, and
77   /// post layout binding. The implementation is responsible for storing
78   /// information about the relocation so that it can be emitted during
79   /// WriteObject().
80   virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
81                                 const MCFragment *Fragment,
82                                 const MCFixup &Fixup, MCValue Target,
83                                 bool &IsPCRel, uint64_t &FixedValue) = 0;
84
85   /// \brief Check whether the difference (A - B) between two symbol
86   /// references is fully resolved.
87   ///
88   /// Clients are not required to answer precisely and may conservatively return
89   /// false, even when a difference is fully resolved.
90   bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
91                                           const MCSymbolRefExpr *A,
92                                           const MCSymbolRefExpr *B,
93                                           bool InSet) const;
94
95   virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
96                                                       const MCSymbol &SymA,
97                                                       const MCFragment &FB,
98                                                       bool InSet,
99                                                       bool IsPCRel) const;
100
101   /// \brief True if this symbol (which is a variable) is weak. This is not
102   /// just STB_WEAK, but more generally whether or not we can evaluate
103   /// past it.
104   virtual bool isWeak(const MCSymbol &Sym) const;
105
106   /// \brief Write the object file.
107   ///
108   /// This routine is called by the assembler after layout and relaxation is
109   /// complete, fixups have been evaluated and applied, and relocations
110   /// generated.
111   virtual void WriteObject(MCAssembler &Asm,
112                            const MCAsmLayout &Layout) = 0;
113
114   /// @}
115   /// \name Binary Output
116   /// @{
117
118   void Write8(uint8_t Value) {
119     OS << char(Value);
120   }
121
122   void WriteLE16(uint16_t Value) {
123     support::endian::Writer<support::little>(OS).write(Value);
124   }
125
126   void WriteLE32(uint32_t Value) {
127     support::endian::Writer<support::little>(OS).write(Value);
128   }
129
130   void WriteLE64(uint64_t Value) {
131     support::endian::Writer<support::little>(OS).write(Value);
132   }
133
134   void WriteBE16(uint16_t Value) {
135     support::endian::Writer<support::big>(OS).write(Value);
136   }
137
138   void WriteBE32(uint32_t Value) {
139     support::endian::Writer<support::big>(OS).write(Value);
140   }
141
142   void WriteBE64(uint64_t Value) {
143     support::endian::Writer<support::big>(OS).write(Value);
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(const 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