[llvm-branch-commits] [lld] 43299d5 - [lld][ELF] Deduplicate PC-relative indirect relocation logic for RISC-V and LoongArch (#176312)
Cullen Rhodes via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 22 00:27:59 PST 2026
Author: hev
Date: 2026-01-22T08:27:36Z
New Revision: 43299d52234bd98ca649329c49d513351c586b44
URL: https://github.com/llvm/llvm-project/commit/43299d52234bd98ca649329c49d513351c586b44
DIFF: https://github.com/llvm/llvm-project/commit/43299d52234bd98ca649329c49d513351c586b44.diff
LOG: [lld][ELF] Deduplicate PC-relative indirect relocation logic for RISC-V and LoongArch (#176312)
(cherry picked from commit 3af2e51eb91a96232efc4497059d5c6360cc094b)
Added:
Modified:
lld/ELF/InputSection.cpp
Removed:
################################################################################
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index a9afd3449ebb2..7402c8454c023 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -661,68 +661,41 @@ static uint64_t getARMStaticBase(const Symbol &sym) {
return os->ptLoad->firstSec->addr;
}
-// For RE_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually
-// points the corresponding R_RISCV_PCREL_HI20 relocation, and the target VA
-// is calculated using PCREL_HI20's symbol.
-//
-// This function returns the R_RISCV_PCREL_HI20 relocation from the
-// R_RISCV_PCREL_LO12 relocation.
-static Relocation *getRISCVPCRelHi20(Ctx &ctx, const InputSectionBase *loSec,
- const Relocation &loReloc) {
- uint64_t addend = loReloc.addend;
- Symbol *sym = loReloc.sym;
-
- const Defined *d = cast<Defined>(sym);
- if (!d->section) {
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_RISCV_PCREL_LO12 relocation points to an absolute symbol: "
- << sym->getName();
- return nullptr;
+struct RISCVPCRel {
+ static constexpr const char *loReloc = "R_RISCV_PCREL_LO12";
+ static constexpr const char *hiReloc = "R_RISCV_PCREL_HI20";
+
+ static bool isHiReloc(uint32_t type) {
+ return is_contained({R_RISCV_PCREL_HI20, R_RISCV_GOT_HI20,
+ R_RISCV_TLS_GD_HI20, R_RISCV_TLS_GOT_HI20},
+ type);
}
- InputSection *hiSec = cast<InputSection>(d->section);
-
- if (hiSec != loSec)
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_RISCV_PCREL_LO12 relocation points to a symbol '"
- << sym->getName() << "' in a
diff erent section '" << hiSec->name
- << "'";
-
- if (addend != 0)
- Warn(ctx) << loSec->getLocation(loReloc.offset)
- << ": non-zero addend in R_RISCV_PCREL_LO12 relocation to "
- << hiSec->getObjMsg(d->value) << " is ignored";
-
- // Relocations are sorted by offset, so we can use std::equal_range to do
- // binary search.
- Relocation hiReloc;
- hiReloc.offset = d->value;
- auto range =
- std::equal_range(hiSec->relocs().begin(), hiSec->relocs().end(), hiReloc,
- [](const Relocation &lhs, const Relocation &rhs) {
- return lhs.offset < rhs.offset;
- });
-
- for (auto it = range.first; it != range.second; ++it)
- if (it->type == R_RISCV_PCREL_HI20 || it->type == R_RISCV_GOT_HI20 ||
- it->type == R_RISCV_TLS_GD_HI20 || it->type == R_RISCV_TLS_GOT_HI20)
- return &*it;
-
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_RISCV_PCREL_LO12 relocation points to "
- << hiSec->getObjMsg(d->value)
- << " without an associated R_RISCV_PCREL_HI20 relocation";
- return nullptr;
-}
+};
+
+struct LoongArchPCAdd {
+ static constexpr const char *loReloc = "R_LARCH_*PCADD_LO12";
+ static constexpr const char *hiReloc = "R_LARCH_*PCADD_HI20";
+
+ static bool isHiReloc(uint32_t type) {
+ return is_contained({R_LARCH_PCADD_HI20, R_LARCH_GOT_PCADD_HI20,
+ R_LARCH_TLS_IE_PCADD_HI20, R_LARCH_TLS_LD_PCADD_HI20,
+ R_LARCH_TLS_GD_PCADD_HI20,
+ R_LARCH_TLS_DESC_PCADD_HI20},
+ type);
+ }
+};
-// For RE_LARCH_PC_INDIRECT (R_LARCH_*PCADD_LO12), the symbol actually points
-// the corresponding R_LARCH_*PCADD_HI20 relocation, and the target VA is
-// calculated using PCADD_HI20's symbol.
+// For PC-relative indirect relocations (e.g. R_RISCV_PCREL_LO12_* and
+// R_LARCH_*PCADD_LO12), the symbol referenced by the LO12 relocation does not
+// directly represent the final target address. Instead, it points to the
+// corresponding HI20 relocation, and the target VA is computed using the
+// symbol associated with that HI20 relocation.
//
-// This function returns the R_LARCH_*PCADD_HI20 relocation from the
-// R_LARCH_*PCADD_LO12 relocation.
-static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
- const InputSectionBase *loSec,
- const Relocation &loReloc) {
+// This helper locates and returns the matching HI20 relocation corresponding
+// to a given LO12 relocation.
+template <typename PCRel>
+static Relocation *getPCRelHi20(Ctx &ctx, const InputSectionBase *loSec,
+ const Relocation &loReloc) {
int64_t addend = loReloc.addend;
Symbol *sym = loReloc.sym;
@@ -733,25 +706,22 @@ static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
return nullptr;
}
if (!d->section) {
- Err(ctx)
- << loSec->getLocation(loReloc.offset)
- << ": R_LARCH_*PCADD_LO12 relocation points to an absolute symbol: "
- << sym->getName();
+ Err(ctx) << loSec->getLocation(loReloc.offset) << ": " << PCRel::loReloc
+ << " relocation points to an absolute symbol: " << sym->getName();
return nullptr;
}
InputSection *hiSec = cast<InputSection>(d->section);
if (hiSec != loSec) {
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_LARCH_*PCADD_LO12 relocation points to a symbol '"
- << sym->getName() << "' in a
diff erent section '" << hiSec->name
- << "'";
+ Err(ctx) << loSec->getLocation(loReloc.offset) << ": " << PCRel::loReloc
+ << " relocation points to a symbol '" << sym->getName()
+ << "' in a
diff erent section '" << hiSec->name << "'";
return nullptr;
}
if (addend != 0)
- Warn(ctx) << loSec->getLocation(loReloc.offset)
- << ": non-zero addend in R_LARCH_*PCADD_LO12 relocation to "
+ Warn(ctx) << loSec->getLocation(loReloc.offset) << ": non-zero addend in "
+ << PCRel::loReloc << " relocation to "
<< hiSec->getObjMsg(d->value) << " is ignored";
// Relocations are sorted by offset, so we can use std::equal_range to do
@@ -765,17 +735,12 @@ static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
});
for (auto it = range.first; it != range.second; ++it)
- if (it->type == R_LARCH_PCADD_HI20 || it->type == R_LARCH_GOT_PCADD_HI20 ||
- it->type == R_LARCH_TLS_IE_PCADD_HI20 ||
- it->type == R_LARCH_TLS_LD_PCADD_HI20 ||
- it->type == R_LARCH_TLS_GD_PCADD_HI20 ||
- it->type == R_LARCH_TLS_DESC_PCADD_HI20)
+ if (PCRel::isHiReloc(it->type))
return &*it;
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_LARCH_*PCADD_LO12 relocation points to "
- << hiSec->getObjMsg(d->value)
- << " without an associated R_LARCH_*PCADD_HI20 relocation";
+ Err(ctx) << loSec->getLocation(loReloc.offset) << ": " << PCRel::loReloc
+ << " relocation points to " << hiSec->getObjMsg(d->value)
+ << " without an associated " << PCRel::hiReloc << " relocation";
return nullptr;
}
@@ -954,12 +919,12 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
return getAArch64Page(val) - getAArch64Page(p);
}
case RE_RISCV_PC_INDIRECT: {
- if (const Relocation *hiRel = getRISCVPCRelHi20(ctx, this, r))
+ if (const Relocation *hiRel = getPCRelHi20<RISCVPCRel>(ctx, this, r))
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx));
return 0;
}
case RE_LOONGARCH_PC_INDIRECT: {
- if (const Relocation *hiRel = getLoongArchPCAddHi20(ctx, this, r))
+ if (const Relocation *hiRel = getPCRelHi20<LoongArchPCAdd>(ctx, this, r))
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx, a));
return 0;
}
More information about the llvm-branch-commits
mailing list