[Lldb-commits] [lldb] [lldb] Refactor PrepareToExecuteJITExpression (PR #224888)
Lang Hames via lldb-commits
lldb-commits at lists.llvm.org
Mon Sep 21 15:53:34 PDT 2026
https://github.com/lhames updated https://github.com/llvm/llvm-project/pull/224888
>From 4352ca5578cb90912a318cafd4c068a69bc65687 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at apple.com>
Date: Sun, 20 Sep 2026 15:53:06 +1000
Subject: [PATCH 1/3] [lldb] Refactor PrepareToExecuteJITExpression
Refactor the body of PrepareToExecuteJITExpression into two methods:
AllocateInterpreterStackFrame and AllocateAndMaterializeStruct.
This change is purely mechanical, but improves readability and sets
up a future refactor: AllocateAndMaterializeStruct is generic expression
setup and should remain where it is, but AllocateInterpreterStackFrame
is only needed on the interpreter path and can be sunk into that path in
a future commit.
---
.../lldb/Expression/LLVMUserExpression.h | 10 ++
lldb/source/Expression/LLVMUserExpression.cpp | 124 ++++++++++--------
2 files changed, 80 insertions(+), 54 deletions(-)
diff --git a/lldb/include/lldb/Expression/LLVMUserExpression.h b/lldb/include/lldb/Expression/LLVMUserExpression.h
index 568765d9b3d01..d72e56f90ab95 100644
--- a/lldb/include/lldb/Expression/LLVMUserExpression.h
+++ b/lldb/include/lldb/Expression/LLVMUserExpression.h
@@ -111,6 +111,16 @@ class LLVMUserExpression : public UserExpression {
///to the expression have been
///materialized.
Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer.
+
+private:
+ // Allocate the interpreter's private, host-only stack, if one has not been
+ // allocated already. Idempotent.
+ bool AllocateInterpreterStackFrame(DiagnosticManager &diagnostic_manager,
+ Target &target, Process *process);
+
+ // Allocate and materialize the struct.
+ bool AllocateAndMaterializeStruct(DiagnosticManager &diagnostic_manager,
+ const lldb::StackFrameSP &frame);
};
} // namespace lldb_private
diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp
index eaecb3dbfe726..81ca9d437a53e 100644
--- a/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/lldb/source/Expression/LLVMUserExpression.cpp
@@ -319,67 +319,83 @@ bool LLVMUserExpression::PrepareToExecuteJITExpression(
return false;
}
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
- if (m_materialized_address == LLDB_INVALID_ADDRESS) {
- IRMemoryMap::AllocationPolicy policy =
- m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly
- : IRMemoryMap::eAllocationPolicyMirror;
-
- const bool zero_memory = false;
- if (auto address_or_error = m_execution_unit_sp->Malloc(
- m_materializer_up->GetStructByteSize(),
- m_materializer_up->GetStructAlignment(),
- lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy,
- zero_memory)) {
- m_materialized_address = *address_or_error;
- } else {
- diagnostic_manager.Printf(
- lldb::eSeverityError,
- "Couldn't allocate space for materialized struct: %s",
- toString(address_or_error.takeError()).c_str());
- return false;
- }
- }
-
- struct_address = m_materialized_address;
+ // Early out if no JIT'd expr and can't interpret.
+ if (m_jit_start_addr == LLDB_INVALID_ADDRESS && !m_can_interpret)
+ return true;
- if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) {
- size_t stack_frame_size = target->GetExprAllocSize();
- if (stack_frame_size == 0) {
- ABISP abi_sp;
- if (process && (abi_sp = process->GetABI()))
- stack_frame_size = abi_sp->GetStackFrameSize();
- else
- stack_frame_size = 512 * 1024;
- }
+ if (m_can_interpret &&
+ !AllocateInterpreterStackFrame(diagnostic_manager, target, process.get()))
+ return false;
- const bool zero_memory = false;
- if (auto address_or_error = m_execution_unit_sp->Malloc(
- stack_frame_size, 8,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyHostOnly, zero_memory)) {
- m_stack_frame_bottom = *address_or_error;
- m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
- } else {
- diagnostic_manager.Printf(
- lldb::eSeverityError,
- "Couldn't allocate space for the stack frame: %s",
- toString(address_or_error.takeError()).c_str());
- return false;
- }
- }
+ return AllocateAndMaterializeStruct(diagnostic_manager, frame);
+}
- Status materialize_error;
+bool LLVMUserExpression::AllocateInterpreterStackFrame(
+ DiagnosticManager &diagnostic_manager, Target &target, Process *process) {
+ if (m_stack_frame_bottom != LLDB_INVALID_ADDRESS)
+ return true;
+
+ size_t stack_frame_size = target->GetExprAllocSize();
+ if (stack_frame_size == 0) {
+ ABISP abi_sp;
+ if (process && (abi_sp = process->GetABI()))
+ stack_frame_size = abi_sp->GetStackFrameSize();
+ else
+ stack_frame_size = 512 * 1024;
+ }
- m_dematerializer_sp = m_materializer_up->Materialize(
- frame, *m_execution_unit_sp, struct_address, materialize_error);
+ const bool zero_memory = false;
+ if (auto address_or_error = m_execution_unit_sp->Malloc(
+ stack_frame_size, 8,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyHostOnly, zero_memory)) {
+ m_stack_frame_bottom = *address_or_error;
+ m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
+ return true;
+ } else {
+ diagnostic_manager.Printf(lldb::eSeverityError,
+ "Couldn't allocate space for the stack frame: %s",
+ toString(address_or_error.takeError()).c_str());
+ return false;
+ }
+}
- if (!materialize_error.Success()) {
- diagnostic_manager.Printf(lldb::eSeverityError,
- "Couldn't materialize: %s",
- materialize_error.AsCString());
+bool LLVMUserExpression::AllocateAndMaterializeStruct(
+ DiagnosticManager &diagnostic_manager, const lldb::StackFrameSP &frame) {
+
+ if (m_materialized_address == LLDB_INVALID_ADDRESS) {
+ IRMemoryMap::AllocationPolicy policy =
+ m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly
+ : IRMemoryMap::eAllocationPolicyMirror;
+
+ const bool zero_memory = false;
+ if (auto address_or_error = m_execution_unit_sp->Malloc(
+ m_materializer_up->GetStructByteSize(),
+ m_materializer_up->GetStructAlignment(),
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy,
+ zero_memory)) {
+ m_materialized_address = *address_or_error;
+ } else {
+ diagnostic_manager.Printf(
+ lldb::eSeverityError,
+ "Couldn't allocate space for materialized struct: %s",
+ toString(address_or_error.takeError()).c_str());
return false;
}
}
+
+ struct_address = m_materialized_address;
+
+ Status materialize_error;
+
+ m_dematerializer_sp = m_materializer_up->Materialize(
+ frame, *m_execution_unit_sp, struct_address, materialize_error);
+
+ if (!materialize_error.Success()) {
+ diagnostic_manager.Printf(lldb::eSeverityError, "Couldn't materialize: %s",
+ materialize_error.AsCString());
+ return false;
+ }
+
return true;
}
>From b3efc5fdba544c7895611ecb5f902ea052bb222e Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at apple.com>
Date: Tue, 22 Sep 2026 00:17:48 +1000
Subject: [PATCH 2/3] Fix compilation errors, update testcase, clang-format.
---
lldb/include/lldb/Expression/LLVMUserExpression.h | 3 ++-
lldb/source/Expression/LLVMUserExpression.cpp | 8 ++++++--
.../memory-allocation/TestMemoryAllocSettings.py | 11 +++++++++--
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/lldb/include/lldb/Expression/LLVMUserExpression.h b/lldb/include/lldb/Expression/LLVMUserExpression.h
index d72e56f90ab95..5158f2033ade3 100644
--- a/lldb/include/lldb/Expression/LLVMUserExpression.h
+++ b/lldb/include/lldb/Expression/LLVMUserExpression.h
@@ -120,7 +120,8 @@ class LLVMUserExpression : public UserExpression {
// Allocate and materialize the struct.
bool AllocateAndMaterializeStruct(DiagnosticManager &diagnostic_manager,
- const lldb::StackFrameSP &frame);
+ lldb::StackFrameSP &frame,
+ lldb::addr_t &struct_address);
};
} // namespace lldb_private
diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp
index 81ca9d437a53e..1f615c10a7aa3 100644
--- a/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/lldb/source/Expression/LLVMUserExpression.cpp
@@ -323,11 +323,14 @@ bool LLVMUserExpression::PrepareToExecuteJITExpression(
if (m_jit_start_addr == LLDB_INVALID_ADDRESS && !m_can_interpret)
return true;
+ if (!AllocateAndMaterializeStruct(diagnostic_manager, frame, struct_address))
+ return false;
+
if (m_can_interpret &&
!AllocateInterpreterStackFrame(diagnostic_manager, target, process.get()))
return false;
- return AllocateAndMaterializeStruct(diagnostic_manager, frame);
+ return true;
}
bool LLVMUserExpression::AllocateInterpreterStackFrame(
@@ -361,7 +364,8 @@ bool LLVMUserExpression::AllocateInterpreterStackFrame(
}
bool LLVMUserExpression::AllocateAndMaterializeStruct(
- DiagnosticManager &diagnostic_manager, const lldb::StackFrameSP &frame) {
+ DiagnosticManager &diagnostic_manager, lldb::StackFrameSP &frame,
+ lldb::addr_t &struct_address) {
if (m_materialized_address == LLDB_INVALID_ADDRESS) {
IRMemoryMap::AllocationPolicy policy =
diff --git a/lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py b/lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py
index a82141a0792f2..e7fae4d4066f6 100644
--- a/lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py
+++ b/lldb/test/API/commands/expression/memory-allocation/TestMemoryAllocSettings.py
@@ -27,10 +27,17 @@ def test(self):
with open(self.log_file, "r") as f:
log = f.read()
+ # The materialized struct is allocated first, so it lands at
+ # expr-alloc-address.
alloc0 = re.search("^.*IRMemoryMap::Malloc.+?0xdead0000.*$", log, re.MULTILINE)
- # Malloc adds additional bytes to allocation size, hence 10007
+ # The interpreter's stack frame is allocated last. Materializing the
+ # struct allocates the persistent result variable in between, so the
+ # stack frame lands two expr-alloc-align boundaries along, at 0xdead2000.
+ # Its size comes from expr-alloc-size: Malloc rounds the request up to the
+ # requested alignment (8 here) and then adds alignment - 1 bytes, so
+ # 10000 becomes 10007.
alloc1 = re.search(
- r"^.*IRMemoryMap::Malloc\s*?\(10007.+?0xdead1000.*$", log, re.MULTILINE
+ r"^.*IRMemoryMap::Malloc\s*?\(10007.+?0xdead2000.*$", log, re.MULTILINE
)
self.assertTrue(alloc0, "Couldn't find an allocation at a given address.")
self.assertTrue(
>From dd4c573d6430f972e69dde57e317fc15c8175936 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at apple.com>
Date: Tue, 22 Sep 2026 08:53:08 +1000
Subject: [PATCH 3/3] Improve comment, fix more compile issues
---
lldb/include/lldb/Expression/LLVMUserExpression.h | 14 ++++++++++----
lldb/source/Expression/LLVMUserExpression.cpp | 8 ++++----
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/lldb/include/lldb/Expression/LLVMUserExpression.h b/lldb/include/lldb/Expression/LLVMUserExpression.h
index 5158f2033ade3..599c00ae017fb 100644
--- a/lldb/include/lldb/Expression/LLVMUserExpression.h
+++ b/lldb/include/lldb/Expression/LLVMUserExpression.h
@@ -118,10 +118,16 @@ class LLVMUserExpression : public UserExpression {
bool AllocateInterpreterStackFrame(DiagnosticManager &diagnostic_manager,
Target &target, Process *process);
- // Allocate and materialize the struct.
- bool AllocateAndMaterializeStruct(DiagnosticManager &diagnostic_manager,
- lldb::StackFrameSP &frame,
- lldb::addr_t &struct_address);
+ // Prepare the struct holding the expression arguments.
+ //
+ // Materialize expression arguments into the argument struct
+ // (m_materialized_address).
+ //
+ // This method allocates the struct on first call, and reuses the original
+ // allocation on subsequent calls.
+ bool PrepareArgumentStruct(DiagnosticManager &diagnostic_manager,
+ lldb::StackFrameSP &frame,
+ lldb::addr_t &struct_address);
};
} // namespace lldb_private
diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp
index 1f615c10a7aa3..098b5a2b65bad 100644
--- a/lldb/source/Expression/LLVMUserExpression.cpp
+++ b/lldb/source/Expression/LLVMUserExpression.cpp
@@ -323,11 +323,11 @@ bool LLVMUserExpression::PrepareToExecuteJITExpression(
if (m_jit_start_addr == LLDB_INVALID_ADDRESS && !m_can_interpret)
return true;
- if (!AllocateAndMaterializeStruct(diagnostic_manager, frame, struct_address))
+ if (!PrepareArgumentStruct(diagnostic_manager, frame, struct_address))
return false;
if (m_can_interpret &&
- !AllocateInterpreterStackFrame(diagnostic_manager, target, process.get()))
+ !AllocateInterpreterStackFrame(diagnostic_manager, *target, process.get()))
return false;
return true;
@@ -338,7 +338,7 @@ bool LLVMUserExpression::AllocateInterpreterStackFrame(
if (m_stack_frame_bottom != LLDB_INVALID_ADDRESS)
return true;
- size_t stack_frame_size = target->GetExprAllocSize();
+ size_t stack_frame_size = target.GetExprAllocSize();
if (stack_frame_size == 0) {
ABISP abi_sp;
if (process && (abi_sp = process->GetABI()))
@@ -363,7 +363,7 @@ bool LLVMUserExpression::AllocateInterpreterStackFrame(
}
}
-bool LLVMUserExpression::AllocateAndMaterializeStruct(
+bool LLVMUserExpression::PrepareArgumentStruct(
DiagnosticManager &diagnostic_manager, lldb::StackFrameSP &frame,
lldb::addr_t &struct_address) {
More information about the lldb-commits
mailing list