diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -1737,6 +1737,9 @@ Error makeTargetOutOfRangeError(const LinkGraph &G, const Block &B, const Edge &E); +Error makeAlignmentError(llvm::orc::ExecutorAddr Loc, uint64_t Value, int N, + const Edge &E); + /// Base case for edge-visitors where the visitor-list is empty. inline void visitEdge(LinkGraph &G, Block *B, Edge &E) {} diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -163,20 +163,13 @@ return (Num & (((1ULL << Size) - 1) << Low)) >> Low; } -inline Error checkAlignment(llvm::orc::ExecutorAddr loc, uint64_t v, int n, - const Edge &E) { - if (v & (n - 1)) - return make_error("0x" + llvm::utohexstr(loc.getValue()) + - " improper alignment for relocation " + - formatv("{0:d}", E.getKind()) + ": 0x" + - llvm::utohexstr(v) + " is not aligned to " + - Twine(n) + " bytes"); - return Error::success(); +static inline bool isAlignmentCorrect(uint64_t Value, int N) { + return (Value & (N - 1)) ? false : true; } -static inline bool isInRangeForImmS32(int64_t Value) { - return (Value >= std::numeric_limits::min() && - Value <= std::numeric_limits::max()); +// Requires 0 < N <= 64. +static inline bool isInRangeForImm(int64_t Value, int N) { + return Value == llvm::SignExtend64(Value, N); } class ELFJITLinker_riscv : public JITLinker { @@ -208,10 +201,10 @@ } case R_RISCV_BRANCH: { int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; - Error AlignmentIssue = checkAlignment(FixupAddress, Value, 2, E); - if (AlignmentIssue) { - return AlignmentIssue; - } + if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 12))) + return makeTargetOutOfRangeError(G, B, E); + if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); uint32_t Imm31_25 = extractBits(Value, 5, 6) << 25 | extractBits(Value, 12, 1) << 31; uint32_t Imm11_7 = @@ -222,10 +215,10 @@ } case R_RISCV_JAL: { int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; - Error AlignmentIssue = checkAlignment(FixupAddress, Value, 2, E); - if (AlignmentIssue) { - return AlignmentIssue; - } + if (LLVM_UNLIKELY(!isInRangeForImm(Value >> 1, 20))) + return makeTargetOutOfRangeError(G, B, E); + if (LLVM_UNLIKELY(!isAlignmentCorrect(Value, 2))) + return makeAlignmentError(FixupAddress, Value, 2, E); uint32_t Imm20 = extractBits(Value, 20, 1) << 31; uint32_t Imm10_1 = extractBits(Value, 1, 10) << 21; uint32_t Imm11 = extractBits(Value, 11, 1) << 20; @@ -237,7 +230,7 @@ case R_RISCV_HI20: { int64_t Value = (E.getTarget().getAddress() + E.getAddend()).getValue(); int64_t Hi = Value + 0x800; - if (LLVM_UNLIKELY(!isInRangeForImmS32(Hi))) + if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32))) return makeTargetOutOfRangeError(G, B, E); uint32_t RawInstr = *(little32_t *)FixupPtr; *(little32_t *)FixupPtr = @@ -257,7 +250,7 @@ case R_RISCV_CALL: { int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; int64_t Hi = Value + 0x800; - if (LLVM_UNLIKELY(!isInRangeForImmS32(Hi))) + if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32))) return makeTargetOutOfRangeError(G, B, E); int32_t Lo = Value & 0xFFF; uint32_t RawInstrAuipc = *(little32_t *)FixupPtr; @@ -271,7 +264,7 @@ case R_RISCV_PCREL_HI20: { int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress; int64_t Hi = Value + 0x800; - if (LLVM_UNLIKELY(!isInRangeForImmS32(Hi))) + if (LLVM_UNLIKELY(!isInRangeForImm(Hi, 32))) return makeTargetOutOfRangeError(G, B, E); uint32_t RawInstr = *(little32_t *)FixupPtr; *(little32_t *)FixupPtr = diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp --- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp @@ -393,6 +393,15 @@ return make_error(std::move(ErrMsg)); } +Error makeAlignmentError(llvm::orc::ExecutorAddr Loc, uint64_t Value, int N, + const Edge &E) { + return make_error("0x" + llvm::utohexstr(Loc.getValue()) + + " improper alignment for relocation " + + formatv("{0:d}", E.getKind()) + ": 0x" + + llvm::utohexstr(Value) + + " is not aligned to " + Twine(N) + " bytes"); +} + Expected> createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) { auto Magic = identify_magic(ObjectBuffer.getBuffer());