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