diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp index da9ad4960ef41d..cf87106ec5a3df 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp @@ -380,6 +380,8 @@ void AVRAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, MutableArrayRef Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const { + if (Fixup.getKind() >= FirstLiteralRelocationKind) + return; adjustFixupValue(Fixup, Target, Value, &Asm.getContext()); if (Value == 0) return; // Doesn't change encoding. @@ -404,6 +406,21 @@ void AVRAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, } } +std::optional AVRAsmBackend::getFixupKind(StringRef Name) const { + unsigned Type; + Type = llvm::StringSwitch(Name) +#define ELF_RELOC(X, Y) .Case(#X, Y) +#include "llvm/BinaryFormat/ELFRelocs/AVR.def" +#undef ELF_RELOC + .Case("BFD_RELOC_NONE", ELF::R_AVR_NONE) + .Case("BFD_RELOC_16", ELF::R_AVR_16) + .Case("BFD_RELOC_32", ELF::R_AVR_32) + .Default(-1u); + if (Type != -1u) + return static_cast(FirstLiteralRelocationKind + Type); + return std::nullopt; +} + MCFixupKindInfo const &AVRAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { // NOTE: Many AVR fixups work on sets of non-contignous bits. We work around // this by saying that the fixup is the size of the entire instruction. @@ -463,6 +480,11 @@ MCFixupKindInfo const &AVRAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { {"fixup_port5", 3, 5, 0}, }; + // Fixup kinds from .reloc directive are like R_AVR_NONE. They do not require + // any extra processing. + if (Kind >= FirstLiteralRelocationKind) + return MCAsmBackend::getFixupKindInfo(FK_NONE); + if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); @@ -488,7 +510,7 @@ bool AVRAsmBackend::shouldForceRelocation(const MCAssembler &Asm, const MCValue &Target) { switch ((unsigned)Fixup.getKind()) { default: - return false; + return Fixup.getKind() >= FirstLiteralRelocationKind; // Fixups which should always be recorded as relocations. case AVR::fixup_7_pcrel: case AVR::fixup_13_pcrel: diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h index ea7fc30ab9d034..c4cb595f775a50 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h @@ -42,6 +42,7 @@ class AVRAsmBackend : public MCAsmBackend { uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const override; + std::optional getFixupKind(StringRef Name) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; unsigned getNumFixupKinds() const override { diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp index 850ddf0d94584c..d9a7a3addef3ab 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp @@ -37,6 +37,9 @@ AVRELFObjectWriter::AVRELFObjectWriter(uint8_t OSABI) unsigned AVRELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { + const unsigned Kind = Fixup.getTargetKind(); + if (Kind >= FirstLiteralRelocationKind) + return Kind - FirstLiteralRelocationKind; MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); switch ((unsigned)Fixup.getKind()) { case FK_Data_1: diff --git a/llvm/test/MC/AVR/reloc-directive-err.s b/llvm/test/MC/AVR/reloc-directive-err.s new file mode 100644 index 00000000000000..d660bde487e3ab --- /dev/null +++ b/llvm/test/MC/AVR/reloc-directive-err.s @@ -0,0 +1,10 @@ +# RUN: llvm-mc -triple=avr %s 2>&1 | FileCheck --check-prefix=PRINT %s +# RUN: not llvm-mc -filetype=obj -triple=avr %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 + +# PRINT: .reloc 0, BFD_RELOC_64, 0 +# CHECK: {{.*}}.s:[[#@LINE+1]]:11: error: unknown relocation name +.reloc 0, BFD_RELOC_64, 0 diff --git a/llvm/test/MC/AVR/reloc-directive.s b/llvm/test/MC/AVR/reloc-directive.s new file mode 100644 index 00000000000000..60913172502cf7 --- /dev/null +++ b/llvm/test/MC/AVR/reloc-directive.s @@ -0,0 +1,43 @@ +# RUN: llvm-mc -triple=avr %s | FileCheck --check-prefix=PRINT %s +# RUN: llvm-mc -filetype=obj -triple=avr %s | llvm-readobj -r - | FileCheck %s + +# PRINT: .reloc 4, R_AVR_NONE, .data +# PRINT-NEXT: .reloc 2, R_AVR_NONE, foo+4 +# PRINT-NEXT: .reloc 0, R_AVR_NONE, 8 +# PRINT: .reloc 0, R_AVR_32, .data+2 +# PRINT-NEXT: .reloc 0, R_AVR_16, foo+3 +# PRINT: .reloc 0, BFD_RELOC_NONE, 9 +# PRINT-NEXT: .reloc 0, BFD_RELOC_16, 9 +# PRINT-NEXT: .reloc 0, BFD_RELOC_32, 9 + +# CHECK: Section ({{.*}}) .rela.text { +# CHECK-NEXT: 0x4 R_AVR_NONE .data 0x0 +# CHECK-NEXT: 0x2 R_AVR_NONE foo 0x4 +# CHECK-NEXT: 0x0 R_AVR_NONE - 0x8 +# CHECK-NEXT: 0x0 R_AVR_32 .data 0x2 +# CHECK-NEXT: 0x0 R_AVR_16 foo 0x3 +# CHECK-NEXT: 0x0 R_AVR_NONE - 0x9 +# CHECK-NEXT: 0x0 R_AVR_16 - 0x9 +# CHECK-NEXT: 0x0 R_AVR_32 - 0x9 +# CHECK-NEXT: } + +.text + ret + nop + nop + .reloc 4, R_AVR_NONE, .data + .reloc 2, R_AVR_NONE, foo+4 + .reloc 0, R_AVR_NONE, 8 + + .reloc 0, R_AVR_32, .data+2 + .reloc 0, R_AVR_16, foo+3 + + .reloc 0, BFD_RELOC_NONE, 9 + .reloc 0, BFD_RELOC_16, 9 + .reloc 0, BFD_RELOC_32, 9 + +.data +.globl foo +foo: + .word 0 + .word 0