blob: dc93f7124a52992649fa540b043dfdece4d520f5 [file] [log] [blame]
Rafael Espindola38a400d2011-12-22 01:57:09 +00001//===-- 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/PPCFixupKinds.h"
11#include "MCTargetDesc/PPCMCTargetDesc.h"
12#include "llvm/MC/MCELFObjectWriter.h"
13#include "llvm/Support/ErrorHandling.h"
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000014#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCValue.h"
Rafael Espindola38a400d2011-12-22 01:57:09 +000016
17using namespace llvm;
18
19namespace {
20 class PPCELFObjectWriter : public MCELFObjectTargetWriter {
21 public:
22 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
23
24 virtual ~PPCELFObjectWriter();
25 protected:
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000026 virtual unsigned getRelocTypeInner(const MCValue &Target,
27 const MCFixup &Fixup,
28 bool IsPCRel) const;
Rafael Espindola38a400d2011-12-22 01:57:09 +000029 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
30 bool IsPCRel, bool IsRelocWithSymbol,
31 int64_t Addend) const;
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000032 virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
33 const MCFixup &Fixup,
34 bool IsPCRel) const;
Rafael Espindola38a400d2011-12-22 01:57:09 +000035 virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset);
36 };
37}
38
39PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
40 : MCELFObjectTargetWriter(Is64Bit, OSABI,
41 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
Rafael Espindola25009622011-12-22 18:38:06 +000042 /*HasRelocationAddend*/ true) {}
Rafael Espindola38a400d2011-12-22 01:57:09 +000043
44PPCELFObjectWriter::~PPCELFObjectWriter() {
45}
46
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000047unsigned 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
Rafael Espindola38a400d2011-12-22 01:57:09 +000054 // 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 Type = ELF::R_PPC_REL24;
62 break;
63 case FK_PCRel_4:
64 Type = ELF::R_PPC_REL32;
65 break;
66 }
67 } else {
68 switch ((unsigned)Fixup.getKind()) {
69 default: llvm_unreachable("invalid fixup kind!");
70 case PPC::fixup_ppc_br24:
71 Type = ELF::R_PPC_ADDR24;
72 break;
73 case PPC::fixup_ppc_brcond14:
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +000074 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
Rafael Espindola38a400d2011-12-22 01:57:09 +000075 break;
76 case PPC::fixup_ppc_ha16:
Ulrich Weigand85578502012-11-13 19:24:36 +000077 switch (Modifier) {
78 default: llvm_unreachable("Unsupported Modifier");
79 case MCSymbolRefExpr::VK_PPC_TPREL16_HA:
80 Type = ELF::R_PPC_TPREL16_HA;
81 break;
82 case MCSymbolRefExpr::VK_None:
83 Type = ELF::R_PPC_ADDR16_HA;
84 break;
85 }
Rafael Espindola38a400d2011-12-22 01:57:09 +000086 break;
87 case PPC::fixup_ppc_lo16:
Ulrich Weigand85578502012-11-13 19:24:36 +000088 switch (Modifier) {
89 default: llvm_unreachable("Unsupported Modifier");
90 case MCSymbolRefExpr::VK_PPC_TPREL16_LO:
91 Type = ELF::R_PPC_TPREL16_LO;
92 break;
93 case MCSymbolRefExpr::VK_None:
94 Type = ELF::R_PPC_ADDR16_LO;
95 break;
96 }
Rafael Espindola38a400d2011-12-22 01:57:09 +000097 break;
98 case PPC::fixup_ppc_lo14:
99 Type = ELF::R_PPC_ADDR14;
100 break;
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +0000101 case PPC::fixup_ppc_toc:
102 Type = ELF::R_PPC64_TOC;
103 break;
104 case PPC::fixup_ppc_toc16:
105 Type = ELF::R_PPC64_TOC16;
106 break;
107 case PPC::fixup_ppc_toc16_ds:
108 Type = ELF::R_PPC64_TOC16_DS;
109 break;
110 case FK_Data_8:
111 switch (Modifier) {
112 default: llvm_unreachable("Unsupported Modifier");
113 case MCSymbolRefExpr::VK_PPC_TOC:
114 Type = ELF::R_PPC64_TOC;
115 break;
116 case MCSymbolRefExpr::VK_None:
117 Type = ELF::R_PPC64_ADDR64;
118 break;
119 }
120 break;
Rafael Espindola38a400d2011-12-22 01:57:09 +0000121 case FK_Data_4:
122 Type = ELF::R_PPC_ADDR32;
123 break;
124 case FK_Data_2:
125 Type = ELF::R_PPC_ADDR16;
126 break;
127 }
128 }
129 return Type;
130}
131
Adhemerval Zanellaf2aceda2012-10-25 12:27:42 +0000132unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
133 const MCFixup &Fixup,
134 bool IsPCRel,
135 bool IsRelocWithSymbol,
136 int64_t Addend) const {
137 return getRelocTypeInner(Target, Fixup, IsPCRel);
138}
139
140const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target,
141 const MCFixup &Fixup,
142 bool IsPCRel) const {
143 assert(Target.getSymA() && "SymA cannot be 0");
144 const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol();
145
146 unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel);
147
148 // The .odp creation emits a relocation against the symbol ".TOC." which
149 // create a R_PPC64_TOC relocation. However the relocation symbol name
150 // in final object creation should be NULL, since the symbol does not
151 // really exist, it is just the reference to TOC base for the current
152 // object file.
153 bool EmitThisSym = RelocType != ELF::R_PPC64_TOC;
154
155 if (EmitThisSym && !Symbol.isTemporary())
156 return &Symbol;
157 return NULL;
158}
159
Rafael Espindola38a400d2011-12-22 01:57:09 +0000160void PPCELFObjectWriter::
161adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) {
162 switch ((unsigned)Fixup.getKind()) {
163 case PPC::fixup_ppc_ha16:
164 case PPC::fixup_ppc_lo16:
Adhemerval Zanella1be10dc2012-10-25 14:29:13 +0000165 case PPC::fixup_ppc_toc16:
166 case PPC::fixup_ppc_toc16_ds:
Rafael Espindola38a400d2011-12-22 01:57:09 +0000167 RelocOffset += 2;
168 break;
169 default:
170 break;
171 }
172}
173
174MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
175 bool Is64Bit,
176 uint8_t OSABI) {
177 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
Rafael Espindola25009622011-12-22 18:38:06 +0000178 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
Rafael Espindola38a400d2011-12-22 01:57:09 +0000179}