Author: Mark de Wever Date: 2024-03-17T14:56:35+01:00 New Revision: 56d45b09dcd6c880215481bcc3c6d6281a04d264
URL: https://github.com/llvm/llvm-project/commit/56d45b09dcd6c880215481bcc3c6d6281a04d264 DIFF: https://github.com/llvm/llvm-project/commit/56d45b09dcd6c880215481bcc3c6d6281a04d264.diff LOG: [lldb][libc++] Adds slice_array data formatters. (#85544) Co-authored-by: Michael Buch <michaelbuc...@gmail.com> Added: lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp Modified: lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxx.h lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp Removed: ################################################################################ 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..323de11b1c97c9 --- /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_ points 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"; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits