Skip to content

[lldb][libc++] Adds valarray data formatters. #80609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 10, 2024

Conversation

mordante
Copy link
Member

@mordante mordante commented Feb 4, 2024

The code is heavily based on the vector data formatter.

@llvmbot
Copy link
Member

llvmbot commented Feb 4, 2024

@llvm/pr-subscribers-lldb

Author: Mark de Wever (mordante)

Changes

The code is heavily based on the vector data formatter.


Full diff: https://github.com/llvm/llvm-project/pull/80609.diff

7 Files Affected:

  • (modified) lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt (+1)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+9)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/LibCxx.h (+4)
  • (added) lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp (+140)
  • (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/Makefile (+5)
  • (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py (+78)
  • (added) lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp (+17)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 21108b27896a1..97fa894ea7376 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -17,6 +17,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
   LibCxxTuple.cpp
   LibCxxUnorderedMap.cpp
   LibCxxVariant.cpp
+  LibCxxValarray.cpp
   LibCxxVector.cpp
   LibStdcpp.cpp
   LibStdcppTuple.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index e0de80880376a..af2f97f6b40ee 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -750,6 +750,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
       "libc++ std::vector synthetic children",
       "^std::__[[:alnum:]]+::vector<.+>$", stl_deref_flags, true);
+  AddCXXSynthetic(
+      cpp_category_sp,
+      lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator,
+      "libc++ std::valarray synthetic children",
+      "^std::__[[:alnum:]]+::valarray<.+>(( )?&)?$", stl_deref_flags, true);
   AddCXXSynthetic(
       cpp_category_sp,
       lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
@@ -871,6 +876,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
                 lldb_private::formatters::LibcxxContainerSummaryProvider,
                 "libc++ std::vector summary provider",
                 "^std::__[[:alnum:]]+::vector<.+>$", stl_summary_flags, true);
+  AddCXXSummary(
+      cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
+      "libc++ std::valarray summary provider",
+      "^std::__[[:alnum:]]+::valarray<.+>(( )?&)?$", stl_summary_flags, true);
   AddCXXSummary(
       cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
       "libc++ std::list summary provider",
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index 72da6b2426efe..a3fff03f2c642 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -219,6 +219,10 @@ SyntheticChildrenFrontEnd *
 LibcxxStdVectorSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                         lldb::ValueObjectSP);
 
+SyntheticChildrenFrontEnd *
+LibcxxStdValarraySyntheticFrontEndCreator(CXXSyntheticChildren *,
+                                          lldb::ValueObjectSP);
+
 SyntheticChildrenFrontEnd *
 LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                       lldb::ValueObjectSP);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp
new file mode 100644
index 0000000000000..5ec4df3da3c90
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp
@@ -0,0 +1,140 @@
+//===-- LibCxxValarray.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include <optional>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+namespace formatters {
+class LibcxxStdValarraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+  LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+  ~LibcxxStdValarraySyntheticFrontEnd() override;
+
+  size_t CalculateNumChildren() override;
+
+  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+  bool Update() override;
+
+  bool MightHaveChildren() override;
+
+  size_t GetIndexOfChildWithName(ConstString name) override;
+
+private:
+  ValueObject *m_start = nullptr;
+  ValueObject *m_finish = nullptr;
+  CompilerType m_element_type;
+  uint32_t m_element_size = 0;
+};
+
+} // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+    LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+    : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
+  if (valobj_sp)
+    Update();
+}
+
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+    ~LibcxxStdValarraySyntheticFrontEnd() {
+  // these need to stay around because they are child objects who will follow
+  // their parent's life cycle
+  // delete m_start;
+  // delete m_finish;
+}
+
+size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+    CalculateNumChildren() {
+  if (!m_start || !m_finish)
+    return 0;
+  uint64_t start_val = m_start->GetValueAsUnsigned(0);
+  uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
+
+  if (start_val == 0 || finish_val == 0)
+    return 0;
+
+  if (start_val >= finish_val)
+    return 0;
+
+  size_t num_children = (finish_val - start_val);
+  if (num_children % m_element_size)
+    return 0;
+  return num_children / m_element_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::GetChildAtIndex(
+    size_t idx) {
+  if (!m_start || !m_finish)
+    return lldb::ValueObjectSP();
+
+  uint64_t offset = idx * m_element_size;
+  offset = offset + m_start->GetValueAsUnsigned(0);
+  StreamString name;
+  name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+  return CreateValueObjectFromAddress(name.GetString(), offset,
+                                      m_backend.GetExecutionContextRef(),
+                                      m_element_type);
+}
+
+bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::Update() {
+  m_start = m_finish = nullptr;
+
+  CompilerType type = m_backend.GetCompilerType();
+  if (type.GetNumTemplateArguments() == 0)
+    return false;
+
+  m_element_type = type.GetTypeTemplateArgument(0);
+  if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr))
+    m_element_size = *size;
+
+  if (m_element_size == 0)
+    return false;
+
+  ValueObjectSP start = m_backend.GetChildMemberWithName("__begin_");
+  ValueObjectSP finish = m_backend.GetChildMemberWithName("__end_");
+
+  if (!start || !finish)
+    return false;
+
+  m_start = start.get();
+  m_finish = finish.get();
+
+  return false;
+}
+
+bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+    MightHaveChildren() {
+  return true;
+}
+
+size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+    GetIndexOfChildWithName(ConstString name) {
+  if (!m_start || !m_finish)
+    return UINT32_MAX;
+  return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator(
+    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+  if (!valobj_sp)
+    return nullptr;
+  return new LibcxxStdValarraySyntheticFrontEnd(valobj_sp);
+}
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/Makefile
new file mode 100644
index 0000000000000..c5df567e01a2a
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/Makefile
@@ -0,0 +1,5 @@
+CXX_SOURCES := main.cpp
+
+USE_LIBCPP := 1
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py
new file mode 100644
index 0000000000000..7b54b3485d04d
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py
@@ -0,0 +1,78 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LibcxxChronoDataFormatterTestCase(TestBase):
+    @add_test_categories(["libc++"])
+    def test_with_run_command(self):
+        """Test that that file and class static variables display correctly."""
+        self.build()
+        (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "break here", lldb.SBFileSpec("main.cpp", False)
+        )
+
+        self.expect(
+            "frame variable va_int",
+            substrs=[
+                "va_int = size=4",
+                "[0] = 0",
+                "[1] = 0",
+                "[2] = 0",
+                "[3] = 0",
+                "}",
+            ],
+        )
+
+        lldbutil.continue_to_breakpoint(process, bkpt)
+        self.expect(
+            "frame variable va_int",
+            substrs=[
+                "va_int = size=4",
+                "[0] = 1",
+                "[1] = 12",
+                "[2] = 123",
+                "[3] = 1234",
+                "}",
+            ],
+        )
+
+        # check access-by-index
+        self.expect("frame variable va_int[0]", substrs=["1"])
+        self.expect("frame variable va_int[1]", substrs=["12"])
+        self.expect("frame variable va_int[2]", substrs=["123"])
+        self.expect("frame variable va_int[3]", substrs=["1234"])
+        self.expect(
+            "frame variable va_int[4]",
+            error=True,
+            substrs=['array index 4 is not valid for "(valarray<int>) va_int"'],
+        )
+
+        self.expect(
+            "frame variable va_double",
+            substrs=[
+                "va_double = size=4",
+                "[0] = 1",
+                "[1] = 0.5",
+                "[2] = 0.25",
+                "[3] = 0.125",
+                "}",
+            ],
+        )
+
+        # check access-by-index
+        self.expect("frame variable va_double[0]", substrs=["1"])
+        self.expect("frame variable va_double[1]", substrs=["0.5"])
+        self.expect("frame variable va_double[2]", substrs=["0.25"])
+        self.expect("frame variable va_double[3]", substrs=["0.125"])
+        self.expect(
+            "frame variable va_double[4]",
+            error=True,
+            substrs=['array index 4 is not valid for "(valarray<double>) va_double"'],
+        )
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp
new file mode 100644
index 0000000000000..f32921e16fa10
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp
@@ -0,0 +1,17 @@
+#include <iostream>
+#include <valarray>
+
+int main() {
+
+  std::valarray<int> va_int(4);
+  std::cout << "break here";
+
+  va_int[0] = 1;
+  va_int[1] = 12;
+  va_int[2] = 123;
+  va_int[3] = 1234;
+
+  std::valarray<double> va_double({1.0, 0.5, 0.25, 0.125});
+
+  std::cout << "break here\n";
+}

Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM to me generally (just some minor stylistic comments)

The code is heavily based on the vector data formatter.
@mordante mordante force-pushed the reviews/lldb/valarray_data_formatter branch from 12b03c9 to 661f43e Compare February 10, 2024 19:37
Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@mordante mordante merged commit 5e9eaf8 into llvm:main Feb 10, 2024
@mordante mordante deleted the reviews/lldb/valarray_data_formatter branch February 10, 2024 19:44
Michael137 pushed a commit to Michael137/llvm-project that referenced this pull request Feb 16, 2024
The code is heavily based on the vector data formatter.

(cherry picked from commit 5e9eaf8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants