LLVM 20.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
94 uint64_t Value) const override;
95 void relaxInstruction(MCInst &Inst,
96 const MCSubtargetInfo &STI) const override;
98 const MCSubtargetInfo *STI) const override;
99
100 unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const;
101
102 bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
103 const MCValue &Target,
104 const MCSubtargetInfo *STI) override;
105};
106
107} // end anonymous namespace
108
109/// The number of bytes the fixup may change.
110static unsigned getFixupKindNumBytes(unsigned Kind) {
111 switch (Kind) {
112 default:
113 llvm_unreachable("Unknown fixup kind!");
114
115 case FK_Data_1:
116 return 1;
117
118 case FK_Data_2:
119 case FK_SecRel_2:
120 return 2;
121
133 return 3;
134
139 case FK_Data_4:
140 case FK_SecRel_4:
141 return 4;
142
143 case FK_Data_8:
144 return 8;
145 }
146}
147
148static unsigned AdrImmBits(unsigned Value) {
149 unsigned lo2 = Value & 0x3;
150 unsigned hi19 = (Value & 0x1ffffc) >> 2;
151 return (hi19 << 5) | (lo2 << 29);
152}
153
156 const Triple &TheTriple, bool IsResolved) {
157 int64_t SignedValue = static_cast<int64_t>(Value);
158 switch (Fixup.getTargetKind()) {
159 default:
160 llvm_unreachable("Unknown fixup kind!");
162 if (!isInt<21>(SignedValue))
163 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
164 return AdrImmBits(Value & 0x1fffffULL);
166 assert(!IsResolved);
167 if (TheTriple.isOSBinFormatCOFF()) {
168 if (!isInt<21>(SignedValue))
169 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
170 return AdrImmBits(Value & 0x1fffffULL);
171 }
172 return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
175 // Signed 19-bit immediate which gets multiplied by 4
176 if (!isInt<21>(SignedValue))
177 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
178 if (Value & 0x3)
179 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
180 // Low two bits are not encoded.
181 return (Value >> 2) & 0x7ffff;
184 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
185 Value &= 0xfff;
186 // Unsigned 12-bit immediate
187 if (!isUInt<12>(Value))
188 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
189 return Value;
191 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
192 Value &= 0xfff;
193 // Unsigned 12-bit immediate which gets multiplied by 2
194 if (!isUInt<13>(Value))
195 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
196 if (Value & 0x1)
197 Ctx.reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
198 return Value >> 1;
200 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
201 Value &= 0xfff;
202 // Unsigned 12-bit immediate which gets multiplied by 4
203 if (!isUInt<14>(Value))
204 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
205 if (Value & 0x3)
206 Ctx.reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
207 return Value >> 2;
209 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
210 Value &= 0xfff;
211 // Unsigned 12-bit immediate which gets multiplied by 8
212 if (!isUInt<15>(Value))
213 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
214 if (Value & 0x7)
215 Ctx.reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
216 return Value >> 3;
218 if (TheTriple.isOSBinFormatCOFF() && !IsResolved)
219 Value &= 0xfff;
220 // Unsigned 12-bit immediate which gets multiplied by 16
221 if (!isUInt<16>(Value))
222 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
223 if (Value & 0xf)
224 Ctx.reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
225 return Value >> 4;
228 static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
231 if (!RefKind) {
232 // The fixup is an expression
233 if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
234 Ctx.reportError(Fixup.getLoc(),
235 "fixup value out of range [-0xFFFF, 0xFFFF]");
236
237 // Invert the negative immediate because it will feed into a MOVN.
238 if (SignedValue < 0)
239 SignedValue = ~SignedValue;
240 Value = static_cast<uint64_t>(SignedValue);
241 } else
242 // VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
243 // ever be resolved in the assembler.
244 Ctx.reportError(Fixup.getLoc(),
245 "relocation for a thread-local variable points to an "
246 "absolute symbol");
247 return Value;
248 }
249
250 if (!IsResolved) {
251 // FIXME: Figure out when this can actually happen, and verify our
252 // behavior.
253 Ctx.reportError(Fixup.getLoc(), "unresolved movw fixup not yet "
254 "implemented");
255 return Value;
256 }
257
259 switch (AArch64MCExpr::getAddressFrag(RefKind)) {
261 break;
263 SignedValue = SignedValue >> 16;
264 break;
266 SignedValue = SignedValue >> 32;
267 break;
269 SignedValue = SignedValue >> 48;
270 break;
271 default:
272 llvm_unreachable("Variant kind doesn't correspond to fixup");
273 }
274
275 } else {
276 switch (AArch64MCExpr::getAddressFrag(RefKind)) {
278 break;
280 Value = Value >> 16;
281 break;
283 Value = Value >> 32;
284 break;
286 Value = Value >> 48;
287 break;
288 default:
289 llvm_unreachable("Variant kind doesn't correspond to fixup");
290 }
291 }
292
293 if (RefKind & AArch64MCExpr::VK_NC) {
294 Value &= 0xFFFF;
295 }
297 if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
298 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
299
300 // Invert the negative immediate because it will feed into a MOVN.
301 if (SignedValue < 0)
302 SignedValue = ~SignedValue;
303 Value = static_cast<uint64_t>(SignedValue);
304 }
305 else if (Value > 0xFFFF) {
306 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
307 }
308 return Value;
309 }
311 // Signed 16-bit immediate
312 if (!isInt<16>(SignedValue))
313 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
314 // Low two bits are not encoded (4-byte alignment assumed).
315 if (Value & 0x3)
316 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
317 return (Value >> 2) & 0x3fff;
319 // Unsigned PC-relative offset, so invert the negative immediate.
320 SignedValue = -SignedValue;
321 Value = static_cast<uint64_t>(SignedValue);
322 // Check valid 18-bit unsigned range.
323 if (SignedValue < 0 || SignedValue > ((1 << 18) - 1))
324 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
325 // Low two bits are not encoded (4-byte alignment assumed).
326 if (Value & 0b11)
327 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
328 return (Value >> 2) & 0xffff;
331 if (TheTriple.isOSBinFormatCOFF() && !IsResolved && SignedValue != 0) {
332 // MSVC link.exe and lld do not support this relocation type
333 // with a non-zero offset
334 Ctx.reportError(Fixup.getLoc(),
335 "cannot perform a PC-relative fixup with a non-zero "
336 "symbol offset");
337 }
338 // Signed 28-bit immediate
339 if (!isInt<28>(SignedValue))
340 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
341 // Low two bits are not encoded (4-byte alignment assumed).
342 if (Value & 0x3)
343 Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
344 return (Value >> 2) & 0x3ffffff;
345 case FK_Data_1:
346 case FK_Data_2:
347 case FK_Data_4:
348 case FK_Data_8:
349 case FK_SecRel_2:
350 case FK_SecRel_4:
351 return Value;
352 }
353}
354
355std::optional<MCFixupKind>
356AArch64AsmBackend::getFixupKind(StringRef Name) const {
357 if (!TheTriple.isOSBinFormatELF())
358 return std::nullopt;
359
361#define ELF_RELOC(X, Y) .Case(#X, Y)
362#include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
363#undef ELF_RELOC
364 .Case("BFD_RELOC_NONE", ELF::R_AARCH64_NONE)
365 .Case("BFD_RELOC_16", ELF::R_AARCH64_ABS16)
366 .Case("BFD_RELOC_32", ELF::R_AARCH64_ABS32)
367 .Case("BFD_RELOC_64", ELF::R_AARCH64_ABS64)
368 .Default(-1u);
369 if (Type == -1u)
370 return std::nullopt;
371 return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
372}
373
374/// getFixupKindContainereSizeInBytes - The number of bytes of the
375/// container involved in big endian or 0 if the item is little endian
376unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const {
377 if (Endian == llvm::endianness::little)
378 return 0;
379
380 switch (Kind) {
381 default:
382 llvm_unreachable("Unknown fixup kind!");
383
384 case FK_Data_1:
385 return 1;
386 case FK_Data_2:
387 return 2;
388 case FK_Data_4:
389 return 4;
390 case FK_Data_8:
391 return 8;
392
408 // Instructions are always little endian
409 return 0;
410 }
411}
412
413void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
414 const MCValue &Target,
416 bool IsResolved,
417 const MCSubtargetInfo *STI) const {
418 if (Fixup.getTargetKind() == FK_Data_8 && TheTriple.isOSBinFormatELF()) {
419 auto RefKind = static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
421 if (SymLoc == AArch64AuthMCExpr::VK_AUTH ||
422 SymLoc == AArch64AuthMCExpr::VK_AUTHADDR) {
423 assert(Value == 0);
424 const auto *Expr = cast<AArch64AuthMCExpr>(Fixup.getValue());
425 Value = (uint64_t(Expr->getDiscriminator()) << 32) |
426 (uint64_t(Expr->getKey()) << 60) |
427 (uint64_t(Expr->hasAddressDiversity()) << 63);
428 }
429 }
430
431 if (!Value)
432 return; // Doesn't change encoding.
433 unsigned Kind = Fixup.getKind();
434 if (Kind >= FirstLiteralRelocationKind)
435 return;
436 unsigned NumBytes = getFixupKindNumBytes(Kind);
437 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
438 MCContext &Ctx = Asm.getContext();
439 int64_t SignedValue = static_cast<int64_t>(Value);
440 // Apply any target-specific value adjustments.
441 Value = adjustFixupValue(Fixup, Target, Value, Ctx, TheTriple, IsResolved);
442
443 // Shift the value into position.
444 Value <<= Info.TargetOffset;
445
446 unsigned Offset = Fixup.getOffset();
447 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
448
449 // Used to point to big endian bytes.
450 unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(Fixup.getKind());
451
452 // For each byte of the fragment that the fixup touches, mask in the
453 // bits from the fixup value.
454 if (FulleSizeInBytes == 0) {
455 // Handle as little-endian
456 for (unsigned i = 0; i != NumBytes; ++i) {
457 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
458 }
459 } else {
460 // Handle as big-endian
461 assert((Offset + FulleSizeInBytes) <= Data.size() && "Invalid fixup size!");
462 assert(NumBytes <= FulleSizeInBytes && "Invalid fixup size!");
463 for (unsigned i = 0; i != NumBytes; ++i) {
464 unsigned Idx = FulleSizeInBytes - 1 - i;
465 Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
466 }
467 }
468
469 // FIXME: getFixupKindInfo() and getFixupKindNumBytes() could be fixed to
470 // handle this more cleanly. This may affect the output of -show-mc-encoding.
472 static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
474 (!RefKind && Fixup.getTargetKind() == AArch64::fixup_aarch64_movw)) {
475 // If the immediate is negative, generate MOVN else MOVZ.
476 // (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
477 if (SignedValue < 0)
478 Data[Offset + 3] &= ~(1 << 6);
479 else
480 Data[Offset + 3] |= (1 << 6);
481 }
482}
483
484bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
485 uint64_t Value) const {
486 // FIXME: This isn't correct for AArch64. Just moving the "generic" logic
487 // into the targets for now.
488 //
489 // Relax if the value is too big for a (signed) i8.
490 return int64_t(Value) != int64_t(int8_t(Value));
491}
492
493void AArch64AsmBackend::relaxInstruction(MCInst &Inst,
494 const MCSubtargetInfo &STI) const {
495 llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
496}
497
498bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
499 const MCSubtargetInfo *STI) const {
500 // If the count is not 4-byte aligned, we must be writing data into the text
501 // section (otherwise we have unaligned instructions, and thus have far
502 // bigger problems), so just write zeros instead.
503 OS.write_zeros(Count % 4);
504
505 // We are properly aligned, so write NOPs as requested.
506 Count /= 4;
507 for (uint64_t i = 0; i != Count; ++i)
508 OS.write("\x1f\x20\x03\xd5", 4);
509 return true;
510}
511
512bool AArch64AsmBackend::shouldForceRelocation(const MCAssembler &Asm,
513 const MCFixup &Fixup,
514 const MCValue &Target,
515 const MCSubtargetInfo *STI) {
516 unsigned Kind = Fixup.getKind();
517 if (Kind >= FirstLiteralRelocationKind)
518 return true;
519
520 // The ADRP instruction adds some multiple of 0x1000 to the current PC &
521 // ~0xfff. This means that the required offset to reach a symbol can vary by
522 // up to one step depending on where the ADRP is in memory. For example:
523 //
524 // ADRP x0, there
525 // there:
526 //
527 // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and
528 // we'll need that as an offset. At any other address "there" will be in the
529 // same page as the ADRP and the instruction should encode 0x0. Assuming the
530 // section isn't 0x1000-aligned, we therefore need to delegate this decision
531 // to the linker -- a relocation!
533 return true;
534
535 return false;
536}
537
538namespace {
539
540namespace CU {
541
542/// Compact unwind encoding values.
544 /// A "frameless" leaf function, where no non-volatile registers are
545 /// saved. The return remains in LR throughout the function.
546 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
547
548 /// No compact unwind encoding available. Instead the low 23-bits of
549 /// the compact unwind encoding is the offset of the DWARF FDE in the
550 /// __eh_frame section. This mode is never used in object files. It is only
551 /// generated by the linker in final linked images, which have only DWARF info
552 /// for a function.
553 UNWIND_ARM64_MODE_DWARF = 0x03000000,
554
555 /// This is a standard arm64 prologue where FP/LR are immediately
556 /// pushed on the stack, then SP is copied to FP. If there are any
557 /// non-volatile register saved, they are copied into the stack fame in pairs
558 /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the
559 /// five X pairs and four D pairs can be saved, but the memory layout must be
560 /// in register number order.
561 UNWIND_ARM64_MODE_FRAME = 0x04000000,
562
563 /// Frame register pair encodings.
564 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
565 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
566 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
567 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
568 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
569 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
570 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
571 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
572 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800
573};
574
575} // end CU namespace
576
577// FIXME: This should be in a separate file.
578class DarwinAArch64AsmBackend : public AArch64AsmBackend {
579 const MCRegisterInfo &MRI;
580
581 /// Encode compact unwind stack adjustment for frameless functions.
582 /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h.
583 /// The stack size always needs to be 16 byte aligned.
584 uint32_t encodeStackAdjustment(uint32_t StackSize) const {
585 return (StackSize / 16) << 12;
586 }
587
588public:
589 DarwinAArch64AsmBackend(const Target &T, const Triple &TT,
590 const MCRegisterInfo &MRI)
591 : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {}
592
593 std::unique_ptr<MCObjectTargetWriter>
594 createObjectTargetWriter() const override {
596 uint32_t CPUSubType = cantFail(MachO::getCPUSubType(TheTriple));
597 return createAArch64MachObjectWriter(CPUType, CPUSubType,
598 TheTriple.isArch32Bit());
599 }
600
601 /// Generate the compact unwind encoding from the CFI directives.
602 uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
603 const MCContext *Ctxt) const override {
605 if (Instrs.empty())
606 return CU::UNWIND_ARM64_MODE_FRAMELESS;
607 if (!isDarwinCanonicalPersonality(FI->Personality) &&
609 return CU::UNWIND_ARM64_MODE_DWARF;
610
611 bool HasFP = false;
612 uint64_t StackSize = 0;
613
614 uint64_t CompactUnwindEncoding = 0;
615 int64_t CurOffset = 0;
616 for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
617 const MCCFIInstruction &Inst = Instrs[i];
618
619 switch (Inst.getOperation()) {
620 default:
621 // Cannot handle this directive: bail out.
622 return CU::UNWIND_ARM64_MODE_DWARF;
624 // Defines a frame pointer.
625 unsigned XReg =
626 getXRegFromWReg(*MRI.getLLVMRegNum(Inst.getRegister(), true));
627
628 // Other CFA registers than FP are not supported by compact unwind.
629 // Fallback on DWARF.
630 // FIXME: When opt-remarks are supported in MC, add a remark to notify
631 // the user.
632 if (XReg != AArch64::FP)
633 return CU::UNWIND_ARM64_MODE_DWARF;
634
635 if (i + 2 >= e)
636 return CU::UNWIND_ARM64_MODE_DWARF;
637
638 const MCCFIInstruction &LRPush = Instrs[++i];
640 return CU::UNWIND_ARM64_MODE_DWARF;
641 const MCCFIInstruction &FPPush = Instrs[++i];
643 return CU::UNWIND_ARM64_MODE_DWARF;
644
645 if (FPPush.getOffset() + 8 != LRPush.getOffset())
646 return CU::UNWIND_ARM64_MODE_DWARF;
647 CurOffset = FPPush.getOffset();
648
649 unsigned LRReg = *MRI.getLLVMRegNum(LRPush.getRegister(), true);
650 unsigned FPReg = *MRI.getLLVMRegNum(FPPush.getRegister(), true);
651
652 LRReg = getXRegFromWReg(LRReg);
653 FPReg = getXRegFromWReg(FPReg);
654
655 if (LRReg != AArch64::LR || FPReg != AArch64::FP)
656 return CU::UNWIND_ARM64_MODE_DWARF;
657
658 // Indicate that the function has a frame.
659 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME;
660 HasFP = true;
661 break;
662 }
664 if (StackSize != 0)
665 return CU::UNWIND_ARM64_MODE_DWARF;
666 StackSize = std::abs(Inst.getOffset());
667 break;
668 }
670 // Registers are saved in pairs. We expect there to be two consecutive
671 // `.cfi_offset' instructions with the appropriate registers specified.
672 unsigned Reg1 = *MRI.getLLVMRegNum(Inst.getRegister(), true);
673 if (i + 1 == e)
674 return CU::UNWIND_ARM64_MODE_DWARF;
675
676 if (CurOffset != 0 && Inst.getOffset() != CurOffset - 8)
677 return CU::UNWIND_ARM64_MODE_DWARF;
678 CurOffset = Inst.getOffset();
679
680 const MCCFIInstruction &Inst2 = Instrs[++i];
682 return CU::UNWIND_ARM64_MODE_DWARF;
683 unsigned Reg2 = *MRI.getLLVMRegNum(Inst2.getRegister(), true);
684
685 if (Inst2.getOffset() != CurOffset - 8)
686 return CU::UNWIND_ARM64_MODE_DWARF;
687 CurOffset = Inst2.getOffset();
688
689 // N.B. The encodings must be in register number order, and the X
690 // registers before the D registers.
691
692 // X19/X20 pair = 0x00000001,
693 // X21/X22 pair = 0x00000002,
694 // X23/X24 pair = 0x00000004,
695 // X25/X26 pair = 0x00000008,
696 // X27/X28 pair = 0x00000010
697 Reg1 = getXRegFromWReg(Reg1);
698 Reg2 = getXRegFromWReg(Reg2);
699
700 if (Reg1 == AArch64::X19 && Reg2 == AArch64::X20 &&
701 (CompactUnwindEncoding & 0xF1E) == 0)
702 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X19_X20_PAIR;
703 else if (Reg1 == AArch64::X21 && Reg2 == AArch64::X22 &&
704 (CompactUnwindEncoding & 0xF1C) == 0)
705 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X21_X22_PAIR;
706 else if (Reg1 == AArch64::X23 && Reg2 == AArch64::X24 &&
707 (CompactUnwindEncoding & 0xF18) == 0)
708 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X23_X24_PAIR;
709 else if (Reg1 == AArch64::X25 && Reg2 == AArch64::X26 &&
710 (CompactUnwindEncoding & 0xF10) == 0)
711 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X25_X26_PAIR;
712 else if (Reg1 == AArch64::X27 && Reg2 == AArch64::X28 &&
713 (CompactUnwindEncoding & 0xF00) == 0)
714 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X27_X28_PAIR;
715 else {
716 Reg1 = getDRegFromBReg(Reg1);
717 Reg2 = getDRegFromBReg(Reg2);
718
719 // D8/D9 pair = 0x00000100,
720 // D10/D11 pair = 0x00000200,
721 // D12/D13 pair = 0x00000400,
722 // D14/D15 pair = 0x00000800
723 if (Reg1 == AArch64::D8 && Reg2 == AArch64::D9 &&
724 (CompactUnwindEncoding & 0xE00) == 0)
725 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D8_D9_PAIR;
726 else if (Reg1 == AArch64::D10 && Reg2 == AArch64::D11 &&
727 (CompactUnwindEncoding & 0xC00) == 0)
728 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D10_D11_PAIR;
729 else if (Reg1 == AArch64::D12 && Reg2 == AArch64::D13 &&
730 (CompactUnwindEncoding & 0x800) == 0)
731 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D12_D13_PAIR;
732 else if (Reg1 == AArch64::D14 && Reg2 == AArch64::D15)
733 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D14_D15_PAIR;
734 else
735 // A pair was pushed which we cannot handle.
736 return CU::UNWIND_ARM64_MODE_DWARF;
737 }
738
739 break;
740 }
741 }
742 }
743
744 if (!HasFP) {
745 // With compact unwind info we can only represent stack adjustments of up
746 // to 65520 bytes.
747 if (StackSize > 65520)
748 return CU::UNWIND_ARM64_MODE_DWARF;
749
750 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAMELESS;
751 CompactUnwindEncoding |= encodeStackAdjustment(StackSize);
752 }
753
754 return CompactUnwindEncoding;
755 }
756};
757
758} // end anonymous namespace
759
760namespace {
761
762class ELFAArch64AsmBackend : public AArch64AsmBackend {
763public:
764 uint8_t OSABI;
765 bool IsILP32;
766
767 ELFAArch64AsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
768 bool IsLittleEndian, bool IsILP32)
769 : AArch64AsmBackend(T, TT, IsLittleEndian), OSABI(OSABI),
770 IsILP32(IsILP32) {}
771
772 std::unique_ptr<MCObjectTargetWriter>
773 createObjectTargetWriter() const override {
774 return createAArch64ELFObjectWriter(OSABI, IsILP32);
775 }
776};
777
778}
779
780namespace {
781class COFFAArch64AsmBackend : public AArch64AsmBackend {
782public:
783 COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple)
784 : AArch64AsmBackend(T, TheTriple, /*IsLittleEndian*/ true) {}
785
786 std::unique_ptr<MCObjectTargetWriter>
787 createObjectTargetWriter() const override {
788 return createAArch64WinCOFFObjectWriter(TheTriple);
789 }
790};
791}
792
794 const MCSubtargetInfo &STI,
795 const MCRegisterInfo &MRI,
796 const MCTargetOptions &Options) {
797 const Triple &TheTriple = STI.getTargetTriple();
798 if (TheTriple.isOSBinFormatMachO()) {
799 return new DarwinAArch64AsmBackend(T, TheTriple, MRI);
800 }
801
802 if (TheTriple.isOSBinFormatCOFF())
803 return new COFFAArch64AsmBackend(T, TheTriple);
804
805 assert(TheTriple.isOSBinFormatELF() && "Invalid target");
806
807 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
808 bool IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
809 return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/true,
810 IsILP32);
811}
812
814 const MCSubtargetInfo &STI,
815 const MCRegisterInfo &MRI,
816 const MCTargetOptions &Options) {
817 const Triple &TheTriple = STI.getTargetTriple();
818 assert(TheTriple.isOSBinFormatELF() &&
819 "Big endian is only supported for ELF targets!");
820 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
821 bool IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
822 return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/false,
823 IsILP32);
824}
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
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:42
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:179
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value) const
Simple predicate for targets where !Resolved implies requiring relaxation.
Definition: MCAsmBackend.h:169
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:96
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...
unsigned getRegister() const
Definition: MCDwarf.h:683
OpType getOperation() const
Definition: MCDwarf.h:680
int64_t getOffset() const
Definition: MCDwarf.h:705
Context object for machine code objects.
Definition: MCContext.h:83
bool emitCompactUnwindNonCanonical() const
Definition: MCContext.cpp:938
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1068
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...
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:732
OSType getOS() const
Get the parsed operating system type of this triple.
Definition: Triple.h:382
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Definition: Triple.h:724
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
Definition: Triple.h:390
bool isArch32Bit() const
Test whether the architecture is 32-bit.
Definition: Triple.cpp:1655
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:719
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:480
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:756
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:733
std::vector< MCCFIInstruction > Instructions
Definition: MCDwarf.h:735
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...