danilashtefan created this revision.
Herald added a subscriber: mgorny.
danilashtefan requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D112180

Files:
  lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
  lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
  lldb/source/Plugins/Language/CPlusPlus/LibStdcppBitset.cpp
  
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/Makefile
  
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/TestDataFormatterStdBitset.py
  
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/main.cpp

Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/main.cpp
@@ -0,0 +1,29 @@
+#include <bitset>
+#include <stdio.h>
+
+template<std::size_t N>
+void fill(std::bitset<N> &b) {
+  b.set();
+  b[0] = b[1] = false;
+  for (std::size_t i = 2; i < N; ++i) {
+    for (std::size_t j = 2*i; j < N; j+=i)
+      b[j] = false;
+  }
+}
+
+template<std::size_t N>
+void by_ref_and_ptr(std::bitset<N> &ref, std::bitset<N> *ptr) {
+    // Check ref and ptr
+    return;
+}
+
+int main() {
+  std::bitset<0> empty;
+  std::bitset<13> small;
+  fill(small);
+  std::bitset<70> large;
+  fill(large);
+  by_ref_and_ptr(small, &small); // break here
+  by_ref_and_ptr(large, &large);
+  return 0;
+}
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/TestDataFormatterStdBitset.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/TestDataFormatterStdBitset.py
@@ -0,0 +1,232 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class StdBitsetDataFormatterTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        TestBase.setUp(self)
+        primes = [1]*300
+        primes[0] = primes[1] = 0
+        for i in range(2, len(primes)):
+            for j in range(2*i, len(primes), i):
+                primes[j] = 0
+        self.primes = primes
+
+    def check(self, name, size):
+        var = self.frame().FindVariable(name)
+        self.assertTrue(var.IsValid())
+        self.assertEqual(var.GetNumChildren(), size)
+        for i in range(size):
+            child = var.GetChildAtIndex(i)
+            self.assertEqual(child.GetValueAsUnsigned(), self.primes[i],
+                    "variable: %s, index: %d"%(name, size))
+
+    @add_test_categories(["libstdcxx"])
+    def test_value(self):
+        """Test that std::bitset is displayed correctly"""
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, '// break here',
+                lldb.SBFileSpec("main.cpp", False))
+
+        self.check("empty", 0)
+        self.check("small", 13)
+        self.check("large", 70)
+
+    @add_test_categories(["libstdcxx"])
+    def test_ptr_and_ref(self):
+        """Test that ref and ptr to std::bitset is displayed correctly"""
+        self.build()
+        (_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self,
+                'Check ref and ptr',
+                lldb.SBFileSpec("main.cpp", False))
+
+        #self.check("ref", 13)
+        #self.check("ptr", 13)
+        self.expect("p ref",
+                    substrs=['[0] = false',
+                    '[1] = false',
+                    '[2] = true',
+                    '[3] = true', 
+                    '[4] = false', 
+                    '[5] = true', 
+                    '[6] = false', 
+                    '[7] = true', 
+                    '[8] = false',
+                    '[9] = false', 
+                    '[10] = false', 
+                    '[11] = true', 
+                    '[12] = false'])
+
+        self.expect("p *ptr",
+                    substrs=['[0] = false',
+                    '[1] = false',
+                    '[2] = true',
+                    '[3] = true', 
+                    '[4] = false', 
+                    '[5] = true', 
+                    '[6] = false', 
+                    '[7] = true', 
+                    '[8] = false',
+                    '[9] = false', 
+                    '[10] = false', 
+                    '[11] = true', 
+                    '[12] = false'])
+
+     
+
+        lldbutil.continue_to_breakpoint(process, bkpt)
+
+        self.expect("p ref",
+                    substrs=['[0] = false',
+                    '[1] = false',
+                    '[2] = true',
+                    '[3] = true',
+                    '[4] = false',
+                    '[5] = true',
+                    '[6] = false',
+                    '[7] = true',
+                    '[8] = false',
+                    '[9] = false',
+                    '[10] = false',
+                    '[11] = true',
+                    '[12] = false',
+                    '[13] = true',
+                    '[14] = false',
+                    '[15] = false',
+                    '[16] = false',
+                    '[17] = true',
+                    '[18] = false',
+                    '[19] = true',
+                    '[20] = false',
+                    '[21] = false',
+                    '[22] = false',
+                    '[23] = true',
+                    '[24] = false',
+                    '[25] = false',
+                    '[26] = false',
+                    '[27] = false',
+                    '[28] = false',
+                    '[29] = true',
+                    '[30] = false',
+                    '[31] = true',
+                    '[32] = false',
+                    '[33] = false',
+                    '[34] = false',
+                    '[35] = false',
+                    '[36] = false',
+                    '[37] = true',
+                    '[38] = false',
+                    '[39] = false',
+                    '[40] = false',
+                    '[41] = true',
+                    '[42] = false',
+                    '[43] = true',
+                    '[44] = false',
+                    '[45] = false',
+                    '[46] = false',
+                    '[47] = true',
+                    '[48] = false',
+                    '[49] = false',
+                    '[50] = false',
+                    '[51] = false',
+                    '[52] = false',
+                    '[53] = true',
+                    '[54] = false',
+                    '[55] = false',
+                    '[56] = false',
+                    '[57] = false',
+                    '[58] = false',
+                    '[59] = true',
+                    '[60] = false',
+                    '[61] = true',
+                    '[62] = false',
+                    '[63] = false',
+                    '[64] = false',
+                    '[65] = false',
+                    '[66] = false',
+                    '[67] = true',
+                    '[68] = false',
+                    '[69] = false'])
+
+        self.expect("p *ptr",
+                    substrs=['[0] = false',
+                    '[1] = false',
+                    '[2] = true',
+                    '[3] = true',
+                    '[4] = false',
+                    '[5] = true',
+                    '[6] = false',
+                    '[7] = true',
+                    '[8] = false',
+                    '[9] = false',
+                    '[10] = false',
+                    '[11] = true',
+                    '[12] = false',
+                    '[13] = true',
+                    '[14] = false',
+                    '[15] = false',
+                    '[16] = false',
+                    '[17] = true',
+                    '[18] = false',
+                    '[19] = true',
+                    '[20] = false',
+                    '[21] = false',
+                    '[22] = false',
+                    '[23] = true',
+                    '[24] = false',
+                    '[25] = false',
+                    '[26] = false',
+                    '[27] = false',
+                    '[28] = false',
+                    '[29] = true',
+                    '[30] = false',
+                    '[31] = true',
+                    '[32] = false',
+                    '[33] = false',
+                    '[34] = false',
+                    '[35] = false',
+                    '[36] = false',
+                    '[37] = true',
+                    '[38] = false',
+                    '[39] = false',
+                    '[40] = false',
+                    '[41] = true',
+                    '[42] = false',
+                    '[43] = true',
+                    '[44] = false',
+                    '[45] = false',
+                    '[46] = false',
+                    '[47] = true',
+                    '[48] = false',
+                    '[49] = false',
+                    '[50] = false',
+                    '[51] = false',
+                    '[52] = false',
+                    '[53] = true',
+                    '[54] = false',
+                    '[55] = false',
+                    '[56] = false',
+                    '[57] = false',
+                    '[58] = false',
+                    '[59] = true',
+                    '[60] = false',
+                    '[61] = true',
+                    '[62] = false',
+                    '[63] = false',
+                    '[64] = false',
+                    '[65] = false',
+                    '[66] = false',
+                    '[67] = true',
+                    '[68] = false',
+                    '[69] = false'])
\ No newline at end of file
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/bitset/Makefile
@@ -0,0 +1,5 @@
+CXX_SOURCES := main.cpp
+
+USE_LIBSTDCPP := 1
+
+include Makefile.rules
Index: lldb/source/Plugins/Language/CPlusPlus/LibStdcppBitset.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Language/CPlusPlus/LibStdcppBitset.cpp
@@ -0,0 +1,121 @@
+//===-- LibCStdcppBitset.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 "LibStdcpp.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace {
+
+class BitsetcppFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+  BitsetcppFrontEnd(ValueObject &valobj);
+
+  size_t GetIndexOfChildWithName(ConstString name) override {
+    return formatters::ExtractIndexFromString(name.GetCString());
+  }
+
+  bool MightHaveChildren() override { return true; }
+  bool Update() override;
+  size_t CalculateNumChildren() override { return m_elements.size(); }
+  ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+private:
+  // The lifetime of a ValueObject and all its derivative ValueObjects
+  // (children, clones, etc.) is managed by a ClusterManager. These
+  // objects are only destroyed when every shared pointer to any of them
+  // is destroyed, so we must not store a shared pointer to any ValueObject
+  // derived from our backend ValueObject (since we're in the same cluster).
+  // Value objects created from raw data (i.e. in a different cluster) must
+  // be referenced via shared pointer to keep them alive, however.
+  std::vector<ValueObjectSP> m_elements;
+  ValueObject* m_first = nullptr;
+  CompilerType m_bool_type;
+  ByteOrder m_byte_order = eByteOrderInvalid;
+  uint8_t m_byte_size = 0;
+};
+} // namespace
+
+BitsetcppFrontEnd::BitsetcppFrontEnd(ValueObject &valobj)
+    : SyntheticChildrenFrontEnd(valobj) {
+  m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool);
+  if (auto target_sp = m_backend.GetTargetSP()) {
+    m_byte_order = target_sp->GetArchitecture().GetByteOrder();
+    m_byte_size = target_sp->GetArchitecture().GetAddressByteSize();
+    Update();
+  }
+}
+
+bool BitsetcppFrontEnd::Update() {
+  m_elements.clear();
+  m_first = nullptr;
+
+  TargetSP target_sp = m_backend.GetTargetSP();
+  if (!target_sp)
+    return false;
+  size_t capping_size = target_sp->GetMaximumNumberOfChildrenToDisplay();
+
+  size_t size = 0;
+  if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0))
+    size = arg->value.getLimitedValue(capping_size);
+
+  m_elements.assign(size, ValueObjectSP());
+  m_first = m_backend.GetChildMemberWithName(ConstString("_M_w"), true).get();
+  return false;
+}
+
+ValueObjectSP BitsetcppFrontEnd::GetChildAtIndex(size_t idx) {
+  if (idx >= m_elements.size() || !m_first)
+    return ValueObjectSP();
+
+  if (m_elements[idx])
+    return m_elements[idx];
+
+  ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false);
+  CompilerType type;
+  ValueObjectSP chunk;
+  // For small bitsets __first_ is not an array, but a plain size_t.
+  if (m_first->GetCompilerType().IsArrayType(&type)) {
+    llvm::Optional<uint64_t> bit_size =
+        type.GetBitSize(ctx.GetBestExecutionContextScope());
+    if (!bit_size || *bit_size == 0)
+      return {};
+    chunk = m_first->GetChildAtIndex(idx / *bit_size, true);
+  } else {
+    type = m_first->GetCompilerType();
+    chunk = m_first->GetSP();
+  }
+  if (!type || !chunk)
+    return {};
+
+  llvm::Optional<uint64_t> bit_size =
+      type.GetBitSize(ctx.GetBestExecutionContextScope());
+  if (!bit_size || *bit_size == 0)
+    return {};
+  size_t chunk_idx = idx % *bit_size;
+  uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx));
+  DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size);
+
+  m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(),
+                                              data, ctx, m_bool_type);
+
+
+  return m_elements[idx];
+}
+
+SyntheticChildrenFrontEnd *formatters::LibStdcppBitsetSyntheticFrontEndCreator(
+    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+  if (valobj_sp)
+    return new BitsetcppFrontEnd(*valobj_sp);
+  return nullptr;
+}
Index: lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
+++ lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -41,6 +41,11 @@
 LibStdcppTupleSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                        lldb::ValueObjectSP);
 
+
+SyntheticChildrenFrontEnd *
+LibStdcppBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *,
+                                       lldb::ValueObjectSP);
+
 SyntheticChildrenFrontEnd *
 LibStdcppVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                                 lldb::ValueObjectSP);
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -311,7 +311,7 @@
 public:
   void reset() { Alloc.Reset(); }
 
-  template <typename T, typename... Args> T *makeNode(Args &&... args) {
+  template <typename T, typename... Args> T *makeNode(Args &&...args) {
     return new (Alloc.Allocate(sizeof(T), alignof(T)))
         T(std::forward<Args>(args)...);
   }
@@ -332,13 +332,12 @@
 public:
   ManglingSubstitutor() : Base(nullptr, nullptr) {}
 
-  template<typename... Ts>
-  ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) {
+  template <typename... Ts>
+  ConstString substitute(llvm::StringRef Mangled, Ts &&...Vals) {
     this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
     return substituteImpl(Mangled);
   }
 
-
 protected:
   void reset(llvm::StringRef Mangled) {
     Base::reset(Mangled.begin(), Mangled.end());
@@ -392,7 +391,6 @@
         llvm::StringRef(Written, std::distance(Written, currentParserPos()));
     Written = currentParserPos();
   }
-
 };
 
 /// Given a mangled function `Mangled`, replace all the primitive function type
@@ -566,26 +564,23 @@
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
                 "std::u16string summary provider",
-                ConstString(
-                    "^std::__[[:alnum:]]+::basic_string<char16_t, "
-                    "std::__[[:alnum:]]+::char_traits<char16_t>, "
-                    "std::__[[:alnum:]]+::allocator<char16_t> >$"),
+                ConstString("^std::__[[:alnum:]]+::basic_string<char16_t, "
+                            "std::__[[:alnum:]]+::char_traits<char16_t>, "
+                            "std::__[[:alnum:]]+::allocator<char16_t> >$"),
                 stl_summary_flags, true);
 
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibcxxStringSummaryProviderUTF32,
                 "std::u32string summary provider",
-                ConstString(
-                    "^std::__[[:alnum:]]+::basic_string<char32_t, "
-                    "std::__[[:alnum:]]+::char_traits<char32_t>, "
-                    "std::__[[:alnum:]]+::allocator<char32_t> >$"),
+                ConstString("^std::__[[:alnum:]]+::basic_string<char32_t, "
+                            "std::__[[:alnum:]]+::char_traits<char32_t>, "
+                            "std::__[[:alnum:]]+::allocator<char32_t> >$"),
                 stl_summary_flags, true);
 
-  AddCXXSummary(cpp_category_sp,
-                lldb_private::formatters::LibcxxWStringSummaryProvider,
-                "std::wstring summary provider",
-                ConstString("^std::__[[:alnum:]]+::wstring$"),
-                stl_summary_flags, true);
+  AddCXXSummary(
+      cpp_category_sp, lldb_private::formatters::LibcxxWStringSummaryProvider,
+      "std::wstring summary provider",
+      ConstString("^std::__[[:alnum:]]+::wstring$"), stl_summary_flags, true);
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibcxxWStringSummaryProvider,
                 "std::wstring summary provider",
@@ -782,11 +777,11 @@
                 "libc++ std::tuple summary provider",
                 ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
                 stl_summary_flags, true);
-  AddCXXSummary(
-      cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
-      "libc++ std::atomic summary provider",
-      ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_summary_flags,
-      true);
+  AddCXXSummary(cpp_category_sp,
+                lldb_private::formatters::LibCxxAtomicSummaryProvider,
+                "libc++ std::atomic summary provider",
+                ConstString("^std::__[[:alnum:]]+::atomic<.+>$"),
+                stl_summary_flags, true);
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibcxxOptionalSummaryProvider,
                 "libc++ std::optional summary provider",
@@ -873,7 +868,8 @@
                   "std::allocator<char> >"),
       cxx11_string_summary_sp);
   cpp_category_sp->GetTypeSummariesContainer()->Add(
-      ConstString("std::__cxx11::basic_string<unsigned char, std::char_traits<unsigned char>, "
+      ConstString("std::__cxx11::basic_string<unsigned char, "
+                  "std::char_traits<unsigned char>, "
                   "std::allocator<unsigned char> >"),
       cxx11_string_summary_sp);
 
@@ -969,6 +965,12 @@
       "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
       stl_synth_flags, true);
 
+        AddCXXSynthetic(
+      cpp_category_sp,
+      lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator,
+      "std::bitset synthetic child",
+      ConstString("^std::bitset<.+>(( )?&)?$"), stl_synth_flags, true);
+
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
                 "libstdc++ std::unique_ptr summary provider",
@@ -1177,9 +1179,8 @@
 
   llvm::call_once(g_initialize, []() -> void {
     g_formatters.push_back([](lldb_private::ValueObject &valobj,
-                              lldb::DynamicValueType,
-                              FormatManager &
-                                  fmt_mgr) -> SyntheticChildren::SharedPointer {
+                              lldb::DynamicValueType, FormatManager &fmt_mgr)
+                               -> SyntheticChildren::SharedPointer {
       static CXXSyntheticChildren::SharedPointer formatter_sp(
           new CXXSyntheticChildren(
               SyntheticChildren::Flags()
@@ -1196,9 +1197,8 @@
       return nullptr;
     });
     g_formatters.push_back([](lldb_private::ValueObject &valobj,
-                              lldb::DynamicValueType,
-                              FormatManager &
-                                  fmt_mgr) -> SyntheticChildren::SharedPointer {
+                              lldb::DynamicValueType, FormatManager &fmt_mgr)
+                               -> SyntheticChildren::SharedPointer {
       static CXXSyntheticChildren::SharedPointer formatter_sp(
           new CXXSyntheticChildren(
               SyntheticChildren::Flags()
@@ -1213,7 +1213,6 @@
       }
       return nullptr;
     });
-
   });
 
   return g_formatters;
Index: lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -6,6 +6,7 @@
   LibCxx.cpp
   LibCxxAtomic.cpp
   LibCxxBitset.cpp
+  LibStdcppBitset.cpp
   LibCxxInitializerList.cpp
   LibCxxList.cpp
   LibCxxMap.cpp
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to