[C++11] Add 'override' keyword to virtual methods that override their base class.
[oota-llvm.git] / lib / Target / X86 / MCTargetDesc / X86ELFObjectWriter.cpp
1 //===-- X86ELFObjectWriter.cpp - X86 ELF Writer ---------------------------===//
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 #include "MCTargetDesc/X86FixupKinds.h"
11 #include "MCTargetDesc/X86MCTargetDesc.h"
12 #include "llvm/MC/MCELFObjectWriter.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCValue.h"
15 #include "llvm/Support/ELF.h"
16 #include "llvm/Support/ErrorHandling.h"
17
18 using namespace llvm;
19
20 namespace {
21   class X86ELFObjectWriter : public MCELFObjectTargetWriter {
22   public:
23     X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
24
25     virtual ~X86ELFObjectWriter();
26   protected:
27     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
28                           bool IsPCRel, bool IsRelocWithSymbol,
29                           int64_t Addend) const override;
30   };
31 }
32
33 X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
34                                        uint16_t EMachine)
35   : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
36                             // Only i386 uses Rel instead of RelA.
37                             /*HasRelocationAddend*/ EMachine != ELF::EM_386) {}
38
39 X86ELFObjectWriter::~X86ELFObjectWriter()
40 {}
41
42 unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
43                                           const MCFixup &Fixup,
44                                           bool IsPCRel,
45                                           bool IsRelocWithSymbol,
46                                           int64_t Addend) const {
47   // determine the type of the relocation
48
49   MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
50     MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
51   unsigned Type;
52   if (getEMachine() == ELF::EM_X86_64) {
53     if (IsPCRel) {
54       switch ((unsigned)Fixup.getKind()) {
55       default: llvm_unreachable("invalid fixup kind!");
56
57       case FK_Data_8: Type = ELF::R_X86_64_PC64; break;
58       case FK_Data_4: Type = ELF::R_X86_64_PC32; break;
59       case FK_Data_2: Type = ELF::R_X86_64_PC16; break;
60       case FK_Data_1: Type = ELF::R_X86_64_PC8; break;
61
62       case FK_PCRel_8:
63         assert(Modifier == MCSymbolRefExpr::VK_None);
64         Type = ELF::R_X86_64_PC64;
65         break;
66       case X86::reloc_signed_4byte:
67       case X86::reloc_riprel_4byte_movq_load:
68       case X86::reloc_riprel_4byte:
69       case FK_PCRel_4:
70         switch (Modifier) {
71         default:
72           llvm_unreachable("Unimplemented");
73         case MCSymbolRefExpr::VK_None:
74           Type = ELF::R_X86_64_PC32;
75           break;
76         case MCSymbolRefExpr::VK_PLT:
77           Type = ELF::R_X86_64_PLT32;
78           break;
79         case MCSymbolRefExpr::VK_GOTPCREL:
80           Type = ELF::R_X86_64_GOTPCREL;
81           break;
82         case MCSymbolRefExpr::VK_GOTTPOFF:
83           Type = ELF::R_X86_64_GOTTPOFF;
84         break;
85         case MCSymbolRefExpr::VK_TLSGD:
86           Type = ELF::R_X86_64_TLSGD;
87           break;
88         case MCSymbolRefExpr::VK_TLSLD:
89           Type = ELF::R_X86_64_TLSLD;
90           break;
91         }
92         break;
93       case FK_PCRel_2:
94         assert(Modifier == MCSymbolRefExpr::VK_None);
95         Type = ELF::R_X86_64_PC16;
96         break;
97       case FK_PCRel_1:
98         assert(Modifier == MCSymbolRefExpr::VK_None);
99         Type = ELF::R_X86_64_PC8;
100         break;
101       }
102     } else {
103       switch ((unsigned)Fixup.getKind()) {
104       default: llvm_unreachable("invalid fixup kind!");
105       case FK_Data_8:
106         switch (Modifier) {
107         default:
108           llvm_unreachable("Unimplemented");
109         case MCSymbolRefExpr::VK_None:
110           Type = ELF::R_X86_64_64;
111           break;
112         case MCSymbolRefExpr::VK_GOT:
113           Type = ELF::R_X86_64_GOT64;
114           break;
115         case MCSymbolRefExpr::VK_GOTOFF:
116           Type = ELF::R_X86_64_GOTOFF64;
117           break;
118         case MCSymbolRefExpr::VK_TPOFF:
119           Type = ELF::R_X86_64_TPOFF64;
120           break;
121         case MCSymbolRefExpr::VK_DTPOFF:
122           Type = ELF::R_X86_64_DTPOFF64;
123           break;
124         }
125         break;
126       case X86::reloc_signed_4byte:
127         switch (Modifier) {
128         default:
129           llvm_unreachable("Unimplemented");
130         case MCSymbolRefExpr::VK_None:
131           Type = ELF::R_X86_64_32S;
132           break;
133         case MCSymbolRefExpr::VK_GOT:
134           Type = ELF::R_X86_64_GOT32;
135           break;
136         case MCSymbolRefExpr::VK_GOTPCREL:
137           Type = ELF::R_X86_64_GOTPCREL;
138           break;
139         case MCSymbolRefExpr::VK_TPOFF:
140           Type = ELF::R_X86_64_TPOFF32;
141           break;
142         case MCSymbolRefExpr::VK_DTPOFF:
143           Type = ELF::R_X86_64_DTPOFF32;
144           break;
145         }
146         break;
147       case FK_Data_4:
148         Type = ELF::R_X86_64_32;
149         break;
150       case FK_Data_2: Type = ELF::R_X86_64_16; break;
151       case FK_PCRel_1:
152       case FK_Data_1: Type = ELF::R_X86_64_8; break;
153       }
154     }
155   } else if (getEMachine() == ELF::EM_386) {
156     if (IsPCRel) {
157       switch ((unsigned)Fixup.getKind()) {
158       default: llvm_unreachable("invalid fixup kind!");
159
160       case X86::reloc_global_offset_table:
161         Type = ELF::R_386_GOTPC;
162         break;
163
164       case FK_PCRel_1:
165       case FK_Data_1:
166         switch (Modifier) {
167         default:
168           llvm_unreachable("Unimplemented");
169         case MCSymbolRefExpr::VK_None:
170           Type = ELF::R_386_PC8;
171           break;
172         }
173         break;
174
175       case FK_PCRel_2:
176       case FK_Data_2:
177         switch (Modifier) {
178         default:
179           llvm_unreachable("Unimplemented");
180         case MCSymbolRefExpr::VK_None:
181           Type = ELF::R_386_PC16;
182           break;
183         }
184         break;
185
186       case X86::reloc_signed_4byte:
187       case FK_PCRel_4:
188       case FK_Data_4:
189         switch (Modifier) {
190         default:
191           llvm_unreachable("Unimplemented");
192         case MCSymbolRefExpr::VK_None:
193           Type = ELF::R_386_PC32;
194           break;
195         case MCSymbolRefExpr::VK_PLT:
196           Type = ELF::R_386_PLT32;
197           break;
198         }
199         break;
200       }
201     } else {
202       switch ((unsigned)Fixup.getKind()) {
203       default: llvm_unreachable("invalid fixup kind!");
204
205       case X86::reloc_global_offset_table:
206         Type = ELF::R_386_GOTPC;
207         break;
208
209       // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
210       // instead?
211       case X86::reloc_signed_4byte:
212       case FK_PCRel_4:
213       case FK_Data_4:
214         switch (Modifier) {
215         default:
216           llvm_unreachable("Unimplemented");
217         case MCSymbolRefExpr::VK_None:
218           Type = ELF::R_386_32;
219           break;
220         case MCSymbolRefExpr::VK_GOT:
221           Type = ELF::R_386_GOT32;
222           break;
223         case MCSymbolRefExpr::VK_GOTOFF:
224           Type = ELF::R_386_GOTOFF;
225           break;
226         case MCSymbolRefExpr::VK_TLSGD:
227           Type = ELF::R_386_TLS_GD;
228           break;
229         case MCSymbolRefExpr::VK_TPOFF:
230           Type = ELF::R_386_TLS_LE_32;
231           break;
232         case MCSymbolRefExpr::VK_INDNTPOFF:
233           Type = ELF::R_386_TLS_IE;
234           break;
235         case MCSymbolRefExpr::VK_NTPOFF:
236           Type = ELF::R_386_TLS_LE;
237           break;
238         case MCSymbolRefExpr::VK_GOTNTPOFF:
239           Type = ELF::R_386_TLS_GOTIE;
240           break;
241         case MCSymbolRefExpr::VK_TLSLDM:
242           Type = ELF::R_386_TLS_LDM;
243           break;
244         case MCSymbolRefExpr::VK_DTPOFF:
245           Type = ELF::R_386_TLS_LDO_32;
246           break;
247         case MCSymbolRefExpr::VK_GOTTPOFF:
248           Type = ELF::R_386_TLS_IE_32;
249           break;
250         }
251         break;
252       case FK_Data_2: Type = ELF::R_386_16; break;
253       case FK_PCRel_1:
254       case FK_Data_1: Type = ELF::R_386_8; break;
255       }
256     }
257   } else
258     llvm_unreachable("Unsupported ELF machine type.");
259
260   return Type;
261 }
262
263 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
264                                                bool IsELF64,
265                                                uint8_t OSABI,
266                                                uint16_t EMachine) {
267   MCELFObjectTargetWriter *MOTW =
268     new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
269   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
270 }