Reduce indentation after return. NFC.
[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     virtual ~X86ELFObjectWriter();
26   protected:
27     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
28                           bool IsPCRel) const override;
29   };
30 }
31
32 X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
33                                        uint16_t EMachine)
34   : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
35                             // Only i386 uses Rel instead of RelA.
36                             /*HasRelocationAddend*/ EMachine != ELF::EM_386) {}
37
38 X86ELFObjectWriter::~X86ELFObjectWriter()
39 {}
40
41 unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
42                                           const MCFixup &Fixup,
43                                           bool IsPCRel) const {
44   // determine the type of the relocation
45
46   MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
47   if (getEMachine() == ELF::EM_X86_64) {
48     if (IsPCRel) {
49       switch ((unsigned)Fixup.getKind()) {
50       default:
51         llvm_unreachable("invalid fixup kind!");
52
53       case FK_Data_8:
54         return ELF::R_X86_64_PC64;
55       case FK_Data_4:
56         return ELF::R_X86_64_PC32;
57       case FK_Data_2:
58         return ELF::R_X86_64_PC16;
59       case FK_Data_1:
60         return ELF::R_X86_64_PC8;
61       case FK_PCRel_8:
62         assert(Modifier == MCSymbolRefExpr::VK_None);
63         return ELF::R_X86_64_PC64;
64       case X86::reloc_signed_4byte:
65       case X86::reloc_riprel_4byte_movq_load:
66       case X86::reloc_riprel_4byte:
67       case FK_PCRel_4:
68         switch (Modifier) {
69         default:
70           llvm_unreachable("Unimplemented");
71         case MCSymbolRefExpr::VK_None:
72           return ELF::R_X86_64_PC32;
73         case MCSymbolRefExpr::VK_PLT:
74           return ELF::R_X86_64_PLT32;
75         case MCSymbolRefExpr::VK_GOTPCREL:
76           return ELF::R_X86_64_GOTPCREL;
77         case MCSymbolRefExpr::VK_GOTTPOFF:
78           return ELF::R_X86_64_GOTTPOFF;
79         case MCSymbolRefExpr::VK_TLSGD:
80           return ELF::R_X86_64_TLSGD;
81         case MCSymbolRefExpr::VK_TLSLD:
82           return ELF::R_X86_64_TLSLD;
83         }
84       case FK_PCRel_2:
85         assert(Modifier == MCSymbolRefExpr::VK_None);
86         return ELF::R_X86_64_PC16;
87       case FK_PCRel_1:
88         assert(Modifier == MCSymbolRefExpr::VK_None);
89         return ELF::R_X86_64_PC8;
90       }
91     }
92     switch ((unsigned)Fixup.getKind()) {
93     default:
94       llvm_unreachable("invalid fixup kind!");
95     case X86::reloc_global_offset_table8:
96       return ELF::R_X86_64_GOTPC64;
97     case X86::reloc_global_offset_table:
98       return ELF::R_X86_64_GOTPC32;
99     case FK_Data_8:
100       switch (Modifier) {
101       default:
102         llvm_unreachable("Unimplemented");
103       case MCSymbolRefExpr::VK_None:
104         return ELF::R_X86_64_64;
105       case MCSymbolRefExpr::VK_GOT:
106         return ELF::R_X86_64_GOT64;
107       case MCSymbolRefExpr::VK_GOTOFF:
108         return ELF::R_X86_64_GOTOFF64;
109       case MCSymbolRefExpr::VK_TPOFF:
110         return ELF::R_X86_64_TPOFF64;
111       case MCSymbolRefExpr::VK_DTPOFF:
112         return ELF::R_X86_64_DTPOFF64;
113       case MCSymbolRefExpr::VK_SIZE:
114         return ELF::R_X86_64_SIZE64;
115       }
116     case X86::reloc_signed_4byte:
117       switch (Modifier) {
118       default:
119         llvm_unreachable("Unimplemented");
120       case MCSymbolRefExpr::VK_None:
121         return ELF::R_X86_64_32S;
122       case MCSymbolRefExpr::VK_GOT:
123         return ELF::R_X86_64_GOT32;
124       case MCSymbolRefExpr::VK_GOTPCREL:
125         return ELF::R_X86_64_GOTPCREL;
126       case MCSymbolRefExpr::VK_TPOFF:
127         return ELF::R_X86_64_TPOFF32;
128       case MCSymbolRefExpr::VK_DTPOFF:
129         return ELF::R_X86_64_DTPOFF32;
130       case MCSymbolRefExpr::VK_SIZE:
131         return ELF::R_X86_64_SIZE32;
132       }
133     case FK_Data_4:
134       return ELF::R_X86_64_32;
135     case FK_Data_2:
136       return ELF::R_X86_64_16;
137     case FK_PCRel_1:
138     case FK_Data_1:
139       return ELF::R_X86_64_8;
140     }
141   }
142   assert(getEMachine() == ELF::EM_386 && "Unsupported ELF machine type.");
143   if (IsPCRel) {
144     switch ((unsigned)Fixup.getKind()) {
145     default:
146       llvm_unreachable("invalid fixup kind!");
147
148     case X86::reloc_global_offset_table:
149       return ELF::R_386_GOTPC;
150     case FK_PCRel_1:
151     case FK_Data_1:
152       switch (Modifier) {
153       default:
154         llvm_unreachable("Unimplemented");
155       case MCSymbolRefExpr::VK_None:
156         return ELF::R_386_PC8;
157       }
158     case FK_PCRel_2:
159     case FK_Data_2:
160       switch (Modifier) {
161       default:
162         llvm_unreachable("Unimplemented");
163       case MCSymbolRefExpr::VK_None:
164         return ELF::R_386_PC16;
165       }
166     case X86::reloc_riprel_4byte:
167     case X86::reloc_signed_4byte:
168     case FK_PCRel_4:
169     case FK_Data_4:
170       switch (Modifier) {
171       default:
172         llvm_unreachable("Unimplemented");
173       case MCSymbolRefExpr::VK_None:
174         return ELF::R_386_PC32;
175       case MCSymbolRefExpr::VK_PLT:
176         return ELF::R_386_PLT32;
177       }
178     }
179   } else {
180     switch ((unsigned)Fixup.getKind()) {
181     default:
182       llvm_unreachable("invalid fixup kind!");
183     case X86::reloc_global_offset_table:
184       return ELF::R_386_GOTPC;
185
186     // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
187     // instead?
188     case X86::reloc_signed_4byte:
189     case FK_PCRel_4:
190     case FK_Data_4:
191       switch (Modifier) {
192       default:
193         llvm_unreachable("Unimplemented");
194       case MCSymbolRefExpr::VK_None:
195         return ELF::R_386_32;
196       case MCSymbolRefExpr::VK_GOT:
197         return ELF::R_386_GOT32;
198       case MCSymbolRefExpr::VK_PLT:
199         return ELF::R_386_PLT32;
200       case MCSymbolRefExpr::VK_GOTOFF:
201         return ELF::R_386_GOTOFF;
202       case MCSymbolRefExpr::VK_TLSGD:
203         return ELF::R_386_TLS_GD;
204       case MCSymbolRefExpr::VK_TPOFF:
205         return ELF::R_386_TLS_LE_32;
206       case MCSymbolRefExpr::VK_INDNTPOFF:
207         return ELF::R_386_TLS_IE;
208       case MCSymbolRefExpr::VK_NTPOFF:
209         return ELF::R_386_TLS_LE;
210       case MCSymbolRefExpr::VK_GOTNTPOFF:
211         return ELF::R_386_TLS_GOTIE;
212       case MCSymbolRefExpr::VK_TLSLDM:
213         return ELF::R_386_TLS_LDM;
214       case MCSymbolRefExpr::VK_DTPOFF:
215         return ELF::R_386_TLS_LDO_32;
216       case MCSymbolRefExpr::VK_GOTTPOFF:
217         return ELF::R_386_TLS_IE_32;
218       }
219     case FK_Data_2:
220       return ELF::R_386_16;
221     case FK_PCRel_1:
222     case FK_Data_1:
223       return ELF::R_386_8;
224     }
225   }
226 }
227
228 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
229                                                bool IsELF64,
230                                                uint8_t OSABI,
231                                                uint16_t EMachine) {
232   MCELFObjectTargetWriter *MOTW =
233     new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
234   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
235 }