Skip to content

Commit 78f39dc

Browse files
authored
[JITLink][RISCV] Use hashmap to find PCREL_HI20 edge (#78849)
As noted in issues #68594 and #73935, `JITLink/RISCV/ELF_ehframe.s` fails with libstdc++'s expensive checks because `getRISCVPCRelHi20` calls `std::equal_range` on the edges which may not be ordered by their offset. Instead let `ELFJITLinker_riscv` build a hashmap of all edges with type `R_RISCV_PCREL_HI20` that can be looked up in constant time. Closes #73935
1 parent dbe4143 commit 78f39dc

File tree

1 file changed

+35
-33
lines changed

1 file changed

+35
-33
lines changed

llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -133,38 +133,6 @@ const uint8_t
133133
namespace llvm {
134134
namespace jitlink {
135135

136-
static Expected<const Edge &> getRISCVPCRelHi20(const Edge &E) {
137-
using namespace riscv;
138-
assert((E.getKind() == R_RISCV_PCREL_LO12_I ||
139-
E.getKind() == R_RISCV_PCREL_LO12_S) &&
140-
"Can only have high relocation for R_RISCV_PCREL_LO12_I or "
141-
"R_RISCV_PCREL_LO12_S");
142-
143-
const Symbol &Sym = E.getTarget();
144-
const Block &B = Sym.getBlock();
145-
orc::ExecutorAddrDiff Offset = Sym.getOffset();
146-
147-
struct Comp {
148-
bool operator()(const Edge &Lhs, orc::ExecutorAddrDiff Offset) {
149-
return Lhs.getOffset() < Offset;
150-
}
151-
bool operator()(orc::ExecutorAddrDiff Offset, const Edge &Rhs) {
152-
return Offset < Rhs.getOffset();
153-
}
154-
};
155-
156-
auto Bound =
157-
std::equal_range(B.edges().begin(), B.edges().end(), Offset, Comp{});
158-
159-
for (auto It = Bound.first; It != Bound.second; ++It) {
160-
if (It->getKind() == R_RISCV_PCREL_HI20)
161-
return *It;
162-
}
163-
164-
return make_error<JITLinkError>(
165-
"No HI20 PCREL relocation type be found for LO12 PCREL relocation type");
166-
}
167-
168136
static uint32_t extractBits(uint32_t Num, unsigned Low, unsigned Size) {
169137
return (Num & (((1ULL << Size) - 1) << Low)) >> Low;
170138
}
@@ -184,9 +152,43 @@ class ELFJITLinker_riscv : public JITLinker<ELFJITLinker_riscv> {
184152
public:
185153
ELFJITLinker_riscv(std::unique_ptr<JITLinkContext> Ctx,
186154
std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
187-
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
155+
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
156+
JITLinkerBase::getPassConfig().PostAllocationPasses.push_back(
157+
[this](LinkGraph &G) { return gatherRISCVPCRelHi20(G); });
158+
}
188159

189160
private:
161+
DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *>
162+
RelHi20;
163+
164+
Error gatherRISCVPCRelHi20(LinkGraph &G) {
165+
for (Block *B : G.blocks())
166+
for (Edge &E : B->edges())
167+
if (E.getKind() == R_RISCV_PCREL_HI20)
168+
RelHi20[{B, E.getOffset()}] = &E;
169+
170+
return Error::success();
171+
}
172+
173+
Expected<const Edge &> getRISCVPCRelHi20(const Edge &E) const {
174+
using namespace riscv;
175+
assert((E.getKind() == R_RISCV_PCREL_LO12_I ||
176+
E.getKind() == R_RISCV_PCREL_LO12_S) &&
177+
"Can only have high relocation for R_RISCV_PCREL_LO12_I or "
178+
"R_RISCV_PCREL_LO12_S");
179+
180+
const Symbol &Sym = E.getTarget();
181+
const Block &B = Sym.getBlock();
182+
orc::ExecutorAddrDiff Offset = Sym.getOffset();
183+
184+
auto It = RelHi20.find({&B, Offset});
185+
if (It != RelHi20.end())
186+
return *It->second;
187+
188+
return make_error<JITLinkError>("No HI20 PCREL relocation type be found "
189+
"for LO12 PCREL relocation type");
190+
}
191+
190192
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
191193
using namespace riscv;
192194
using namespace llvm::support;

0 commit comments

Comments
 (0)