Index: include/llvm/MC/MCWinCOFFObjectWriter.h =================================================================== --- include/llvm/MC/MCWinCOFFObjectWriter.h +++ include/llvm/MC/MCWinCOFFObjectWriter.h @@ -32,7 +32,6 @@ unsigned getMachine() const { return Machine; } virtual unsigned getRelocType(MCContext &Ctx, const MCReloc &Reloc, - bool IsCrossSection, const MCAsmBackend &MAB) const = 0; virtual bool recordRelocation(const MCReloc &) const { return true; } }; Index: lib/MC/ELFObjectWriter.cpp =================================================================== --- lib/MC/ELFObjectWriter.cpp +++ lib/MC/ELFObjectWriter.cpp @@ -625,8 +625,6 @@ const MCAsmLayout &Layout, const MCFragment *Fragment, MCReloc &Fixup) { - bool IsPCRel = Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags & - MCFixupKindInfo::FKF_IsPCRel; MCReloc &Target = Fixup; uint64_t &FixedValue = Fixup.getConstant(); const MCSectionELF &FixupSection = cast(*Fragment->getParent()); @@ -634,43 +632,11 @@ uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); MCContext &Ctx = Asm.getContext(); - if (const MCSymbol *SymBP = Target.getSymB()) { - // Let A, B and C being the components of Target and R be the location of - // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). - // If it is pcrel, we want to compute (A - B + C - R). - - // In general, ELF has no relocations for -B. It can only represent (A + C) - // or (A + C - R). If B = R + K and the relocation is not pcrel, we can - // replace B to implement it: (A - R - K + C) - if (IsPCRel) { - Ctx.reportError( - Fixup.getLoc(), - "No relocation available to represent this relative expression"); - return; - } - - const MCSymbol &SymB = *SymBP; - - if (SymB.isUndefined()) { - Ctx.reportError(Fixup.getLoc(), - Twine("symbol '") + SymB.getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - assert(!SymB.isAbsolute() && "Should have been folded"); - const MCSection &SecB = SymB.getSection(); - if (&SecB != &FixupSection) { - Ctx.reportError(Fixup.getLoc(), - "Cannot represent a difference across sections"); - return; - } - - Fixup.setKind(Asm.getBackend().getPCRelKind(Fixup.getKind())); - uint64_t SymBOffset = Layout.getSymbolOffset(SymB); - uint64_t K = SymBOffset - FixupOffset; - IsPCRel = true; - C -= K; + if (Target.getSymB()) { + Ctx.reportError( + Fixup.getLoc(), + "No relocation available to represent this relative expression"); + return; } // We either rejected the fixup or folded B into C at this point. Index: lib/MC/MCAssembler.cpp =================================================================== --- lib/MC/MCAssembler.cpp +++ lib/MC/MCAssembler.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCFragment.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" @@ -185,6 +186,50 @@ return S.getFragment()->getAtom(); } +static void tryConvertingToPcRel(const MCAsmLayout &Layout, + const MCFragment &Fragment, + MCReloc &Reloc) { + MCAssembler &Asm = Layout.getAssembler(); + // Let A, B and C being the components of Target and R be the location of + // the relocation. If the relocation is not pcrel, we want to compute (A - B + + // C). If it is pcrel, we want to compute (A - B + C - R). + + // If B = R + K and the relocation is not pcrel, we can replace B to + // implement it: (A - R - K + C). This is particularly important for + // ELF and COFF which don't have relocations that subtract an + // arbitrary symbol. + if (!Reloc.getSymB()) + return; + + const MCSymbol &SymB = *Reloc.getSymB(); + if (SymB.isUndefined()) + return; + assert(!SymB.isAbsolute() && "Should have been folded"); + + const MCSection &SecB = SymB.getSection(); + const MCSection &RelocSection = *Fragment.getParent(); + if (&SecB != &RelocSection) + return; + + // Don't do this for MachO. One would expect to only need to check + // the atom in here as we check the section above, but there are + // still too many odd broken tests with that. + if (Asm.getContext().getObjectFileInfo()->getObjectFileType() == + MCObjectFileInfo::IsMachO) + return; + + Optional PCKind = Asm.getBackend().getPCRelKind(Reloc.getKind()); + if (!PCKind) + return; + + uint64_t SymBOffset = Layout.getSymbolOffset(SymB); + uint64_t FixupOffset = Layout.getFragmentOffset(&Fragment) + Reloc.getOffset(); + uint64_t Delta = SymBOffset - FixupOffset; + Reloc.setConstant(Reloc.getConstant() - Delta); + Reloc.setKind(*PCKind); + Reloc.setSymB(nullptr); +} + bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, MCReloc &Reloc) const { @@ -246,6 +291,8 @@ Value = Target.getConstant(); + tryConvertingToPcRel(Layout, *DF, Reloc); + // Let the backend force a relocation if needed. if (IsResolved && Backend.shouldForceRelocation(*this, Fixup, Target)) IsResolved = false; Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -357,42 +357,11 @@ bool IsPCRel = Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel; - if (const MCSymbol *SymBP = Fixup.getSymB()) { - // Let A, B and C being the components of Target and R be the location of - // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). - // If it is pcrel, we want to compute (A - B + C - R). - - // In general, Wasm has no relocations for -B. It can only represent (A + C) - // or (A + C - R). If B = R + K and the relocation is not pcrel, we can - // replace B to implement it: (A - R - K + C) - if (IsPCRel) { - Ctx.reportError( - Fixup.getLoc(), - "No relocation available to represent this relative expression"); - return; - } - - const MCSymbol &SymB = *SymBP; - - if (SymB.isUndefined()) { - Ctx.reportError(Fixup.getLoc(), - Twine("symbol '") + SymB.getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - assert(!SymB.isAbsolute() && "Should have been folded"); - const MCSection &SecB = SymB.getSection(); - if (&SecB != &FixupSection) { - Ctx.reportError(Fixup.getLoc(), - "Cannot represent a difference across sections"); - return; - } - - uint64_t SymBOffset = Layout.getSymbolOffset(SymB); - uint64_t K = SymBOffset - FixupOffset; - IsPCRel = true; - C -= K; + if (Fixup.getSymB()) { + Ctx.reportError( + Fixup.getLoc(), + "No relocation available to represent this relative expression"); + return; } // We either rejected the fixup or folded B into C at this point. Index: lib/MC/WinCOFFObjectWriter.cpp =================================================================== --- lib/MC/WinCOFFObjectWriter.cpp +++ lib/MC/WinCOFFObjectWriter.cpp @@ -738,25 +738,12 @@ const MCSymbol *B = Target.getSymB(); if (B) { - if (!B->getFragment()) { - Asm.getContext().reportError( - Fixup.getLoc(), - Twine("symbol '") + B->getName() + - "' can not be undefined in a subtraction expression"); - return; - } - - // Offset of the symbol in the section - int64_t OffsetOfB = Layout.getSymbolOffset(*B); - - // Offset of the relocation in the section - int64_t OffsetOfRelocation = - Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - - FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.getConstant(); - } else { - FixedValue = Target.getConstant(); + Asm.getContext().reportError( + Fixup.getLoc(), + "No relocation available to represent this relative expression"); + return; } + FixedValue = Target.getConstant(); COFFRelocation Reloc; @@ -782,7 +769,7 @@ Reloc.Data.VirtualAddress += Fixup.getOffset(); Reloc.Data.Type = TargetObjectWriter->getRelocType( - Asm.getContext(), Fixup, B, Asm.getBackend()); + Asm.getContext(), Fixup, Asm.getBackend()); // FIXME: Can anyone explain what this does other than adjust for the size // of the offset? Index: lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp =================================================================== --- lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp +++ lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp @@ -33,7 +33,6 @@ ~AArch64WinCOFFObjectWriter() override = default; unsigned getRelocType(MCContext &Ctx, const MCReloc &Fixup, - bool IsCrossSection, const MCAsmBackend &MAB) const override; bool recordRelocation(const MCReloc &) const override; @@ -44,7 +43,6 @@ unsigned AArch64WinCOFFObjectWriter::getRelocType(MCContext &Ctx, const MCReloc &Fixup, - bool IsCrossSection, const MCAsmBackend &MAB) const { const MCFixupKindInfo &Info = MAB.getFixupKindInfo(Fixup.getKind()); report_fatal_error(Twine("unsupported relocation type: ") + Info.Name); Index: lib/Target/ARM/MCTargetDesc/ARMWinCOFFObjectWriter.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMWinCOFFObjectWriter.cpp +++ lib/Target/ARM/MCTargetDesc/ARMWinCOFFObjectWriter.cpp @@ -34,7 +34,6 @@ ~ARMWinCOFFObjectWriter() override = default; unsigned getRelocType(MCContext &Ctx, const MCReloc &Reloc, - bool IsCrossSection, const MCAsmBackend &MAB) const override; bool recordRelocation(const MCReloc &) const override; @@ -44,7 +43,6 @@ unsigned ARMWinCOFFObjectWriter::getRelocType(MCContext &Context, const MCReloc &Fixup, - bool IsCrossSection, const MCAsmBackend &MAB) const { const MCReloc &Target = Fixup; assert(getMachine() == COFF::IMAGE_FILE_MACHINE_ARMNT && Index: lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp =================================================================== --- lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp +++ lib/Target/X86/MCTargetDesc/X86WinCOFFObjectWriter.cpp @@ -27,7 +27,6 @@ ~X86WinCOFFObjectWriter() override = default; unsigned getRelocType(MCContext &Ctx, const MCReloc &Reloc, - bool IsCrossSection, const MCAsmBackend &MAB) const override; }; @@ -39,23 +38,19 @@ unsigned X86WinCOFFObjectWriter::getRelocType(MCContext &Ctx, const MCReloc &Fixup, - bool IsCrossSection, const MCAsmBackend &MAB) const { const MCReloc &Target = Fixup; unsigned FixupKind = Fixup.getKind(); - if (IsCrossSection) { - if (FixupKind != FK_Data_4 && FixupKind != llvm::X86::reloc_signed_4byte) { - 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) { switch (FixupKind) { + case FK_PCRel_1: + case FK_PCRel_2: + case FK_PCRel_8: + Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression"); + return COFF::IMAGE_REL_AMD64_ADDR32; case FK_PCRel_4: case X86::reloc_riprel_4byte: case X86::reloc_riprel_4byte_movq_load: Index: test/MC/AArch64/error-location.s =================================================================== --- test/MC/AArch64/error-location.s +++ test/MC/AArch64/error-location.s @@ -4,7 +4,7 @@ // source appears, this file is carefully ordered so that that is the case. .text -// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: symbol 'undef' can not be undefined in a subtraction expression +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression .word (0-undef) // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: expected relocatable expression @@ -13,7 +13,7 @@ // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression adr x0, #a-undef -// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Cannot represent a difference across sections +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression .word x_a - y_a // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 1-byte data relocations not supported Index: test/MC/AArch64/label-arithmetic-diags-elf.s =================================================================== --- test/MC/AArch64/label-arithmetic-diags-elf.s +++ test/MC/AArch64/label-arithmetic-diags-elf.s @@ -34,10 +34,10 @@ add w0, w1, #(end - external) cmp w0, #(end - external) - // CHECK: error: symbol 'external' can not be undefined in a subtraction expression + // CHECK: error: No relocation available to represent this relative expression // CHECK-NEXT: add w0, w1, #(end - external) // CHECK-NEXT: ^ - // CHECK: error: symbol 'external' can not be undefined in a subtraction expression + // CHECK: error: No relocation available to represent this relative expression // CHECK-NEXT: cmp w0, #(end - external) // CHECK-NEXT: ^ @@ -63,18 +63,18 @@ end_across_sec: add w0, w1, #(end_across_sec - start) cmp w0, #(end_across_sec - start) - // CHECK: error: Cannot represent a difference across sections + // CHECK: error: No relocation available to represent this relative expression // CHECK-NEXT: add w0, w1, #(end_across_sec - start) // CHECK-NEXT: ^ - // CHECK: error: Cannot represent a difference across sections + // CHECK: error: No relocation available to represent this relative expression // CHECK-NEXT: cmp w0, #(end_across_sec - start) // CHECK-NEXT: ^ add w0, w1, #(sec_y - sec_x) cmp w0, #(sec_y - sec_x) - // CHECK: error: Cannot represent a difference across sections + // CHECK: error: No relocation available to represent this relative expression // CHECK-NEXT: add w0, w1, #(sec_y - sec_x) // CHECK-NEXT: ^ - // CHECK: error: Cannot represent a difference across sections + // CHECK: error: No relocation available to represent this relative expression // CHECK-NEXT: cmp w0, #(sec_y - sec_x) // CHECK-NEXT: ^ Index: test/MC/ARM/cmp-immediate-fixup-error2.s =================================================================== --- test/MC/ARM/cmp-immediate-fixup-error2.s +++ test/MC/ARM/cmp-immediate-fixup-error2.s @@ -2,6 +2,6 @@ .text cmp r0, #(l1 - unknownLabel) -@ CHECK: error: symbol 'unknownLabel' can not be undefined in a subtraction expression +@ CHECK: error: No relocation available to represent this relative expression l1: Index: test/MC/ARM/error-location.s =================================================================== --- test/MC/ARM/error-location.s +++ test/MC/ARM/error-location.s @@ -4,7 +4,7 @@ @ source appears, this file is carefully ordered so that that is the case. .text -@ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: symbol 'undef' can not be undefined in a subtraction expression +@ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression .word (0-undef) @ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: expected relocatable expression @@ -13,7 +13,7 @@ @ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression adr r0, #a-undef -@ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Cannot represent a difference across sections +@ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression .word x_a - y_a Index: test/MC/COFF/bad-expr.s =================================================================== --- test/MC/COFF/bad-expr.s +++ test/MC/COFF/bad-expr.s @@ -1,7 +1,6 @@ // RUN: not llvm-mc -filetype=obj -triple i386-pc-win32 %s 2>&1 | FileCheck %s -// CHECK: symbol '__ImageBase' can not be undefined in a subtraction expression - .data _x: +// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression .long _x-__ImageBase Index: test/MC/ELF/bad-expr.s =================================================================== --- test/MC/ELF/bad-expr.s +++ test/MC/ELF/bad-expr.s @@ -4,7 +4,7 @@ .data x: -// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: symbol '__executable_start' can not be undefined in a subtraction expression +// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression .quad x-__executable_start // CHECK: [[@LINE+1]]:{{[0-9]+}}: error: unsupported subtraction of qualified symbol Index: test/MC/ELF/bad-expr3.s =================================================================== --- test/MC/ELF/bad-expr3.s +++ test/MC/ELF/bad-expr3.s @@ -1,8 +1,7 @@ // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o /dev/null \ // RUN: 2>&1 | FileCheck %s -// CHECK: Cannot represent a difference across sections - +// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: No relocation available to represent this relative expression .long foo - bar .section .zed foo: