Index: lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp =================================================================== --- lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -30,12 +30,14 @@ class AArch64AsmBackend : public MCAsmBackend { static const unsigned PCRelFlagVal = MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel; + Triple TheTriple; + public: bool IsLittleEndian; public: - AArch64AsmBackend(const Target &T, bool IsLittleEndian) - : MCAsmBackend(), IsLittleEndian(IsLittleEndian) {} + AArch64AsmBackend(const Target &T, const Triple &TT, bool IsLittleEndian) + : MCAsmBackend(), TheTriple(TT), IsLittleEndian(IsLittleEndian) {} unsigned getNumFixupKinds() const override { return AArch64::NumTargetFixupKinds; @@ -143,7 +145,8 @@ } static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext &Ctx) { + MCContext &Ctx, const Triple &TheTriple, + bool IsResolved) { unsigned Kind = Fixup.getKind(); int64_t SignedValue = static_cast(Value); switch (Kind) { @@ -154,6 +157,9 @@ Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); return AdrImmBits(Value & 0x1fffffULL); case AArch64::fixup_aarch64_pcrel_adrp_imm21: + assert(!IsResolved); + if (TheTriple.isOSBinFormatCOFF()) + return AdrImmBits(Value & 0x1fffffULL); return AdrImmBits((Value & 0x1fffff000ULL) >> 12); case AArch64::fixup_aarch64_ldr_pcrel_imm19: case AArch64::fixup_aarch64_pcrel_branch19: @@ -166,11 +172,15 @@ return (Value >> 2) & 0x7ffff; case AArch64::fixup_aarch64_add_imm12: case AArch64::fixup_aarch64_ldst_imm12_scale1: + if (TheTriple.isOSBinFormatCOFF() && !IsResolved) + Value &= 0xfff; // Unsigned 12-bit immediate if (Value >= 0x1000) Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); return Value; case AArch64::fixup_aarch64_ldst_imm12_scale2: + if (TheTriple.isOSBinFormatCOFF() && !IsResolved) + Value &= 0xfff; // Unsigned 12-bit immediate which gets multiplied by 2 if (Value >= 0x2000) Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); @@ -178,6 +188,8 @@ Ctx.reportError(Fixup.getLoc(), "fixup must be 2-byte aligned"); return Value >> 1; case AArch64::fixup_aarch64_ldst_imm12_scale4: + if (TheTriple.isOSBinFormatCOFF() && !IsResolved) + Value &= 0xfff; // Unsigned 12-bit immediate which gets multiplied by 4 if (Value >= 0x4000) Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); @@ -185,6 +197,8 @@ Ctx.reportError(Fixup.getLoc(), "fixup must be 4-byte aligned"); return Value >> 2; case AArch64::fixup_aarch64_ldst_imm12_scale8: + if (TheTriple.isOSBinFormatCOFF() && !IsResolved) + Value &= 0xfff; // Unsigned 12-bit immediate which gets multiplied by 8 if (Value >= 0x8000) Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); @@ -192,6 +206,8 @@ Ctx.reportError(Fixup.getLoc(), "fixup must be 8-byte aligned"); return Value >> 3; case AArch64::fixup_aarch64_ldst_imm12_scale16: + if (TheTriple.isOSBinFormatCOFF() && !IsResolved) + Value &= 0xfff; // Unsigned 12-bit immediate which gets multiplied by 16 if (Value >= 0x10000) Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); @@ -278,7 +294,7 @@ MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); MCContext &Ctx = Asm.getContext(); // Apply any target-specific value adjustments. - Value = adjustFixupValue(Fixup, Value, Ctx); + Value = adjustFixupValue(Fixup, Value, Ctx, TheTriple, IsResolved); // Shift the value into position. Value <<= Info.TargetOffset; @@ -412,8 +428,9 @@ } public: - DarwinAArch64AsmBackend(const Target &T, const MCRegisterInfo &MRI) - : AArch64AsmBackend(T, /*IsLittleEndian*/true), MRI(MRI) {} + DarwinAArch64AsmBackend(const Target &T, const Triple &TT, + const MCRegisterInfo &MRI) + : AArch64AsmBackend(T, TT, /*IsLittleEndian*/ true), MRI(MRI) {} MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { return createAArch64MachObjectWriter(OS, MachO::CPU_TYPE_ARM64, @@ -560,9 +577,10 @@ uint8_t OSABI; bool IsILP32; - ELFAArch64AsmBackend(const Target &T, uint8_t OSABI, bool IsLittleEndian, - bool IsILP32) - : AArch64AsmBackend(T, IsLittleEndian), OSABI(OSABI), IsILP32(IsILP32) {} + ELFAArch64AsmBackend(const Target &T, const Triple &TT, uint8_t OSABI, + bool IsLittleEndian, bool IsILP32) + : AArch64AsmBackend(T, TT, IsLittleEndian), OSABI(OSABI), + IsILP32(IsILP32) {} MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { return createAArch64ELFObjectWriter(OS, OSABI, IsLittleEndian, IsILP32); @@ -575,7 +593,7 @@ class COFFAArch64AsmBackend : public AArch64AsmBackend { public: COFFAArch64AsmBackend(const Target &T, const Triple &TheTriple) - : AArch64AsmBackend(T, /*IsLittleEndian*/true) {} + : AArch64AsmBackend(T, TheTriple, /*IsLittleEndian*/ true) {} MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { return createAArch64WinCOFFObjectWriter(OS); @@ -589,7 +607,7 @@ StringRef CPU, const MCTargetOptions &Options) { if (TheTriple.isOSBinFormatMachO()) - return new DarwinAArch64AsmBackend(T, MRI); + return new DarwinAArch64AsmBackend(T, TheTriple, MRI); if (TheTriple.isOSBinFormatCOFF()) return new COFFAArch64AsmBackend(T, TheTriple); @@ -598,7 +616,8 @@ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); bool IsILP32 = Options.getABIName() == "ilp32"; - return new ELFAArch64AsmBackend(T, OSABI, /*IsLittleEndian=*/true, IsILP32); + return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/true, + IsILP32); } MCAsmBackend *llvm::createAArch64beAsmBackend(const Target &T, @@ -610,5 +629,6 @@ "Big endian is only supported for ELF targets!"); uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); bool IsILP32 = Options.getABIName() == "ilp32"; - return new ELFAArch64AsmBackend(T, OSABI, /*IsLittleEndian=*/false, IsILP32); + return new ELFAArch64AsmBackend(T, TheTriple, OSABI, /*IsLittleEndian=*/false, + IsILP32); } Index: test/MC/AArch64/coff-relocations.s =================================================================== --- test/MC/AArch64/coff-relocations.s +++ test/MC/AArch64/coff-relocations.s @@ -1,5 +1,6 @@ -; RUN: llvm-mc -triple aarch64-windows -filetype obj -o - %s | \ -; RUN: llvm-readobj -r - | FileCheck %s +; RUN: llvm-mc -triple aarch64-windows -filetype obj -o %t.obj %s +; RUN: llvm-readobj -r %t.obj | FileCheck %s +; RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix DISASM ; IMAGE_REL_ARM64_ADDR32 .Linfo_foo: @@ -37,6 +38,13 @@ ; IMAGE_REL_ARM64_SECTION .secidx func +.align 2 +adrp x0, baz + 0x12345 +baz: +add x0, x0, :lo12:foo + 0x12345 +ldrb w0, [x0, :lo12:foo + 0x12345] +ldr x0, [x0, :lo12:foo + 0x12348] + ; CHECK: Format: COFF-ARM64 ; CHECK: Arch: aarch64 ; CHECK: AddressSize: 64bit @@ -52,5 +60,14 @@ ; CHECK: 0x24 IMAGE_REL_ARM64_PAGEBASE_REL21 bar ; CHECK: 0x28 IMAGE_REL_ARM64_SECREL .text ; CHECK: 0x2C IMAGE_REL_ARM64_SECTION func +; CHECK: 0x30 IMAGE_REL_ARM64_PAGEBASE_REL21 baz +; CHECK: 0x34 IMAGE_REL_ARM64_PAGEOFFSET_12A foo +; CHECK: 0x38 IMAGE_REL_ARM64_PAGEOFFSET_12L foo +; CHECK: 0x3C IMAGE_REL_ARM64_PAGEOFFSET_12L foo ; CHECK: } ; CHECK: ] + +; DISASM: 30: 20 1a 09 b0 adrp x0, #305418240 +; DISASM: 34: 00 14 0d 91 add x0, x0, #837 +; DISASM: 38: 00 14 4d 39 ldrb w0, [x0, #837] +; DISASM: 3c: 00 a4 41 f9 ldr x0, [x0, #840] Index: test/MC/AArch64/fixup-out-of-range.s =================================================================== --- test/MC/AArch64/fixup-out-of-range.s +++ test/MC/AArch64/fixup-out-of-range.s @@ -1,4 +1,5 @@ // RUN: not llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s +// RUN: not llvm-mc -triple aarch64-windows -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range adr x0, distant