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