[PowerPC] Support absolute branches
[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_PPC_TOC:
131         Type = ELF::R_PPC64_TOC16;
132         break;
133       case MCSymbolRefExpr::VK_PPC_TOC_LO:
134         Type = ELF::R_PPC64_TOC16_LO;
135         break;
136       case MCSymbolRefExpr::VK_PPC_TOC_HI:
137         Type = ELF::R_PPC64_TOC16_HI;
138         break;
139       case MCSymbolRefExpr::VK_PPC_TOC_HA:
140         Type = ELF::R_PPC64_TOC16_HA;
141         break;
142       case MCSymbolRefExpr::VK_PPC_TPREL:
143         Type = ELF::R_PPC_TPREL16;
144         break;
145       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
146         Type = ELF::R_PPC_TPREL16_LO;
147         break;
148       case MCSymbolRefExpr::VK_PPC_TPREL_HI:
149         Type = ELF::R_PPC_TPREL16_HI;
150         break;
151       case MCSymbolRefExpr::VK_PPC_TPREL_HA:
152         Type = ELF::R_PPC_TPREL16_HA;
153         break;
154       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
155         Type = ELF::R_PPC64_TPREL16_HIGHER;
156         break;
157       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
158         Type = ELF::R_PPC64_TPREL16_HIGHERA;
159         break;
160       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
161         Type = ELF::R_PPC64_TPREL16_HIGHEST;
162         break;
163       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
164         Type = ELF::R_PPC64_TPREL16_HIGHESTA;
165         break;
166       case MCSymbolRefExpr::VK_PPC_DTPREL:
167         Type = ELF::R_PPC64_DTPREL16;
168         break;
169       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
170         Type = ELF::R_PPC64_DTPREL16_LO;
171         break;
172       case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
173         Type = ELF::R_PPC64_DTPREL16_HI;
174         break;
175       case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
176         Type = ELF::R_PPC64_DTPREL16_HA;
177         break;
178       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
179         Type = ELF::R_PPC64_DTPREL16_HIGHER;
180         break;
181       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
182         Type = ELF::R_PPC64_DTPREL16_HIGHERA;
183         break;
184       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
185         Type = ELF::R_PPC64_DTPREL16_HIGHEST;
186         break;
187       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
188         Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
189         break;
190       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
191         Type = ELF::R_PPC64_GOT_TLSGD16;
192         break;
193       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
194         Type = ELF::R_PPC64_GOT_TLSGD16_LO;
195         break;
196       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
197         Type = ELF::R_PPC64_GOT_TLSGD16_HI;
198         break;
199       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
200         Type = ELF::R_PPC64_GOT_TLSGD16_HA;
201         break;
202       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
203         Type = ELF::R_PPC64_GOT_TLSLD16;
204         break;
205       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
206         Type = ELF::R_PPC64_GOT_TLSLD16_LO;
207         break;
208       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
209         Type = ELF::R_PPC64_GOT_TLSLD16_HI;
210         break;
211       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
212         Type = ELF::R_PPC64_GOT_TLSLD16_HA;
213         break;
214       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
215         Type = ELF::R_PPC64_GOT_TPREL16_HI;
216         break;
217       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
218         Type = ELF::R_PPC64_GOT_TPREL16_HA;
219         break;
220       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
221         Type = ELF::R_PPC64_GOT_DTPREL16_HI;
222         break;
223       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
224         Type = ELF::R_PPC64_GOT_DTPREL16_HA;
225         break;
226       }
227       break;
228     case PPC::fixup_ppc_half16ds:
229       switch (Modifier) {
230       default: llvm_unreachable("Unsupported Modifier");
231       case MCSymbolRefExpr::VK_None:
232         Type = ELF::R_PPC64_ADDR16_DS;
233         break;
234       case MCSymbolRefExpr::VK_PPC_LO:
235         Type = ELF::R_PPC64_ADDR16_LO_DS;
236         break;
237       case MCSymbolRefExpr::VK_PPC_TOC:
238         Type = ELF::R_PPC64_TOC16_DS;
239         break;
240       case MCSymbolRefExpr::VK_PPC_TOC_LO:
241         Type = ELF::R_PPC64_TOC16_LO_DS;
242         break;
243       case MCSymbolRefExpr::VK_PPC_TPREL:
244         Type = ELF::R_PPC64_TPREL16_DS;
245         break;
246       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
247         Type = ELF::R_PPC64_TPREL16_LO_DS;
248         break;
249       case MCSymbolRefExpr::VK_PPC_DTPREL:
250         Type = ELF::R_PPC64_DTPREL16_DS;
251         break;
252       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
253         Type = ELF::R_PPC64_DTPREL16_LO_DS;
254         break;
255       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
256         Type = ELF::R_PPC64_GOT_TPREL16_DS;
257         break;
258       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
259         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
260         break;
261       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
262         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
263         break;
264       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
265         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
266         break;
267       }
268       break;
269     case PPC::fixup_ppc_tlsreg:
270       Type = ELF::R_PPC64_TLS;
271       break;
272     case PPC::fixup_ppc_nofixup:
273       switch (Modifier) {
274       default: llvm_unreachable("Unsupported Modifier");
275       case MCSymbolRefExpr::VK_PPC_TLSGD:
276         Type = ELF::R_PPC64_TLSGD;
277         break;
278       case MCSymbolRefExpr::VK_PPC_TLSLD:
279         Type = ELF::R_PPC64_TLSLD;
280         break;
281       }
282       break;
283     case FK_Data_8:
284       switch (Modifier) {
285       default: llvm_unreachable("Unsupported Modifier");
286       case MCSymbolRefExpr::VK_PPC_TOCBASE:
287         Type = ELF::R_PPC64_TOC;
288         break;
289       case MCSymbolRefExpr::VK_None:
290         Type = ELF::R_PPC64_ADDR64;
291         break;
292       }
293       break;
294     case FK_Data_4:
295       Type = ELF::R_PPC_ADDR32;
296       break;
297     case FK_Data_2:
298       Type = ELF::R_PPC_ADDR16;
299       break;
300     }
301   }
302   return Type;
303 }
304
305 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
306                                           const MCFixup &Fixup,
307                                           bool IsPCRel,
308                                           bool IsRelocWithSymbol,
309                                           int64_t Addend) const {
310   return getRelocTypeInner(Target, Fixup, IsPCRel);
311 }
312
313 const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target,
314                                                             const MCFixup &Fixup,
315                                                             bool IsPCRel) const {
316   assert(Target.getSymA() && "SymA cannot be 0");
317   const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol();
318
319   unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel);
320
321   // The .odp creation emits a relocation against the symbol ".TOC." which
322   // create a R_PPC64_TOC relocation. However the relocation symbol name
323   // in final object creation should be NULL, since the symbol does not
324   // really exist, it is just the reference to TOC base for the current
325   // object file.
326   bool EmitThisSym = RelocType != ELF::R_PPC64_TOC;
327
328   if (EmitThisSym && !Symbol.isTemporary())
329     return &Symbol;
330   return NULL;
331 }
332
333 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
334                                                bool Is64Bit,
335                                                uint8_t OSABI) {
336   MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
337   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/false);
338 }