expose a new code emitter object
[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_WRITE = 1, SHF_ALLOC = 2, SHF_EXECINSTR = 4 };
114
115       ELFSection(const char *name = "", unsigned offset = 0)
116         : Name(name), Type(0), Flags(0), Addr(0), Offset(offset), Size(0),
117           Link(0), Info(0), Align(0), EntSize(0) {
118       }
119     };
120
121     /// SectionList - This is the list of sections that we have emitted to the
122     /// file.  Once the file has been completely built, the section header table
123     /// is constructed from this info.
124     std::vector<ELFSection> SectionList;
125
126     /// ELFSym - This struct contains information about each symbol that is
127     /// added to logical symbol table for the module.  This is eventually
128     /// turned into a real symbol table in the file.
129     struct ELFSym {
130       GlobalValue *GV;        // The global value this corresponds to.
131       //std::string Name;       // Name of the symbol.
132       unsigned NameIdx;       // Index in .strtab of name, once emitted.
133       uint64_t Value;
134       unsigned Size;
135       unsigned char Info;
136       unsigned char Other;
137       unsigned short SectionIdx;
138
139       enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 };
140       enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3,
141              STT_FILE = 4 };
142       ELFSym(GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0),
143                                 Other(0), SectionIdx(0) {}
144
145       void SetBind(unsigned X) {
146         assert(X == (X & 0xF) && "Bind value out of range!");
147         Info = (Info & 0x0F) | (X << 4);
148       }
149       void SetType(unsigned X) {
150         assert(X == (X & 0xF) && "Type value out of range!");
151         Info = (Info & 0xF0) | X;
152       }
153     };
154
155     /// SymbolTable - This is the list of symbols we have emitted to the file.
156     /// This actually gets rearranged before emission to OutputBuffer (to put
157     /// the local symbols first in the list).
158     std::vector<ELFSym> SymbolTable;
159
160     // As we accumulate the ELF file into OutputBuffer, we occasionally need to
161     // keep track of locations to update later (e.g. the location of the section
162     // table in the ELF header.  These members keep track of the offset in
163     // OffsetBuffer of these various pieces to update and other locations in the
164     // file.
165     unsigned ELFHeader_e_shoff_Offset;     // e_shoff    in ELF header.
166     unsigned ELFHeader_e_shstrndx_Offset;  // e_shstrndx in ELF header.
167     unsigned ELFHeader_e_shnum_Offset;     // e_shnum    in ELF header.
168
169     // align - Emit padding into the file until the current output position is
170     // aligned to the specified power of two boundary.
171     void align(unsigned Boundary) {
172       assert(Boundary && (Boundary & (Boundary-1)) == 0 &&
173              "Must align to 2^k boundary");
174       while (OutputBuffer.size() & (Boundary-1))
175         outbyte(0xAB);
176     }
177
178     void outbyte(unsigned char X) { OutputBuffer.push_back(X); }
179     void outhalf(unsigned short X) {
180       if (isLittleEndian) {
181         OutputBuffer.push_back(X&255);
182         OutputBuffer.push_back(X >> 8);
183       } else {
184         OutputBuffer.push_back(X >> 8);
185         OutputBuffer.push_back(X&255);
186       }
187     }
188     void outword(unsigned X) {
189       if (isLittleEndian) {
190         OutputBuffer.push_back((X >>  0) & 255);
191         OutputBuffer.push_back((X >>  8) & 255);
192         OutputBuffer.push_back((X >> 16) & 255);
193         OutputBuffer.push_back((X >> 24) & 255);
194       } else {
195         OutputBuffer.push_back((X >> 24) & 255);
196         OutputBuffer.push_back((X >> 16) & 255);
197         OutputBuffer.push_back((X >>  8) & 255);
198         OutputBuffer.push_back((X >>  0) & 255);
199       }
200     }
201     void outaddr(uint64_t X) {
202       if (!is64Bit)
203         outword((unsigned)X);
204       else
205         assert(0 && "Emission of 64-bit data not implemented yet!");
206     }
207
208     // fix functions - Replace an existing entry at an offset.
209     void fixhalf(unsigned short X, unsigned Offset) {
210       unsigned char *P = &OutputBuffer[Offset];
211       P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
212       P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
213     }
214
215     void fixword(unsigned X, unsigned Offset) {
216       unsigned char *P = &OutputBuffer[Offset];
217       P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
218       P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
219       P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
220       P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
221     }
222
223     void fixaddr(uint64_t X, unsigned Offset) {
224       if (!is64Bit)
225         fixword((unsigned)X, Offset);
226       else
227         assert(0 && "Emission of 64-bit data not implemented yet!");
228     }
229
230   private:
231     void EmitGlobal(GlobalVariable *GV, ELFSection &DataSection,
232                     ELFSection &BSSSection);
233
234     void EmitSymbolTable();
235
236     void EmitSectionTableStringTable();
237     void EmitSectionTable();
238   };
239 }
240
241 #endif