xref: /llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp (revision b852fb1ec5fa15f0b913cc4988cbd09239b19904)
1ea9ff9faSAdrian Prantl //===-- LibCxxSpan.cpp ----------------------------------------------------===//
2ea9ff9faSAdrian Prantl //
3ea9ff9faSAdrian Prantl // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ea9ff9faSAdrian Prantl // See https://llvm.org/LICENSE.txt for license information.
5ea9ff9faSAdrian Prantl // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ea9ff9faSAdrian Prantl //
7ea9ff9faSAdrian Prantl //===----------------------------------------------------------------------===//
8ea9ff9faSAdrian Prantl 
9ea9ff9faSAdrian Prantl #include "LibCxx.h"
10ea9ff9faSAdrian Prantl 
11ea9ff9faSAdrian Prantl #include "lldb/DataFormatters/FormattersHelpers.h"
12ea9ff9faSAdrian Prantl #include "lldb/Utility/ConstString.h"
13*b852fb1eSJonas Devlieghere #include "lldb/ValueObject/ValueObject.h"
14ea9ff9faSAdrian Prantl #include "llvm/ADT/APSInt.h"
15f190ce62SKazu Hirata #include <optional>
16ea9ff9faSAdrian Prantl 
17ea9ff9faSAdrian Prantl using namespace lldb;
18ea9ff9faSAdrian Prantl using namespace lldb_private;
19ea9ff9faSAdrian Prantl using namespace lldb_private::formatters;
20ea9ff9faSAdrian Prantl 
21ea9ff9faSAdrian Prantl namespace lldb_private {
22ea9ff9faSAdrian Prantl namespace formatters {
23ea9ff9faSAdrian Prantl 
24ea9ff9faSAdrian Prantl class LibcxxStdSpanSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
25ea9ff9faSAdrian Prantl public:
26ea9ff9faSAdrian Prantl   LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
27ea9ff9faSAdrian Prantl 
28ea9ff9faSAdrian Prantl   ~LibcxxStdSpanSyntheticFrontEnd() override = default;
29ea9ff9faSAdrian Prantl 
30624ea68cSAdrian Prantl   llvm::Expected<uint32_t> CalculateNumChildren() override;
31ea9ff9faSAdrian Prantl 
32e710523eSAdrian Prantl   lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
33ea9ff9faSAdrian Prantl 
34ea9ff9faSAdrian Prantl   /// Determines properties of the std::span<> associated with this object
35ea9ff9faSAdrian Prantl   //
36ea9ff9faSAdrian Prantl   // std::span can either be instantiated with a compile-time known
37ea9ff9faSAdrian Prantl   // extent or a std::dynamic_extent (this is the default if only the
38ea9ff9faSAdrian Prantl   // type template argument is provided). The layout of std::span
39ea9ff9faSAdrian Prantl   // depends on whether the extent is dynamic or not. For static
40ea9ff9faSAdrian Prantl   // extents (e.g., std::span<int, 9>):
41ea9ff9faSAdrian Prantl   //
42ea9ff9faSAdrian Prantl   // (std::__1::span<const int, 9>) s = {
43ea9ff9faSAdrian Prantl   //   __data = 0x000000016fdff494
44ea9ff9faSAdrian Prantl   // }
45ea9ff9faSAdrian Prantl   //
46ea9ff9faSAdrian Prantl   // For dynamic extents, e.g., std::span<int>, the layout is:
47ea9ff9faSAdrian Prantl   //
48ea9ff9faSAdrian Prantl   // (std::__1::span<const int, 18446744073709551615>) s = {
49ea9ff9faSAdrian Prantl   //   __data = 0x000000016fdff494
50ea9ff9faSAdrian Prantl   //   __size = 6
51ea9ff9faSAdrian Prantl   // }
52ea9ff9faSAdrian Prantl   //
53ea9ff9faSAdrian Prantl   // This function checks for a '__size' member to determine the number
54ea9ff9faSAdrian Prantl   // of elements in the span. If no such member exists, we get the size
55ea9ff9faSAdrian Prantl   // from the only other place it can be: the template argument.
56d7fb94b6SMichael Buch   lldb::ChildCacheState Update() override;
57ea9ff9faSAdrian Prantl 
58ea9ff9faSAdrian Prantl   bool MightHaveChildren() override;
59ea9ff9faSAdrian Prantl 
60ea9ff9faSAdrian Prantl   size_t GetIndexOfChildWithName(ConstString name) override;
61ea9ff9faSAdrian Prantl 
62ea9ff9faSAdrian Prantl private:
63ea9ff9faSAdrian Prantl   ValueObject *m_start = nullptr; ///< First element of span. Held, not owned.
64ea9ff9faSAdrian Prantl   CompilerType m_element_type{};  ///< Type of span elements.
65ea9ff9faSAdrian Prantl   size_t m_num_elements = 0;      ///< Number of elements in span.
66ea9ff9faSAdrian Prantl   uint32_t m_element_size = 0;    ///< Size in bytes of each span element.
67ea9ff9faSAdrian Prantl };
68ea9ff9faSAdrian Prantl 
69ea9ff9faSAdrian Prantl lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
70ea9ff9faSAdrian Prantl     LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
71ea9ff9faSAdrian Prantl     : SyntheticChildrenFrontEnd(*valobj_sp) {
72ea9ff9faSAdrian Prantl   if (valobj_sp)
73ea9ff9faSAdrian Prantl     Update();
74ea9ff9faSAdrian Prantl }
75ea9ff9faSAdrian Prantl 
76624ea68cSAdrian Prantl llvm::Expected<uint32_t> lldb_private::formatters::
77624ea68cSAdrian Prantl     LibcxxStdSpanSyntheticFrontEnd::CalculateNumChildren() {
78ea9ff9faSAdrian Prantl   return m_num_elements;
79ea9ff9faSAdrian Prantl }
80ea9ff9faSAdrian Prantl 
81ea9ff9faSAdrian Prantl lldb::ValueObjectSP
82ea9ff9faSAdrian Prantl lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::GetChildAtIndex(
83e710523eSAdrian Prantl     uint32_t idx) {
84ea9ff9faSAdrian Prantl   if (!m_start)
85ea9ff9faSAdrian Prantl     return {};
86ea9ff9faSAdrian Prantl 
87ea9ff9faSAdrian Prantl   uint64_t offset = idx * m_element_size;
88ea9ff9faSAdrian Prantl   offset = offset + m_start->GetValueAsUnsigned(0);
89ea9ff9faSAdrian Prantl   StreamString name;
90ea9ff9faSAdrian Prantl   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
91ea9ff9faSAdrian Prantl   return CreateValueObjectFromAddress(name.GetString(), offset,
92ea9ff9faSAdrian Prantl                                       m_backend.GetExecutionContextRef(),
93ea9ff9faSAdrian Prantl                                       m_element_type);
94ea9ff9faSAdrian Prantl }
95ea9ff9faSAdrian Prantl 
96d7fb94b6SMichael Buch lldb::ChildCacheState
97d7fb94b6SMichael Buch lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() {
98ea9ff9faSAdrian Prantl   // Get element type.
992f4a66eeSAdrian Prantl   ValueObjectSP data_type_finder_sp = GetChildMemberWithName(
1002f4a66eeSAdrian Prantl       m_backend, {ConstString("__data_"), ConstString("__data")});
101ea9ff9faSAdrian Prantl   if (!data_type_finder_sp)
102d7fb94b6SMichael Buch     return lldb::ChildCacheState::eRefetch;
103ea9ff9faSAdrian Prantl 
104ea9ff9faSAdrian Prantl   m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
105ea9ff9faSAdrian Prantl 
106ea9ff9faSAdrian Prantl   // Get element size.
1072fe83274SKazu Hirata   if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
108ea9ff9faSAdrian Prantl     m_element_size = *size;
109ea9ff9faSAdrian Prantl 
110ea9ff9faSAdrian Prantl     // Get data.
111ea9ff9faSAdrian Prantl     if (m_element_size > 0) {
112ea9ff9faSAdrian Prantl       m_start = data_type_finder_sp.get();
113ea9ff9faSAdrian Prantl     }
114ea9ff9faSAdrian Prantl 
115ea9ff9faSAdrian Prantl     // Get number of elements.
1162f4a66eeSAdrian Prantl     if (auto size_sp = GetChildMemberWithName(
1172f4a66eeSAdrian Prantl             m_backend, {ConstString("__size_"), ConstString("__size")})) {
118ea9ff9faSAdrian Prantl       m_num_elements = size_sp->GetValueAsUnsigned(0);
119ea9ff9faSAdrian Prantl     } else if (auto arg =
120ea9ff9faSAdrian Prantl                    m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) {
121ea9ff9faSAdrian Prantl 
122ea9ff9faSAdrian Prantl       m_num_elements = arg->value.getLimitedValue();
123ea9ff9faSAdrian Prantl     }
124ea9ff9faSAdrian Prantl   }
125ea9ff9faSAdrian Prantl 
126d7fb94b6SMichael Buch   return lldb::ChildCacheState::eReuse;
127ea9ff9faSAdrian Prantl }
128ea9ff9faSAdrian Prantl 
129ea9ff9faSAdrian Prantl bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
130ea9ff9faSAdrian Prantl     MightHaveChildren() {
131ea9ff9faSAdrian Prantl   return true;
132ea9ff9faSAdrian Prantl }
133ea9ff9faSAdrian Prantl 
134ea9ff9faSAdrian Prantl size_t lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
135ea9ff9faSAdrian Prantl     GetIndexOfChildWithName(ConstString name) {
136ea9ff9faSAdrian Prantl   if (!m_start)
137ea9ff9faSAdrian Prantl     return UINT32_MAX;
138ea9ff9faSAdrian Prantl   return ExtractIndexFromString(name.GetCString());
139ea9ff9faSAdrian Prantl }
140ea9ff9faSAdrian Prantl 
141ea9ff9faSAdrian Prantl lldb_private::SyntheticChildrenFrontEnd *
142ea9ff9faSAdrian Prantl LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *,
143ea9ff9faSAdrian Prantl                                       lldb::ValueObjectSP valobj_sp) {
144ea9ff9faSAdrian Prantl   if (!valobj_sp)
145ea9ff9faSAdrian Prantl     return nullptr;
146ea9ff9faSAdrian Prantl   CompilerType type = valobj_sp->GetCompilerType();
147ea9ff9faSAdrian Prantl   if (!type.IsValid() || type.GetNumTemplateArguments() != 2)
148ea9ff9faSAdrian Prantl     return nullptr;
149ea9ff9faSAdrian Prantl   return new LibcxxStdSpanSyntheticFrontEnd(valobj_sp);
150ea9ff9faSAdrian Prantl }
151ea9ff9faSAdrian Prantl 
152ea9ff9faSAdrian Prantl } // namespace formatters
153ea9ff9faSAdrian Prantl } // namespace lldb_private
154