xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- LibCxxValarray.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "LibCxx.h"
10 
11 #include "lldb/DataFormatters/FormattersHelpers.h"
12 #include "lldb/ValueObject/ValueObject.h"
13 #include <optional>
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 using namespace lldb_private::formatters;
18 
19 namespace lldb_private {
20 namespace formatters {
21 class LibcxxStdValarraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
22 public:
23   LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
24 
25   ~LibcxxStdValarraySyntheticFrontEnd() override;
26 
27   llvm::Expected<uint32_t> CalculateNumChildren() override;
28 
29   lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
30 
31   lldb::ChildCacheState Update() override;
32 
33   llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
34 
35 private:
36   /// A non-owning pointer to valarray's __begin_ member.
37   ValueObject *m_start = nullptr;
38   /// A non-owning pointer to valarray's __end_ member.
39   ValueObject *m_finish = nullptr;
40   /// The type of valarray's template argument T.
41   CompilerType m_element_type;
42   /// The sizeof valarray's template argument T.
43   uint32_t m_element_size = 0;
44 };
45 
46 } // namespace formatters
47 } // namespace lldb_private
48 
49 lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)50     LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
51     : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
52   if (valobj_sp)
53     Update();
54 }
55 
56 lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
~LibcxxStdValarraySyntheticFrontEnd()57     ~LibcxxStdValarraySyntheticFrontEnd() {
58   // these need to stay around because they are child objects who will follow
59   // their parent's life cycle
60   // delete m_start;
61   // delete m_finish;
62 }
63 
64 llvm::Expected<uint32_t> lldb_private::formatters::
CalculateNumChildren()65     LibcxxStdValarraySyntheticFrontEnd::CalculateNumChildren() {
66   if (!m_start || !m_finish)
67     return 0;
68   uint64_t start_val = m_start->GetValueAsUnsigned(0);
69   uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
70 
71   if (start_val == 0 || finish_val == 0)
72     return 0;
73 
74   if (start_val >= finish_val)
75     return 0;
76 
77   size_t num_children = (finish_val - start_val);
78   if (num_children % m_element_size)
79     return 0;
80   return num_children / m_element_size;
81 }
82 
83 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx)84 lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::GetChildAtIndex(
85     uint32_t idx) {
86   if (!m_start || !m_finish)
87     return lldb::ValueObjectSP();
88 
89   uint64_t offset = idx * m_element_size;
90   offset = offset + m_start->GetValueAsUnsigned(0);
91   StreamString name;
92   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
93   return CreateValueObjectFromAddress(name.GetString(), offset,
94                                       m_backend.GetExecutionContextRef(),
95                                       m_element_type);
96 }
97 
98 lldb::ChildCacheState
Update()99 lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::Update() {
100   m_start = m_finish = nullptr;
101 
102   CompilerType type = m_backend.GetCompilerType();
103   if (type.GetNumTemplateArguments() == 0)
104     return ChildCacheState::eRefetch;
105 
106   m_element_type = type.GetTypeTemplateArgument(0);
107   if (std::optional<uint64_t> size =
108           llvm::expectedToOptional(m_element_type.GetByteSize(nullptr)))
109     m_element_size = *size;
110 
111   if (m_element_size == 0)
112     return ChildCacheState::eRefetch;
113 
114   ValueObjectSP start = m_backend.GetChildMemberWithName("__begin_");
115   ValueObjectSP finish = m_backend.GetChildMemberWithName("__end_");
116 
117   if (!start || !finish)
118     return ChildCacheState::eRefetch;
119 
120   m_start = start.get();
121   m_finish = finish.get();
122 
123   return ChildCacheState::eRefetch;
124 }
125 
126 llvm::Expected<size_t>
127 lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)128     GetIndexOfChildWithName(ConstString name) {
129   if (!m_start || !m_finish)
130     return llvm::createStringError("Type has no child named '%s'",
131                                    name.AsCString());
132   auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());
133   if (!optional_idx) {
134     return llvm::createStringError("Type has no child named '%s'",
135                                    name.AsCString());
136   }
137   return *optional_idx;
138 }
139 
140 lldb_private::SyntheticChildrenFrontEnd *
LibcxxStdValarraySyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)141 lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator(
142     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
143   if (!valobj_sp)
144     return nullptr;
145   return new LibcxxStdValarraySyntheticFrontEnd(valobj_sp);
146 }
147