blob: 856946555198aa5998419c2563074bc9da094752 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//===-- AArch64AsmBackend.cpp - AArch64 Assembler Backend -----------------===//
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 "AArch64.h"
11#include "AArch64RegisterInfo.h"
12#include "MCTargetDesc/AArch64FixupKinds.h"
Daniel Sanders50f17232015-09-15 16:17:27 +000013#include "llvm/ADT/Triple.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000014#include "llvm/BinaryFormat/MachO.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000015#include "llvm/MC/MCAsmBackend.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000016#include "llvm/MC/MCAssembler.h"
Oliver Stannarda5520b02016-04-01 09:14:50 +000017#include "llvm/MC/MCContext.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000018#include "llvm/MC/MCDirectives.h"
Chad Rosierafe7c932014-08-06 16:05:02 +000019#include "llvm/MC/MCELFObjectWriter.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000020#include "llvm/MC/MCFixupKindInfo.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000021#include "llvm/MC/MCObjectWriter.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000022#include "llvm/MC/MCSectionELF.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/MC/MCSectionMachO.h"
Peter Collingbournee8813e62015-03-24 21:47:03 +000024#include "llvm/MC/MCValue.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/Support/ErrorHandling.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000026using namespace llvm;
27
28namespace {
29
30class AArch64AsmBackend : public MCAsmBackend {
31 static const unsigned PCRelFlagVal =
32 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel;
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +000033 Triple TheTriple;
34
Keith Walker8c44bf12016-01-20 15:59:14 +000035public:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +000036 AArch64AsmBackend(const Target &T, const Triple &TT, bool IsLittleEndian)
Peter Collingbourne571a3302018-05-21 17:57:19 +000037 : MCAsmBackend(IsLittleEndian ? support::little : support::big),
38 TheTriple(TT) {}
Tim Northover3b0846e2014-05-24 12:50:23 +000039
40 unsigned getNumFixupKinds() const override {
41 return AArch64::NumTargetFixupKinds;
42 }
43
44 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
45 const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = {
Rafael Espindola3ac4c092017-06-20 22:53:29 +000046 // This table *must* be in the order that the fixup_* kinds are defined
47 // in AArch64FixupKinds.h.
48 //
49 // Name Offset (bits) Size (bits) Flags
50 {"fixup_aarch64_pcrel_adr_imm21", 0, 32, PCRelFlagVal},
51 {"fixup_aarch64_pcrel_adrp_imm21", 0, 32, PCRelFlagVal},
52 {"fixup_aarch64_add_imm12", 10, 12, 0},
53 {"fixup_aarch64_ldst_imm12_scale1", 10, 12, 0},
54 {"fixup_aarch64_ldst_imm12_scale2", 10, 12, 0},
55 {"fixup_aarch64_ldst_imm12_scale4", 10, 12, 0},
56 {"fixup_aarch64_ldst_imm12_scale8", 10, 12, 0},
57 {"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
58 {"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
59 {"fixup_aarch64_movw", 5, 16, 0},
60 {"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
61 {"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
62 {"fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal},
63 {"fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal},
64 {"fixup_aarch64_tlsdesc_call", 0, 0, 0}};
Tim Northover3b0846e2014-05-24 12:50:23 +000065
66 if (Kind < FirstTargetFixupKind)
67 return MCAsmBackend::getFixupKindInfo(Kind);
68
69 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
70 "Invalid kind!");
71 return Infos[Kind - FirstTargetFixupKind];
72 }
73
Rafael Espindola801b42d2017-06-23 22:52:36 +000074 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
75 const MCValue &Target, MutableArrayRef<char> Data,
Peter Smith57f661b2018-06-06 09:40:06 +000076 uint64_t Value, bool IsResolved,
77 const MCSubtargetInfo *STI) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +000078
Peter Smith57f661b2018-06-06 09:40:06 +000079 bool mayNeedRelaxation(const MCInst &Inst,
80 const MCSubtargetInfo &STI) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +000081 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
82 const MCRelaxableFragment *DF,
83 const MCAsmLayout &Layout) const override;
Nirav Dave86030622016-07-11 14:23:53 +000084 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
85 MCInst &Res) const override;
Peter Collingbourne571a3302018-05-21 17:57:19 +000086 bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +000087
88 void HandleAssemblerFlag(MCAssemblerFlag Flag) {}
89
90 unsigned getPointerSize() const { return 8; }
Keith Walker8c44bf12016-01-20 15:59:14 +000091
92 unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const;
Martin Storsjob2e9fcf2017-07-19 20:14:32 +000093
94 bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
95 const MCValue &Target) override;
Tim Northover3b0846e2014-05-24 12:50:23 +000096};
97
98} // end anonymous namespace
99
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000100/// The number of bytes the fixup may change.
Tim Northover3b0846e2014-05-24 12:50:23 +0000101static unsigned getFixupKindNumBytes(unsigned Kind) {
102 switch (Kind) {
103 default:
Craig Topper2a30d782014-06-18 05:05:13 +0000104 llvm_unreachable("Unknown fixup kind!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000105
106 case AArch64::fixup_aarch64_tlsdesc_call:
107 return 0;
108
109 case FK_Data_1:
110 return 1;
111
Tim Northover3b0846e2014-05-24 12:50:23 +0000112 case AArch64::fixup_aarch64_movw:
Mandeep Singh Granga210f1d2017-07-17 00:05:32 +0000113 case FK_Data_2:
114 case FK_SecRel_2:
Tim Northover3b0846e2014-05-24 12:50:23 +0000115 return 2;
116
117 case AArch64::fixup_aarch64_pcrel_branch14:
118 case AArch64::fixup_aarch64_add_imm12:
119 case AArch64::fixup_aarch64_ldst_imm12_scale1:
120 case AArch64::fixup_aarch64_ldst_imm12_scale2:
121 case AArch64::fixup_aarch64_ldst_imm12_scale4:
122 case AArch64::fixup_aarch64_ldst_imm12_scale8:
123 case AArch64::fixup_aarch64_ldst_imm12_scale16:
124 case AArch64::fixup_aarch64_ldr_pcrel_imm19:
125 case AArch64::fixup_aarch64_pcrel_branch19:
126 return 3;
127
128 case AArch64::fixup_aarch64_pcrel_adr_imm21:
129 case AArch64::fixup_aarch64_pcrel_adrp_imm21:
130 case AArch64::fixup_aarch64_pcrel_branch26:
131 case AArch64::fixup_aarch64_pcrel_call26:
132 case FK_Data_4:
Mandeep Singh Granga210f1d2017-07-17 00:05:32 +0000133 case FK_SecRel_4:
Tim Northover3b0846e2014-05-24 12:50:23 +0000134 return 4;
135
136 case FK_Data_8:
137 return 8;
138 }
139}
140
141static unsigned AdrImmBits(unsigned Value) {
142 unsigned lo2 = Value & 0x3;
143 unsigned hi19 = (Value & 0x1ffffc) >> 2;
144 return (hi19 << 5) | (lo2 << 29);
145}
146
Oliver Stannarda5520b02016-04-01 09:14:50 +0000147static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000148 MCContext &Ctx, const Triple &TheTriple,
149 bool IsResolved) {
Oliver Stannarda5520b02016-04-01 09:14:50 +0000150 unsigned Kind = Fixup.getKind();
Tim Northover3b0846e2014-05-24 12:50:23 +0000151 int64_t SignedValue = static_cast<int64_t>(Value);
152 switch (Kind) {
153 default:
Craig Topperd3c02f12015-01-05 10:15:49 +0000154 llvm_unreachable("Unknown fixup kind!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000155 case AArch64::fixup_aarch64_pcrel_adr_imm21:
Alex Bradbury866113c2017-04-05 10:16:14 +0000156 if (SignedValue > 2097151 || SignedValue < -2097152)
157 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
Tim Northover3b0846e2014-05-24 12:50:23 +0000158 return AdrImmBits(Value & 0x1fffffULL);
159 case AArch64::fixup_aarch64_pcrel_adrp_imm21:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000160 assert(!IsResolved);
161 if (TheTriple.isOSBinFormatCOFF())
162 return AdrImmBits(Value & 0x1fffffULL);
Tim Northover3b0846e2014-05-24 12:50:23 +0000163 return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
164 case AArch64::fixup_aarch64_ldr_pcrel_imm19:
165 case AArch64::fixup_aarch64_pcrel_branch19:
166 // Signed 21-bit immediate
167 if (SignedValue > 2097151 || SignedValue < -2097152)
Alex Bradbury866113c2017-04-05 10:16:14 +0000168 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
169 if (Value & 0x3)
170 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
Tim Northover3b0846e2014-05-24 12:50:23 +0000171 // Low two bits are not encoded.
172 return (Value >> 2) & 0x7ffff;
173 case AArch64::fixup_aarch64_add_imm12:
174 case AArch64::fixup_aarch64_ldst_imm12_scale1:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000175 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
176 Value &= 0xfff;
Tim Northover3b0846e2014-05-24 12:50:23 +0000177 // Unsigned 12-bit immediate
Alex Bradbury866113c2017-04-05 10:16:14 +0000178 if (Value >= 0x1000)
179 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
Tim Northover3b0846e2014-05-24 12:50:23 +0000180 return Value;
181 case AArch64::fixup_aarch64_ldst_imm12_scale2:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000182 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
183 Value &= 0xfff;
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 // Unsigned 12-bit immediate which gets multiplied by 2
Alex Bradbury866113c2017-04-05 10:16:14 +0000185 if (Value >= 0x2000)
186 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
187 if (Value & 0x1)
188 Ctx.reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
Tim Northover3b0846e2014-05-24 12:50:23 +0000189 return Value >> 1;
190 case AArch64::fixup_aarch64_ldst_imm12_scale4:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000191 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
192 Value &= 0xfff;
Tim Northover3b0846e2014-05-24 12:50:23 +0000193 // Unsigned 12-bit immediate which gets multiplied by 4
Alex Bradbury866113c2017-04-05 10:16:14 +0000194 if (Value >= 0x4000)
195 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
196 if (Value & 0x3)
197 Ctx.reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
Tim Northover3b0846e2014-05-24 12:50:23 +0000198 return Value >> 2;
199 case AArch64::fixup_aarch64_ldst_imm12_scale8:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000200 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
201 Value &= 0xfff;
Tim Northover3b0846e2014-05-24 12:50:23 +0000202 // Unsigned 12-bit immediate which gets multiplied by 8
Alex Bradbury866113c2017-04-05 10:16:14 +0000203 if (Value >= 0x8000)
204 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
205 if (Value & 0x7)
206 Ctx.reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
Tim Northover3b0846e2014-05-24 12:50:23 +0000207 return Value >> 3;
208 case AArch64::fixup_aarch64_ldst_imm12_scale16:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000209 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
210 Value &= 0xfff;
Tim Northover3b0846e2014-05-24 12:50:23 +0000211 // Unsigned 12-bit immediate which gets multiplied by 16
Alex Bradbury866113c2017-04-05 10:16:14 +0000212 if (Value >= 0x10000)
213 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
214 if (Value & 0xf)
215 Ctx.reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
Tim Northover3b0846e2014-05-24 12:50:23 +0000216 return Value >> 4;
217 case AArch64::fixup_aarch64_movw:
Alex Bradbury866113c2017-04-05 10:16:14 +0000218 Ctx.reportError(Fixup.getLoc(),
219 "no resolvable MOVZ/MOVK fixups supported yet");
Tim Northover3b0846e2014-05-24 12:50:23 +0000220 return Value;
221 case AArch64::fixup_aarch64_pcrel_branch14:
222 // Signed 16-bit immediate
Alex Bradbury866113c2017-04-05 10:16:14 +0000223 if (SignedValue > 32767 || SignedValue < -32768)
224 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
Tim Northover3b0846e2014-05-24 12:50:23 +0000225 // Low two bits are not encoded (4-byte alignment assumed).
Alex Bradbury866113c2017-04-05 10:16:14 +0000226 if (Value & 0x3)
227 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
Tim Northover3b0846e2014-05-24 12:50:23 +0000228 return (Value >> 2) & 0x3fff;
229 case AArch64::fixup_aarch64_pcrel_branch26:
230 case AArch64::fixup_aarch64_pcrel_call26:
231 // Signed 28-bit immediate
Alex Bradbury866113c2017-04-05 10:16:14 +0000232 if (SignedValue > 134217727 || SignedValue < -134217728)
233 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
Tim Northover3b0846e2014-05-24 12:50:23 +0000234 // Low two bits are not encoded (4-byte alignment assumed).
Alex Bradbury866113c2017-04-05 10:16:14 +0000235 if (Value & 0x3)
236 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
Tim Northover3b0846e2014-05-24 12:50:23 +0000237 return (Value >> 2) & 0x3ffffff;
238 case FK_Data_1:
239 case FK_Data_2:
240 case FK_Data_4:
241 case FK_Data_8:
Mandeep Singh Granga210f1d2017-07-17 00:05:32 +0000242 case FK_SecRel_2:
243 case FK_SecRel_4:
Tim Northover3b0846e2014-05-24 12:50:23 +0000244 return Value;
245 }
246}
247
Keith Walker8c44bf12016-01-20 15:59:14 +0000248/// getFixupKindContainereSizeInBytes - The number of bytes of the
249/// container involved in big endian or 0 if the item is little endian
250unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const {
Peter Collingbourne571a3302018-05-21 17:57:19 +0000251 if (Endian == support::little)
Keith Walker8c44bf12016-01-20 15:59:14 +0000252 return 0;
253
254 switch (Kind) {
255 default:
256 llvm_unreachable("Unknown fixup kind!");
257
258 case FK_Data_1:
259 return 1;
260 case FK_Data_2:
261 return 2;
262 case FK_Data_4:
263 return 4;
264 case FK_Data_8:
265 return 8;
266
267 case AArch64::fixup_aarch64_tlsdesc_call:
268 case AArch64::fixup_aarch64_movw:
269 case AArch64::fixup_aarch64_pcrel_branch14:
270 case AArch64::fixup_aarch64_add_imm12:
271 case AArch64::fixup_aarch64_ldst_imm12_scale1:
272 case AArch64::fixup_aarch64_ldst_imm12_scale2:
273 case AArch64::fixup_aarch64_ldst_imm12_scale4:
274 case AArch64::fixup_aarch64_ldst_imm12_scale8:
275 case AArch64::fixup_aarch64_ldst_imm12_scale16:
276 case AArch64::fixup_aarch64_ldr_pcrel_imm19:
277 case AArch64::fixup_aarch64_pcrel_branch19:
278 case AArch64::fixup_aarch64_pcrel_adr_imm21:
279 case AArch64::fixup_aarch64_pcrel_adrp_imm21:
280 case AArch64::fixup_aarch64_pcrel_branch26:
281 case AArch64::fixup_aarch64_pcrel_call26:
282 // Instructions are always little endian
283 return 0;
284 }
285}
286
Rafael Espindola801b42d2017-06-23 22:52:36 +0000287void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
288 const MCValue &Target,
Rafael Espindola88d9e372017-06-21 23:06:53 +0000289 MutableArrayRef<char> Data, uint64_t Value,
Peter Smith57f661b2018-06-06 09:40:06 +0000290 bool IsResolved,
291 const MCSubtargetInfo *STI) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000292 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
293 if (!Value)
294 return; // Doesn't change encoding.
295 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
Rafael Espindolaf3512922017-06-24 00:26:57 +0000296 MCContext &Ctx = Asm.getContext();
Tim Northover3b0846e2014-05-24 12:50:23 +0000297 // Apply any target-specific value adjustments.
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000298 Value = adjustFixupValue(Fixup, Value, Ctx, TheTriple, IsResolved);
Tim Northover3b0846e2014-05-24 12:50:23 +0000299
300 // Shift the value into position.
301 Value <<= Info.TargetOffset;
302
303 unsigned Offset = Fixup.getOffset();
Rafael Espindola88d9e372017-06-21 23:06:53 +0000304 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000305
Keith Walker8c44bf12016-01-20 15:59:14 +0000306 // Used to point to big endian bytes.
307 unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(Fixup.getKind());
308
Tim Northover3b0846e2014-05-24 12:50:23 +0000309 // For each byte of the fragment that the fixup touches, mask in the
310 // bits from the fixup value.
Keith Walker8c44bf12016-01-20 15:59:14 +0000311 if (FulleSizeInBytes == 0) {
312 // Handle as little-endian
313 for (unsigned i = 0; i != NumBytes; ++i) {
314 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
315 }
316 } else {
317 // Handle as big-endian
Rafael Espindola88d9e372017-06-21 23:06:53 +0000318 assert((Offset + FulleSizeInBytes) <= Data.size() && "Invalid fixup size!");
Keith Walker8c44bf12016-01-20 15:59:14 +0000319 assert(NumBytes <= FulleSizeInBytes && "Invalid fixup size!");
320 for (unsigned i = 0; i != NumBytes; ++i) {
321 unsigned Idx = FulleSizeInBytes - 1 - i;
322 Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
323 }
324 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000325}
326
Peter Smith57f661b2018-06-06 09:40:06 +0000327bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst,
328 const MCSubtargetInfo &STI) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000329 return false;
330}
331
332bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
333 uint64_t Value,
334 const MCRelaxableFragment *DF,
335 const MCAsmLayout &Layout) const {
336 // FIXME: This isn't correct for AArch64. Just moving the "generic" logic
337 // into the targets for now.
338 //
339 // Relax if the value is too big for a (signed) i8.
340 return int64_t(Value) != int64_t(int8_t(Value));
341}
342
343void AArch64AsmBackend::relaxInstruction(const MCInst &Inst,
Nirav Dave86030622016-07-11 14:23:53 +0000344 const MCSubtargetInfo &STI,
Tim Northover3b0846e2014-05-24 12:50:23 +0000345 MCInst &Res) const {
Craig Topperd3c02f12015-01-05 10:15:49 +0000346 llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
Tim Northover3b0846e2014-05-24 12:50:23 +0000347}
348
Peter Collingbourne571a3302018-05-21 17:57:19 +0000349bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000350 // If the count is not 4-byte aligned, we must be writing data into the text
351 // section (otherwise we have unaligned instructions, and thus have far
352 // bigger problems), so just write zeros instead.
Peter Collingbourne571a3302018-05-21 17:57:19 +0000353 OS.write_zeros(Count % 4);
Tim Northover3b0846e2014-05-24 12:50:23 +0000354
355 // We are properly aligned, so write NOPs as requested.
356 Count /= 4;
357 for (uint64_t i = 0; i != Count; ++i)
Peter Collingbourne571a3302018-05-21 17:57:19 +0000358 support::endian::write<uint32_t>(OS, 0xd503201f, Endian);
Tim Northover3b0846e2014-05-24 12:50:23 +0000359 return true;
360}
361
Martin Storsjob2e9fcf2017-07-19 20:14:32 +0000362bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm,
363 const MCFixup &Fixup,
364 const MCValue &Target) {
365 // The ADRP instruction adds some multiple of 0x1000 to the current PC &
366 // ~0xfff. This means that the required offset to reach a symbol can vary by
367 // up to one step depending on where the ADRP is in memory. For example:
368 //
369 // ADRP x0, there
370 // there:
371 //
372 // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and
373 // we'll need that as an offset. At any other address "there" will be in the
374 // same page as the ADRP and the instruction should encode 0x0. Assuming the
375 // section isn't 0x1000-aligned, we therefore need to delegate this decision
376 // to the linker -- a relocation!
377 if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21)
378 return true;
379 return false;
380}
381
Tim Northover3b0846e2014-05-24 12:50:23 +0000382namespace {
383
384namespace CU {
385
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000386/// Compact unwind encoding values.
Tim Northover3b0846e2014-05-24 12:50:23 +0000387enum CompactUnwindEncodings {
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000388 /// A "frameless" leaf function, where no non-volatile registers are
Tim Northover3b0846e2014-05-24 12:50:23 +0000389 /// saved. The return remains in LR throughout the function.
Tim Northover87442c12016-02-23 21:49:05 +0000390 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
Tim Northover3b0846e2014-05-24 12:50:23 +0000391
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000392 /// No compact unwind encoding available. Instead the low 23-bits of
Tim Northover3b0846e2014-05-24 12:50:23 +0000393 /// the compact unwind encoding is the offset of the DWARF FDE in the
394 /// __eh_frame section. This mode is never used in object files. It is only
395 /// generated by the linker in final linked images, which have only DWARF info
396 /// for a function.
Tim Northover87442c12016-02-23 21:49:05 +0000397 UNWIND_ARM64_MODE_DWARF = 0x03000000,
Tim Northover3b0846e2014-05-24 12:50:23 +0000398
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000399 /// This is a standard arm64 prologue where FP/LR are immediately
Tim Northover3b0846e2014-05-24 12:50:23 +0000400 /// pushed on the stack, then SP is copied to FP. If there are any
401 /// non-volatile register saved, they are copied into the stack fame in pairs
402 /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the
403 /// five X pairs and four D pairs can be saved, but the memory layout must be
404 /// in register number order.
Tim Northover87442c12016-02-23 21:49:05 +0000405 UNWIND_ARM64_MODE_FRAME = 0x04000000,
Tim Northover3b0846e2014-05-24 12:50:23 +0000406
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000407 /// Frame register pair encodings.
Tim Northover87442c12016-02-23 21:49:05 +0000408 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
409 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
410 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
411 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
412 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
413 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
414 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
415 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
416 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800
Tim Northover3b0846e2014-05-24 12:50:23 +0000417};
418
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000419} // end CU namespace
Tim Northover3b0846e2014-05-24 12:50:23 +0000420
421// FIXME: This should be in a separate file.
422class DarwinAArch64AsmBackend : public AArch64AsmBackend {
423 const MCRegisterInfo &MRI;
424
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000425 /// Encode compact unwind stack adjustment for frameless functions.
Tim Northover87442c12016-02-23 21:49:05 +0000426 /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
Tim Northover3b0846e2014-05-24 12:50:23 +0000427 /// The stack size always needs to be 16 byte aligned.
428 uint32_t encodeStackAdjustment(uint32_t StackSize) const {
429 return (StackSize / 16) << 12;
430 }
431
432public:
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000433 DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
434 const MCRegisterInfo &MRI)
435 : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000436
Peter Collingbournedcd7d6c2018-05-21 19:20:29 +0000437 std::unique_ptr<MCObjectTargetWriter>
438 createObjectTargetWriter() const override {
439 return createAArch64MachObjectWriter(MachO::CPU_TYPE_ARM64,
Tim Northover3b0846e2014-05-24 12:50:23 +0000440 MachO::CPU_SUBTYPE_ARM64_ALL);
441 }
442
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000443 /// Generate the compact unwind encoding from the CFI directives.
Tim Northover3b0846e2014-05-24 12:50:23 +0000444 uint32_t generateCompactUnwindEncoding(
445 ArrayRef<MCCFIInstruction> Instrs) const override {
446 if (Instrs.empty())
Tim Northover87442c12016-02-23 21:49:05 +0000447 return CU::UNWIND_ARM64_MODE_FRAMELESS;
Tim Northover3b0846e2014-05-24 12:50:23 +0000448
449 bool HasFP = false;
450 unsigned StackSize = 0;
451
452 uint32_t CompactUnwindEncoding = 0;
453 for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
454 const MCCFIInstruction &Inst = Instrs[i];
455
456 switch (Inst.getOperation()) {
457 default:
458 // Cannot handle this directive: bail out.
Tim Northover87442c12016-02-23 21:49:05 +0000459 return CU::UNWIND_ARM64_MODE_DWARF;
Tim Northover3b0846e2014-05-24 12:50:23 +0000460 case MCCFIInstruction::OpDefCfa: {
461 // Defines a frame pointer.
Francis Visoiu Mistrih90aba022018-05-31 16:33:26 +0000462 unsigned XReg =
463 getXRegFromWReg(MRI.getLLVMRegNum(Inst.getRegister(), true));
464
465 // Other CFA registers than FP are not supported by compact unwind.
466 // Fallback on DWARF.
467 // FIXME: When opt-remarks are supported in MC, add a remark to notify
468 // the user.
469 if (XReg != AArch64::FP)
470 return CU::UNWIND_ARM64_MODE_DWARF;
471
472 assert(XReg == AArch64::FP && "Invalid frame pointer!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000473 assert(i + 2 < e && "Insufficient CFI instructions to define a frame!");
474
475 const MCCFIInstruction &LRPush = Instrs[++i];
476 assert(LRPush.getOperation() == MCCFIInstruction::OpOffset &&
477 "Link register not pushed!");
478 const MCCFIInstruction &FPPush = Instrs[++i];
479 assert(FPPush.getOperation() == MCCFIInstruction::OpOffset &&
480 "Frame pointer not pushed!");
481
482 unsigned LRReg = MRI.getLLVMRegNum(LRPush.getRegister(), true);
483 unsigned FPReg = MRI.getLLVMRegNum(FPPush.getRegister(), true);
484
485 LRReg = getXRegFromWReg(LRReg);
486 FPReg = getXRegFromWReg(FPReg);
487
488 assert(LRReg == AArch64::LR && FPReg == AArch64::FP &&
489 "Pushing invalid registers for frame!");
490
491 // Indicate that the function has a frame.
Tim Northover87442c12016-02-23 21:49:05 +0000492 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME;
Tim Northover3b0846e2014-05-24 12:50:23 +0000493 HasFP = true;
494 break;
495 }
496 case MCCFIInstruction::OpDefCfaOffset: {
497 assert(StackSize == 0 && "We already have the CFA offset!");
498 StackSize = std::abs(Inst.getOffset());
499 break;
500 }
501 case MCCFIInstruction::OpOffset: {
502 // Registers are saved in pairs. We expect there to be two consecutive
503 // `.cfi_offset' instructions with the appropriate registers specified.
504 unsigned Reg1 = MRI.getLLVMRegNum(Inst.getRegister(), true);
505 if (i + 1 == e)
Tim Northover87442c12016-02-23 21:49:05 +0000506 return CU::UNWIND_ARM64_MODE_DWARF;
Tim Northover3b0846e2014-05-24 12:50:23 +0000507
508 const MCCFIInstruction &Inst2 = Instrs[++i];
509 if (Inst2.getOperation() != MCCFIInstruction::OpOffset)
Tim Northover87442c12016-02-23 21:49:05 +0000510 return CU::UNWIND_ARM64_MODE_DWARF;
Tim Northover3b0846e2014-05-24 12:50:23 +0000511 unsigned Reg2 = MRI.getLLVMRegNum(Inst2.getRegister(), true);
512
513 // N.B. The encodings must be in register number order, and the X
514 // registers before the D registers.
515
516 // X19/X20 pair = 0x00000001,
517 // X21/X22 pair = 0x00000002,
518 // X23/X24 pair = 0x00000004,
519 // X25/X26 pair = 0x00000008,
520 // X27/X28 pair = 0x00000010
521 Reg1 = getXRegFromWReg(Reg1);
522 Reg2 = getXRegFromWReg(Reg2);
523
524 if (Reg1 == AArch64::X19 && Reg2 == AArch64::X20 &&
525 (CompactUnwindEncoding & 0xF1E) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000526 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X19_X20_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000527 else if (Reg1 == AArch64::X21 && Reg2 == AArch64::X22 &&
528 (CompactUnwindEncoding & 0xF1C) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000529 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X21_X22_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000530 else if (Reg1 == AArch64::X23 && Reg2 == AArch64::X24 &&
531 (CompactUnwindEncoding & 0xF18) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000532 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X23_X24_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000533 else if (Reg1 == AArch64::X25 && Reg2 == AArch64::X26 &&
534 (CompactUnwindEncoding & 0xF10) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000535 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X25_X26_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000536 else if (Reg1 == AArch64::X27 && Reg2 == AArch64::X28 &&
537 (CompactUnwindEncoding & 0xF00) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000538 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X27_X28_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000539 else {
540 Reg1 = getDRegFromBReg(Reg1);
541 Reg2 = getDRegFromBReg(Reg2);
542
543 // D8/D9 pair = 0x00000100,
544 // D10/D11 pair = 0x00000200,
545 // D12/D13 pair = 0x00000400,
546 // D14/D15 pair = 0x00000800
547 if (Reg1 == AArch64::D8 && Reg2 == AArch64::D9 &&
548 (CompactUnwindEncoding & 0xE00) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000549 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D8_D9_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000550 else if (Reg1 == AArch64::D10 && Reg2 == AArch64::D11 &&
551 (CompactUnwindEncoding & 0xC00) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000552 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D10_D11_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000553 else if (Reg1 == AArch64::D12 && Reg2 == AArch64::D13 &&
554 (CompactUnwindEncoding & 0x800) == 0)
Tim Northover87442c12016-02-23 21:49:05 +0000555 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D12_D13_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000556 else if (Reg1 == AArch64::D14 && Reg2 == AArch64::D15)
Tim Northover87442c12016-02-23 21:49:05 +0000557 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D14_D15_PAIR;
Tim Northover3b0846e2014-05-24 12:50:23 +0000558 else
559 // A pair was pushed which we cannot handle.
Tim Northover87442c12016-02-23 21:49:05 +0000560 return CU::UNWIND_ARM64_MODE_DWARF;
Tim Northover3b0846e2014-05-24 12:50:23 +0000561 }
562
563 break;
564 }
565 }
566 }
567
568 if (!HasFP) {
569 // With compact unwind info we can only represent stack adjustments of up
570 // to 65520 bytes.
571 if (StackSize > 65520)
Tim Northover87442c12016-02-23 21:49:05 +0000572 return CU::UNWIND_ARM64_MODE_DWARF;
Tim Northover3b0846e2014-05-24 12:50:23 +0000573
Tim Northover87442c12016-02-23 21:49:05 +0000574 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAMELESS;
Tim Northover3b0846e2014-05-24 12:50:23 +0000575 CompactUnwindEncoding |= encodeStackAdjustment(StackSize);
576 }
577
578 return CompactUnwindEncoding;
579 }
580};
581
582} // end anonymous namespace
583
584namespace {
585
586class ELFAArch64AsmBackend : public AArch64AsmBackend {
587public:
588 uint8_t OSABI;
Joel Jones504bf332016-10-24 13:37:13 +0000589 bool IsILP32;
Tim Northover3b0846e2014-05-24 12:50:23 +0000590
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000591 ELFAArch64AsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
592 bool IsLittleEndian, bool IsILP32)
593 : AArch64AsmBackend(T, TT, IsLittleEndian), OSABI(OSABI),
594 IsILP32(IsILP32) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000595
Peter Collingbournedcd7d6c2018-05-21 19:20:29 +0000596 std::unique_ptr<MCObjectTargetWriter>
597 createObjectTargetWriter() const override {
598 return createAArch64ELFObjectWriter(OSABI, IsILP32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000599 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000600};
601
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000602}
Tim Northover3b0846e2014-05-24 12:50:23 +0000603
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000604namespace {
605class COFFAArch64AsmBackend : public AArch64AsmBackend {
606public:
607 COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple)
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000608 : AArch64AsmBackend(T, TheTriple, /*IsLittleEndian*/ true) {}
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000609
Peter Collingbournedcd7d6c2018-05-21 19:20:29 +0000610 std::unique_ptr<MCObjectTargetWriter>
611 createObjectTargetWriter() const override {
612 return createAArch64WinCOFFObjectWriter();
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000613 }
614};
615}
616
Tim Northover3b0846e2014-05-24 12:50:23 +0000617MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T,
Alex Bradburyb22f7512018-01-03 08:53:05 +0000618 const MCSubtargetInfo &STI,
Daniel Sanders418caf52015-06-10 10:35:34 +0000619 const MCRegisterInfo &MRI,
Joel Jones373d7d32016-07-25 17:18:28 +0000620 const MCTargetOptions &Options) {
Alex Bradburyb22f7512018-01-03 08:53:05 +0000621 const Triple &TheTriple = STI.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000622 if (TheTriple.isOSBinFormatMachO())
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000623 return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
Tim Northover3b0846e2014-05-24 12:50:23 +0000624
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000625 if (TheTriple.isOSBinFormatCOFF())
626 return new COFFAArch64AsmBackend(T, TheTriple);
627
Mandeep Singh Grang6f61e232017-06-28 19:37:38 +0000628 assert(TheTriple.isOSBinFormatELF() && "Invalid target");
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000629
Daniel Sanders50f17232015-09-15 16:17:27 +0000630 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
Joel Jones504bf332016-10-24 13:37:13 +0000631 bool IsILP32 = Options.getABIName() == "ilp32";
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000632 return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/true,
633 IsILP32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000634}
635
636MCAsmBackend *llvm::createAArch64beAsmBackend(const Target &T,
Alex Bradburyb22f7512018-01-03 08:53:05 +0000637 const MCSubtargetInfo &STI,
Daniel Sanders418caf52015-06-10 10:35:34 +0000638 const MCRegisterInfo &MRI,
Joel Jones373d7d32016-07-25 17:18:28 +0000639 const MCTargetOptions &Options) {
Alex Bradburyb22f7512018-01-03 08:53:05 +0000640 const Triple &TheTriple = STI.getTargetTriple();
Daniel Sanders50f17232015-09-15 16:17:27 +0000641 assert(TheTriple.isOSBinFormatELF() &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000642 "Big endian is only supported for ELF targets!");
Daniel Sanders50f17232015-09-15 16:17:27 +0000643 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
Joel Jones504bf332016-10-24 13:37:13 +0000644 bool IsILP32 = Options.getABIName() == "ilp32";
Martin Storsjo0b7bf7a2017-07-26 11:19:17 +0000645 return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/false,
646 IsILP32);
Tim Northover3b0846e2014-05-24 12:50:23 +0000647}