avogelsgesang updated this revision to Diff 461232.
avogelsgesang marked an inline comment as done.
avogelsgesang added a comment.

address review comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132815/new/

https://reviews.llvm.org/D132815

Files:
  lldb/packages/Python/lldbsuite/test/lldbtest.py
  lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
  lldb/source/Plugins/Language/CPlusPlus/Coroutines.h
  
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py

Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py
===================================================================
--- lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py
@@ -68,7 +68,7 @@
                 result_children=[
                     ValueCheck(name="resume", summary = test_generator_func_ptr_re),
                     ValueCheck(name="destroy", summary = test_generator_func_ptr_re),
-                    ValueCheck(name="promise", value="-1")
+                    ValueCheck(name="promise", dereference=ValueCheck(value="-1"))
                 ])
 
         # Run until after the `co_yield`
Index: lldb/source/Plugins/Language/CPlusPlus/Coroutines.h
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/Coroutines.h
+++ lldb/source/Plugins/Language/CPlusPlus/Coroutines.h
@@ -44,7 +44,9 @@
   size_t GetIndexOfChildWithName(ConstString name) override;
 
 private:
-  lldb::ValueObjectSP m_frame_ptr_sp;
+  lldb::ValueObjectSP m_resume_ptr_sp;
+  lldb::ValueObjectSP m_destroy_ptr_sp;
+  lldb::ValueObjectSP m_promise_ptr_sp;
 };
 
 SyntheticChildrenFrontEnd *
Index: lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
@@ -16,34 +16,35 @@
 using namespace lldb_private;
 using namespace lldb_private::formatters;
 
-static ValueObjectSP GetCoroFramePtrFromHandle(ValueObject &valobj) {
-  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+static lldb::addr_t GetCoroFramePtrFromHandle(ValueObjectSP valobj_sp) {
   if (!valobj_sp)
-    return nullptr;
+    return LLDB_INVALID_ADDRESS;
 
   // We expect a single pointer in the `coroutine_handle` class.
   // We don't care about its name.
   if (valobj_sp->GetNumChildren() != 1)
-    return nullptr;
+    return LLDB_INVALID_ADDRESS;
   ValueObjectSP ptr_sp(valobj_sp->GetChildAtIndex(0, true));
   if (!ptr_sp)
-    return nullptr;
+    return LLDB_INVALID_ADDRESS;
   if (!ptr_sp->GetCompilerType().IsPointerType())
-    return nullptr;
-
-  return ptr_sp;
-}
-
-static Function *ExtractFunction(ValueObjectSP &frame_ptr_sp, int offset) {
-  lldb::TargetSP target_sp = frame_ptr_sp->GetTargetSP();
-  lldb::ProcessSP process_sp = frame_ptr_sp->GetProcessSP();
-  auto ptr_size = process_sp->GetAddressByteSize();
+    return LLDB_INVALID_ADDRESS;
 
   AddressType addr_type;
-  lldb::addr_t frame_ptr_addr = frame_ptr_sp->GetPointerValue(&addr_type);
+  lldb::addr_t frame_ptr_addr = ptr_sp->GetPointerValue(&addr_type);
   if (!frame_ptr_addr || frame_ptr_addr == LLDB_INVALID_ADDRESS)
-    return nullptr;
+    return LLDB_INVALID_ADDRESS;
   lldbassert(addr_type == AddressType::eAddressTypeLoad);
+  if (addr_type != AddressType::eAddressTypeLoad)
+    return LLDB_INVALID_ADDRESS;
+
+  return frame_ptr_addr;
+}
+
+static Function *ExtractFunction(lldb::TargetSP target_sp,
+                                 lldb::addr_t frame_ptr_addr, int offset) {
+  lldb::ProcessSP process_sp = target_sp->GetProcessSP();
+  auto ptr_size = process_sp->GetAddressByteSize();
 
   Status error;
   auto func_ptr_addr = frame_ptr_addr + offset * ptr_size;
@@ -59,12 +60,14 @@
   return func_address.CalculateSymbolContextFunction();
 }
 
-static Function *ExtractResumeFunction(ValueObjectSP &frame_ptr_sp) {
-  return ExtractFunction(frame_ptr_sp, 0);
+static Function *ExtractResumeFunction(lldb::TargetSP target_sp,
+                                       lldb::addr_t frame_ptr_addr) {
+  return ExtractFunction(target_sp, frame_ptr_addr, 0);
 }
 
-static Function *ExtractDestroyFunction(ValueObjectSP &frame_ptr_sp) {
-  return ExtractFunction(frame_ptr_sp, 1);
+static Function *ExtractDestroyFunction(lldb::TargetSP target_sp,
+                                        lldb::addr_t frame_ptr_addr) {
+  return ExtractFunction(target_sp, frame_ptr_addr, 1);
 }
 
 static bool IsNoopResumeDestroy(Function *f) {
@@ -125,43 +128,26 @@
   return promise_type->GetForwardCompilerType();
 }
 
-static CompilerType GetCoroutineFrameType(TypeSystemClang &ast_ctx,
-                                          CompilerType promise_type) {
-  CompilerType void_type = ast_ctx.GetBasicType(lldb::eBasicTypeVoid);
-  CompilerType coro_func_type = ast_ctx.CreateFunctionType(
-      /*result_type=*/void_type, /*args=*/&void_type, /*num_args=*/1,
-      /*is_variadic=*/false, /*qualifiers=*/0);
-  CompilerType coro_abi_type;
-  if (promise_type.IsVoidType()) {
-    coro_abi_type = ast_ctx.CreateStructForIdentifier(
-        ConstString(), {{"resume", coro_func_type.GetPointerType()},
-                        {"destroy", coro_func_type.GetPointerType()}});
-  } else {
-    coro_abi_type = ast_ctx.CreateStructForIdentifier(
-        ConstString(), {{"resume", coro_func_type.GetPointerType()},
-                        {"destroy", coro_func_type.GetPointerType()},
-                        {"promise", promise_type}});
-  }
-  return coro_abi_type;
-}
-
 bool lldb_private::formatters::StdlibCoroutineHandleSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
-  ValueObjectSP ptr_sp(GetCoroFramePtrFromHandle(valobj));
-  if (!ptr_sp)
+  lldb::addr_t frame_ptr_addr =
+      GetCoroFramePtrFromHandle(valobj.GetNonSyntheticValue());
+  if (frame_ptr_addr == LLDB_INVALID_ADDRESS)
     return false;
 
-  if (!ptr_sp->GetValueAsUnsigned(0)) {
+  if (frame_ptr_addr == 0) {
     stream << "nullptr";
     return true;
   }
-  if (IsNoopResumeDestroy(ExtractResumeFunction(ptr_sp)) &&
-      IsNoopResumeDestroy(ExtractDestroyFunction(ptr_sp))) {
+
+  lldb::TargetSP target_sp = valobj.GetTargetSP();
+  if (IsNoopResumeDestroy(ExtractResumeFunction(target_sp, frame_ptr_addr)) &&
+      IsNoopResumeDestroy(ExtractDestroyFunction(target_sp, frame_ptr_addr))) {
     stream << "noop_coroutine";
     return true;
   }
 
-  stream.Printf("coro frame = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
+  stream.Printf("coro frame = 0x%" PRIx64, frame_ptr_addr);
   return true;
 }
 
@@ -177,39 +163,67 @@
 
 size_t lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
     CalculateNumChildren() {
-  if (!m_frame_ptr_sp)
+  if (!m_resume_ptr_sp || !m_destroy_ptr_sp)
     return 0;
 
-  return m_frame_ptr_sp->GetNumChildren();
+  return m_promise_ptr_sp ? 3 : 2;
 }
 
 lldb::ValueObjectSP lldb_private::formatters::
     StdlibCoroutineHandleSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
-  if (!m_frame_ptr_sp)
-    return lldb::ValueObjectSP();
-
-  return m_frame_ptr_sp->GetChildAtIndex(idx, true);
+  switch (idx) {
+  case 0:
+    return m_resume_ptr_sp;
+  case 1:
+    return m_destroy_ptr_sp;
+  case 2:
+    return m_promise_ptr_sp;
+  }
+  return lldb::ValueObjectSP();
 }
 
 bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
     Update() {
-  m_frame_ptr_sp.reset();
+  m_resume_ptr_sp.reset();
+  m_destroy_ptr_sp.reset();
+  m_promise_ptr_sp.reset();
 
-  ValueObjectSP valobj_sp = m_backend.GetSP();
+  ValueObjectSP valobj_sp = m_backend.GetNonSyntheticValue();
   if (!valobj_sp)
     return false;
 
-  ValueObjectSP ptr_sp(GetCoroFramePtrFromHandle(m_backend));
-  if (!ptr_sp)
+  lldb::addr_t frame_ptr_addr = GetCoroFramePtrFromHandle(valobj_sp);
+  if (frame_ptr_addr == 0 || frame_ptr_addr == LLDB_INVALID_ADDRESS)
     return false;
 
-  Function *resume_func = ExtractResumeFunction(ptr_sp);
-  Function *destroy_func = ExtractDestroyFunction(ptr_sp);
+  lldb::TargetSP target_sp = m_backend.GetTargetSP();
+  Function *resume_func = ExtractResumeFunction(target_sp, frame_ptr_addr);
+  Function *destroy_func = ExtractDestroyFunction(target_sp, frame_ptr_addr);
 
-  if (IsNoopResumeDestroy(resume_func) && IsNoopResumeDestroy(destroy_func)) {
-    // For `std::noop_coroutine()`, we don't want to display any child nodes.
+  // For `std::noop_coroutine()`, we don't want to display any child nodes.
+  if (IsNoopResumeDestroy(resume_func) && IsNoopResumeDestroy(destroy_func))
     return false;
-  }
+
+  TypeSystemClang *ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(
+      valobj_sp->GetCompilerType().GetTypeSystem());
+  if (!ast_ctx)
+    return {};
+
+  // Create the `resume` and `destroy` children
+  auto &exe_ctx = m_backend.GetExecutionContextRef();
+  lldb::ProcessSP process_sp = target_sp->GetProcessSP();
+  auto ptr_size = process_sp->GetAddressByteSize();
+  CompilerType void_type = ast_ctx->GetBasicType(lldb::eBasicTypeVoid);
+  CompilerType coro_func_type = ast_ctx->CreateFunctionType(
+      /*result_type=*/void_type, /*args=*/&void_type, /*num_args=*/1,
+      /*is_variadic=*/false, /*qualifiers=*/0);
+  CompilerType coro_func_ptr_type = coro_func_type.GetPointerType();
+  m_resume_ptr_sp = CreateValueObjectFromAddress(
+      "resume", frame_ptr_addr + 0 * ptr_size, exe_ctx, coro_func_ptr_type);
+  lldbassert(m_resume_ptr_sp);
+  m_destroy_ptr_sp = CreateValueObjectFromAddress(
+      "destroy", frame_ptr_addr + 1 * ptr_size, exe_ctx, coro_func_ptr_type);
+  lldbassert(m_destroy_ptr_sp);
 
   // Get the `promise_type` from the template argument
   CompilerType promise_type(
@@ -224,14 +238,16 @@
     }
   }
 
-  // Build the coroutine frame type
-  TypeSystemClang *ast_ctx = llvm::dyn_cast_or_null<TypeSystemClang>(
-      ptr_sp->GetCompilerType().GetTypeSystem());
-  if (!ast_ctx)
-    return {};
-  CompilerType coro_frame_type = GetCoroutineFrameType(*ast_ctx, promise_type);
-
-  m_frame_ptr_sp = ptr_sp->Cast(coro_frame_type.GetPointerType());
+  // Add the `promise` member. We intentionally add `promise` as a pointer type
+  // instead of a value type, and don't automatically dereference this pointer.
+  // We do so to avoid potential very deep recursion in case there is a cycle in
+  // formed between `std::coroutine_handle`s and their promises.
+  lldb::ValueObjectSP promise = CreateValueObjectFromAddress(
+      "promise", frame_ptr_addr + 2 * ptr_size, exe_ctx, promise_type);
+  Status error;
+  lldb::ValueObjectSP promisePtr = promise->AddressOf(error);
+  if (error.Success())
+    m_promise_ptr_sp = promisePtr->Clone(ConstString("promise"));
 
   return false;
 }
@@ -243,10 +259,17 @@
 
 size_t StdlibCoroutineHandleSyntheticFrontEnd::GetIndexOfChildWithName(
     ConstString name) {
-  if (!m_frame_ptr_sp)
+  if (!m_resume_ptr_sp || !m_destroy_ptr_sp)
     return UINT32_MAX;
 
-  return m_frame_ptr_sp->GetIndexOfChildWithName(name);
+  if (name == ConstString("resume"))
+    return 0;
+  if (name == ConstString("destroy"))
+    return 1;
+  if (name == ConstString("promise_ptr") && m_promise_ptr_sp)
+    return 2;
+
+  return UINT32_MAX;
 }
 
 SyntheticChildrenFrontEnd *
Index: lldb/packages/Python/lldbsuite/test/lldbtest.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -246,7 +246,7 @@
 
 class ValueCheck:
     def __init__(self, name=None, value=None, type=None, summary=None,
-                 children=None):
+                 children=None, dereference=None):
         """
         :param name: The name that the SBValue should have. None if the summary
                      should not be checked.
@@ -261,12 +261,15 @@
                          The order of checks is the order of the checks in the
                          list. The number of checks has to match the number of
                          children.
+        :param dereference: A ValueCheck for the SBValue returned by the
+                            `Dereference` function.
         """
         self.expect_name = name
         self.expect_value = value
         self.expect_type = type
         self.expect_summary = summary
         self.children = children
+        self.dereference = dereference
 
     def check_value(self, test_base, val, error_msg=None):
         """
@@ -305,6 +308,9 @@
         if self.children is not None:
             self.check_value_children(test_base, val, error_msg)
 
+        if self.dereference is not None:
+            self.dereference.check_value(test_base, val.Dereference(), error_msg)
+
     def check_value_children(self, test_base, val, error_msg=None):
         """
         Checks that the children of a SBValue match a certain structure and
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to