diff options
Diffstat (limited to 'llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp')
| -rw-r--r-- | llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp index 71a0f14368ac..0dc97104610b 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -154,18 +154,22 @@ public: std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig) : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { JITLinkerBase::getPassConfig().PostAllocationPasses.push_back( - [this](LinkGraph &G) { return gatherRISCVPCRelHi20(G); }); + [this](LinkGraph &G) { return gatherRISCVPairs(G); }); } private: DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *> RelHi20; + DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *> + SetULEB128; - Error gatherRISCVPCRelHi20(LinkGraph &G) { + Error gatherRISCVPairs(LinkGraph &G) { for (Block *B : G.blocks()) for (Edge &E : B->edges()) if (E.getKind() == R_RISCV_PCREL_HI20) RelHi20[{B, E.getOffset()}] = &E; + else if (E.getKind() == R_RISCV_SET_ULEB128) + SetULEB128[{B, E.getOffset()}] = &E; return Error::success(); } @@ -189,6 +193,20 @@ private: "for LO12 PCREL relocation type"); } + Expected<const Edge &> getRISCVSetULEB128(const Block &B, + const Edge &E) const { + using namespace riscv; + assert(E.getKind() == R_RISCV_SUB_ULEB128 && + "Can only have pair relocation for R_RISCV_SUB_ULEB128"); + + auto It = SetULEB128.find({&B, E.getOffset()}); + if (It != SetULEB128.end()) + return *It->second; + + return make_error<JITLinkError>( + "No RISCV_SET_ULEB128 relocation type be found"); + } + Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { using namespace riscv; using namespace llvm::support; @@ -467,6 +485,21 @@ private: *(little32_t *)FixupPtr = static_cast<uint32_t>(Value); break; } + case R_RISCV_SET_ULEB128: + break; + case R_RISCV_SUB_ULEB128: { + auto SetULEB128 = getRISCVSetULEB128(B, E); + if (!SetULEB128) + return SetULEB128.takeError(); + uint64_t Value = SetULEB128->getTarget().getAddress() + + SetULEB128->getAddend() - E.getTarget().getAddress() - + E.getAddend(); + if (overwriteULEB128(reinterpret_cast<uint8_t *>(FixupPtr), Value) >= + 0x80) + return make_error<StringError>("ULEB128 value exceeds available space", + inconvertibleErrorCode()); + break; + } } return Error::success(); } @@ -843,6 +876,10 @@ private: return EdgeKind_riscv::R_RISCV_32_PCREL; case ELF::R_RISCV_ALIGN: return EdgeKind_riscv::AlignRelaxable; + case ELF::R_RISCV_SET_ULEB128: + return EdgeKind_riscv::R_RISCV_SET_ULEB128; + case ELF::R_RISCV_SUB_ULEB128: + return EdgeKind_riscv::R_RISCV_SUB_ULEB128; } return make_error<JITLinkError>( |
