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