[Lldb-commits] [lldb] [lldb] Refactor PrepareToExecuteJITExpression (PR #224888)

Lang Hames via lldb-commits lldb-commits at lists.llvm.org
Mon Sep 21 07:24:10 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/2] [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/2] 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(



More information about the lldb-commits mailing list