Add support for emitting 64-bit integers
[oota-llvm.git] / include / llvm / CodeGen / ELFWriter.h
1 //===-- ELFWriter.h - Target-independent ELF writer support -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the ELFWriter class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CODEGEN_ELFWRITER_H
15 #define LLVM_CODEGEN_ELFWRITER_H
16
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18
19 namespace llvm {
20   class GlobalVariable;
21   class Mangler;
22   class MachineCodeEmitter;
23   class ELFCodeEmitter;
24
25   /// ELFWriter - This class implements the common target-independent code for
26   /// writing ELF files.  Targets should derive a class from this to
27   /// parameterize the output format.
28   ///
29   class ELFWriter : public MachineFunctionPass {
30     friend class ELFCodeEmitter;
31   public:
32     MachineCodeEmitter &getMachineCodeEmitter() const {
33       return *(MachineCodeEmitter*)MCE;
34     }
35
36     ~ELFWriter();
37
38   protected:
39     ELFWriter(std::ostream &O, TargetMachine &TM);
40
41     /// Output stream to send the resultant object file to.
42     ///
43     std::ostream &O;
44
45     /// Target machine description.
46     ///
47     TargetMachine &TM;
48
49     /// Mang - The object used to perform name mangling for this module.
50     ///
51     Mangler *Mang;
52
53     /// MCE - The MachineCodeEmitter object that we are exposing to emit machine
54     /// code for functions to the .o file.
55     ELFCodeEmitter *MCE;
56
57     //===------------------------------------------------------------------===//
58     // Properties to be set by the derived class ctor, used to configure the
59     // ELFWriter.
60
61     // e_machine - This field is the target specific value to emit as the
62     // e_machine member of the ELF header.
63     unsigned short e_machine;
64
65     // e_flags - The machine flags for the target.  This defaults to zero.
66     unsigned e_flags;
67
68     //===------------------------------------------------------------------===//
69     // Properties inferred automatically from the target machine.
70     //
71
72     /// is64Bit/isLittleEndian - This information is inferred from the target
73     /// machine directly, indicating whether to emit a 32- or 64-bit ELF file.
74     bool is64Bit, isLittleEndian;
75
76     /// doInitialization - Emit the file header and all of the global variables
77     /// for the module to the ELF file.
78     bool doInitialization(Module &M);
79
80     bool runOnMachineFunction(MachineFunction &MF);
81
82
83     /// doFinalization - Now that the module has been completely processed, emit
84     /// the ELF file to 'O'.
85     bool doFinalization(Module &M);
86
87   private:
88     // The buffer we are accumulating the file into.  Note that this should be
89     // changed into something much more efficient later (and the bytecode writer
90     // as well!).
91     std::vector<unsigned char> OutputBuffer;
92
93     /// ELFSection - This struct contains information about each section that is
94     /// emitted to the OutputBuffer.  This is eventually turned into the section
95     /// header table at the end of the file.
96     struct ELFSection {
97       std::string Name;       // Name of the section.
98       unsigned NameIdx;       // Index in .shstrtab of name, once emitted.
99       unsigned Type;
100       unsigned Flags;
101       uint64_t Addr;
102       unsigned Offset;
103       unsigned Size;
104       unsigned Link;
105       unsigned Info;
106       unsigned Align;
107       unsigned EntSize;
108
109       enum { SHT_NULL = 0, SHT_PROGBITS = 1, SHT_SYMTAB = 2, SHT_STRTAB = 3,
110              SHT_RELA = 4, SHT_HASH = 5, SHT_DYNAMIC = 6, SHT_NOTE = 7,
111              SHT_NOBITS = 8, SHT_REL = 9, SHT_SHLIB = 10, SHT_DYNSYM = 11 };
112       enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1, SHN_COMMON = 0xFFF2 };
113       enum {   // SHF - ELF Section Header Flags
114         SHF_WRITE            = 1 << 0, // Writable
115         SHF_ALLOC            = 1 << 1, // Mapped into the process addr space
116         SHF_EXECINSTR        = 1 << 2, // Executable
117         SHF_MERGE            = 1 << 4, // Might be merged if equal
118         SHF_STRINGS          = 1 << 5, // Contains null-terminated strings
119         SHF_INFO_LINK        = 1 << 6, // 'sh_info' contains SHT index
120         SHF_LINK_ORDER       = 1 << 7, // Preserve order after combining
121         SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required
122         SHF_GROUP            = 1 << 9, // Section is a member of a group
123         SHF_TLS              = 1 << 10,// Section holds thread-local data
124       };
125
126       ELFSection(const char *name = "", unsigned offset = 0)
127         : Name(name), Type(0), Flags(0), Addr(0), Offset(offset), Size(0),
128           Link(0), Info(0), Align(0), EntSize(0) {
129       }
130     };
131
132     /// SectionList - This is the list of sections that we have emitted to the
133     /// file.  Once the file has been completely built, the section header table
134     /// is constructed from this info.
135     std::vector<ELFSection> SectionList;
136
137     /// ELFSym - This struct contains information about each symbol that is
138     /// added to logical symbol table for the module.  This is eventually
139     /// turned into a real symbol table in the file.
140     struct ELFSym {
141       const GlobalValue *GV;    // The global value this corresponds to.
142       unsigned NameIdx;         // Index in .strtab of name, once emitted.
143       uint64_t Value;
144       unsigned Size;
145       unsigned char Info;
146       unsigned char Other;
147       unsigned short SectionIdx;
148
149       enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 };
150       enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3,
151              STT_FILE = 4 };
152       ELFSym(const GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0),
153                                       Other(0), SectionIdx(0) {}
154
155       void SetBind(unsigned X) {
156         assert(X == (X & 0xF) && "Bind value out of range!");
157         Info = (Info & 0x0F) | (X << 4);
158       }
159       void SetType(unsigned X) {
160         assert(X == (X & 0xF) && "Type value out of range!");
161         Info = (Info & 0xF0) | X;
162       }
163     };
164
165     /// SymbolTable - This is the list of symbols we have emitted to the file.
166     /// This actually gets rearranged before emission to OutputBuffer (to put
167     /// the local symbols first in the list).
168     std::vector<ELFSym> SymbolTable;
169
170     // As we accumulate the ELF file into OutputBuffer, we occasionally need to
171     // keep track of locations to update later (e.g. the location of the section
172     // table in the ELF header.  These members keep track of the offset in
173     // OffsetBuffer of these various pieces to update and other locations in the
174     // file.
175     unsigned ELFHeader_e_shoff_Offset;     // e_shoff    in ELF header.
176     unsigned ELFHeader_e_shstrndx_Offset;  // e_shstrndx in ELF header.
177     unsigned ELFHeader_e_shnum_Offset;     // e_shnum    in ELF header.
178
179     // align - Emit padding into the file until the current output position is
180     // aligned to the specified power of two boundary.
181     void align(unsigned Boundary) {
182       assert(Boundary && (Boundary & (Boundary-1)) == 0 &&
183              "Must align to 2^k boundary");
184       while (OutputBuffer.size() & (Boundary-1))
185         outbyte(0xAB);
186     }
187
188     void outbyte(unsigned char X) { OutputBuffer.push_back(X); }
189     void outhalf(unsigned short X) {
190       if (isLittleEndian) {
191         OutputBuffer.push_back(X&255);
192         OutputBuffer.push_back(X >> 8);
193       } else {
194         OutputBuffer.push_back(X >> 8);
195         OutputBuffer.push_back(X&255);
196       }
197     }
198     void outword(unsigned X) {
199       if (isLittleEndian) {
200         OutputBuffer.push_back((X >>  0) & 255);
201         OutputBuffer.push_back((X >>  8) & 255);
202         OutputBuffer.push_back((X >> 16) & 255);
203         OutputBuffer.push_back((X >> 24) & 255);
204       } else {
205         OutputBuffer.push_back((X >> 24) & 255);
206         OutputBuffer.push_back((X >> 16) & 255);
207         OutputBuffer.push_back((X >>  8) & 255);
208         OutputBuffer.push_back((X >>  0) & 255);
209       }
210     }
211     void outxword(uint64_t X) {
212       if (isLittleEndian) {
213         OutputBuffer.push_back((X >>  0) & 255);
214         OutputBuffer.push_back((X >>  8) & 255);
215         OutputBuffer.push_back((X >> 16) & 255);
216         OutputBuffer.push_back((X >> 24) & 255);
217         OutputBuffer.push_back((X >> 32) & 255);
218         OutputBuffer.push_back((X >> 40) & 255);
219         OutputBuffer.push_back((X >> 48) & 255);
220         OutputBuffer.push_back((X >> 56) & 255);
221       } else {
222         OutputBuffer.push_back((X >> 56) & 255);
223         OutputBuffer.push_back((X >> 48) & 255);
224         OutputBuffer.push_back((X >> 40) & 255);
225         OutputBuffer.push_back((X >> 32) & 255);
226         OutputBuffer.push_back((X >> 24) & 255);
227         OutputBuffer.push_back((X >> 16) & 255);
228         OutputBuffer.push_back((X >>  8) & 255);
229         OutputBuffer.push_back((X >>  0) & 255);
230       }
231     }
232     void outaddr32(unsigned X) {
233       outword(X);
234     }
235     void outaddr64(uint64_t X) {
236       outxword(X);
237     }
238     void outaddr(uint64_t X) {
239       if (!is64Bit)
240         outword((unsigned)X);
241       else
242         outxword(X);
243     }
244
245     // fix functions - Replace an existing entry at an offset.
246     void fixhalf(unsigned short X, unsigned Offset) {
247       unsigned char *P = &OutputBuffer[Offset];
248       P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
249       P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
250     }
251
252     void fixword(unsigned X, unsigned Offset) {
253       unsigned char *P = &OutputBuffer[Offset];
254       P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
255       P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
256       P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
257       P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
258     }
259
260     void fixaddr(uint64_t X, unsigned Offset) {
261       if (!is64Bit)
262         fixword((unsigned)X, Offset);
263       else
264         assert(0 && "Emission of 64-bit data not implemented yet!");
265     }
266
267   private:
268     void EmitGlobal(GlobalVariable *GV, ELFSection &DataSection,
269                     ELFSection &BSSSection);
270
271     void EmitSymbolTable();
272
273     void EmitSectionTableStringTable();
274     void EmitSectionTable();
275   };
276 }
277
278 #endif