Completely rewrite ELFObjectWriter::RecordRelocation.
[oota-llvm.git] / lib / Target / PowerPC / MCTargetDesc / PPCELFObjectWriter.cpp
1 //===-- PPCELFObjectWriter.cpp - PPC 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/PPCMCTargetDesc.h"
11 #include "MCTargetDesc/PPCFixupKinds.h"
12 #include "MCTargetDesc/PPCMCExpr.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCValue.h"
17 #include "llvm/Support/ErrorHandling.h"
18
19 using namespace llvm;
20
21 namespace {
22   class PPCELFObjectWriter : public MCELFObjectTargetWriter {
23   public:
24     PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
25
26     virtual ~PPCELFObjectWriter();
27   protected:
28     virtual unsigned getRelocTypeInner(const MCValue &Target,
29                                        const MCFixup &Fixup,
30                                        bool IsPCRel) const;
31     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
32                           bool IsPCRel) const override;
33   };
34 }
35
36 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37   : MCELFObjectTargetWriter(Is64Bit, OSABI,
38                             Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
39                             /*HasRelocationAddend*/ true) {}
40
41 PPCELFObjectWriter::~PPCELFObjectWriter() {
42 }
43
44 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCFixup &Fixup) {
45   const MCExpr *Expr = Fixup.getValue();
46
47   if (Expr->getKind() != MCExpr::Target)
48     return Fixup.getAccessVariant();
49
50   switch (cast<PPCMCExpr>(Expr)->getKind()) {
51   case PPCMCExpr::VK_PPC_None:
52     return MCSymbolRefExpr::VK_None;
53   case PPCMCExpr::VK_PPC_LO:
54     return MCSymbolRefExpr::VK_PPC_LO;
55   case PPCMCExpr::VK_PPC_HI:
56     return MCSymbolRefExpr::VK_PPC_HI;
57   case PPCMCExpr::VK_PPC_HA:
58     return MCSymbolRefExpr::VK_PPC_HA;
59   case PPCMCExpr::VK_PPC_HIGHERA:
60     return MCSymbolRefExpr::VK_PPC_HIGHERA;
61   case PPCMCExpr::VK_PPC_HIGHER:
62     return MCSymbolRefExpr::VK_PPC_HIGHER;
63   case PPCMCExpr::VK_PPC_HIGHEST:
64     return MCSymbolRefExpr::VK_PPC_HIGHEST;
65   case PPCMCExpr::VK_PPC_HIGHESTA:
66     return MCSymbolRefExpr::VK_PPC_HIGHESTA;
67   }
68   llvm_unreachable("unknown PPCMCExpr kind");
69 }
70
71 unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
72                                                const MCFixup &Fixup,
73                                                bool IsPCRel) const
74 {
75   MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Fixup);
76
77   // determine the type of the relocation
78   unsigned Type;
79   if (IsPCRel) {
80     switch ((unsigned)Fixup.getKind()) {
81     default:
82       llvm_unreachable("Unimplemented");
83     case PPC::fixup_ppc_br24:
84     case PPC::fixup_ppc_br24abs:
85       Type = ELF::R_PPC_REL24;
86       break;
87     case PPC::fixup_ppc_brcond14:
88     case PPC::fixup_ppc_brcond14abs:
89       Type = ELF::R_PPC_REL14;
90       break;
91     case PPC::fixup_ppc_half16:
92       switch (Modifier) {
93       default: llvm_unreachable("Unsupported Modifier");
94       case MCSymbolRefExpr::VK_None:
95         Type = ELF::R_PPC_REL16;
96         break;
97       case MCSymbolRefExpr::VK_PPC_LO:
98         Type = ELF::R_PPC_REL16_LO;
99         break;
100       case MCSymbolRefExpr::VK_PPC_HI:
101         Type = ELF::R_PPC_REL16_HI;
102         break;
103       case MCSymbolRefExpr::VK_PPC_HA:
104         Type = ELF::R_PPC_REL16_HA;
105         break;
106       }
107       break;
108     case FK_Data_4:
109     case FK_PCRel_4:
110       Type = ELF::R_PPC_REL32;
111       break;
112     case FK_Data_8:
113     case FK_PCRel_8:
114       Type = ELF::R_PPC64_REL64;
115       break;
116     }
117   } else {
118     switch ((unsigned)Fixup.getKind()) {
119       default: llvm_unreachable("invalid fixup kind!");
120     case PPC::fixup_ppc_br24abs:
121       Type = ELF::R_PPC_ADDR24;
122       break;
123     case PPC::fixup_ppc_brcond14abs:
124       Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
125       break;
126     case PPC::fixup_ppc_half16:
127       switch (Modifier) {
128       default: llvm_unreachable("Unsupported Modifier");
129       case MCSymbolRefExpr::VK_None:
130         Type = ELF::R_PPC_ADDR16;
131         break;
132       case MCSymbolRefExpr::VK_PPC_LO:
133         Type = ELF::R_PPC_ADDR16_LO;
134         break;
135       case MCSymbolRefExpr::VK_PPC_HI:
136         Type = ELF::R_PPC_ADDR16_HI;
137         break;
138       case MCSymbolRefExpr::VK_PPC_HA:
139         Type = ELF::R_PPC_ADDR16_HA;
140         break;
141       case MCSymbolRefExpr::VK_PPC_HIGHER:
142         Type = ELF::R_PPC64_ADDR16_HIGHER;
143         break;
144       case MCSymbolRefExpr::VK_PPC_HIGHERA:
145         Type = ELF::R_PPC64_ADDR16_HIGHERA;
146         break;
147       case MCSymbolRefExpr::VK_PPC_HIGHEST:
148         Type = ELF::R_PPC64_ADDR16_HIGHEST;
149         break;
150       case MCSymbolRefExpr::VK_PPC_HIGHESTA:
151         Type = ELF::R_PPC64_ADDR16_HIGHESTA;
152         break;
153       case MCSymbolRefExpr::VK_GOT:
154         Type = ELF::R_PPC_GOT16;
155         break;
156       case MCSymbolRefExpr::VK_PPC_GOT_LO:
157         Type = ELF::R_PPC_GOT16_LO;
158         break;
159       case MCSymbolRefExpr::VK_PPC_GOT_HI:
160         Type = ELF::R_PPC_GOT16_HI;
161         break;
162       case MCSymbolRefExpr::VK_PPC_GOT_HA:
163         Type = ELF::R_PPC_GOT16_HA;
164         break;
165       case MCSymbolRefExpr::VK_PPC_TOC:
166         Type = ELF::R_PPC64_TOC16;
167         break;
168       case MCSymbolRefExpr::VK_PPC_TOC_LO:
169         Type = ELF::R_PPC64_TOC16_LO;
170         break;
171       case MCSymbolRefExpr::VK_PPC_TOC_HI:
172         Type = ELF::R_PPC64_TOC16_HI;
173         break;
174       case MCSymbolRefExpr::VK_PPC_TOC_HA:
175         Type = ELF::R_PPC64_TOC16_HA;
176         break;
177       case MCSymbolRefExpr::VK_PPC_TPREL:
178         Type = ELF::R_PPC_TPREL16;
179         break;
180       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
181         Type = ELF::R_PPC_TPREL16_LO;
182         break;
183       case MCSymbolRefExpr::VK_PPC_TPREL_HI:
184         Type = ELF::R_PPC_TPREL16_HI;
185         break;
186       case MCSymbolRefExpr::VK_PPC_TPREL_HA:
187         Type = ELF::R_PPC_TPREL16_HA;
188         break;
189       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
190         Type = ELF::R_PPC64_TPREL16_HIGHER;
191         break;
192       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
193         Type = ELF::R_PPC64_TPREL16_HIGHERA;
194         break;
195       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
196         Type = ELF::R_PPC64_TPREL16_HIGHEST;
197         break;
198       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
199         Type = ELF::R_PPC64_TPREL16_HIGHESTA;
200         break;
201       case MCSymbolRefExpr::VK_PPC_DTPREL:
202         Type = ELF::R_PPC64_DTPREL16;
203         break;
204       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
205         Type = ELF::R_PPC64_DTPREL16_LO;
206         break;
207       case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
208         Type = ELF::R_PPC64_DTPREL16_HI;
209         break;
210       case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
211         Type = ELF::R_PPC64_DTPREL16_HA;
212         break;
213       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
214         Type = ELF::R_PPC64_DTPREL16_HIGHER;
215         break;
216       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
217         Type = ELF::R_PPC64_DTPREL16_HIGHERA;
218         break;
219       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
220         Type = ELF::R_PPC64_DTPREL16_HIGHEST;
221         break;
222       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
223         Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
224         break;
225       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
226         Type = ELF::R_PPC64_GOT_TLSGD16;
227         break;
228       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
229         Type = ELF::R_PPC64_GOT_TLSGD16_LO;
230         break;
231       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
232         Type = ELF::R_PPC64_GOT_TLSGD16_HI;
233         break;
234       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
235         Type = ELF::R_PPC64_GOT_TLSGD16_HA;
236         break;
237       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
238         Type = ELF::R_PPC64_GOT_TLSLD16;
239         break;
240       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
241         Type = ELF::R_PPC64_GOT_TLSLD16_LO;
242         break;
243       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
244         Type = ELF::R_PPC64_GOT_TLSLD16_HI;
245         break;
246       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
247         Type = ELF::R_PPC64_GOT_TLSLD16_HA;
248         break;
249       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
250         /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
251            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
252         Type = ELF::R_PPC64_GOT_TPREL16_DS;
253         break;
254       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
255         /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
256            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
257         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
258         break;
259       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
260         Type = ELF::R_PPC64_GOT_TPREL16_HI;
261         break;
262       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
263         /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
264            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
265         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
266         break;
267       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
268         /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
269            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
270         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
271         break;
272       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
273         Type = ELF::R_PPC64_GOT_TPREL16_HA;
274         break;
275       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
276         Type = ELF::R_PPC64_GOT_DTPREL16_HI;
277         break;
278       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
279         Type = ELF::R_PPC64_GOT_DTPREL16_HA;
280         break;
281       }
282       break;
283     case PPC::fixup_ppc_half16ds:
284       switch (Modifier) {
285       default: llvm_unreachable("Unsupported Modifier");
286       case MCSymbolRefExpr::VK_None:
287         Type = ELF::R_PPC64_ADDR16_DS;
288         break;
289       case MCSymbolRefExpr::VK_PPC_LO:
290         Type = ELF::R_PPC64_ADDR16_LO_DS;
291         break;
292       case MCSymbolRefExpr::VK_GOT:
293         Type = ELF::R_PPC64_GOT16_DS;
294         break;
295       case MCSymbolRefExpr::VK_PPC_GOT_LO:
296         Type = ELF::R_PPC64_GOT16_LO_DS;
297         break;
298       case MCSymbolRefExpr::VK_PPC_TOC:
299         Type = ELF::R_PPC64_TOC16_DS;
300         break;
301       case MCSymbolRefExpr::VK_PPC_TOC_LO:
302         Type = ELF::R_PPC64_TOC16_LO_DS;
303         break;
304       case MCSymbolRefExpr::VK_PPC_TPREL:
305         Type = ELF::R_PPC64_TPREL16_DS;
306         break;
307       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
308         Type = ELF::R_PPC64_TPREL16_LO_DS;
309         break;
310       case MCSymbolRefExpr::VK_PPC_DTPREL:
311         Type = ELF::R_PPC64_DTPREL16_DS;
312         break;
313       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
314         Type = ELF::R_PPC64_DTPREL16_LO_DS;
315         break;
316       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
317         Type = ELF::R_PPC64_GOT_TPREL16_DS;
318         break;
319       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
320         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
321         break;
322       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
323         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
324         break;
325       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
326         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
327         break;
328       }
329       break;
330     case PPC::fixup_ppc_nofixup:
331       switch (Modifier) {
332       default: llvm_unreachable("Unsupported Modifier");
333       case MCSymbolRefExpr::VK_PPC_TLSGD:
334         Type = ELF::R_PPC64_TLSGD;
335         break;
336       case MCSymbolRefExpr::VK_PPC_TLSLD:
337         Type = ELF::R_PPC64_TLSLD;
338         break;
339       case MCSymbolRefExpr::VK_PPC_TLS:
340         Type = ELF::R_PPC64_TLS;
341         break;
342       }
343       break;
344     case FK_Data_8:
345       switch (Modifier) {
346       default: llvm_unreachable("Unsupported Modifier");
347       case MCSymbolRefExpr::VK_PPC_TOCBASE:
348         Type = ELF::R_PPC64_TOC;
349         break;
350       case MCSymbolRefExpr::VK_None:
351         Type = ELF::R_PPC64_ADDR64;
352         break;
353       case MCSymbolRefExpr::VK_PPC_DTPMOD:
354         Type = ELF::R_PPC64_DTPMOD64;
355         break;
356       case MCSymbolRefExpr::VK_PPC_TPREL:
357         Type = ELF::R_PPC64_TPREL64;
358         break;
359       case MCSymbolRefExpr::VK_PPC_DTPREL:
360         Type = ELF::R_PPC64_DTPREL64;
361         break;
362       }
363       break;
364     case FK_Data_4:
365       Type = ELF::R_PPC_ADDR32;
366       break;
367     case FK_Data_2:
368       Type = ELF::R_PPC_ADDR16;
369       break;
370     }
371   }
372   return Type;
373 }
374
375 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
376                                           const MCFixup &Fixup,
377                                           bool IsPCRel) const {
378   return getRelocTypeInner(Target, Fixup, IsPCRel);
379 }
380
381 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
382                                                bool Is64Bit,
383                                                bool IsLittleEndian,
384                                                uint8_t OSABI) {
385   MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
386   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
387 }