add a name mangler 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
23   /// ELFWriter - This class implements the common target-independent code for
24   /// writing ELF files.  Targets should derive a class from this to
25   /// parameterize the output format.
26   ///
27   class ELFWriter : public MachineFunctionPass {
28   protected:
29     ELFWriter(std::ostream &O, TargetMachine &TM);
30
31     /// Output stream to send the resultant object file to.
32     ///
33     std::ostream &O;
34
35     /// Target machine description.
36     ///
37     TargetMachine &TM;
38
39     /// Mang - The object used to perform name mangling for this module.
40     ///
41     Mangler *Mang;
42
43     //===------------------------------------------------------------------===//
44     // Properties to be set by the derived class ctor, used to configure the
45     // ELFWriter.
46
47     // e_machine - This field is the target specific value to emit as the
48     // e_machine member of the ELF header.
49     unsigned short e_machine;
50
51     // e_flags - The machine flags for the target.  This defaults to zero.
52     unsigned e_flags;
53
54     //===------------------------------------------------------------------===//
55     // Properties inferred automatically from the target machine.
56     //
57
58     /// is64Bit/isLittleEndian - This information is inferred from the target
59     /// machine directly, indicating whether to emit a 32- or 64-bit ELF file.
60     bool is64Bit, isLittleEndian;
61
62     /// doInitialization - Emit the file header and all of the global variables
63     /// for the module to the ELF file.
64     bool doInitialization(Module &M);
65
66     bool runOnMachineFunction(MachineFunction &MF);
67
68
69     /// doFinalization - Now that the module has been completely processed, emit
70     /// the ELF file to 'O'.
71     bool doFinalization(Module &M);
72
73   private:
74     // The buffer we are accumulating the file into.  Note that this should be
75     // changed into something much more efficient later (and the bytecode writer
76     // as well!).
77     std::vector<unsigned char> OutputBuffer;
78
79     /// ELFSection - This struct contains information about each section that is
80     /// emitted to the OutputBuffer.  This is eventually turned into the section
81     /// header table at the end of the file.
82     struct ELFSection {
83       std::string Name;       // Name of the section.
84       unsigned NameIdx;       // Index in .shstrtab of name, once emitted.
85       unsigned Type;
86       unsigned Flags;
87       uint64_t Addr;
88       unsigned Offset;
89       unsigned Size;
90       unsigned Link;
91       unsigned Info;
92       unsigned Align;
93       unsigned EntSize;
94
95       enum { SHT_NULL = 0, SHT_PROGBITS = 1, SHT_SYMTAB = 2, SHT_STRTAB = 3,
96              SHT_RELA = 4, SHT_HASH = 5, SHT_DYNAMIC = 6, SHT_NOTE = 7,
97              SHT_NOBITS = 8, SHT_REL = 9, SHT_SHLIB = 10, SHT_DYNSYM = 11 };
98       enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1, SHN_COMMON = 0xFFF2 };
99       enum { SHF_WRITE = 1, SHF_ALLOC = 2, SHF_EXECINSTR = 4 };
100
101       ELFSection(const char *name = "", unsigned offset = 0)
102         : Name(name), Type(0), Flags(0), Addr(0), Offset(offset), Size(0),
103           Link(0), Info(0), Align(0), EntSize(0) {
104       }
105     };
106
107     /// SectionList - This is the list of sections that we have emitted to the
108     /// file.  Once the file has been completely built, the section header table
109     /// is constructed from this info.
110     std::vector<ELFSection> SectionList;
111
112     /// ELFSym - This struct contains information about each symbol that is
113     /// added to logical symbol table for the module.  This is eventually
114     /// turned into a real symbol table in the file.
115     struct ELFSym {
116       GlobalValue *GV;        // The global value this corresponds to.
117       //std::string Name;       // Name of the symbol.
118       unsigned NameIdx;       // Index in .strtab of name, once emitted.
119       uint64_t Value;
120       unsigned Size;
121       unsigned char Info;
122       unsigned char Other;
123       unsigned short SectionIdx;
124
125       enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 };
126       enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3,
127              STT_FILE = 4 };
128       ELFSym(GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0),
129                                 Other(0), SectionIdx(0) {}
130
131       void SetBind(unsigned X) {
132         assert(X == (X & 0xF) && "Bind value out of range!");
133         Info = (Info & 0x0F) | (X << 4);
134       }
135       void SetType(unsigned X) {
136         assert(X == (X & 0xF) && "Type value out of range!");
137         Info = (Info & 0xF0) | X;
138       }
139     };
140
141     /// SymbolTable - This is the list of symbols we have emitted to the file.
142     /// This actually gets rearranged before emission to OutputBuffer (to put
143     /// the local symbols first in the list).
144     std::vector<ELFSym> SymbolTable;
145
146
147     // As we accumulate the ELF file into OutputBuffer, we occasionally need to
148     // keep track of locations to update later (e.g. the location of the section
149     // table in the ELF header.  These members keep track of the offset in
150     // OffsetBuffer of these various pieces to update and other locations in the
151     // file.
152     unsigned ELFHeader_e_shoff_Offset;     // e_shoff    in ELF header.
153     unsigned ELFHeader_e_shstrndx_Offset;  // e_shstrndx in ELF header.
154     unsigned ELFHeader_e_shnum_Offset;     // e_shnum    in ELF header.
155
156     // align - Emit padding into the file until the current output position is
157     // aligned to the specified power of two boundary.
158     void align(unsigned Boundary) {
159       assert(Boundary && (Boundary & (Boundary-1)) == 0 &&
160              "Must align to 2^k boundary");
161       while (OutputBuffer.size() & (Boundary-1))
162         outbyte(0xAB);
163     }
164
165     void outbyte(unsigned char X) { OutputBuffer.push_back(X); }
166     void outhalf(unsigned short X) {
167       if (isLittleEndian) {
168         OutputBuffer.push_back(X&255);
169         OutputBuffer.push_back(X >> 8);
170       } else {
171         OutputBuffer.push_back(X >> 8);
172         OutputBuffer.push_back(X&255);
173       }
174     }
175     void outword(unsigned X) {
176       if (isLittleEndian) {
177         OutputBuffer.push_back((X >>  0) & 255);
178         OutputBuffer.push_back((X >>  8) & 255);
179         OutputBuffer.push_back((X >> 16) & 255);
180         OutputBuffer.push_back((X >> 24) & 255);
181       } else {
182         OutputBuffer.push_back((X >> 24) & 255);
183         OutputBuffer.push_back((X >> 16) & 255);
184         OutputBuffer.push_back((X >>  8) & 255);
185         OutputBuffer.push_back((X >>  0) & 255);
186       }
187     }
188     void outaddr(uint64_t X) {
189       if (!is64Bit)
190         outword((unsigned)X);
191       else
192         assert(0 && "Emission of 64-bit data not implemented yet!");
193     }
194
195     // fix functions - Replace an existing entry at an offset.
196     void fixhalf(unsigned short X, unsigned Offset) {
197       unsigned char *P = &OutputBuffer[Offset];
198       P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
199       P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
200     }
201
202     void fixword(unsigned X, unsigned Offset) {
203       unsigned char *P = &OutputBuffer[Offset];
204       P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
205       P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
206       P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
207       P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
208     }
209
210     void fixaddr(uint64_t X, unsigned Offset) {
211       if (!is64Bit)
212         fixword((unsigned)X, Offset);
213       else
214         assert(0 && "Emission of 64-bit data not implemented yet!");
215     }
216
217   private:
218     void EmitGlobal(GlobalVariable *GV, ELFSection &DataSection,
219                     ELFSection &BSSSection);
220
221     void EmitSymbolTable();
222
223     void EmitSectionTableStringTable();
224     void EmitSectionTable();
225   };
226 }
227
228 #endif