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 @@ -368,11 +368,7 @@ /// Default -- Visible in the public interface of the linkage unit. /// Hidden -- Visible within the linkage unit, but not exported from it. /// Local -- Visible only within the LinkGraph. -enum class Scope : uint8_t { - Default, - Hidden, - Local -}; +enum class Scope : uint8_t { Default, Hidden, Local }; /// For debugging output. const char *getScopeName(Scope S); @@ -812,8 +808,7 @@ using ExternalSymbolSet = DenseSet; using BlockSet = DenseSet; - template - Addressable &createAddressable(ArgTs &&... Args) { + template Addressable &createAddressable(ArgTs &&...Args) { Addressable *A = reinterpret_cast(Allocator.Allocate()); new (A) Addressable(std::forward(Args)...); @@ -825,7 +820,7 @@ Allocator.Deallocate(&A); } - template Block &createBlock(ArgTs &&... Args) { + template Block &createBlock(ArgTs &&...Args) { Block *B = reinterpret_cast(Allocator.Allocate()); new (B) Block(std::forward(Args)...); B->getSection().addBlock(*B); @@ -1372,10 +1367,9 @@ /// Remove a block. The block reference is defunct after calling this /// function and should no longer be used. void removeBlock(Block &B) { - assert(llvm::none_of(B.getSection().symbols(), - [&](const Symbol *Sym) { - return &Sym->getBlock() == &B; - }) && + assert(llvm::none_of( + B.getSection().symbols(), + [&](const Symbol *Sym) { return &Sym->getBlock() == &B; }) && "Block still has symbols attached"); B.getSection().removeBlock(B); destroyBlock(B); @@ -1737,6 +1731,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, const Edge &E) { + 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, E))) + 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, E))) + 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 = @@ -285,8 +278,8 @@ auto RelHI20 = getRISCVPCRelHi20(E); if (!RelHI20) return RelHI20.takeError(); - int64_t Value = RelHI20->getTarget().getAddress() + - RelHI20->getAddend() - E.getTarget().getAddress(); + int64_t Value = RelHI20->getTarget().getAddress() + RelHI20->getAddend() - + E.getTarget().getAddress(); int64_t Lo = Value & 0xFFF; uint32_t RawInstr = *(little32_t *)FixupPtr; *(little32_t *)FixupPtr = @@ -298,8 +291,8 @@ // pairs with current relocation R_RISCV_PCREL_LO12_S. So here may need a // check. auto RelHI20 = getRISCVPCRelHi20(E); - int64_t Value = RelHI20->getTarget().getAddress() + - RelHI20->getAddend() - E.getTarget().getAddress(); + int64_t Value = RelHI20->getTarget().getAddress() + RelHI20->getAddend() - + E.getTarget().getAddress(); int64_t Lo = Value & 0xFFF; uint32_t Imm31_25 = extractBits(Lo, 5, 7) << 25; uint32_t Imm11_7 = extractBits(Lo, 0, 5) << 7; @@ -553,17 +546,17 @@ if ((*ELFObj)->getArch() == Triple::riscv64) { auto &ELFObjFile = cast>(**ELFObj); - return ELFLinkGraphBuilder_riscv( - (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), - (*ELFObj)->makeTriple()) + return ELFLinkGraphBuilder_riscv((*ELFObj)->getFileName(), + ELFObjFile.getELFFile(), + (*ELFObj)->makeTriple()) .buildGraph(); } else { assert((*ELFObj)->getArch() == Triple::riscv32 && "Invalid triple for RISCV ELF object file"); auto &ELFObjFile = cast>(**ELFObj); - return ELFLinkGraphBuilder_riscv( - (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), - (*ELFObj)->makeTriple()) + return ELFLinkGraphBuilder_riscv((*ELFObj)->getFileName(), + ELFObjFile.getELFFile(), + (*ELFObj)->makeTriple()) .buildGraph(); } } 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());