[lld] [ELF] Add target-specific relocation scanning for RISC-V (PR #181332)

Jessica Clarke via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 5 06:37:06 PST 2026


================
@@ -356,29 +320,154 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
   // Many relocations end up in sec.relocations.
   sec.relocations.reserve(rels.size());
 
-  StringRef rvVendor;
+  StringRef vendor;
   for (auto it = rels.begin(); it != rels.end(); ++it) {
     RelType type = it->getType(false);
     uint32_t symIndex = it->getSymbol(false);
     Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex);
-    const uint8_t *loc = sec.content().data() + it->r_offset;
+    uint64_t offset = it->r_offset;
+    if (sym.isUndefined() && symIndex != 0 &&
+        rs.maybeReportUndefined(cast<Undefined>(sym), offset))
+      continue;
+    int64_t addend = rs.getAddend<ELFT>(*it, type);
+    RelExpr expr;
+    // Relocation types that only need a RelExpr set `expr` and break out of
+    // the switch to reach rs.process(). Types that need special handling
+    // (fast-path helpers, TLS) call a handler and use `continue`.
+    switch (type) {
+    case R_RISCV_NONE:
+      continue;
 
-    if (type == R_RISCV_VENDOR) {
-      if (!rvVendor.empty())
-        Err(ctx) << getErrorLoc(ctx, loc)
-                 << "malformed consecutive R_RISCV_VENDOR relocations";
-      rvVendor = sym.getName();
+    // Absolute relocations:
+    case R_RISCV_32:
+    case R_RISCV_64:
+    case R_RISCV_HI20:
+    case R_RISCV_LO12_I:
+    case R_RISCV_LO12_S:
+      expr = R_ABS;
+      break;
+
+    // PC-relative relocations:
+    case R_RISCV_JAL:
+    case R_RISCV_BRANCH:
+    case R_RISCV_PCREL_HI20:
+    case R_RISCV_RVC_BRANCH:
+    case R_RISCV_RVC_JUMP:
+    case R_RISCV_32_PCREL:
+      rs.processR_PC(type, offset, addend, sym);
       continue;
-    } else if (!rvVendor.empty()) {
-      Err(ctx) << getErrorLoc(ctx, loc)
-               << "unknown vendor-specific relocation (" << type.v
-               << ") in namespace '" << rvVendor << "' against symbol '" << &sym
-               << "'";
-      rvVendor = "";
+    case R_RISCV_PCREL_LO12_I:
+    case R_RISCV_PCREL_LO12_S:
+      expr = RE_RISCV_PC_INDIRECT;
+      break;
+
+    // PLT-generating relocations:
+    case R_RISCV_CALL:
+    case R_RISCV_CALL_PLT:
+    case R_RISCV_PLT32:
+      rs.processR_PLT_PC(type, offset, addend, sym);
       continue;
-    }
 
-    rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type));
+    // GOT-generating relocations:
+    case R_RISCV_GOT_HI20:
+    case R_RISCV_GOT32_PCREL:
+      expr = R_GOT_PC;
+      break;
+
+    // TLS relocations:
+    case R_RISCV_TPREL_HI20:
+    case R_RISCV_TPREL_LO12_I:
+    case R_RISCV_TPREL_LO12_S:
+      if (rs.checkTlsLe(offset, sym, type))
+        continue;
+      expr = R_TPREL;
+      break;
+    case R_RISCV_TLS_GOT_HI20:
+      // There is no IE to LE optimization.
+      sym.setFlags(NEEDS_TLSIE);
+      sec.addReloc({R_GOT_PC, type, offset, addend, &sym});
----------------
jrtc27 wrote:

Hm, seems handleTlsIe already exists; why not use that? enableIeToLe = false and ieExpr = R_GOT_PC should trivially be optimised to this, but avoid the duplication and lack of abstraction.

https://github.com/llvm/llvm-project/pull/181332


More information about the llvm-commits mailing list