[Lldb-commits] [lldb] [lldb][libc++] Adds slice_array data formatters. (PR #85544)
Mark de Wever via lldb-commits
lldb-commits at lists.llvm.org
Sun Mar 17 06:56:29 PDT 2024
https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/85544
>From 52d525c8377fe36d2c8c7705736482ee6a021366 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sat, 16 Mar 2024 17:25:32 +0100
Subject: [PATCH 1/2] [lldb][libc++] Adds slice_array data formatters.
---
.../Plugins/Language/CPlusPlus/CMakeLists.txt | 1 +
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 10 ++
.../Plugins/Language/CPlusPlus/LibCxx.h | 8 +
.../Language/CPlusPlus/LibCxxSliceArray.cpp | 166 ++++++++++++++++++
.../TestDataFormatterLibcxxValarray.py | 31 ++++
.../libcxx/valarray/main.cpp | 3 +
6 files changed, 219 insertions(+)
create mode 100644 lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 97fa894ea73761..0c6fdb2b957315 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -13,6 +13,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibCxxMap.cpp
LibCxxQueue.cpp
LibCxxRangesRefView.cpp
+ LibCxxSliceArray.cpp
LibCxxSpan.cpp
LibCxxTuple.cpp
LibCxxUnorderedMap.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 675ca385186102..4a536096a066ff 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -755,6 +755,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP 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::LibcxxStdSliceArraySyntheticFrontEndCreator,
+ "libc++ std::slice_array synthetic children",
+ "^std::__[[:alnum:]]+::slice_array<.+>$", stl_deref_flags, true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
@@ -880,6 +885,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP 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::LibcxxStdSliceArraySummaryProvider,
+ "libc++ std::slice_array summary provider",
+ "^std::__[[:alnum:]]+::slice_array<.+>$", 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 a59f21841ec890..d8b807d180e068 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -59,6 +59,10 @@ bool LibcxxWStringViewSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // libc++ std::wstring_view
+bool LibcxxStdSliceArraySummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libc++ std::slice_array
+
bool LibcxxSmartPointerSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions
@@ -223,6 +227,10 @@ SyntheticChildrenFrontEnd *
LibcxxStdValarraySyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
+SyntheticChildrenFrontEnd *
+LibcxxStdSliceArraySyntheticFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP);
+
SyntheticChildrenFrontEnd *
LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp
new file mode 100644
index 00000000000000..724514dd0697b9
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp
@@ -0,0 +1,166 @@
+//===-- LibCxxSliceArray.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 {
+
+bool LibcxxStdSliceArraySummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ ValueObjectSP obj = valobj.GetNonSyntheticValue();
+ if (!obj)
+ return false;
+
+ ValueObjectSP ptr_sp = obj->GetChildMemberWithName("__size_");
+ if (!ptr_sp)
+ return false;
+ const size_t size = ptr_sp->GetValueAsUnsigned(0);
+
+ ptr_sp = obj->GetChildMemberWithName("__stride_");
+ if (!ptr_sp)
+ return false;
+ const size_t stride = ptr_sp->GetValueAsUnsigned(0);
+
+ stream.Printf("stride=%" PRIu64 " size=%" PRIu64, stride, size);
+
+ return true;
+}
+
+/// Data formatter for libc++'s std::slice_array.
+///
+/// A slice_array is created by using:
+/// operator[](std::slice slicearr);
+/// and std::slice is created by:
+/// slice(std::size_t start, std::size_t size, std::size_t stride);
+/// The std::slice_array has the following members:
+/// - __vp_ pointes to std::valarray::__begin_ + @a start
+/// - __size_ is @a size
+/// - __stride_is @a stride
+class LibcxxStdSliceArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdSliceArraySyntheticFrontEnd() override;
+
+ llvm::Expected<uint32_t> CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
+
+ lldb::ChildCacheState Update() override;
+
+ bool MightHaveChildren() override;
+
+ size_t GetIndexOfChildWithName(ConstString name) override;
+
+private:
+ /// A non-owning pointer to slice_array.__vp_.
+ ValueObject *m_start = nullptr;
+ /// slice_array.__size_.
+ size_t m_size = 0;
+ /// slice_array.__stride_.
+ size_t m_stride = 0;
+ /// The type of slize_array's template argument T.
+ CompilerType m_element_type;
+ /// The sizeof slize_array's template argument T.
+ uint32_t m_element_size = 0;
+};
+
+} // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
+ LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
+ if (valobj_sp)
+ Update();
+}
+
+lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
+ ~LibcxxStdSliceArraySyntheticFrontEnd() {
+ // these need to stay around because they are child objects who will follow
+ // their parent's life cycle
+ // delete m_start;
+}
+
+llvm::Expected<uint32_t> lldb_private::formatters::
+ LibcxxStdSliceArraySyntheticFrontEnd::CalculateNumChildren() {
+ return m_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::GetChildAtIndex(
+ uint32_t idx) {
+ if (!m_start)
+ return lldb::ValueObjectSP();
+
+ uint64_t offset = idx * m_stride * 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);
+}
+
+lldb::ChildCacheState
+lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::Update() {
+ m_start = nullptr;
+
+ CompilerType type = m_backend.GetCompilerType();
+ if (type.GetNumTemplateArguments() == 0)
+ return ChildCacheState::eRefetch;
+
+ 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 ChildCacheState::eRefetch;
+
+ ValueObjectSP start = m_backend.GetChildMemberWithName("__vp_");
+ ValueObjectSP size = m_backend.GetChildMemberWithName("__size_");
+ ValueObjectSP stride = m_backend.GetChildMemberWithName("__stride_");
+
+ if (!start || !size || !stride)
+ return ChildCacheState::eRefetch;
+
+ m_start = start.get();
+ m_size = size->GetValueAsUnsigned(0);
+ m_stride = stride->GetValueAsUnsigned(0);
+
+ return ChildCacheState::eRefetch;
+}
+
+bool lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
+ MightHaveChildren() {
+ return true;
+}
+
+size_t lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::
+ GetIndexOfChildWithName(ConstString name) {
+ if (!m_start)
+ return std::numeric_limits<size_t>::max();
+ return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+ if (!valobj_sp)
+ return nullptr;
+ return new LibcxxStdSliceArraySyntheticFrontEnd(valobj_sp);
+}
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
index 7b54b3485d04d4..b59b770ed6790d 100644
--- 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
@@ -18,6 +18,10 @@ def test_with_run_command(self):
self, "break here", lldb.SBFileSpec("main.cpp", False)
)
+ #
+ # std::valarray
+ #
+
self.expect(
"frame variable va_int",
substrs=[
@@ -76,3 +80,30 @@ def test_with_run_command(self):
error=True,
substrs=['array index 4 is not valid for "(valarray<double>) va_double"'],
)
+
+ #
+ # std::slice_array
+ #
+
+ self.expect(
+ "frame variable sa",
+ substrs=[
+ "sa = stride=2 size=4",
+ "[0] = 1",
+ "[1] = 3",
+ "[2] = 5",
+ "[3] = 7",
+ "}",
+ ],
+ )
+
+ # check access-by-index
+ self.expect("frame variable sa[0]", substrs=["1"])
+ self.expect("frame variable sa[1]", substrs=["3"])
+ self.expect("frame variable sa[2]", substrs=["5"])
+ self.expect("frame variable sa[3]", substrs=["7"])
+ self.expect(
+ "frame variable sa[4]",
+ error=True,
+ substrs=['array index 4 is not valid for "(slice_array<int>) sa"'],
+ )
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
index f32921e16fa10e..1481d8b4032927 100644
--- 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
@@ -13,5 +13,8 @@ int main() {
std::valarray<double> va_double({1.0, 0.5, 0.25, 0.125});
+ std::valarray<int> va({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
+ std::slice_array<int> sa = va[std::slice(1, 4, 2)];
+
std::cout << "break here\n";
}
>From 75f56452d9d20a0b5e20dd09a60f8a72a46fb7be Mon Sep 17 00:00:00 2001
From: Mark de Wever <zar-rpg at xs4all.nl>
Date: Sun, 17 Mar 2024 14:56:23 +0100
Subject: [PATCH 2/2] Update
lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp
Co-authored-by: Michael Buch <michaelbuch12 at gmail.com>
---
lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp
index 724514dd0697b9..323de11b1c97c9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp
@@ -47,7 +47,7 @@ bool LibcxxStdSliceArraySummaryProvider(ValueObject &valobj, Stream &stream,
/// and std::slice is created by:
/// slice(std::size_t start, std::size_t size, std::size_t stride);
/// The std::slice_array has the following members:
-/// - __vp_ pointes to std::valarray::__begin_ + @a start
+/// - __vp_ points to std::valarray::__begin_ + @a start
/// - __size_ is @a size
/// - __stride_is @a stride
class LibcxxStdSliceArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
More information about the lldb-commits
mailing list