diff --git a/llvm/include/llvm/MC/MCFixup.h b/llvm/include/llvm/MC/MCFixup.h --- a/llvm/include/llvm/MC/MCFixup.h +++ b/llvm/include/llvm/MC/MCFixup.h @@ -55,9 +55,14 @@ FirstTargetFixupKind = 128, - // Limit range of target fixups, in case we want to pack more efficiently - // later. - MaxTargetFixupKind = (1 << 8) + /// The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for + /// relocations coming from .reloc directive. Fixup kind + /// FirstLiteralRelocationKind+V represents the relocation type with number V. + FirstLiteralRelocationKind = 256, + + /// Set limit to accommodate the highest reloc type in use for all Targets, + /// currently R_AARCH64_IRELATIVE at 1032, including room for expansion. + MaxFixupKind = FirstLiteralRelocationKind + 1032 + 32, }; /// Encode information on a single operation to perform on a byte @@ -92,7 +97,7 @@ public: static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc = SMLoc()) { - assert(Kind < MaxTargetFixupKind && "Kind out of range!"); + assert(Kind <= MaxFixupKind && "Kind out of range!"); MCFixup FI; FI.Value = Value; FI.Offset = Offset; diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -48,10 +48,17 @@ } // end anonymous namespace Optional ARMAsmBackend::getFixupKind(StringRef Name) const { - if (STI.getTargetTriple().isOSBinFormatELF() && Name == "R_ARM_NONE") - return FK_NONE; + if (!STI.getTargetTriple().isOSBinFormatELF()) + return None; - return MCAsmBackend::getFixupKind(Name); + unsigned Type = llvm::StringSwitch(Name) +#define ELF_RELOC(X, Y) .Case(#X, Y) +#include "llvm/BinaryFormat/ELFRelocs/ARM.def" +#undef ELF_RELOC + .Default(-1u); + if (Type == -1u) + return None; + return static_cast(FirstLiteralRelocationKind + Type); } const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { @@ -172,6 +179,11 @@ {"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel} }; + // Fixup kinds from .reloc directive are like R_ARM_NONE. They do not require + // any extra processing. + if (Kind >= FirstLiteralRelocationKind) + return MCAsmBackend::getFixupKindInfo(FK_NONE); + if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); @@ -438,7 +450,6 @@ default: Ctx.reportError(Fixup.getLoc(), "bad relocation fixup type"); return 0; - case FK_NONE: case FK_Data_1: case FK_Data_2: case FK_Data_4: @@ -871,7 +882,7 @@ const MCSymbolRefExpr *A = Target.getSymA(); const MCSymbol *Sym = A ? &A->getSymbol() : nullptr; const unsigned FixupKind = Fixup.getKind(); - if (FixupKind == FK_NONE) + if (FixupKind >= FirstLiteralRelocationKind) return true; if (FixupKind == ARM::fixup_arm_thumb_bl) { assert(Sym && "How did we resolve this?"); @@ -915,9 +926,6 @@ default: llvm_unreachable("Unknown fixup kind!"); - case FK_NONE: - return 0; - case FK_Data_1: case ARM::fixup_arm_thumb_bcc: case ARM::fixup_arm_thumb_cp: @@ -979,9 +987,6 @@ default: llvm_unreachable("Unknown fixup kind!"); - case FK_NONE: - return 0; - case FK_Data_1: return 1; case FK_Data_2: @@ -1037,7 +1042,10 @@ MutableArrayRef Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo* STI) const { - unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); + unsigned Kind = Fixup.getKind(); + if (Kind >= FirstLiteralRelocationKind) + return; + unsigned NumBytes = getFixupKindNumBytes(Kind); MCContext &Ctx = Asm.getContext(); Value = adjustFixupValue(Asm, Fixup, Target, Value, IsResolved, Ctx, STI); if (!Value) @@ -1049,7 +1057,7 @@ // Used to point to big endian bytes. unsigned FullSizeBytes; if (Endian == support::big) { - FullSizeBytes = getFixupKindContainerSizeBytes(Fixup.getKind()); + FullSizeBytes = getFixupKindContainerSizeBytes(Kind); assert((Offset + FullSizeBytes) <= Data.size() && "Invalid fixup size!"); assert(NumBytes <= FullSizeBytes && "Invalid fixup size!"); } diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -79,6 +79,9 @@ const MCFixup &Fixup, bool IsPCRel, MCContext &Ctx) const { + unsigned Kind = Fixup.getTargetKind(); + if (Kind >= FirstLiteralRelocationKind) + return Kind - FirstLiteralRelocationKind; MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); if (IsPCRel) { @@ -152,12 +155,10 @@ return ELF::R_ARM_THM_BF18; } } - switch (Fixup.getTargetKind()) { + switch (Kind) { default: Ctx.reportFatalError(Fixup.getLoc(), "unsupported relocation on symbol"); return ELF::R_ARM_NONE; - case FK_NONE: - return ELF::R_ARM_NONE; case FK_Data_1: switch (Modifier) { default: diff --git a/llvm/test/MC/ARM/reloc-directive-err.s b/llvm/test/MC/ARM/reloc-directive-err.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/reloc-directive-err.s @@ -0,0 +1,6 @@ +# RUN: llvm-mc -triple=armv7 %s 2>&1 | FileCheck --check-prefix=PRINT %s +# RUN: not llvm-mc -filetype=obj -triple=armv7 %s -o /dev/null 2>&1 | FileCheck %s + +# PRINT: .reloc 0, R_INVALID, 0 +# CHECK: {{.*}}.s:[[# @LINE+1]]:11: error: unknown relocation name +.reloc 0, R_INVALID, 0 diff --git a/llvm/test/MC/ARM/reloc-directive.s b/llvm/test/MC/ARM/reloc-directive.s --- a/llvm/test/MC/ARM/reloc-directive.s +++ b/llvm/test/MC/ARM/reloc-directive.s @@ -17,6 +17,10 @@ .reloc 4, R_ARM_NONE, foo+4 .reloc 0, R_ARM_NONE, 8 + .reloc 0, R_ARM_ALU_PC_G0, .data+2 + .reloc 0, R_ARM_LDR_PC_G0, foo+3 + .reloc 0, R_ARM_THM_ALU_PREL_11_0, 5 + .data .globl foo foo: @@ -27,11 +31,17 @@ # PRINT: .reloc 8, R_ARM_NONE, .data # PRINT: .reloc 4, R_ARM_NONE, foo+4 # PRINT: .reloc 0, R_ARM_NONE, 8 +# PRINT: .reloc 0, R_ARM_ALU_PC_G0, .data+2 +# PRINT: .reloc 0, R_ARM_LDR_PC_G0, foo+3 +# PRINT: .reloc 0, R_ARM_THM_ALU_PREL_11_0, 5 # ARM relocations use the Elf32_Rel format. Addends are neither stored in the # relocation entries nor applied in the referenced locations. # CHECK: 0x8 R_ARM_NONE .data 0x0 # CHECK-NEXT: 0x4 R_ARM_NONE foo 0x0 # CHECK-NEXT: 0x0 R_ARM_NONE - 0x0 +# CHECK-NEXT: 0x0 R_ARM_ALU_PC_G0 .data 0x0 +# CHECK-NEXT: 0x0 R_ARM_LDR_PC_G0 foo 0x0 +# CHECK-NEXT: 0x0 R_ARM_THM_ALU_PREL_11_0 - 0x0 # HEX: 0x00000000 00000000 00000000