From b24c432c7efc837fb5747c90bbfcb3c02bdd946c Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Sat, 20 Jan 2024 15:52:09 +0100 Subject: [PATCH] [JITLink][RISCV] Use hashmap to find PCREL_HI20 edge 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. --- .../lib/ExecutionEngine/JITLink/ELF_riscv.cpp | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp index d0701ba08bd91..627f186ca5914 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -133,38 +133,6 @@ const uint8_t namespace llvm { namespace jitlink { -static Expected getRISCVPCRelHi20(const Edge &E) { - using namespace riscv; - assert((E.getKind() == R_RISCV_PCREL_LO12_I || - E.getKind() == R_RISCV_PCREL_LO12_S) && - "Can only have high relocation for R_RISCV_PCREL_LO12_I or " - "R_RISCV_PCREL_LO12_S"); - - const Symbol &Sym = E.getTarget(); - const Block &B = Sym.getBlock(); - orc::ExecutorAddrDiff Offset = Sym.getOffset(); - - struct Comp { - bool operator()(const Edge &Lhs, orc::ExecutorAddrDiff Offset) { - return Lhs.getOffset() < Offset; - } - bool operator()(orc::ExecutorAddrDiff Offset, const Edge &Rhs) { - return Offset < Rhs.getOffset(); - } - }; - - auto Bound = - std::equal_range(B.edges().begin(), B.edges().end(), Offset, Comp{}); - - for (auto It = Bound.first; It != Bound.second; ++It) { - if (It->getKind() == R_RISCV_PCREL_HI20) - return *It; - } - - return make_error( - "No HI20 PCREL relocation type be found for LO12 PCREL relocation type"); -} - static uint32_t extractBits(uint32_t Num, unsigned Low, unsigned Size) { return (Num & (((1ULL << Size) - 1) << Low)) >> Low; } @@ -184,9 +152,43 @@ class ELFJITLinker_riscv : public JITLinker { public: ELFJITLinker_riscv(std::unique_ptr Ctx, std::unique_ptr G, PassConfiguration PassConfig) - : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {} + : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { + JITLinkerBase::getPassConfig().PostAllocationPasses.push_back( + [this](LinkGraph &G) { return gatherRISCVPCRelHi20(G); }); + } private: + DenseMap, const Edge *> + RelHi20; + + Error gatherRISCVPCRelHi20(LinkGraph &G) { + for (Block *B : G.blocks()) + for (Edge &E : B->edges()) + if (E.getKind() == R_RISCV_PCREL_HI20) + RelHi20[{B, E.getOffset()}] = &E; + + return Error::success(); + } + + Expected getRISCVPCRelHi20(const Edge &E) const { + using namespace riscv; + assert((E.getKind() == R_RISCV_PCREL_LO12_I || + E.getKind() == R_RISCV_PCREL_LO12_S) && + "Can only have high relocation for R_RISCV_PCREL_LO12_I or " + "R_RISCV_PCREL_LO12_S"); + + const Symbol &Sym = E.getTarget(); + const Block &B = Sym.getBlock(); + orc::ExecutorAddrDiff Offset = Sym.getOffset(); + + auto It = RelHi20.find({&B, Offset}); + if (It != RelHi20.end()) + return *It->second; + + return make_error("No HI20 PCREL relocation type be found " + "for LO12 PCREL relocation type"); + } + Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { using namespace riscv; using namespace llvm::support;