LLVM 19.0.0git
AArch64AsmBackend.cpp
Go to the documentation of this file.
1//===-- AArch64AsmBackend.cpp - AArch64 Assembler Backend -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
15#include "llvm/MC/MCAssembler.h"
16#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCValue.h"
31using namespace llvm;
32
33namespace {
34
35class AArch64AsmBackend : public MCAsmBackend {
36 static const unsigned PCRelFlagVal =
38protected:
39 Triple TheTriple;
40
41public:
42 AArch64AsmBackend(const Target &T, const Triple &TT, bool IsLittleEndian)
43 : MCAsmBackend(IsLittleEndian ? llvm::endianness::little
44 : llvm::endianness::big),
45 TheTriple(TT) {}
46
47 unsigned getNumFixupKinds() const override {
49 }
50
51 std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
52
53 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
54 const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = {
55 // This table *must* be in the order that the fixup_* kinds are defined
56 // in AArch64FixupKinds.h.
57 //
58 // Name Offset (bits) Size (bits) Flags
59 {"fixup_aarch64_pcrel_adr_imm21", 0, 32, PCRelFlagVal},
60 {"fixup_aarch64_pcrel_adrp_imm21", 0, 32, PCRelFlagVal},
61 {"fixup_aarch64_add_imm12", 10, 12, 0},
62 {"fixup_aarch64_ldst_imm12_scale1", 10, 12, 0},
63 {"fixup_aarch64_ldst_imm12_scale2", 10, 12, 0},
64 {"fixup_aarch64_ldst_imm12_scale4", 10, 12, 0},
65 {"fixup_aarch64_ldst_imm12_scale8", 10, 12, 0},
66 {"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
67 {"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal},
68 {"fixup_aarch64_movw", 5, 16, 0},
69 {"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal},
70 {"fixup_aarch64_pcrel_branch16", 5, 16, PCRelFlagVal},
71 {"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal},
72 {"fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal},
73 {"fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal}};
74
75 // Fixup kinds from .reloc directive are like R_AARCH64_NONE. They do not
76 // require any extra processing.
79
80 if (Kind < FirstTargetFixupKind)
82
83 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
84 "Invalid kind!");
85 return Infos[Kind - FirstTargetFixupKind];
86 }
87
88 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
90 uint64_t Value, bool IsResolved,
91 const MCSubtargetInfo *STI) const override;
92
95 const MCAsmLayout &Layout) const override;
96 void relaxInstruction(MCInst &Inst,
97 const MCSubtargetInfo &STI) const override;
99 const MCSubtargetInfo *STI) const override;
100
101 unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const;
102
103 bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
104 const MCValue &Target,
105 const MCSubtargetInfo *STI) override;
106};
107
108} // end anonymous namespace
109
110/// The number of bytes the fixup may change.
111static unsigned getFixupKindNumBytes(unsigned Kind) {
112 switch (Kind) {
113 default:
114 llvm_unreachable("Unknown fixup kind!");
115
116 case FK_Data_1:
117 return 1;
118
119 case FK_Data_2:
120 case FK_SecRel_2:
121 return 2;
122
134 return 3;
135
140 case FK_Data_4:
141 case FK_SecRel_4:
142 return 4;
143
144 case FK_Data_8:
145 return 8;
146 }
147}
148
149static unsigned AdrImmBits(unsigned Value) {
150 unsigned lo2 = Value & 0x3;
151 unsigned hi19 = (Value & 0x1ffffc) >> 2;
152 return (hi19 << 5) | (lo2 << 29);
153}
154
157 const Triple &TheTriple, bool IsResolved) {
158 int64_t SignedValue = static_cast<int64_t>(Value);
159 switch (Fixup.getTargetKind()) {
160 default:
161 llvm_unreachable("Unknown fixup kind!");
163 if (!isInt<21>(SignedValue))
164 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
165 return AdrImmBits(Value & 0x1fffffULL);
167 assert(!IsResolved);
168 if (TheTriple.isOSBinFormatCOFF()) {
169 if (!isInt<21>(SignedValue))
170 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
171 return AdrImmBits(Value & 0x1fffffULL);
172 }
173 return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
176 // Signed 19-bit immediate which gets multiplied by 4
177 if (!isInt<21>(SignedValue))
178 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
179 if (Value & 0x3)
180 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
181 // Low two bits are not encoded.
182 return (Value >> 2) & 0x7ffff;
185 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
186 Value &= 0xfff;
187 // Unsigned 12-bit immediate
188 if (!isUInt<12>(Value))
189 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
190 return Value;
192 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
193 Value &= 0xfff;
194 // Unsigned 12-bit immediate which gets multiplied by 2
195 if (!isUInt<13>(Value))
196 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
197 if (Value & 0x1)
198 Ctx.reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
199 return Value >> 1;
201 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
202 Value &= 0xfff;
203 // Unsigned 12-bit immediate which gets multiplied by 4
204 if (!isUInt<14>(Value))
205 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
206 if (Value & 0x3)
207 Ctx.reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
208 return Value >> 2;
210 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
211 Value &= 0xfff;
212 // Unsigned 12-bit immediate which gets multiplied by 8
213 if (!isUInt<15>(Value))
214 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
215 if (Value & 0x7)
216 Ctx.reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
217 return Value >> 3;
219 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
220 Value &= 0xfff;
221 // Unsigned 12-bit immediate which gets multiplied by 16
222 if (!isUInt<16>(Value))
223 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
224 if (Value & 0xf)
225 Ctx.reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
226 return Value >> 4;
229 static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
232 if (!RefKind) {
233 // The fixup is an expression
234 if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
235 Ctx.reportError(Fixup.getLoc(),
236 "fixup value out of range [-0xFFFF, 0xFFFF]");
237
238 // Invert the negative immediate because it will feed into a MOVN.
239 if (SignedValue < 0)
240 SignedValue = ~SignedValue;
241 Value = static_cast<uint64_t>(SignedValue);
242 } else
243 // VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
244 // ever be resolved in the assembler.
245 Ctx.reportError(Fixup.getLoc(),
246 "relocation for a thread-local variable points to an "
247 "absolute symbol");
248 return Value;
249 }
250
251 if (!IsResolved) {
252 // FIXME: Figure out when this can actually happen, and verify our
253 // behavior.
254 Ctx.reportError(Fixup.getLoc(), "unresolved movw fixup not yet "
255 "implemented");
256 return Value;
257 }
258
260 switch (AArch64MCExpr::getAddressFrag(RefKind)) {
262 break;
264 SignedValue = SignedValue >> 16;
265 break;
267 SignedValue = SignedValue >> 32;
268 break;
270 SignedValue = SignedValue >> 48;
271 break;
272 default:
273 llvm_unreachable("Variant kind doesn't correspond to fixup");
274 }
275
276 } else {
277 switch (AArch64MCExpr::getAddressFrag(RefKind)) {
279 break;
281 Value = Value >> 16;
282 break;
284 Value = Value >> 32;
285 break;
287 Value = Value >> 48;
288 break;
289 default:
290 llvm_unreachable("Variant kind doesn't correspond to fixup");
291 }
292 }
293
294 if (RefKind & AArch64MCExpr::VK_NC) {
295 Value &= 0xFFFF;
296 }
298 if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
299 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
300
301 // Invert the negative immediate because it will feed into a MOVN.
302 if (SignedValue < 0)
303 SignedValue = ~SignedValue;
304 Value = static_cast<uint64_t>(SignedValue);
305 }
306 else if (Value > 0xFFFF) {
307 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
308 }
309 return Value;
310 }
312 // Signed 16-bit immediate
313 if (!isInt<16>(SignedValue))
314 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
315 // Low two bits are not encoded (4-byte alignment assumed).
316 if (Value & 0x3)
317 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
318 return (Value >> 2) & 0x3fff;
320 // Unsigned PC-relative offset, so invert the negative immediate.
321 SignedValue = -SignedValue;
322 Value = static_cast<uint64_t>(SignedValue);
323 // Check valid 18-bit unsigned range.
324 if (SignedValue < 0 || SignedValue > ((1 << 18) - 1))
325 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
326 // Low two bits are not encoded (4-byte alignment assumed).
327 if (Value & 0b11)
328 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
329 return (Value >> 2) & 0xffff;
332 if (TheTriple.isOSBinFormatCOFF() && !IsResolved && SignedValue != 0) {
333 // MSVC link.exe and lld do not support this relocation type
334 // with a non-zero offset
335 Ctx.reportError(Fixup.getLoc(),
336 "cannot perform a PC-relative fixup with a non-zero "
337 "symbol offset");
338 }
339 // Signed 28-bit immediate
340 if (!isInt<28>(SignedValue))
341 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
342 // Low two bits are not encoded (4-byte alignment assumed).
343 if (Value & 0x3)
344 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
345 return (Value >> 2) & 0x3ffffff;
346 case FK_Data_1:
347 case FK_Data_2:
348 case FK_Data_4:
349 case FK_Data_8:
350 case FK_SecRel_2:
351 case FK_SecRel_4:
352 return Value;
353 }
354}
355
356std::optional<MCFixupKind>
357AArch64AsmBackend::getFixupKind(StringRef Name) const {
358 if (!TheTriple.isOSBinFormatELF())
359 return std::nullopt;
360
362#define ELF_RELOC(X, Y) .Case(#X, Y)
363#include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
364#undef ELF_RELOC
365 .Case("BFD_RELOC_NONE", ELF::R_AARCH64_NONE)
366 .Case("BFD_RELOC_16", ELF::R_AARCH64_ABS16)
367 .Case("BFD_RELOC_32", ELF::R_AARCH64_ABS32)
368 .Case("BFD_RELOC_64", ELF::R_AARCH64_ABS64)
369 .Default(-1u);
370 if (Type == -1u)
371 return std::nullopt;
372 return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
373}
374
375/// getFixupKindContainereSizeInBytes - The number of bytes of the
376/// container involved in big endian or 0 if the item is little endian
377unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const {
378 if (Endian == llvm::endianness::little)
379 return 0;
380
381 switch (Kind) {
382 default:
383 llvm_unreachable("Unknown fixup kind!");
384
385 case FK_Data_1:
386 return 1;
387 case FK_Data_2:
388 return 2;
389 case FK_Data_4:
390 return 4;
391 case FK_Data_8:
392 return 8;
393
409 // Instructions are always little endian
410 return 0;
411 }
412}
413
414void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
415 const MCValue &Target,
417 bool IsResolved,
418 const MCSubtargetInfo *STI) const {
419 if (Fixup.getTargetKind() == FK_Data_8 && TheTriple.isOSBinFormatELF()) {
420 auto RefKind = static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
422 if (SymLoc == AArch64AuthMCExpr::VK_AUTH ||
423 SymLoc == AArch64AuthMCExpr::VK_AUTHADDR) {
424 assert(Value == 0);
425 const auto *Expr = cast<AArch64AuthMCExpr>(Fixup.getValue());
426 Value = (uint64_t(Expr->getDiscriminator()) << 32) |
427 (uint64_t(Expr->getKey()) << 60) |
428 (uint64_t(Expr->hasAddressDiversity()) << 63);
429 }
430 }
431
432 if (!Value)
433 return; // Doesn't change encoding.
434 unsigned Kind = Fixup.getKind();
435 if (Kind >= FirstLiteralRelocationKind)
436 return;
437 unsigned NumBytes = getFixupKindNumBytes(Kind);
438 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
439 MCContext &Ctx = Asm.getContext();
440 int64_t SignedValue = static_cast<int64_t>(Value);
441 // Apply any target-specific value adjustments.
442 Value = adjustFixupValue(Fixup, Target, Value, Ctx, TheTriple, IsResolved);
443
444 // Shift the value into position.
445 Value <<= Info.TargetOffset;
446
447 unsigned Offset = Fixup.getOffset();
448 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
449
450 // Used to point to big endian bytes.
451 unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(Fixup.getKind());
452
453 // For each byte of the fragment that the fixup touches, mask in the
454 // bits from the fixup value.
455 if (FulleSizeInBytes == 0) {
456 // Handle as little-endian
457 for (unsigned i = 0; i != NumBytes; ++i) {
458 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
459 }
460 } else {
461 // Handle as big-endian
462 assert((Offset + FulleSizeInBytes) <= Data.size() && "Invalid fixup size!");
463 assert(NumBytes <= FulleSizeInBytes && "Invalid fixup size!");
464 for (unsigned i = 0; i != NumBytes; ++i) {
465 unsigned Idx = FulleSizeInBytes - 1 - i;
466 Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
467 }
468 }
469
470 // FIXME: getFixupKindInfo() and getFixupKindNumBytes() could be fixed to
471 // handle this more cleanly. This may affect the output of -show-mc-encoding.
473 static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
475 (!RefKind && Fixup.getTargetKind() == AArch64::fixup_aarch64_movw)) {
476 // If the immediate is negative, generate MOVN else MOVZ.
477 // (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
478 if (SignedValue < 0)
479 Data[Offset + 3] &= ~(1 << 6);
480 else
481 Data[Offset + 3] |= (1 << 6);
482 }
483}
484
485bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
487 const MCRelaxableFragment *DF,
488 const MCAsmLayout &Layout) const {
489 // FIXME: This isn't correct for AArch64. Just moving the "generic" logic
490 // into the targets for now.
491 //
492 // Relax if the value is too big for a (signed) i8.
493 return int64_t(Value) != int64_t(int8_t(Value));
494}
495
496void AArch64AsmBackend::relaxInstruction(MCInst &Inst,
497 const MCSubtargetInfo &STI) const {
498 llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
499}
500
501bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
502 const MCSubtargetInfo *STI) const {
503 // If the count is not 4-byte aligned, we must be writing data into the text
504 // section (otherwise we have unaligned instructions, and thus have far
505 // bigger problems), so just write zeros instead.
506 OS.write_zeros(Count % 4);
507
508 // We are properly aligned, so write NOPs as requested.
509 Count /= 4;
510 for (uint64_t i = 0; i != Count; ++i)
511 OS.write("\x1f\x20\x03\xd5", 4);
512 return true;
513}
514
515bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm,
516 const MCFixup &Fixup,
517 const MCValue &Target,
518 const MCSubtargetInfo *STI) {
519 unsigned Kind = Fixup.getKind();
520 if (Kind >= FirstLiteralRelocationKind)
521 return true;
522
523 // The ADRP instruction adds some multiple of 0x1000 to the current PC &
524 // ~0xfff. This means that the required offset to reach a symbol can vary by
525 // up to one step depending on where the ADRP is in memory. For example:
526 //
527 // ADRP x0, there
528 // there:
529 //
530 // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and
531 // we'll need that as an offset. At any other address "there" will be in the
532 // same page as the ADRP and the instruction should encode 0x0. Assuming the
533 // section isn't 0x1000-aligned, we therefore need to delegate this decision
534 // to the linker -- a relocation!
536 return true;
537
538 return false;
539}
540
541namespace {
542
543namespace CU {
544
545/// Compact unwind encoding values.
547 /// A "frameless" leaf function, where no non-volatile registers are
548 /// saved. The return remains in LR throughout the function.
549 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
550
551 /// No compact unwind encoding available. Instead the low 23-bits of
552 /// the compact unwind encoding is the offset of the DWARF FDE in the
553 /// __eh_frame section. This mode is never used in object files. It is only
554 /// generated by the linker in final linked images, which have only DWARF info
555 /// for a function.
556 UNWIND_ARM64_MODE_DWARF = 0x03000000,
557
558 /// This is a standard arm64 prologue where FP/LR are immediately
559 /// pushed on the stack, then SP is copied to FP. If there are any
560 /// non-volatile register saved, they are copied into the stack fame in pairs
561 /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the
562 /// five X pairs and four D pairs can be saved, but the memory layout must be
563 /// in register number order.
564 UNWIND_ARM64_MODE_FRAME = 0x04000000,
565
566 /// Frame register pair encodings.
567 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
568 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
569 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
570 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
571 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
572 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
573 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
574 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
575 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800
576};
577
578} // end CU namespace
579
580// FIXME: This should be in a separate file.
581class DarwinAArch64AsmBackend : public AArch64AsmBackend {
582 const MCRegisterInfo &MRI;
583
584 /// Encode compact unwind stack adjustment for frameless functions.
585 /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
586 /// The stack size always needs to be 16 byte aligned.
587 uint32_t encodeStackAdjustment(uint32_t StackSize) const {
588 return (StackSize / 16) << 12;
589 }
590
591public:
592 DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
593 const MCRegisterInfo &MRI)
594 : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
595
596 std::unique_ptr<MCObjectTargetWriter>
597 createObjectTargetWriter() const override {
599 uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TheTriple));
600 return createAArch64MachObjectWriter(CPUType, CPUSubType,
601 TheTriple.isArch32Bit());
602 }
603
604 /// Generate the compact unwind encoding from the CFI directives.
605 uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
606 const MCContext *Ctxt) const override {
608 if (Instrs.empty())
609 return CU::UNWIND_ARM64_MODE_FRAMELESS;
610 if (!isDarwinCanonicalPersonality(FI->Personality) &&
612 return CU::UNWIND_ARM64_MODE_DWARF;
613
614 bool HasFP = false;
615 unsigned StackSize = 0;
616
617 uint32_t CompactUnwindEncoding = 0;
618 int CurOffset = 0;
619 for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
620 const MCCFIInstruction &Inst = Instrs[i];
621
622 switch (Inst.getOperation()) {
623 default:
624 // Cannot handle this directive: bail out.
625 return CU::UNWIND_ARM64_MODE_DWARF;
627 // Defines a frame pointer.
628 unsigned XReg =
629 getXRegFromWReg(*MRI.getLLVMRegNum(Inst.getRegister(), true));
630
631 // Other CFA registers than FP are not supported by compact unwind.
632 // Fallback on DWARF.
633 // FIXME: When opt-remarks are supported in MC, add a remark to notify
634 // the user.
635 if (XReg != AArch64::FP)
636 return CU::UNWIND_ARM64_MODE_DWARF;
637
638 if (i + 2 >= e)
639 return CU::UNWIND_ARM64_MODE_DWARF;
640
641 const MCCFIInstruction &LRPush = Instrs[++i];
643 return CU::UNWIND_ARM64_MODE_DWARF;
644 const MCCFIInstruction &FPPush = Instrs[++i];
646 return CU::UNWIND_ARM64_MODE_DWARF;
647
648 if (FPPush.getOffset() + 8 != LRPush.getOffset())
649 return CU::UNWIND_ARM64_MODE_DWARF;
650 CurOffset = FPPush.getOffset();
651
652 unsigned LRReg = *MRI.getLLVMRegNum(LRPush.getRegister(), true);
653 unsigned FPReg = *MRI.getLLVMRegNum(FPPush.getRegister(), true);
654
655 LRReg = getXRegFromWReg(LRReg);
656 FPReg = getXRegFromWReg(FPReg);
657
658 if (LRReg != AArch64::LR || FPReg != AArch64::FP)
659 return CU::UNWIND_ARM64_MODE_DWARF;
660
661 // Indicate that the function has a frame.
662 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME;
663 HasFP = true;
664 break;
665 }
667 if (StackSize != 0)
668 return CU::UNWIND_ARM64_MODE_DWARF;
669 StackSize = std::abs(Inst.getOffset());
670 break;
671 }
673 // Registers are saved in pairs. We expect there to be two consecutive
674 // `.cfi_offset' instructions with the appropriate registers specified.
675 unsigned Reg1 = *MRI.getLLVMRegNum(Inst.getRegister(), true);
676 if (i + 1 == e)
677 return CU::UNWIND_ARM64_MODE_DWARF;
678
679 if (CurOffset != 0 && Inst.getOffset() != CurOffset - 8)
680 return CU::UNWIND_ARM64_MODE_DWARF;
681 CurOffset = Inst.getOffset();
682
683 const MCCFIInstruction &Inst2 = Instrs[++i];
685 return CU::UNWIND_ARM64_MODE_DWARF;
686 unsigned Reg2 = *MRI.getLLVMRegNum(Inst2.getRegister(), true);
687
688 if (Inst2.getOffset() != CurOffset - 8)
689 return CU::UNWIND_ARM64_MODE_DWARF;
690 CurOffset = Inst2.getOffset();
691
692 // N.B. The encodings must be in register number order, and the X
693 // registers before the D registers.
694
695 // X19/X20 pair = 0x00000001,
696 // X21/X22 pair = 0x00000002,
697 // X23/X24 pair = 0x00000004,
698 // X25/X26 pair = 0x00000008,
699 // X27/X28 pair = 0x00000010
700 Reg1 = getXRegFromWReg(Reg1);
701 Reg2 = getXRegFromWReg(Reg2);
702
703 if (Reg1 == AArch64::X19 && Reg2 == AArch64::X20 &&
704 (CompactUnwindEncoding & 0xF1E) == 0)
705 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X19_X20_PAIR;
706 else if (Reg1 == AArch64::X21 && Reg2 == AArch64::X22 &&
707 (CompactUnwindEncoding & 0xF1C) == 0)
708 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X21_X22_PAIR;
709 else if (Reg1 == AArch64::X23 && Reg2 == AArch64::X24 &&
710 (CompactUnwindEncoding & 0xF18) == 0)
711 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X23_X24_PAIR;
712 else if (Reg1 == AArch64::X25 && Reg2 == AArch64::X26 &&
713 (CompactUnwindEncoding & 0xF10) == 0)
714 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X25_X26_PAIR;
715 else if (Reg1 == AArch64::X27 && Reg2 == AArch64::X28 &&
716 (CompactUnwindEncoding & 0xF00) == 0)
717 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X27_X28_PAIR;
718 else {
719 Reg1 = getDRegFromBReg(Reg1);
720 Reg2 = getDRegFromBReg(Reg2);
721
722 // D8/D9 pair = 0x00000100,
723 // D10/D11 pair = 0x00000200,
724 // D12/D13 pair = 0x00000400,
725 // D14/D15 pair = 0x00000800
726 if (Reg1 == AArch64::D8 && Reg2 == AArch64::D9 &&
727 (CompactUnwindEncoding & 0xE00) == 0)
728 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D8_D9_PAIR;
729 else if (Reg1 == AArch64::D10 && Reg2 == AArch64::D11 &&
730 (CompactUnwindEncoding & 0xC00) == 0)
731 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D10_D11_PAIR;
732 else if (Reg1 == AArch64::D12 && Reg2 == AArch64::D13 &&
733 (CompactUnwindEncoding & 0x800) == 0)
734 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D12_D13_PAIR;
735 else if (Reg1 == AArch64::D14 && Reg2 == AArch64::D15)
736 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D14_D15_PAIR;
737 else
738 // A pair was pushed which we cannot handle.
739 return CU::UNWIND_ARM64_MODE_DWARF;
740 }
741
742 break;
743 }
744 }
745 }
746
747 if (!HasFP) {
748 // With compact unwind info we can only represent stack adjustments of up
749 // to 65520 bytes.
750 if (StackSize > 65520)
751 return CU::UNWIND_ARM64_MODE_DWARF;
752
753 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAMELESS;
754 CompactUnwindEncoding |= encodeStackAdjustment(StackSize);
755 }
756
757 return CompactUnwindEncoding;
758 }
759};
760
761} // end anonymous namespace
762
763namespace {
764
765class ELFAArch64AsmBackend : public AArch64AsmBackend {
766public:
767 uint8_t OSABI;
768 bool IsILP32;
769
770 ELFAArch64AsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
771 bool IsLittleEndian, bool IsILP32)
772 : AArch64AsmBackend(T, TT, IsLittleEndian), OSABI(OSABI),
773 IsILP32(IsILP32) {}
774
775 std::unique_ptr<MCObjectTargetWriter>
776 createObjectTargetWriter() const override {
777 return createAArch64ELFObjectWriter(OSABI, IsILP32);
778 }
779};
780
781}
782
783namespace {
784class COFFAArch64AsmBackend : public AArch64AsmBackend {
785public:
786 COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple)
787 : AArch64AsmBackend(T, TheTriple, /*IsLittleEndian*/ true) {}
788
789 std::unique_ptr<MCObjectTargetWriter>
790 createObjectTargetWriter() const override {
791 return createAArch64WinCOFFObjectWriter(TheTriple);
792 }
793};
794}
795
797 const MCSubtargetInfo &STI,
798 const MCRegisterInfo &MRI,
799 const MCTargetOptions &Options) {
800 const Triple &TheTriple = STI.getTargetTriple();
801 if (TheTriple.isOSBinFormatMachO()) {
802 return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
803 }
804
805 if (TheTriple.isOSBinFormatCOFF())
806 return new COFFAArch64AsmBackend(T, TheTriple);
807
808 assert(TheTriple.isOSBinFormatELF() && "Invalid target");
809
810 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
811 bool IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
812 return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/true,
813 IsILP32);
814}
815
817 const MCSubtargetInfo &STI,
818 const MCRegisterInfo &MRI,
819 const MCTargetOptions &Options) {
820 const Triple &TheTriple = STI.getTargetTriple();
821 assert(TheTriple.isOSBinFormatELF() &&
822 "Big endian is only supported for ELF targets!");
823 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
824 bool IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
825 return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/false,
826 IsILP32);
827}
unsigned const MachineRegisterInfo * MRI
static unsigned AdrImmBits(unsigned Value)
static unsigned getFixupKindNumBytes(unsigned Kind)
The number of bytes the fixup may change.
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
basic Basic Alias true
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
std::string Name
static LVOptions Options
Definition: LVOptions.cpp:25
PowerPC TLS Dynamic Call Fixup
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static VariantKind getSymbolLoc(VariantKind Kind)
static VariantKind getAddressFrag(VariantKind Kind)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:43
virtual bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const =0
Write an (optimal) nop sequence of Count bytes to the given output.
virtual void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const
Relax the instruction in the given fragment to the next wider instruction.
Definition: MCAsmBackend.h:186
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const =0
Simple predicate for targets where !Resolved implies requiring relaxation.
virtual bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, const MCSubtargetInfo *STI)
Hook to check if a relocation is needed for some target specific reason.
Definition: MCAsmBackend.h:102
virtual unsigned getNumFixupKinds() const =0
Get the number of target specific fixup kinds.
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
virtual std::optional< MCFixupKind > getFixupKind(StringRef Name) const
Map a relocation name used in .reloc to a fixup kind.
virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef< char > Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const =0
Apply the Value for given Fixup into the provided data fragment, at the offset specified by the fixup...
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
unsigned getRegister() const
Definition: MCDwarf.h:661
int getOffset() const
Definition: MCDwarf.h:680
OpType getOperation() const
Definition: MCDwarf.h:658
Context object for machine code objects.
Definition: MCContext.h:76
bool emitCompactUnwindNonCanonical() const
Definition: MCContext.cpp:934
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1064
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
Definition: MCFragment.h:274
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
This represents an "assembler immediate".
Definition: MCValue.h:36
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:307
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition: Triple.h:716
OSType getOS() const
Get the parsed operating system type of this triple.
Definition: Triple.h:370
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Definition: Triple.h:708
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
Definition: Triple.h:378
bool isArch32Bit() const
Test whether the architecture is 32-bit.
Definition: Triple.cpp:1542
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:703
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
raw_ostream & write(unsigned char C)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
CompactUnwindEncodings
Compact unwind encoding values.
@ fixup_aarch64_ldst_imm12_scale16
Expected< uint32_t > getCPUSubType(const Triple &T)
Definition: MachO.cpp:95
Expected< uint32_t > getCPUType(const Triple &T)
Definition: MachO.cpp:77
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
std::unique_ptr< MCObjectTargetWriter > createAArch64WinCOFFObjectWriter(const Triple &TheTriple)
static unsigned getXRegFromWReg(unsigned Reg)
MCAsmBackend * createAArch64leAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
static unsigned getDRegFromBReg(unsigned Reg)
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
@ FirstTargetFixupKind
Definition: MCFixup.h:45
@ FK_SecRel_2
A two-byte section relative fixup.
Definition: MCFixup.h:41
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
Definition: MCFixup.h:50
@ FK_Data_8
A eight-byte fixup.
Definition: MCFixup.h:26
@ FK_Data_1
A one-byte fixup.
Definition: MCFixup.h:23
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
@ FK_NONE
A no-op fixup.
Definition: MCFixup.h:22
@ FK_SecRel_4
A four-byte section relative fixup.
Definition: MCFixup.h:42
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:24
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:749
std::unique_ptr< MCObjectTargetWriter > createAArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype, bool IsILP32)
MCAsmBackend * createAArch64beAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
endianness
Definition: bit.h:70
std::unique_ptr< MCObjectTargetWriter > createAArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32)
const MCSymbol * Personality
Definition: MCDwarf.h:702
std::vector< MCCFIInstruction > Instructions
Definition: MCDwarf.h:704
Target independent information on a fixup kind.
@ FKF_IsAlignedDownTo32Bits
Should this fixup kind force a 4-byte aligned effective PC value?
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...