ARM64: initial backend import
[oota-llvm.git] / lib / Target / ARM64 / MCTargetDesc / ARM64ELFObjectWriter.cpp
1 //===-- ARM64ELFObjectWriter.cpp - ARM64 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 // This file handles ELF-specific object emission, converting LLVM's internal
11 // fixups into the appropriate relocations.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "MCTargetDesc/ARM64FixupKinds.h"
16 #include "MCTargetDesc/ARM64MCExpr.h"
17 #include "MCTargetDesc/ARM64MCTargetDesc.h"
18 #include "llvm/MC/MCELFObjectWriter.h"
19 #include "llvm/MC/MCValue.h"
20 #include "llvm/Support/ErrorHandling.h"
21
22 using namespace llvm;
23
24 namespace {
25 class ARM64ELFObjectWriter : public MCELFObjectTargetWriter {
26 public:
27   ARM64ELFObjectWriter(uint8_t OSABI);
28
29   virtual ~ARM64ELFObjectWriter();
30
31 protected:
32   unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
33                         bool IsPCRel) const override;
34
35 private:
36 };
37 }
38
39 ARM64ELFObjectWriter::ARM64ELFObjectWriter(uint8_t OSABI)
40     : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
41                               /*HasRelocationAddend*/ true) {}
42
43 ARM64ELFObjectWriter::~ARM64ELFObjectWriter() {}
44
45 unsigned ARM64ELFObjectWriter::GetRelocType(const MCValue &Target,
46                                             const MCFixup &Fixup,
47                                             bool IsPCRel) const {
48   ARM64MCExpr::VariantKind RefKind =
49       static_cast<ARM64MCExpr::VariantKind>(Target.getRefKind());
50   ARM64MCExpr::VariantKind SymLoc = ARM64MCExpr::getSymbolLoc(RefKind);
51   bool IsNC = ARM64MCExpr::isNotChecked(RefKind);
52
53   assert((!Target.getSymA() ||
54           Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
55          "Should only be expression-level modifiers here");
56
57   assert((!Target.getSymB() ||
58           Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
59          "Should only be expression-level modifiers here");
60
61   if (IsPCRel) {
62     switch ((unsigned)Fixup.getKind()) {
63     case FK_Data_2:
64       return ELF::R_AARCH64_PREL16;
65     case FK_Data_4:
66       return ELF::R_AARCH64_PREL32;
67     case FK_Data_8:
68       return ELF::R_AARCH64_PREL64;
69     case ARM64::fixup_arm64_pcrel_adr_imm21:
70       llvm_unreachable("No ELF relocations supported for ADR at the moment");
71     case ARM64::fixup_arm64_pcrel_adrp_imm21:
72       if (SymLoc == ARM64MCExpr::VK_ABS && !IsNC)
73         return ELF::R_AARCH64_ADR_PREL_PG_HI21;
74       if (SymLoc == ARM64MCExpr::VK_GOT && !IsNC)
75         return ELF::R_AARCH64_ADR_GOT_PAGE;
76       if (SymLoc == ARM64MCExpr::VK_GOTTPREL && !IsNC)
77         return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
78       if (SymLoc == ARM64MCExpr::VK_TLSDESC && !IsNC)
79         return ELF::R_AARCH64_TLSDESC_ADR_PAGE;
80       llvm_unreachable("invalid symbol kind for ADRP relocation");
81     case ARM64::fixup_arm64_pcrel_branch26:
82       return ELF::R_AARCH64_JUMP26;
83     case ARM64::fixup_arm64_pcrel_call26:
84       return ELF::R_AARCH64_CALL26;
85     case ARM64::fixup_arm64_pcrel_imm19:
86       return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
87     default:
88       llvm_unreachable("Unsupported pc-relative fixup kind");
89     }
90   } else {
91     switch ((unsigned)Fixup.getKind()) {
92     case FK_Data_2:
93       return ELF::R_AARCH64_ABS16;
94     case FK_Data_4:
95       return ELF::R_AARCH64_ABS32;
96     case FK_Data_8:
97       return ELF::R_AARCH64_ABS64;
98     case ARM64::fixup_arm64_add_imm12:
99       if (SymLoc == ARM64MCExpr::VK_DTPREL && IsNC)
100         return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC;
101       if (SymLoc == ARM64MCExpr::VK_DTPREL && !IsNC)
102         return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12;
103       if (SymLoc == ARM64MCExpr::VK_TPREL && IsNC)
104         return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC;
105       if (SymLoc == ARM64MCExpr::VK_TPREL && !IsNC)
106         return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12;
107       if (SymLoc == ARM64MCExpr::VK_TLSDESC && IsNC)
108         return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC;
109       if (SymLoc == ARM64MCExpr::VK_ABS && IsNC)
110         return ELF::R_AARCH64_ADD_ABS_LO12_NC;
111
112       report_fatal_error("invalid fixup for add (uimm12) instruction");
113       return 0;
114     case ARM64::fixup_arm64_ldst_imm12_scale1:
115       if (SymLoc == ARM64MCExpr::VK_ABS && IsNC)
116         return ELF::R_AARCH64_LDST8_ABS_LO12_NC;
117       if (SymLoc == ARM64MCExpr::VK_DTPREL && !IsNC)
118         return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12;
119       if (SymLoc == ARM64MCExpr::VK_DTPREL && IsNC)
120         return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC;
121       if (SymLoc == ARM64MCExpr::VK_TPREL && !IsNC)
122         return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12;
123       if (SymLoc == ARM64MCExpr::VK_TPREL && IsNC)
124         return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC;
125
126       report_fatal_error("invalid fixup for 8-bit load/store instruction");
127       return 0;
128     case ARM64::fixup_arm64_ldst_imm12_scale2:
129       if (SymLoc == ARM64MCExpr::VK_ABS && IsNC)
130         return ELF::R_AARCH64_LDST16_ABS_LO12_NC;
131       if (SymLoc == ARM64MCExpr::VK_DTPREL && !IsNC)
132         return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12;
133       if (SymLoc == ARM64MCExpr::VK_DTPREL && IsNC)
134         return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC;
135       if (SymLoc == ARM64MCExpr::VK_TPREL && !IsNC)
136         return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12;
137       if (SymLoc == ARM64MCExpr::VK_TPREL && IsNC)
138         return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC;
139
140       report_fatal_error("invalid fixup for 16-bit load/store instruction");
141       return 0;
142     case ARM64::fixup_arm64_ldst_imm12_scale4:
143       if (SymLoc == ARM64MCExpr::VK_ABS && IsNC)
144         return ELF::R_AARCH64_LDST32_ABS_LO12_NC;
145       if (SymLoc == ARM64MCExpr::VK_DTPREL && !IsNC)
146         return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12;
147       if (SymLoc == ARM64MCExpr::VK_DTPREL && IsNC)
148         return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC;
149       if (SymLoc == ARM64MCExpr::VK_TPREL && !IsNC)
150         return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12;
151       if (SymLoc == ARM64MCExpr::VK_TPREL && IsNC)
152         return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC;
153
154       report_fatal_error("invalid fixup for 32-bit load/store instruction");
155       return 0;
156     case ARM64::fixup_arm64_ldst_imm12_scale8:
157       if (SymLoc == ARM64MCExpr::VK_ABS && IsNC)
158         return ELF::R_AARCH64_LDST64_ABS_LO12_NC;
159       if (SymLoc == ARM64MCExpr::VK_GOT && IsNC)
160         return ELF::R_AARCH64_LD64_GOT_LO12_NC;
161       if (SymLoc == ARM64MCExpr::VK_DTPREL && !IsNC)
162         return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12;
163       if (SymLoc == ARM64MCExpr::VK_DTPREL && IsNC)
164         return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC;
165       if (SymLoc == ARM64MCExpr::VK_TPREL && !IsNC)
166         return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12;
167       if (SymLoc == ARM64MCExpr::VK_TPREL && IsNC)
168         return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC;
169       if (SymLoc == ARM64MCExpr::VK_GOTTPREL && IsNC)
170         return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
171       if (SymLoc == ARM64MCExpr::VK_TLSDESC && IsNC)
172         return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;
173
174       report_fatal_error("invalid fixup for 64-bit load/store instruction");
175       return 0;
176     case ARM64::fixup_arm64_ldst_imm12_scale16:
177       if (SymLoc == ARM64MCExpr::VK_ABS && IsNC)
178         return ELF::R_AARCH64_LDST128_ABS_LO12_NC;
179
180       report_fatal_error("invalid fixup for 128-bit load/store instruction");
181       return 0;
182     case ARM64::fixup_arm64_movw:
183       if (RefKind == ARM64MCExpr::VK_ABS_G3)
184         return ELF::R_AARCH64_MOVW_UABS_G3;
185       if (RefKind == ARM64MCExpr::VK_ABS_G2)
186         return ELF::R_AARCH64_MOVW_UABS_G2;
187       if (RefKind == ARM64MCExpr::VK_ABS_G2_NC)
188         return ELF::R_AARCH64_MOVW_UABS_G2_NC;
189       if (RefKind == ARM64MCExpr::VK_ABS_G1)
190         return ELF::R_AARCH64_MOVW_UABS_G1;
191       if (RefKind == ARM64MCExpr::VK_ABS_G1_NC)
192         return ELF::R_AARCH64_MOVW_UABS_G1_NC;
193       if (RefKind == ARM64MCExpr::VK_ABS_G0)
194         return ELF::R_AARCH64_MOVW_UABS_G0;
195       if (RefKind == ARM64MCExpr::VK_ABS_G0_NC)
196         return ELF::R_AARCH64_MOVW_UABS_G0_NC;
197       if (RefKind == ARM64MCExpr::VK_DTPREL_G2)
198         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
199       if (RefKind == ARM64MCExpr::VK_DTPREL_G1)
200         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1;
201       if (RefKind == ARM64MCExpr::VK_DTPREL_G1_NC)
202         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
203       if (RefKind == ARM64MCExpr::VK_DTPREL_G0)
204         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0;
205       if (RefKind == ARM64MCExpr::VK_DTPREL_G0_NC)
206         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC;
207       if (RefKind == ARM64MCExpr::VK_TPREL_G2)
208         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
209       if (RefKind == ARM64MCExpr::VK_TPREL_G1)
210         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1;
211       if (RefKind == ARM64MCExpr::VK_TPREL_G1_NC)
212         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
213       if (RefKind == ARM64MCExpr::VK_TPREL_G0)
214         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0;
215       if (RefKind == ARM64MCExpr::VK_TPREL_G0_NC)
216         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC;
217       if (RefKind == ARM64MCExpr::VK_GOTTPREL_G1)
218         return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
219       if (RefKind == ARM64MCExpr::VK_GOTTPREL_G0_NC)
220         return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
221       report_fatal_error("invalid fixup for movz/movk instruction");
222       return 0;
223     case ARM64::fixup_arm64_tlsdesc_call:
224       return ELF::R_AARCH64_TLSDESC_CALL;
225     default:
226       llvm_unreachable("Unknown ELF relocation type");
227     }
228   }
229
230   llvm_unreachable("Unimplemented fixup -> relocation");
231 }
232
233 MCObjectWriter *llvm::createARM64ELFObjectWriter(raw_ostream &OS,
234                                                  uint8_t OSABI) {
235   MCELFObjectTargetWriter *MOTW = new ARM64ELFObjectWriter(OSABI);
236   return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true);
237 }