diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -97,47 +97,9 @@ return RISCV::NumTargetFixupKinds; } - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { - const static MCFixupKindInfo Infos[] = { - // This table *must* be in the order that the fixup_* kinds are defined in - // RISCVFixupKinds.h. - // - // name offset bits flags - { "fixup_riscv_hi20", 12, 20, 0 }, - { "fixup_riscv_lo12_i", 20, 12, 0 }, - { "fixup_riscv_lo12_s", 0, 32, 0 }, - { "fixup_riscv_pcrel_hi20", 12, 20, - MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget }, - { "fixup_riscv_pcrel_lo12_i", 20, 12, - MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget }, - { "fixup_riscv_pcrel_lo12_s", 0, 32, - MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget }, - { "fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_tprel_hi20", 12, 20, 0 }, - { "fixup_riscv_tprel_lo12_i", 20, 12, 0 }, - { "fixup_riscv_tprel_lo12_s", 0, 32, 0 }, - { "fixup_riscv_tprel_add", 0, 0, 0 }, - { "fixup_riscv_tls_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_tls_gd_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_riscv_relax", 0, 0, 0 }, - { "fixup_riscv_align", 0, 0, 0 } - }; - static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds, - "Not all fixup kinds added to Infos array"); - - if (Kind < FirstTargetFixupKind) - return MCAsmBackend::getFixupKindInfo(Kind); - - assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && - "Invalid kind!"); - return Infos[Kind - FirstTargetFixupKind]; - } + Optional getFixupKind(StringRef Name) const override; + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -23,12 +23,75 @@ using namespace llvm; +Optional RISCVAsmBackend::getFixupKind(StringRef Name) const { + if (STI.getTargetTriple().isOSBinFormatELF()) { + unsigned Type; + Type = llvm::StringSwitch(Name) +#define ELF_RELOC(X, Y) .Case(#X, Y) +#include "llvm/BinaryFormat/ELFRelocs/RISCV.def" +#undef ELF_RELOC + .Default(-1u); + if (Type != -1u) + return static_cast(FirstLiteralRelocationKind + Type); + } + return None; +} + +const MCFixupKindInfo & +RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[] = { + // This table *must* be in the order that the fixup_* kinds are defined in + // RISCVFixupKinds.h. + // + // name offset bits flags + {"fixup_riscv_hi20", 12, 20, 0}, + {"fixup_riscv_lo12_i", 20, 12, 0}, + {"fixup_riscv_lo12_s", 0, 32, 0}, + {"fixup_riscv_pcrel_hi20", 12, 20, + MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget}, + {"fixup_riscv_pcrel_lo12_i", 20, 12, + MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget}, + {"fixup_riscv_pcrel_lo12_s", 0, 32, + MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget}, + {"fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_tprel_hi20", 12, 20, 0}, + {"fixup_riscv_tprel_lo12_i", 20, 12, 0}, + {"fixup_riscv_tprel_lo12_s", 0, 32, 0}, + {"fixup_riscv_tprel_add", 0, 0, 0}, + {"fixup_riscv_tls_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_tls_gd_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel}, + {"fixup_riscv_relax", 0, 0, 0}, + {"fixup_riscv_align", 0, 0, 0}}; + static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds, + "Not all fixup kinds added to Infos array"); + + // Fixup kinds from .reloc directive are like R_RISCV_NONE. They + // do not require any extra processing. + if (Kind >= FirstLiteralRelocationKind) + return MCAsmBackend::getFixupKindInfo(FK_NONE); + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + return Infos[Kind - FirstTargetFixupKind]; +} + // If linker relaxation is enabled, or the relax option had previously been // enabled, always emit relocations even if the fixup can be resolved. This is // necessary for correctness as offsets may change during relaxation. bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) { + if (Fixup.getKind() >= FirstLiteralRelocationKind) + return true; switch (Fixup.getTargetKind()) { default: break; @@ -318,8 +381,11 @@ MutableArrayRef Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const { + MCFixupKind Kind = Fixup.getKind(); + if (Kind >= FirstLiteralRelocationKind) + return; MCContext &Ctx = Asm.getContext(); - MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); + MCFixupKindInfo Info = getFixupKindInfo(Kind); if (!Value) return; // Doesn't change encoding. // Apply any target-specific value adjustments. diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -52,6 +52,8 @@ const MCExpr *Expr = Fixup.getValue(); // Determine the type of the relocation unsigned Kind = Fixup.getTargetKind(); + if (Kind >= FirstLiteralRelocationKind) + return Kind - FirstLiteralRelocationKind; if (IsPCRel) { switch (Kind) { default: diff --git a/llvm/test/MC/RISCV/reloc-directive-err.s b/llvm/test/MC/RISCV/reloc-directive-err.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/reloc-directive-err.s @@ -0,0 +1,6 @@ +# RUN: llvm-mc -triple=riscv64 %s 2>&1 | FileCheck --check-prefix=PRINT %s +# RUN: not llvm-mc -filetype=obj -triple=riscv64 %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/RISCV/reloc-directive.s b/llvm/test/MC/RISCV/reloc-directive.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/reloc-directive.s @@ -0,0 +1,36 @@ +# RUN: llvm-mc -triple=riscv32 %s | FileCheck --check-prefix=PRINT %s +# RUN: llvm-mc -triple=riscv64 %s | FileCheck --check-prefix=PRINT %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 %s | llvm-readobj -r | FileCheck %s +# RUN: llvm-mc -filetype=obj -triple=riscv64 %s | llvm-readobj -r | FileCheck %s + +# PRINT: .reloc 8, R_RISCV_NONE, .data +# PRINT: .reloc 4, R_RISCV_NONE, foo+4 +# PRINT: .reloc 0, R_RISCV_NONE, 8 +# PRINT: .reloc 0, R_RISCV_32, .data+2 +# PRINT: .reloc 0, R_RISCV_SET32, foo+3 +# PRINT: .reloc 0, R_RISCV_32_PCREL, 5 + +# CHECK: 0x8 R_RISCV_NONE .data 0x0 +# CHECK-NEXT: 0x4 R_RISCV_NONE foo 0x4 +# CHECK-NEXT: 0x0 R_RISCV_NONE - 0x8 +# CHECK-NEXT: 0x0 R_RISCV_32 .data 0x2 +# CHECK-NEXT: 0x0 R_RISCV_SET32 foo 0x3 +# CHECK-NEXT: 0x0 R_RISCV_32_PCREL - 0x5 +.text + ret + nop + nop + .reloc 8, R_RISCV_NONE, .data + .reloc 4, R_RISCV_NONE, foo+4 + .reloc 0, R_RISCV_NONE, 8 + + .reloc 0, R_RISCV_32, .data+2 + .reloc 0, R_RISCV_SET32, foo+3 + .reloc 0, R_RISCV_32_PCREL, 5 + +.data +.globl foo +foo: + .word 0 + .word 0 + .word 0