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