[llvm] [RISCV] Add support for vendor relocations on Xqci extensions (PR #135400)
Sudharsan Veeravalli via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 11 09:40:18 PDT 2025
https://github.com/svs-quic created https://github.com/llvm/llvm-project/pull/135400
This patch adds support for vendor relocations on Qualcomm uC Xqci instructions.
It adds a new fixupNeedsMarkerELFRelocation function that targets can override to add any marker relocations in the ELF object.
The psabi doc describes the vendor relocations here https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#nonstandard-relocations-aka-vendor-specific-relocations
> These vendor-specific relocations must be preceded by a R_RISCV_VENDOR relocation against a vendor identifier symbol. The preceding R_RISCV_VENDOR relocation is used by the linker to choose the correct implementation for the associated nonstandard relocation.
>
> The vendor identifier symbol should be a defined symbol and should set the type to STT_NOTYPE, binding to STB_LOCAL, and the size of symbol to zero.
>From e014feb21d975acb8f22bc06c9e576128016d687 Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Fri, 11 Apr 2025 21:51:14 +0530
Subject: [PATCH] [RISCV] Add support for vendor relocations on Xqci extensions
This patch adds support for vendor relocations on Xqcixx instructions.
---
llvm/include/llvm/MC/MCAsmBackend.h | 12 +++++++++
llvm/lib/MC/ELFObjectWriter.cpp | 15 +++++++++++
.../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 27 +++++++++++++++++++
.../RISCV/MCTargetDesc/RISCVAsmBackend.h | 6 +++++
llvm/test/MC/RISCV/xqcibi-relocations.s | 14 ++++++++++
llvm/test/MC/RISCV/xqcilb-relocations.s | 11 ++++++++
llvm/test/MC/RISCV/xqcili-relocations.s | 9 +++++++
7 files changed, 94 insertions(+)
diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h
index 5953de30c2eb2..fcc67afdc6fc5 100644
--- a/llvm/include/llvm/MC/MCAsmBackend.h
+++ b/llvm/include/llvm/MC/MCAsmBackend.h
@@ -125,6 +125,18 @@ class MCAsmBackend {
return false;
}
+ /// Hook to add any marker relocations that the target may need in addition
+ /// to the normal relocations on instructions. Currently used only by RISCV
+ /// to add vendor relocations.
+ virtual bool fixupNeedsMarkerELFRelocation(MCAssembler &Asm,
+ const MCFragment &F,
+ const MCFixup &Fixup,
+ unsigned &PreRelocType,
+ MCSymbol *&PreRelocSymbol,
+ uint64_t &PreRelocAddend) const {
+ return false;
+ }
+
/// Apply the \p Value for given \p Fixup into the provided data fragment, at
/// the offset specified by the fixup and following the fixup kind as
/// appropriate. Errors (such as an out of range fixup value) should be
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 23d5517920e7b..426937ee415bd 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -1435,6 +1435,21 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
: C;
FixedValue = usesRela(TO, FixupSection) ? 0 : Addend;
+ // Some RISC-V relocations need a marker relocation that appears before the
+ // relocation in question.
+ unsigned PreRelocType;
+ MCSymbol *PreRelocSymbol;
+ uint64_t PreRelocAddend;
+ if (Backend.fixupNeedsMarkerELFRelocation(Asm, *Fragment, Fixup, PreRelocType,
+ PreRelocSymbol, PreRelocAddend)) {
+ auto *SymbolELF = cast<MCSymbolELF>(PreRelocSymbol);
+ if (SymbolELF)
+ SymbolELF->setUsedInReloc();
+ ELFRelocationEntry Rec(FixupOffset, SymbolELF, PreRelocType,
+ PreRelocAddend);
+ Relocations[&FixupSection].push_back(Rec);
+ }
+
if (!RelocateWithSymbol) {
const auto *SectionSymbol =
SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 49c8c6957aa34..bbcb84ea78566 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -702,6 +702,33 @@ bool RISCVAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
return true;
}
+bool RISCVAsmBackend::fixupNeedsMarkerELFRelocation(
+ MCAssembler &Asm, const MCFragment &F, const MCFixup &Fixup,
+ unsigned &PreRelocType, MCSymbol *&PreRelocSymbol,
+ uint64_t &PreRelocAddend) const {
+ switch (Fixup.getTargetKind()) {
+ default:
+ return false;
+ case RISCV::fixup_riscv_qc_e_branch:
+ case RISCV::fixup_riscv_qc_e_32:
+ case RISCV::fixup_riscv_qc_abs20_u:
+ case RISCV::fixup_riscv_qc_e_jump_plt: {
+ MCContext &Ctx = Asm.getContext();
+ MCSymbol *VendorSymbol = Ctx.getOrCreateSymbol("QUALCOMM");
+ MCFragment &DF = F.getParent()->getDummyFragment();
+ VendorSymbol->setFragment(&DF);
+ VendorSymbol->setOffset(0);
+
+ Asm.registerSymbol(*VendorSymbol);
+
+ PreRelocType = ELF::R_RISCV_VENDOR;
+ PreRelocSymbol = VendorSymbol;
+ PreRelocAddend = 0;
+ return true;
+ }
+ }
+}
+
void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
index f5e8d340d9bce..9076074987a37 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
@@ -56,6 +56,12 @@ class RISCVAsmBackend : public MCAsmBackend {
const MCFixup &Fixup, const MCValue &Target,
uint64_t &FixedValue) const override;
+ bool fixupNeedsMarkerELFRelocation(MCAssembler &Asm, const MCFragment &F,
+ const MCFixup &Fixup,
+ unsigned &PreRelocType,
+ MCSymbol *&PreRelocSymbol,
+ uint64_t &PreRelocAddend) const override;
+
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsResolved,
diff --git a/llvm/test/MC/RISCV/xqcibi-relocations.s b/llvm/test/MC/RISCV/xqcibi-relocations.s
index 7028e8a737c86..a0ab7a450349d 100644
--- a/llvm/test/MC/RISCV/xqcibi-relocations.s
+++ b/llvm/test/MC/RISCV/xqcibi-relocations.s
@@ -2,11 +2,13 @@
# RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi %s -o %t.o
# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOC %s
+# RUN: llvm-readelf -s %t.o | FileCheck -check-prefix=VENDORSYM %s
# Check prefixes:
# RELOC - Check the relocation in the object.
# FIXUP - Check the fixup on the instruction.
# INSTR - Check the instruction is handled properly by the ASMPrinter.
+# VENDORSYM - Check the vendor symbol.
.text
@@ -22,6 +24,15 @@ qc.e.bgeui x8, 12, foo
# INSTR: qc.e.bgeui s0, 12, foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_branch
+# Check that we print the correct relocations in exact mode
+.option exact
+qc.e.bgeui x8, 12, foo
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
+# RELOC: R_RISCV_CUSTOM193 foo 0x0
+# INSTR: qc.e.bgeui s0, 12, foo
+# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_branch
+.option noexact
+
# Check that a label in a different section is handled similar to an undefined
# symbol and gets relaxed to (qc.e.bgeui + jal)
qc.e.bltui x4, 9, .bar
@@ -34,6 +45,9 @@ qc.e.beqi x7, 8, .L1
# INSTR: qc.e.beqi t2, 8, .L1
# FIXUP: fixup A - offset: 0, value: .L1, kind: fixup_riscv_qc_e_branch
+# Check that there is only one vendor symbol created and that it is local and NOTYPE
+# VENDORSYM-COUNT-1: 00000000 0 NOTYPE LOCAL DEFAULT 2 QUALCOMM
+
.L1:
ret
diff --git a/llvm/test/MC/RISCV/xqcilb-relocations.s b/llvm/test/MC/RISCV/xqcilb-relocations.s
index a475cde3f6bfd..f9787df352f36 100644
--- a/llvm/test/MC/RISCV/xqcilb-relocations.s
+++ b/llvm/test/MC/RISCV/xqcilb-relocations.s
@@ -2,41 +2,49 @@
# RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilb %s -o %t.o
# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOC %s
+# RUN: llvm-readelf -s %t.o | FileCheck -check-prefix=VENDORSYM %s
# Check prefixes:
# RELOC - Check the relocation in the object.
# FIXUP - Check the fixup on the instruction.
# INSTR - Check the instruction is handled properly by the ASMPrinter.
+# VENDORSYM - Check the vendor symbol.
.text
qc.e.j foo
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM195 foo 0x0
# INSTR: qc.e.j foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_jump_plt
qc.e.j foo at plt
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM195 foo 0x0
# INSTR: qc.e.j foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_jump_plt
qc.e.jal foo at plt
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM195 foo 0x0
# INSTR: qc.e.jal foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_jump_plt
qc.e.jal foo
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM195 foo 0x0
# INSTR: qc.e.jal foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_jump_plt
# Check that a label in a different section is handled similar to an undefined symbol
qc.e.j .bar
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM195 .bar 0x0
# INSTR: qc.e.j .bar
# FIXUP: fixup A - offset: 0, value: .bar, kind: fixup_riscv_qc_e_jump_plt
qc.e.jal .bar
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM195 .bar 0x0
# INSTR: qc.e.jal .bar
# FIXUP: fixup A - offset: 0, value: .bar, kind: fixup_riscv_qc_e_jump_plt
@@ -50,6 +58,9 @@ qc.e.jal .L1
# INSTR:qc.e.jal .L1
# FIXUP: fixup A - offset: 0, value: .L1, kind: fixup_riscv_qc_e_jump_plt
+# Check that there is only one vendor symbol created and that it is local and NOTYPE
+# VENDORSYM-COUNT-1: 00000000 0 NOTYPE LOCAL DEFAULT 2 QUALCOMM
+
.L1:
ret
diff --git a/llvm/test/MC/RISCV/xqcili-relocations.s b/llvm/test/MC/RISCV/xqcili-relocations.s
index b0a3f3bae11d5..b7ed8fedb35f8 100644
--- a/llvm/test/MC/RISCV/xqcili-relocations.s
+++ b/llvm/test/MC/RISCV/xqcili-relocations.s
@@ -2,31 +2,37 @@
# RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcili %s -o %t.o
# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOC %s
+# RUN: llvm-readelf -s %t.o | FileCheck -check-prefix=VENDORSYM %s
# Check prefixes:
# RELOC - Check the relocation in the object.
# FIXUP - Check the fixup on the instruction.
# INSTR - Check the instruction is handled properly by the ASMPrinter.
+# VENDORSYM - Check the vendor symbol.
.text
qc.li x4, %qc.abs20(foo)
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM192 foo 0x0
# INSTR: qc.li tp, %qc.abs20(foo)
# FIXUP: fixup A - offset: 0, value: %qc.abs20(foo), kind: fixup_riscv_qc_abs20_u
qc.e.li x5, foo
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM194 foo 0x0
# INSTR: qc.e.li t0, foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_32
# Check that a label in a different section is handled similar to an undefined symbol
qc.li x9, %qc.abs20(.bar)
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM192 .bar 0x0
# INSTR: qc.li s1, %qc.abs20(.bar)
# FIXUP: fixup A - offset: 0, value: %qc.abs20(.bar), kind: fixup_riscv_qc_abs20_u
qc.e.li x8, .bar
+# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
# RELOC: R_RISCV_CUSTOM194 .bar 0x0
# INSTR: qc.e.li s0, .bar
# FIXUP: fixup A - offset: 0, value: .bar, kind: fixup_riscv_qc_e_32
@@ -40,6 +46,9 @@ qc.e.li x6, .L1
# INSTR: qc.e.li t1, .L1
# FIXUP: fixup A - offset: 0, value: .L1, kind: fixup_riscv_qc_e_32
+# Check that there is only one vendor symbol created and that it is local and NOTYPE
+# VENDORSYM-COUNT-1: 00000000 0 NOTYPE LOCAL DEFAULT 2 QUALCOMM
+
.L1:
ret
More information about the llvm-commits
mailing list