Skip to content

[RISCV] Vendor Relocations for Xqci extension #135400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

svs-quic
Copy link
Contributor

@svs-quic svs-quic commented Apr 11, 2025

This patch implements vendor relocation support for RISC-V, starting with the Xqci extensions.

This is done by re-organising RISCVAsmBackend::evaluateTargetFixup, to also handle emitting the vendor relocation when the fixup is unresolved.

An extra parameter bool RecordReloc is added to evaluateTargetFixup, so that the relocation is only emitted when it should be, as evaluateTargetFixup works the same way.

This adds tests showing resolveable and unresolvable symbols for the xqci fixups (some of which are absolute and some of which are pc-relative), including tests when relaxation is enabled which forces relocations that might otherwise not be needed.

@llvmbot llvmbot added backend:RISC-V mc Machine (object) code labels Apr 11, 2025
@svs-quic svs-quic requested review from topperc, pgodeq and hchandel April 11, 2025 16:40
@llvmbot
Copy link
Member

llvmbot commented Apr 11, 2025

@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-mc

Author: Sudharsan Veeravalli (svs-quic)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/135400.diff

7 Files Affected:

  • (modified) llvm/include/llvm/MC/MCAsmBackend.h (+12)
  • (modified) llvm/lib/MC/ELFObjectWriter.cpp (+15)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (+27)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h (+6)
  • (modified) llvm/test/MC/RISCV/xqcibi-relocations.s (+14)
  • (modified) llvm/test/MC/RISCV/xqcilb-relocations.s (+11)
  • (modified) llvm/test/MC/RISCV/xqcili-relocations.s (+9)
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@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@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
 

@svs-quic svs-quic requested a review from lenary April 11, 2025 16:40
@lenary lenary requested a review from MaskRay April 11, 2025 18:30
@lenary
Copy link
Member

lenary commented Apr 11, 2025

@MaskRay I've tagged you in the review because this hits target-independent MC code. We weren't sure of a better way to accomplish what is needed for the RISC-V R_RISCV_VENDOR relocations. We didn't want a separate fixup (as for Relaxation) because we didn't want to emit the R_RISCV_VENDOR relocation if the fixup could be evaluated/applied by the compiler, and that kind of "evaluating one fixup deletes another fixup" seemed complex and error-prone. Hopefully you find our approach reasonable.

There is linker support for these relocations, in https://github.com/qualcomm/eld - which requires the R_RISCV_VENDOR relocations - but it does look like the tests are missing from this repo.

@lenary
Copy link
Member

lenary commented Apr 11, 2025

Tests for the eld implementation are here: qualcomm/eld#16

unsigned PreRelocType;
MCSymbol *PreRelocSymbol;
uint64_t PreRelocAddend;
if (Backend.fixupNeedsMarkerELFRelocation(Asm, *Fragment, Fixup, PreRelocType,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(MCAssembler.cpp and ELFObjectWriter.cpp have significant tech debt. I try to clean up them from time to time. Just noticed that my latest change 19730e3 might need you to rebase.)

I think we should refrain from adding new hooks. (I added Backend.handleAddSubRelocations in the past, and on reflection we might need some cleanup so that it could be combined with getRelocType).

Can you add an extra fixup when fixup_riscv_qc_e_branch is appended? Or the hook is here because in some scenarios the fixup can be resolved and you don't want to add a redundant marker?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should refrain from adding new hooks.

I do too, but "refrain from" doesn't mean "never". We could not find another way to accomplish this.

Or the hook is here because in some scenarios the fixup can be resolved and you don't want to add a redundant marker?

This. For instance, branches can be evaluated when not relaxing.

From my comment, above:

We didn't want a separate fixup (as for Relaxation) because we didn't want to emit the R_RISCV_VENDOR relocation if the fixup could be evaluated/applied by the compiler, and that kind of "evaluating one fixup deletes another fixup" seemed complex and error-prone.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could customize evaluateTargetFixup. If the fixup is not resolved, call recordRelocation to append the marker relocation, and then rely on the default recordRelocation in evaluateFixup to append the actual relocation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into this, and evaluateTargetFixup doesn't get any info about the fixup being resolved (the info comes from this function when the IsTarget fixup flag is given) - to work this way we'd need to pass more information into this function (the RecordReloc bool), and replicate lots of the logic in evaluateFixup which is bypassed if you have the IsTarget fixup flag.

With all this in mind, I continue to think that the new hook is the best way to achieve vendor relocations for RISC-V.

I realise you've been away recently (me too), I'm happy to discuss this further when you're back.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MaskRay Ping?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixupNeedsMarkerELFRelocation adds unneeded overhead to almost all relocations for most targets.

I still believe evaluateTargetFixup is the best way to add another relocation. Could you demonstrate the change you'd need if we don't use fixupNeedsMarkerELFRelocation?

It's acceptable to pass more args (like RecordReloc) to evaluateTargetFixup, a slow path.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made the change, and commented about the duplicated code, which I don't like having to copy-paste. There is also complex logic working out when IsResolved might not be enough of a signal that a relocation is required, especially as RISC-V forces relocations during relaxation (which is also hard to test).

Copy link
Member

@MaskRay MaskRay May 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cc @jrtc27 who introduced evaluateTargetFixup

Currently, the MCFixupKindInfo::FKF_IsTarget code path in MCAssembler.cpp skips the common code paths (getAddSym/getSubSym), because PCREL_LO12[IS] don't need them.

Now evaluateTargetFixup is reused by QUIC relocations, leading to some duplication. I think we can make evaluateTargetFixup return more information so that QUIC relocations keep reusing the common code path.

// MCAssembler.cpp
  if (FixupFlags & MCFixupKindInfo::FKF_IsTarget) {
    IsResolved =
        getBackend().evaluateTargetFixup(*this, Fixup, DF, Target, STI, Value);
  } else {
    // QUIC relocations should reuse this code path while PCREL_LO12[IS] skip it.
    const MCSymbol *Add = Target.getAddSym(); 7 refs
    const MCSymbol *Sub = Target.getSubSym();

The latter half of the duplication that adds a R_RISCV_VENDOR relocation can probably be refactored to reuse Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

evaluteTargetFixup did exactly what was needed at the time and nothing more. If there are cases now where more of the surrounding code needs reusing then coming up with a way to communicate that seems perfectly reasonable to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've refactored the relocation generation further. There is now an addReloc hook and #140494 demonstrates how to add two relocations from one fixup. For VENDOR, we just need to call .recordRelocation for a specific fixup kind.

@lenary lenary requested a review from tclin914 April 29, 2025 05:51
@lenary
Copy link
Member

lenary commented Apr 29, 2025

@tclin914 I've tagged you because you'll likely want this functionality for the andes extension with relocations, and it would be good to avoid duplicating this work.

# Check that we print the correct relocations in exact mode
.option exact
qc.e.bgeui x8, 12, foo
# RELOC: R_RISCV_VENDOR QUALCOMM 0x0
Copy link
Member

@MaskRay MaskRay May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For relocation generation testing we should use llvm-objdump -dr to test r_offset and test that we don't incorrectly emit redundant relocations. See Sparc/Relocations/relocation-specifier.s for a modern example using llvm-objdump -dr

Looks like R_RISCV_VENDOR is only generated with exact. We should test that without exact there is no QUALCOMM. This is unclear from the PR description.

FIXUP from -show-encoding output is not really useful for relocations. Just remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QUALCOMM should be emitted even without exact, we have started to use exact to avoid instruction compression happening and make testing more specific.

I will move to objdump -dr, I agree it's often clearer. I will revisit these tests.

@resistor
Copy link
Collaborator

Just wanted to note that we (CHERI, and specifically CHERIoT) are very interested in seeing R_RISCV_VENDOR support landed. Is this still moving ahead?

@lenary
Copy link
Member

lenary commented May 16, 2025

@resistor I'm going to try to make some more progress on this today.

This patch implements vendor relocation support for RISC-V, starting
with the Xqci extensions.

This is done by re-organising `RISCVAsmBackend::evaluateTargetFixup`, to
also handle emitting the vendor relocation when the fixup is unresolved.

An extra parameter `bool RecordReloc` is added to `evaluateTargetFixup`,
so that the relocation is only emitted when it should be, as
`evaluateTargetFixup` works the same way.

This adds tests showing resolveable and unresolvable symbols for the
xqci fixups (some of which are absolute and some of which are
pc-relative), including tests when relaxation is enabled which forces
relocations that might otherwise not be needed.

Co-authored-by: Sudharsan Veeravalli <quic_svs@quicinc.com>
@lenary lenary changed the title [RISCV] Add support for vendor relocations on Xqci extensions [RISCV] Vendor Relocations for Xqci extension May 16, 2025
Copy link

github-actions bot commented May 16, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@lenary lenary removed their request for review May 17, 2025 01:46

.text
## This test checks that we emit the right relocations for Xqcilb
## relative jumps. These can be resolved within the same section
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be resolved within the same section and the destination symbol is local?

Otherwise I think there will be a relocation as well. (We also emit a relocation when the destination is a gnu ifunc symbol, which is an edge case that we don't necessarily describe).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think these always need a relocation. I forgot these are to the PLT, was just focussed on them being pc-relative.

I don't think I found the LLVM code to always emit the relocation (that I expect for call_plt), i will look over it all again.

cast<MCSymbolELF>(Ctx.createLocalSymbol(VendorIdentifier));

// Vendor Symbols are Absolute, Local, NOTYPE.
VendorSymbol->setType(ELF::STT_NOTYPE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The symbol is by default NOTYPE and LOCAL. In the rare scenario that the users changes the type/binding, we should respect that.

So setType/setBinding should be omitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants