36 AArch64AsmBackend(
const Target &
T,
const Triple &TT,
bool IsLittleEndian)
42 std::optional<MCFixupKind>
getFixupKind(StringRef Name)
const override;
44 MCFixupKindInfo getFixupKindInfo(
MCFixupKind Kind)
const override {
50 {
"fixup_aarch64_pcrel_adr_imm21", 0, 32, 0},
51 {
"fixup_aarch64_pcrel_adrp_imm21", 0, 32, 0},
52 {
"fixup_aarch64_add_imm12", 10, 12, 0},
53 {
"fixup_aarch64_ldst_imm12_scale1", 10, 12, 0},
54 {
"fixup_aarch64_ldst_imm12_scale2", 10, 12, 0},
55 {
"fixup_aarch64_ldst_imm12_scale4", 10, 12, 0},
56 {
"fixup_aarch64_ldst_imm12_scale8", 10, 12, 0},
57 {
"fixup_aarch64_ldst_imm12_scale16", 10, 12, 0},
58 {
"fixup_aarch64_ldr_pcrel_imm19", 5, 19, 0},
59 {
"fixup_aarch64_movw", 5, 16, 0},
60 {
"fixup_aarch64_pcrel_branch9", 5, 9, 0},
61 {
"fixup_aarch64_pcrel_branch14", 5, 14, 0},
62 {
"fixup_aarch64_pcrel_branch16", 5, 16, 0},
63 {
"fixup_aarch64_pcrel_branch19", 5, 19, 0},
64 {
"fixup_aarch64_pcrel_branch26", 0, 26, 0},
65 {
"fixup_aarch64_pcrel_call26", 0, 26, 0}};
81 void applyFixup(
const MCFragment &,
const MCFixup &,
const MCValue &Target,
82 uint8_t *
Data, uint64_t
Value,
bool IsResolved)
override;
84 bool writeNopData(raw_ostream &OS, uint64_t
Count,
85 const MCSubtargetInfo *STI)
const override;
87 unsigned getFixupKindContainereSizeInBytes(
unsigned Kind)
const;
133 unsigned lo2 =
Value & 0x3;
134 unsigned hi19 = (
Value & 0x1ffffc) >> 2;
135 return (hi19 << 5) | (lo2 << 29);
140 const Triple &TheTriple,
bool IsResolved) {
141 int64_t SignedValue =
static_cast<int64_t
>(
Value);
142 switch (
Fixup.getKind()) {
147 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
153 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
161 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
163 Ctx.reportError(
Fixup.getLoc(),
"fixup not sufficiently aligned");
165 return (
Value >> 2) & 0x7ffff;
172 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
179 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
181 Ctx.reportError(
Fixup.getLoc(),
"fixup must be 2-byte aligned");
188 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
190 Ctx.reportError(
Fixup.getLoc(),
"fixup must be 4-byte aligned");
197 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
199 Ctx.reportError(
Fixup.getLoc(),
"fixup must be 8-byte aligned");
206 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
208 Ctx.reportError(
Fixup.getLoc(),
"fixup must be 16-byte aligned");
217 if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
218 Ctx.reportError(
Fixup.getLoc(),
219 "fixup value out of range [-0xFFFF, 0xFFFF]");
223 SignedValue = ~SignedValue;
228 Ctx.reportError(
Fixup.getLoc(),
229 "relocation for a thread-local variable points to an "
237 Ctx.reportError(
Fixup.getLoc(),
"unresolved movw fixup not yet "
247 SignedValue = SignedValue >> 16;
250 SignedValue = SignedValue >> 32;
253 SignedValue = SignedValue >> 48;
280 if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
281 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
285 SignedValue = ~SignedValue;
287 }
else if (
Value > 0xFFFF) {
288 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
295 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
298 Ctx.reportError(
Fixup.getLoc(),
"fixup not sufficiently aligned");
299 return (
Value >> 2) & 0x1ff;
303 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
306 Ctx.reportError(
Fixup.getLoc(),
"fixup not sufficiently aligned");
307 return (
Value >> 2) & 0x3fff;
310 SignedValue = -SignedValue;
313 if (SignedValue < 0 || SignedValue > ((1 << 18) - 1))
314 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
317 Ctx.reportError(
Fixup.getLoc(),
"fixup not sufficiently aligned");
318 return (
Value >> 2) & 0xffff;
324 Ctx.reportError(
Fixup.getLoc(),
325 "cannot perform a PC-relative fixup with a non-zero "
330 Ctx.reportError(
Fixup.getLoc(),
"fixup value out of range");
333 Ctx.reportError(
Fixup.getLoc(),
"fixup not sufficiently aligned");
334 return (
Value >> 2) & 0x3ffffff;
345std::optional<MCFixupKind>
346AArch64AsmBackend::getFixupKind(
StringRef Name)
const {
350 unsigned Type = llvm::StringSwitch<unsigned>(Name)
351#define ELF_RELOC(X, Y) .Case(#X, Y)
352#include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
354 .Case(
"BFD_RELOC_NONE", ELF::R_AARCH64_NONE)
355 .Case(
"BFD_RELOC_16", ELF::R_AARCH64_ABS16)
356 .Case(
"BFD_RELOC_32", ELF::R_AARCH64_ABS32)
357 .Case(
"BFD_RELOC_64", ELF::R_AARCH64_ABS64)
366unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(
unsigned Kind)
const {
420void AArch64AsmBackend::applyFixup(
const MCFragment &
F,
const MCFixup &
Fixup,
421 const MCValue &Target, uint8_t *
Data,
422 uint64_t
Value,
bool IsResolved) {
425 maybeAddReloc(
F,
Fixup, Target,
Value, IsResolved);
437 "expected relocatable expression");
441 Value = (uint64_t(Expr->getDiscriminator()) << 32) |
442 (uint64_t(Expr->getKey()) << 60) |
443 (uint64_t(Expr->hasAddressDiversity()) << 63);
450 MCFixupKindInfo
Info = getFixupKindInfo(
Fixup.getKind());
452 int64_t SignedValue =
static_cast<int64_t
>(
Value);
460 "Invalid fixup offset!");
463 unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(
Fixup.getKind());
467 if (FulleSizeInBytes == 0) {
469 for (
unsigned i = 0; i != NumBytes; ++i) {
470 Data[i] |= uint8_t((
Value >> (i * 8)) & 0xff);
474 assert(
Fixup.getOffset() + FulleSizeInBytes <=
F.getSize() &&
475 "Invalid fixup size!");
476 assert(NumBytes <= FulleSizeInBytes &&
"Invalid fixup size!");
477 for (
unsigned i = 0; i != NumBytes; ++i) {
478 unsigned Idx = FulleSizeInBytes - 1 - i;
479 Data[Idx] |= uint8_t((
Value >> (i * 8)) & 0xff);
492 Data[3] &= ~(1 << 6);
498bool AArch64AsmBackend::writeNopData(raw_ostream &OS, uint64_t
Count,
499 const MCSubtargetInfo *STI)
const {
507 for (uint64_t i = 0; i !=
Count; ++i)
508 OS.
write(
"\x1f\x20\x03\xd5", 4);
520 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
527 UNWIND_ARM64_MODE_DWARF = 0x03000000,
535 UNWIND_ARM64_MODE_FRAME = 0x04000000,
538 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
539 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
540 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
541 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
542 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
543 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
544 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
545 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
546 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800
552class DarwinAArch64AsmBackend :
public AArch64AsmBackend {
559 return (StackSize / 16) << 12;
563 DarwinAArch64AsmBackend(
const Target &
T,
const Triple &TT,
564 const MCRegisterInfo &MRI)
565 : AArch64AsmBackend(
T,
TT,
true), MRI(MRI) {}
567 std::unique_ptr<MCObjectTargetWriter>
568 createObjectTargetWriter()
const override {
576 uint64_t generateCompactUnwindEncoding(
const MCDwarfFrameInfo *FI,
577 const MCContext *Ctxt)
const override {
579 return CU::UNWIND_ARM64_MODE_DWARF;
584 return CU::UNWIND_ARM64_MODE_DWARF;
588 return CU::UNWIND_ARM64_MODE_DWARF;
592 return CU::UNWIND_ARM64_MODE_FRAMELESS;
593 if (!isDarwinCanonicalPersonality(FI->
Personality) &&
595 return CU::UNWIND_ARM64_MODE_DWARF;
598 uint64_t StackSize = 0;
600 uint64_t CompactUnwindEncoding = 0;
601 int64_t CurOffset = 0;
602 for (
size_t i = 0, e = Instrs.
size(); i != e; ++i) {
603 const MCCFIInstruction &Inst = Instrs[i];
608 return CU::UNWIND_ARM64_MODE_DWARF;
618 if (XReg != AArch64::FP)
619 return CU::UNWIND_ARM64_MODE_DWARF;
622 return CU::UNWIND_ARM64_MODE_DWARF;
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;
632 return CU::UNWIND_ARM64_MODE_DWARF;
641 if (LRReg != AArch64::LR ||
FPReg != AArch64::FP)
642 return CU::UNWIND_ARM64_MODE_DWARF;
645 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME;
651 return CU::UNWIND_ARM64_MODE_DWARF;
660 return CU::UNWIND_ARM64_MODE_DWARF;
662 if (CurOffset != 0 && Inst.
getOffset() != CurOffset - 8)
663 return CU::UNWIND_ARM64_MODE_DWARF;
666 const MCCFIInstruction &Inst2 = Instrs[++i];
668 return CU::UNWIND_ARM64_MODE_DWARF;
672 return CU::UNWIND_ARM64_MODE_DWARF;
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;
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;
722 return CU::UNWIND_ARM64_MODE_DWARF;
733 if (StackSize > 65520)
734 return CU::UNWIND_ARM64_MODE_DWARF;
736 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAMELESS;
737 CompactUnwindEncoding |= encodeStackAdjustment(StackSize);
740 return CompactUnwindEncoding;
748class ELFAArch64AsmBackend :
public AArch64AsmBackend {
753 ELFAArch64AsmBackend(
const Target &
T,
const Triple &TT, uint8_t OSABI,
754 bool IsLittleEndian,
bool IsILP32)
755 : AArch64AsmBackend(
T,
TT, IsLittleEndian), OSABI(OSABI),
758 std::unique_ptr<MCObjectTargetWriter>
759 createObjectTargetWriter()
const override {
767class COFFAArch64AsmBackend :
public AArch64AsmBackend {
769 COFFAArch64AsmBackend(
const Target &
T,
const Triple &TheTriple)
770 : AArch64AsmBackend(
T, TheTriple,
true) {}
772 std::unique_ptr<MCObjectTargetWriter>
773 createObjectTargetWriter()
const override {
785 return new DarwinAArch64AsmBackend(
T, TheTriple, MRI);
789 return new COFFAArch64AsmBackend(
T, TheTriple);
795 return new ELFAArch64AsmBackend(
T, TheTriple, OSABI,
true,
805 "Big endian is only supported for ELF targets!");
808 return new ELFAArch64AsmBackend(
T, TheTriple, OSABI,
false,
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)
static bool shouldForceRelocation(const MCFixup &Fixup)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
PowerPC TLS Dynamic Call Fixup
static constexpr MCPhysReg FPReg
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Generic interface to target specific assembler backends.
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
unsigned getRegister() const
OpType getOperation() const
int64_t getOffset() const
Context object for machine code objects.
LLVM_ABI bool emitCompactUnwindNonCanonical() const
LLVM_ABI EmitDwarfUnwindType emitDwarfUnwindInfo() const
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
std::optional< MCRegister > getLLVMRegNum(uint64_t RegNum, bool isEH) const
Map a dwarf register back to a target register.
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
Represent a constant reference to a string, i.e.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
OSType getOS() const
Get the parsed operating system type of this triple.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
LLVM_ABI bool isArch32Bit() const
Test whether the architecture is 32-bit.
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
LLVM Value Representation.
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.
Specifier getSymbolLoc(Specifier S)
@ fixup_aarch64_pcrel_branch9
@ fixup_aarch64_pcrel_branch16
@ fixup_aarch64_ldst_imm12_scale4
@ fixup_aarch64_pcrel_call26
@ fixup_aarch64_pcrel_branch26
@ fixup_aarch64_pcrel_branch19
@ fixup_aarch64_ldr_pcrel_imm19
@ fixup_aarch64_pcrel_adr_imm21
@ fixup_aarch64_pcrel_branch14
@ fixup_aarch64_ldst_imm12_scale2
@ fixup_aarch64_ldst_imm12_scale16
@ fixup_aarch64_pcrel_adrp_imm21
@ fixup_aarch64_add_imm12
@ fixup_aarch64_ldst_imm12_scale8
@ fixup_aarch64_ldst_imm12_scale1
Specifier getAddressFrag(Specifier S)
LLVM_ABI Expected< uint32_t > getCPUSubType(const Triple &T)
LLVM_ABI Expected< uint32_t > getCPUType(const Triple &T)
VE::Fixups getFixupKind(uint8_t S)
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const ArmConfig &ArmCfg)
Apply fixup expression for edge to block content.
bool isRelocation(MCFixupKind FixupKind)
Context & getContext() const
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
std::unique_ptr< MCObjectTargetWriter > createAArch64WinCOFFObjectWriter(const Triple &TheTriple)
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
MCAsmBackend * createAArch64leAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
@ FK_SecRel_2
A two-byte section relative fixup.
@ FirstLiteralRelocationKind
@ FK_Data_8
A eight-byte fixup.
@ FK_Data_1
A one-byte fixup.
@ FK_Data_4
A four-byte fixup.
@ FK_SecRel_4
A four-byte section relative fixup.
@ FK_Data_2
A two-byte fixup.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
static MCRegister getXRegFromWReg(MCRegister Reg)
ArrayRef(const T &OneElt) -> ArrayRef< T >
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)
static MCRegister getDRegFromBReg(MCRegister Reg)
std::unique_ptr< MCObjectTargetWriter > createAArch64ELFObjectWriter(uint8_t OSABI, bool IsILP32)
const MCSymbol * Personality
std::vector< MCCFIInstruction > Instructions