[llvm] [JITLink] Fix symbol transfer when splitting blocks (PR #225735)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 04:51:12 PDT 2026


https://github.com/maksimra created https://github.com/llvm/llvm-project/pull/225735

splitBlock method truncates the original block before transferring symbols. For symbols assigned to a later child, setting the new offset while the symbol still refers to the truncated block can trigger the offset range assertion.  Preserve the absolute address, move the symbol to its destination block, and then derive the new block-relative offset.

*Example from the added test:*
- Before: 
address = 0x1000, size = 16, range = [0x1000, 0x1010]
---
- After splitting (offsets = {4, 8}):
**child 0**: address = 0x1000, size = 4, range = [0x1000, 0x1004]
**child 1**: address = 0x1004, size = 4, range = [0x1004, 0x1008]
**child 2**: address = 0x1008, size = 8, range = [0x1008, 0x1010]
---
- Symbol: owning block = source block, offset = 15, address = 0x100f (=0x1000 + 15), size = 1
*assert(NewOffset <= getBlock().getSize() && "Offset out of range");*

old behavior:
**NewOffset** = 0x100f - 0x1008 = 7 (relative to child 2),
but the symbol still refers to the truncated source block:

7 > truncatedSourceBlockSize (= 4)
=> fail

right behavior:
The symbol is first moved to child 2, then its offset is set:

**NewOffset** = 0x100f - 0x1008 = 7
7 <= child2BlockSize (= 8)
=> success

>From 16f47f2c6ce5dcc5ed78df4746563ebb38acc043 Mon Sep 17 00:00:00 2001
From: Maksim <rachinskii.mv at phystech.edu>
Date: Wed, 23 Sep 2026 13:09:21 +0300
Subject: [PATCH] [JITLink] Fix symbol transfer when splitting blocks

splitBlock method truncates the original block before transferring symbols. For symbols assigned to a later child, setting the new offset while the symbol still refers to the truncated block can trigger the offset range assertion. Preserve the absolute address, move the symbol to its destination block, and then derive the new block-relative offset.
---
 llvm/lib/ExecutionEngine/JITLink/JITLink.cpp  |  3 ++-
 .../JITLink/LinkGraphTests.cpp                | 22 +++++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index 329414a5e12755..0236e274a05ee6 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -216,8 +216,9 @@ std::vector<Block *> LinkGraph::splitBlockImpl(std::vector<Block *> Blocks,
     }
 
     auto TransferSymbol = [](Symbol &Sym, Block &B) {
-      Sym.setOffset(Sym.getAddress() - B.getAddress());
+      const auto SymAddress = Sym.getAddress();
       Sym.setBlock(B);
+      Sym.setOffset(SymAddress - B.getAddress());
       if (Sym.getSize() > B.getSize())
         Sym.setSize(B.getSize() - Sym.getOffset());
     };
diff --git a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
index c7608734935282..5c8a0ff8c614db 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
+++ b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
@@ -833,6 +833,28 @@ TEST(LinkGraphTest, SplitBlock) {
     EXPECT_EQ(B3.edges().begin()->getOffset(), 0U);
 }
 
+TEST(LinkGraphTest, SplitBlockPreservesLaterSymbolAddress) {
+  LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),
+              Triple("x86_64-apple-darwin"), SubtargetFeatures(),
+              getGenericEdgeKindName);
+  auto &Sec =
+      G.createSection("__data", orc::MemProt::Read | orc::MemProt::Write);
+
+  orc::ExecutorAddr BlockAddr(0x1000);
+  auto &B = G.createContentBlock(Sec, BlockContent, BlockAddr, 1, 0);
+  auto &S = G.addDefinedSymbol(B, 15, "S", 1, Linkage::Strong,
+                               Scope::Default, false, false);
+  const orc::ExecutorAddr SymbolAddr = S.getAddress();
+
+  auto Blocks = G.splitBlock(B, ArrayRef<int>({4, 8}));
+
+  ASSERT_EQ(Blocks.size(), 3U);
+  EXPECT_EQ(&S.getBlock(), Blocks[2]);
+  EXPECT_EQ(S.getOffset(), 7U);
+  EXPECT_EQ(S.getAddress(), SymbolAddr);
+  EXPECT_EQ(S.getSize(), 1U);
+}
+
 TEST(LinkGraphTest, GraphAllocationMethods) {
   LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),
               Triple("x86_64-apple-darwin"), SubtargetFeatures(),



More information about the llvm-commits mailing list