diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp @@ -48,7 +48,10 @@ bool IsCrossSection, const MCAsmBackend &MAB) const { unsigned FixupKind = Fixup.getKind(); if (IsCrossSection) { - if (FixupKind != FK_Data_4) { + // IMAGE_REL_ARM64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so + // that .xword a-b can lower to IMAGE_REL_ARM64_REL32. This allows generic + // instrumentation to not bother with the COFF limitation. + if (FixupKind != FK_Data_4 && FixupKind != FK_Data_8) { Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression"); return COFF::IMAGE_REL_ARM64_ADDR32; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp @@ -42,19 +42,25 @@ const MCFixup &Fixup, bool IsCrossSection, const MCAsmBackend &MAB) const { + const bool Is64Bit = getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64; unsigned FixupKind = Fixup.getKind(); if (IsCrossSection) { - if (FixupKind != FK_Data_4 && FixupKind != llvm::X86::reloc_signed_4byte) { + // IMAGE_REL_AMD64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so + // that .quad a-b can lower to IMAGE_REL_AMD64_REL32. This allows generic + // instrumentation to not bother with the COFF limitation. + if (FixupKind == FK_Data_4 || FixupKind == llvm::X86::reloc_signed_4byte || + (FixupKind == FK_Data_8 && Is64Bit)) { + FixupKind = FK_PCRel_4; + } else { Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression"); return COFF::IMAGE_REL_AMD64_ADDR32; } - FixupKind = FK_PCRel_4; } MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); - if (getMachine() == COFF::IMAGE_FILE_MACHINE_AMD64) { + if (Is64Bit) { switch (FixupKind) { case FK_PCRel_4: case X86::reloc_riprel_4byte: diff --git a/llvm/test/MC/AArch64/coff-relocations.s b/llvm/test/MC/AArch64/coff-relocations.s --- a/llvm/test/MC/AArch64/coff-relocations.s +++ b/llvm/test/MC/AArch64/coff-relocations.s @@ -67,6 +67,10 @@ .word .Linfo_bar - .Ltable .word .Linfo_foo - .Ltable +// As an extension, we allow 64-bit label differences. They lower to +// IMAGE_REL_ARM64_REL32 because IMAGE_REL_ARM64_REL64 does not exist. +.xword .Linfo_foo - .Ltable + // CHECK: Format: COFF-ARM64 // CHECK: Arch: aarch64 // CHECK: AddressSize: 64bit @@ -96,6 +100,7 @@ // CHECK: Section (4) .rdata { // CHECK: 0x0 IMAGE_REL_ARM64_REL32 .text // CHECK: 0x4 IMAGE_REL_ARM64_REL32 .text +// CHECK: 0x8 IMAGE_REL_ARM64_REL32 .text // CHECK: } // CHECK: ] diff --git a/llvm/test/MC/COFF/cross-section-relative-err.s b/llvm/test/MC/COFF/cross-section-relative-err.s --- a/llvm/test/MC/COFF/cross-section-relative-err.s +++ b/llvm/test/MC/COFF/cross-section-relative-err.s @@ -1,3 +1,4 @@ +// RUN: not llvm-mc -filetype=obj -triple i686-pc-win32 %s -o /dev/null 2>&1 | FileCheck %s --check-prefixes=CHECK,I686 // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-win32 %s -o /dev/null 2>&1 | FileCheck %s @@ -7,6 +8,5 @@ // CHECK: [[@LINE+1]]:{{[0-9]+}}: error: Cannot represent this expression .short foo - . -// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: Cannot represent this expression +// I686: [[@LINE+1]]:{{[0-9]+}}: error: Cannot represent this expression .quad foo - . - diff --git a/llvm/test/MC/COFF/cross-section-relative.s b/llvm/test/MC/COFF/cross-section-relative.s --- a/llvm/test/MC/COFF/cross-section-relative.s +++ b/llvm/test/MC/COFF/cross-section-relative.s @@ -57,6 +57,10 @@ .long foobar - . +// As an extension, we allow 64-bit label differences. They lower to +// IMAGE_REL_AMD64_REL32 because IMAGE_REL_AMD64_REL64 does not exist. +.quad foobar - . + // READOBJ: Section { // READOBJ: Number: // READOBJ: Name: .fix (2E 66 69 78 00 00 00 00) @@ -77,7 +81,8 @@ // READOBJ-NEXT: SectionData ( // READOBJ-NEXT: 0000: 04000000 00000000 00000000 00000000 | // READOBJ-NEXT: 0010: 01020000 00000000 00010000 00000000 | -// READOBJ-NEXT: 0020: 04000000 00000000 04000000 | +// READOBJ-NEXT: 0020: 04000000 00000000 04000000 04000000 | +// READOBJ-NEXT: 0030: 00000000 | // READOBJ-NEXT: ) // READOBJ-NEXT: } // READOBJ-NEXT: ] @@ -107,5 +112,11 @@ // READOBJ-NEXT: Symbol: foobar // READOBJ-NEXT: SymbolIndex: 20 // READOBJ-NEXT: } +// READOBJ-NEXT: Relocation { +// READOBJ-NEXT: Offset: 0x2C +// READOBJ-NEXT: Type: IMAGE_REL_AMD64_REL32 (4) +// READOBJ-NEXT: Symbol: foobar +// READOBJ-NEXT: SymbolIndex: 20 +// READOBJ-NEXT: } // READOBJ-NEXT: } // READOBJ-NEXT:]