• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Triple.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/Support/DataTypes.h"
16 #include <cassert>
17 
18 namespace llvm {
19 class MCAsmLayout;
20 class MCAssembler;
21 class MCFixup;
22 class MCFragment;
23 class MCSymbol;
24 class MCSymbolData;
25 class MCSymbolRefExpr;
26 class MCValue;
27 class raw_ostream;
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 &); // DO NOT IMPLEMENT
42   void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
43 
44 protected:
45   raw_ostream &OS;
46 
47   unsigned IsLittleEndian : 1;
48 
49 protected: // Can only create subclasses.
MCObjectWriter(raw_ostream & _OS,bool _IsLittleEndian)50   MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
51     : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
52 
53 public:
54   virtual ~MCObjectWriter();
55 
isLittleEndian()56   bool isLittleEndian() const { return IsLittleEndian; }
57 
getStream()58   raw_ostream &getStream() { return OS; }
59 
60   /// @name High-Level API
61   /// @{
62 
63   /// Perform any late binding of symbols (for example, to assign symbol indices
64   /// for use when generating relocations).
65   ///
66   /// This routine is called by the assembler after layout and relaxation is
67   /// complete.
68   virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
69                                         const MCAsmLayout &Layout) = 0;
70 
71   /// Record a relocation entry.
72   ///
73   /// This routine is called by the assembler after layout and relaxation, and
74   /// post layout binding. The implementation is responsible for storing
75   /// information about the relocation so that it can be emitted during
76   /// WriteObject().
77   virtual void RecordRelocation(const MCAssembler &Asm,
78                                 const MCAsmLayout &Layout,
79                                 const MCFragment *Fragment,
80                                 const MCFixup &Fixup, MCValue Target,
81                                 uint64_t &FixedValue) = 0;
82 
83   /// \brief Check whether the difference (A - B) between two symbol
84   /// references is fully resolved.
85   ///
86   /// Clients are not required to answer precisely and may conservatively return
87   /// false, even when a difference is fully resolved.
88   bool
89   IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
90                                      const MCSymbolRefExpr *A,
91                                      const MCSymbolRefExpr *B,
92                                      bool InSet) const;
93 
94   virtual bool
95   IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
96                                          const MCSymbolData &DataA,
97                                          const MCFragment &FB,
98                                          bool InSet,
99                                          bool IsPCRel) const;
100 
101 
102   /// Write the object file.
103   ///
104   /// This routine is called by the assembler after layout and relaxation is
105   /// complete, fixups have been evaluated and applied, and relocations
106   /// generated.
107   virtual void WriteObject(MCAssembler &Asm,
108                            const MCAsmLayout &Layout) = 0;
109 
110   /// @}
111   /// @name Binary Output
112   /// @{
113 
Write8(uint8_t Value)114   void Write8(uint8_t Value) {
115     OS << char(Value);
116   }
117 
WriteLE16(uint16_t Value)118   void WriteLE16(uint16_t Value) {
119     Write8(uint8_t(Value >> 0));
120     Write8(uint8_t(Value >> 8));
121   }
122 
WriteLE32(uint32_t Value)123   void WriteLE32(uint32_t Value) {
124     WriteLE16(uint16_t(Value >> 0));
125     WriteLE16(uint16_t(Value >> 16));
126   }
127 
WriteLE64(uint64_t Value)128   void WriteLE64(uint64_t Value) {
129     WriteLE32(uint32_t(Value >> 0));
130     WriteLE32(uint32_t(Value >> 32));
131   }
132 
WriteBE16(uint16_t Value)133   void WriteBE16(uint16_t Value) {
134     Write8(uint8_t(Value >> 8));
135     Write8(uint8_t(Value >> 0));
136   }
137 
WriteBE32(uint32_t Value)138   void WriteBE32(uint32_t Value) {
139     WriteBE16(uint16_t(Value >> 16));
140     WriteBE16(uint16_t(Value >> 0));
141   }
142 
WriteBE64(uint64_t Value)143   void WriteBE64(uint64_t Value) {
144     WriteBE32(uint32_t(Value >> 32));
145     WriteBE32(uint32_t(Value >> 0));
146   }
147 
Write16(uint16_t Value)148   void Write16(uint16_t Value) {
149     if (IsLittleEndian)
150       WriteLE16(Value);
151     else
152       WriteBE16(Value);
153   }
154 
Write32(uint32_t Value)155   void Write32(uint32_t Value) {
156     if (IsLittleEndian)
157       WriteLE32(Value);
158     else
159       WriteBE32(Value);
160   }
161 
Write64(uint64_t Value)162   void Write64(uint64_t Value) {
163     if (IsLittleEndian)
164       WriteLE64(Value);
165     else
166       WriteBE64(Value);
167   }
168 
WriteZeros(unsigned N)169   void WriteZeros(unsigned N) {
170     const char Zeros[16] = { 0 };
171 
172     for (unsigned i = 0, e = N / 16; i != e; ++i)
173       OS << StringRef(Zeros, 16);
174 
175     OS << StringRef(Zeros, N % 16);
176   }
177 
178   void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
179     assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
180       "data size greater than fill size, unexpected large write will occur");
181     OS << Str;
182     if (ZeroFillSize)
183       WriteZeros(ZeroFillSize - Str.size());
184   }
185 
186   /// @}
187 
188   /// Utility function to encode a SLEB128 value.
189   static void EncodeSLEB128(int64_t Value, raw_ostream &OS);
190   /// Utility function to encode a ULEB128 value.
191   static void EncodeULEB128(uint64_t Value, raw_ostream &OS);
192 };
193 
194 MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
195 
196 } // End llvm namespace
197 
198 #endif
199