iniital checkin of ELFWriter header.
[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
22   /// ELFWriter - This class implements the common target-independent code for
23   /// writing ELF files.  Targets should derive a class from this to
24   /// parameterize the output format.
25   ///
26   class ELFWriter : public MachineFunctionPass {
27   protected:
28     ELFWriter(std::ostream &O, TargetMachine &TM);
29
30     /// Output stream to send the resultant object file to.
31     ///
32     std::ostream &O;
33
34     /// Target machine description.
35     ///
36     TargetMachine &TM;
37
38     //===------------------------------------------------------------------===//
39     // Properties to be set by the derived class ctor, used to configure the
40     // ELFWriter.
41
42     // e_machine - This field is the target specific value to emit as the
43     // e_machine member of the ELF header.
44     unsigned short e_machine;
45
46     // e_flags - The machine flags for the target.  This defaults to zero.
47     unsigned e_flags;
48
49     //===------------------------------------------------------------------===//
50     // Properties inferred automatically from the target machine.
51     //
52
53     /// is64Bit/isLittleEndian - This information is inferred from the target
54     /// machine directly, indicating whether to emit a 32- or 64-bit ELF file.
55     bool is64Bit, isLittleEndian;
56
57     /// doInitialization - Emit the file header and all of the global variables
58     /// for the module to the ELF file.
59     bool doInitialization(Module &M);
60
61     bool runOnMachineFunction(MachineFunction &MF);
62
63
64     /// doFinalization - Now that the module has been completely processed, emit
65     /// the ELF file to 'O'.
66     bool doFinalization(Module &M);
67
68   private:
69     // The buffer we are accumulating the file into.  Note that this should be
70     // changed into something much more efficient later (and the bytecode writer
71     // as well!).
72     std::vector<unsigned char> OutputBuffer;
73
74     /// ELFSection - This struct contains information about each section that is
75     /// emitted to the OutputBuffer.  This is eventually turned into the section
76     /// header table at the end of the file.
77     struct ELFSection {
78       std::string Name;       // Name of the section.
79       unsigned NameIdx;       // Index in .shstrtab of name, once emitted.
80       unsigned Type;
81       unsigned Flags;
82       uint64_t Addr;
83       unsigned Offset;
84       unsigned Size;
85       unsigned Link;
86       unsigned Info;
87       unsigned Align;
88       unsigned EntSize;
89       ELFSection() : Type(0), Flags(0), Addr(0), Offset(0), Size(0), Link(0),
90                      Info(0), Align(0), EntSize(0) {
91       }
92       ELFSection(const char *name, unsigned offset)
93         : Name(name), Type(0), Flags(0), Addr(0), Offset(offset), Size(0),
94           Link(0), Info(0), Align(0), EntSize(0) {
95       }
96     };
97
98     /// SectionList - This is the list of sections that we have emitted to the
99     /// file.  Once the file has been completely built, the section header table
100     /// is constructed from this info.
101     std::vector<ELFSection> SectionList;
102
103     // As we accumulate the ELF file into OutputBuffer, we occasionally need to
104     // keep track of locations to update later (e.g. the location of the section
105     // table in the ELF header.  These members keep track of the offset in
106     // OffsetBuffer of these various pieces to update and other locations in the
107     // file.
108     unsigned ELFHeader_e_shoff_Offset;     // e_shoff    in ELF header.
109     unsigned ELFHeader_e_shstrndx_Offset;  // e_shstrndx in ELF header.
110     unsigned ELFHeader_e_shnum_Offset;     // e_shnum    in ELF header.
111
112     void outbyte(unsigned char X) { OutputBuffer.push_back(X); }
113     void outhalf(unsigned short X) {
114       if (isLittleEndian) {
115         OutputBuffer.push_back(X&255);
116         OutputBuffer.push_back(X >> 8);
117       } else {
118         OutputBuffer.push_back(X >> 8);
119         OutputBuffer.push_back(X&255);
120       }
121     }
122     void outword(unsigned X) {
123       if (isLittleEndian) {
124         OutputBuffer.push_back((X >>  0) & 255);
125         OutputBuffer.push_back((X >>  8) & 255);
126         OutputBuffer.push_back((X >> 16) & 255);
127         OutputBuffer.push_back((X >> 24) & 255);
128       } else {
129         OutputBuffer.push_back((X >> 24) & 255);
130         OutputBuffer.push_back((X >> 16) & 255);
131         OutputBuffer.push_back((X >>  8) & 255);
132         OutputBuffer.push_back((X >>  0) & 255);
133       }
134     }
135     void outaddr(uint64_t X) {
136       if (!is64Bit)
137         outword((unsigned)X);
138       else
139         assert(0 && "Emission of 64-bit data not implemented yet!");
140     }
141
142     // fix functions - Replace an existing entry at an offset.
143     void fixhalf(unsigned short X, unsigned Offset) {
144       unsigned char *P = &OutputBuffer[Offset];
145       P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
146       P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
147     }
148
149     void fixword(unsigned X, unsigned Offset) {
150       unsigned char *P = &OutputBuffer[Offset];
151       P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
152       P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
153       P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
154       P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
155     }
156
157     void fixaddr(uint64_t X, unsigned Offset) {
158       if (!is64Bit)
159         fixword((unsigned)X, Offset);
160       else
161         assert(0 && "Emission of 64-bit data not implemented yet!");
162     }
163
164   private:
165     void EmitDATASectionGlobal(GlobalVariable *GV);
166     void EmitBSSSectionGlobal(GlobalVariable *GV);
167     void EmitGlobal(GlobalVariable *GV);
168
169     void EmitSectionTableStringTable();
170     void EmitSectionTable();
171   };
172 }
173
174 #endif