[X86] Fix an unused variable warning in released builds.
[oota-llvm.git] / lib / Target / X86 / MCTargetDesc / X86ELFObjectWriter.cpp
1 //===-- X86ELFObjectWriter.cpp - X86 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/X86FixupKinds.h"
11 #include "MCTargetDesc/X86MCTargetDesc.h"
12 #include "llvm/MC/MCELFObjectWriter.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCValue.h"
15 #include "llvm/Support/ELF.h"
16 #include "llvm/Support/ErrorHandling.h"
17
18 using namespace llvm;
19
20 namespace {
21   class X86ELFObjectWriter : public MCELFObjectTargetWriter {
22   public:
23     X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
24
25     ~X86ELFObjectWriter() override;
26
27   protected:
28     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
29                           bool IsPCRel) const override;
30   };
31 }
32
33 X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
34                                        uint16_t EMachine)
35     : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
36                               // Only i386 and IAMCU use Rel instead of RelA.
37                               /*HasRelocationAddend*/
38                               (EMachine != ELF::EM_386) &&
39                                   (EMachine != ELF::EM_IAMCU)) {}
40
41 X86ELFObjectWriter::~X86ELFObjectWriter()
42 {}
43
44 enum X86_64RelType { RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 };
45
46 static X86_64RelType getType64(unsigned Kind,
47                                MCSymbolRefExpr::VariantKind &Modifier,
48                                bool &IsPCRel) {
49   switch (Kind) {
50   default:
51     llvm_unreachable("Unimplemented");
52   case X86::reloc_global_offset_table8:
53     Modifier = MCSymbolRefExpr::VK_GOT;
54     IsPCRel = true;
55     return RT64_64;
56   case FK_Data_8:
57     return RT64_64;
58   case X86::reloc_signed_4byte:
59     if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel)
60       return RT64_32S;
61     return RT64_32;
62   case X86::reloc_global_offset_table:
63     Modifier = MCSymbolRefExpr::VK_GOT;
64     IsPCRel = true;
65     return RT64_32;
66   case FK_Data_4:
67   case FK_PCRel_4:
68   case X86::reloc_riprel_4byte:
69   case X86::reloc_riprel_4byte_movq_load:
70     return RT64_32;
71   case FK_PCRel_2:
72   case FK_Data_2:
73     return RT64_16;
74   case FK_PCRel_1:
75   case FK_Data_1:
76     return RT64_8;
77   }
78 }
79
80 static unsigned getRelocType64(MCSymbolRefExpr::VariantKind Modifier,
81                                X86_64RelType Type, bool IsPCRel) {
82   switch (Modifier) {
83   default:
84     llvm_unreachable("Unimplemented");
85   case MCSymbolRefExpr::VK_None:
86     switch (Type) {
87     case RT64_64:
88       return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
89     case RT64_32:
90       return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
91     case RT64_32S:
92       return ELF::R_X86_64_32S;
93     case RT64_16:
94       return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16;
95     case RT64_8:
96       return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8;
97     }
98   case MCSymbolRefExpr::VK_GOT:
99     switch (Type) {
100     case RT64_64:
101       return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64;
102     case RT64_32:
103       return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32;
104     case RT64_32S:
105     case RT64_16:
106     case RT64_8:
107       llvm_unreachable("Unimplemented");
108     }
109   case MCSymbolRefExpr::VK_GOTOFF:
110     assert(Type == RT64_64);
111     assert(!IsPCRel);
112     return ELF::R_X86_64_GOTOFF64;
113   case MCSymbolRefExpr::VK_TPOFF:
114     assert(!IsPCRel);
115     switch (Type) {
116     case RT64_64:
117       return ELF::R_X86_64_TPOFF64;
118     case RT64_32:
119       return ELF::R_X86_64_TPOFF32;
120     case RT64_32S:
121     case RT64_16:
122     case RT64_8:
123       llvm_unreachable("Unimplemented");
124     }
125   case MCSymbolRefExpr::VK_DTPOFF:
126     assert(!IsPCRel);
127     switch (Type) {
128     case RT64_64:
129       return ELF::R_X86_64_DTPOFF64;
130     case RT64_32:
131       return ELF::R_X86_64_DTPOFF32;
132     case RT64_32S:
133     case RT64_16:
134     case RT64_8:
135       llvm_unreachable("Unimplemented");
136     }
137   case MCSymbolRefExpr::VK_SIZE:
138     assert(!IsPCRel);
139     switch (Type) {
140     case RT64_64:
141       return ELF::R_X86_64_SIZE64;
142     case RT64_32:
143       return ELF::R_X86_64_SIZE32;
144     case RT64_32S:
145     case RT64_16:
146     case RT64_8:
147       llvm_unreachable("Unimplemented");
148     }
149   case MCSymbolRefExpr::VK_TLSGD:
150     assert(Type == RT64_32);
151     return ELF::R_X86_64_TLSGD;
152   case MCSymbolRefExpr::VK_GOTTPOFF:
153     assert(Type == RT64_32);
154     return ELF::R_X86_64_GOTTPOFF;
155   case MCSymbolRefExpr::VK_TLSLD:
156     assert(Type == RT64_32);
157     return ELF::R_X86_64_TLSLD;
158   case MCSymbolRefExpr::VK_PLT:
159     assert(Type == RT64_32);
160     return ELF::R_X86_64_PLT32;
161   case MCSymbolRefExpr::VK_GOTPCREL:
162     assert(Type == RT64_32);
163     return ELF::R_X86_64_GOTPCREL;
164   }
165 }
166
167 enum X86_32RelType { RT32_32, RT32_16, RT32_8 };
168
169 static X86_32RelType getType32(X86_64RelType T) {
170   switch (T) {
171   case RT64_64:
172     llvm_unreachable("Unimplemented");
173   case RT64_32:
174   case RT64_32S:
175     return RT32_32;
176   case RT64_16:
177     return RT32_16;
178   case RT64_8:
179     return RT32_8;
180   }
181   llvm_unreachable("unexpected relocation type!");
182 }
183
184 static unsigned getRelocType32(MCSymbolRefExpr::VariantKind Modifier,
185                                X86_32RelType Type, bool IsPCRel) {
186   switch (Modifier) {
187   default:
188     llvm_unreachable("Unimplemented");
189   case MCSymbolRefExpr::VK_None:
190     switch (Type) {
191     case RT32_32:
192       return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
193     case RT32_16:
194       return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
195     case RT32_8:
196       return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
197     }
198   case MCSymbolRefExpr::VK_GOT:
199     assert(Type == RT32_32);
200     return IsPCRel ? ELF::R_386_GOTPC : ELF::R_386_GOT32;
201   case MCSymbolRefExpr::VK_GOTOFF:
202     assert(Type == RT32_32);
203     assert(!IsPCRel);
204     return ELF::R_386_GOTOFF;
205   case MCSymbolRefExpr::VK_TPOFF:
206     assert(Type == RT32_32);
207     assert(!IsPCRel);
208     return ELF::R_386_TLS_LE_32;
209   case MCSymbolRefExpr::VK_DTPOFF:
210     assert(Type == RT32_32);
211     assert(!IsPCRel);
212     return ELF::R_386_TLS_LDO_32;
213   case MCSymbolRefExpr::VK_TLSGD:
214     assert(Type == RT32_32);
215     assert(!IsPCRel);
216     return ELF::R_386_TLS_GD;
217   case MCSymbolRefExpr::VK_GOTTPOFF:
218     assert(Type == RT32_32);
219     assert(!IsPCRel);
220     return ELF::R_386_TLS_IE_32;
221   case MCSymbolRefExpr::VK_PLT:
222     assert(Type == RT32_32);
223     return ELF::R_386_PLT32;
224   case MCSymbolRefExpr::VK_INDNTPOFF:
225     assert(Type == RT32_32);
226     assert(!IsPCRel);
227     return ELF::R_386_TLS_IE;
228   case MCSymbolRefExpr::VK_NTPOFF:
229     assert(Type == RT32_32);
230     assert(!IsPCRel);
231     return ELF::R_386_TLS_LE;
232   case MCSymbolRefExpr::VK_GOTNTPOFF:
233     assert(Type == RT32_32);
234     assert(!IsPCRel);
235     return ELF::R_386_TLS_GOTIE;
236   case MCSymbolRefExpr::VK_TLSLDM:
237     assert(Type == RT32_32);
238     assert(!IsPCRel);
239     return ELF::R_386_TLS_LDM;
240   }
241 }
242
243 unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
244                                           const MCFixup &Fixup,
245                                           bool IsPCRel) const {
246   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
247   X86_64RelType Type = getType64(Fixup.getKind(), Modifier, IsPCRel);
248   if (getEMachine() == ELF::EM_X86_64)
249     return getRelocType64(Modifier, Type, IsPCRel);
250
251   assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
252          "Unsupported ELF machine type.");
253   return getRelocType32(Modifier, getType32(Type), IsPCRel);
254 }
255
256 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_pwrite_stream &OS,
257                                                bool IsELF64, uint8_t OSABI,
258                                                uint16_t EMachine) {
259   MCELFObjectTargetWriter *MOTW =
260     new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
261   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
262 }