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