xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===-- LibCxxSpan.cpp ----------------------------------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "LibCxx.h"
1081ad6265SDimitry Andric 
1181ad6265SDimitry Andric #include "lldb/Core/ValueObject.h"
1281ad6265SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
1381ad6265SDimitry Andric #include "lldb/Utility/ConstString.h"
1481ad6265SDimitry Andric #include "llvm/ADT/APSInt.h"
15bdd1243dSDimitry Andric #include <optional>
1681ad6265SDimitry Andric 
1781ad6265SDimitry Andric using namespace lldb;
1881ad6265SDimitry Andric using namespace lldb_private;
1981ad6265SDimitry Andric using namespace lldb_private::formatters;
2081ad6265SDimitry Andric 
2181ad6265SDimitry Andric namespace lldb_private {
2281ad6265SDimitry Andric namespace formatters {
2381ad6265SDimitry Andric 
2481ad6265SDimitry Andric class LibcxxStdSpanSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
2581ad6265SDimitry Andric public:
2681ad6265SDimitry Andric   LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
2781ad6265SDimitry Andric 
2881ad6265SDimitry Andric   ~LibcxxStdSpanSyntheticFrontEnd() override = default;
2981ad6265SDimitry Andric 
30*0fca6ea1SDimitry Andric   llvm::Expected<uint32_t> CalculateNumChildren() override;
3181ad6265SDimitry Andric 
32*0fca6ea1SDimitry Andric   lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
3381ad6265SDimitry Andric 
3481ad6265SDimitry Andric   /// Determines properties of the std::span<> associated with this object
3581ad6265SDimitry Andric   //
3681ad6265SDimitry Andric   // std::span can either be instantiated with a compile-time known
3781ad6265SDimitry Andric   // extent or a std::dynamic_extent (this is the default if only the
3881ad6265SDimitry Andric   // type template argument is provided). The layout of std::span
3981ad6265SDimitry Andric   // depends on whether the extent is dynamic or not. For static
4081ad6265SDimitry Andric   // extents (e.g., std::span<int, 9>):
4181ad6265SDimitry Andric   //
4281ad6265SDimitry Andric   // (std::__1::span<const int, 9>) s = {
4381ad6265SDimitry Andric   //   __data = 0x000000016fdff494
4481ad6265SDimitry Andric   // }
4581ad6265SDimitry Andric   //
4681ad6265SDimitry Andric   // For dynamic extents, e.g., std::span<int>, the layout is:
4781ad6265SDimitry Andric   //
4881ad6265SDimitry Andric   // (std::__1::span<const int, 18446744073709551615>) s = {
4981ad6265SDimitry Andric   //   __data = 0x000000016fdff494
5081ad6265SDimitry Andric   //   __size = 6
5181ad6265SDimitry Andric   // }
5281ad6265SDimitry Andric   //
5381ad6265SDimitry Andric   // This function checks for a '__size' member to determine the number
5481ad6265SDimitry Andric   // of elements in the span. If no such member exists, we get the size
5581ad6265SDimitry Andric   // from the only other place it can be: the template argument.
56*0fca6ea1SDimitry Andric   lldb::ChildCacheState Update() override;
5781ad6265SDimitry Andric 
5881ad6265SDimitry Andric   bool MightHaveChildren() override;
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric   size_t GetIndexOfChildWithName(ConstString name) override;
6181ad6265SDimitry Andric 
6281ad6265SDimitry Andric private:
6381ad6265SDimitry Andric   ValueObject *m_start = nullptr; ///< First element of span. Held, not owned.
6481ad6265SDimitry Andric   CompilerType m_element_type{};  ///< Type of span elements.
6581ad6265SDimitry Andric   size_t m_num_elements = 0;      ///< Number of elements in span.
6681ad6265SDimitry Andric   uint32_t m_element_size = 0;    ///< Size in bytes of each span element.
6781ad6265SDimitry Andric };
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
7081ad6265SDimitry Andric     LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
7181ad6265SDimitry Andric     : SyntheticChildrenFrontEnd(*valobj_sp) {
7281ad6265SDimitry Andric   if (valobj_sp)
7381ad6265SDimitry Andric     Update();
7481ad6265SDimitry Andric }
7581ad6265SDimitry Andric 
76*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters::
77*0fca6ea1SDimitry Andric     LibcxxStdSpanSyntheticFrontEnd::CalculateNumChildren() {
7881ad6265SDimitry Andric   return m_num_elements;
7981ad6265SDimitry Andric }
8081ad6265SDimitry Andric 
8181ad6265SDimitry Andric lldb::ValueObjectSP
8281ad6265SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::GetChildAtIndex(
83*0fca6ea1SDimitry Andric     uint32_t idx) {
8481ad6265SDimitry Andric   if (!m_start)
8581ad6265SDimitry Andric     return {};
8681ad6265SDimitry Andric 
8781ad6265SDimitry Andric   uint64_t offset = idx * m_element_size;
8881ad6265SDimitry Andric   offset = offset + m_start->GetValueAsUnsigned(0);
8981ad6265SDimitry Andric   StreamString name;
9081ad6265SDimitry Andric   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
9181ad6265SDimitry Andric   return CreateValueObjectFromAddress(name.GetString(), offset,
9281ad6265SDimitry Andric                                       m_backend.GetExecutionContextRef(),
9381ad6265SDimitry Andric                                       m_element_type);
9481ad6265SDimitry Andric }
9581ad6265SDimitry Andric 
96*0fca6ea1SDimitry Andric lldb::ChildCacheState
97*0fca6ea1SDimitry Andric lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() {
9881ad6265SDimitry Andric   // Get element type.
99bdd1243dSDimitry Andric   ValueObjectSP data_type_finder_sp = GetChildMemberWithName(
100bdd1243dSDimitry Andric       m_backend, {ConstString("__data_"), ConstString("__data")});
10181ad6265SDimitry Andric   if (!data_type_finder_sp)
102*0fca6ea1SDimitry Andric     return lldb::ChildCacheState::eRefetch;
10381ad6265SDimitry Andric 
10481ad6265SDimitry Andric   m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
10581ad6265SDimitry Andric 
10681ad6265SDimitry Andric   // Get element size.
107bdd1243dSDimitry Andric   if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
10881ad6265SDimitry Andric     m_element_size = *size;
10981ad6265SDimitry Andric 
11081ad6265SDimitry Andric     // Get data.
11181ad6265SDimitry Andric     if (m_element_size > 0) {
11281ad6265SDimitry Andric       m_start = data_type_finder_sp.get();
11381ad6265SDimitry Andric     }
11481ad6265SDimitry Andric 
11581ad6265SDimitry Andric     // Get number of elements.
116bdd1243dSDimitry Andric     if (auto size_sp = GetChildMemberWithName(
117bdd1243dSDimitry Andric             m_backend, {ConstString("__size_"), ConstString("__size")})) {
11881ad6265SDimitry Andric       m_num_elements = size_sp->GetValueAsUnsigned(0);
11981ad6265SDimitry Andric     } else if (auto arg =
12081ad6265SDimitry Andric                    m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) {
12181ad6265SDimitry Andric 
12281ad6265SDimitry Andric       m_num_elements = arg->value.getLimitedValue();
12381ad6265SDimitry Andric     }
12481ad6265SDimitry Andric   }
12581ad6265SDimitry Andric 
126*0fca6ea1SDimitry Andric   return lldb::ChildCacheState::eReuse;
12781ad6265SDimitry Andric }
12881ad6265SDimitry Andric 
12981ad6265SDimitry Andric bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
13081ad6265SDimitry Andric     MightHaveChildren() {
13181ad6265SDimitry Andric   return true;
13281ad6265SDimitry Andric }
13381ad6265SDimitry Andric 
13481ad6265SDimitry Andric size_t lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
13581ad6265SDimitry Andric     GetIndexOfChildWithName(ConstString name) {
13681ad6265SDimitry Andric   if (!m_start)
13781ad6265SDimitry Andric     return UINT32_MAX;
13881ad6265SDimitry Andric   return ExtractIndexFromString(name.GetCString());
13981ad6265SDimitry Andric }
14081ad6265SDimitry Andric 
14181ad6265SDimitry Andric lldb_private::SyntheticChildrenFrontEnd *
14281ad6265SDimitry Andric LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *,
14381ad6265SDimitry Andric                                       lldb::ValueObjectSP valobj_sp) {
14481ad6265SDimitry Andric   if (!valobj_sp)
14581ad6265SDimitry Andric     return nullptr;
14681ad6265SDimitry Andric   CompilerType type = valobj_sp->GetCompilerType();
14781ad6265SDimitry Andric   if (!type.IsValid() || type.GetNumTemplateArguments() != 2)
14881ad6265SDimitry Andric     return nullptr;
14981ad6265SDimitry Andric   return new LibcxxStdSpanSyntheticFrontEnd(valobj_sp);
15081ad6265SDimitry Andric }
15181ad6265SDimitry Andric 
15281ad6265SDimitry Andric } // namespace formatters
15381ad6265SDimitry Andric } // namespace lldb_private
154