LLDB mainline
LibCxxSpan.cpp
Go to the documentation of this file.
1//===-- LibCxxSpan.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
14#include "llvm/ADT/APSInt.h"
15#include "llvm/Support/ErrorExtras.h"
16#include <optional>
17
18using namespace lldb;
19using namespace lldb_private;
20using namespace lldb_private::formatters;
21
22namespace lldb_private {
23namespace formatters {
24
26public:
28
29 ~LibcxxStdSpanSyntheticFrontEnd() override = default;
30
31 llvm::Expected<uint32_t> CalculateNumChildren() override;
32
33 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
34
35 /// Determines properties of the std::span<> associated with this object
36 //
37 // std::span can either be instantiated with a compile-time known
38 // extent or a std::dynamic_extent (this is the default if only the
39 // type template argument is provided). The layout of std::span
40 // depends on whether the extent is dynamic or not. For static
41 // extents (e.g., std::span<int, 9>):
42 //
43 // (std::__1::span<const int, 9>) s = {
44 // __data = 0x000000016fdff494
45 // }
46 //
47 // For dynamic extents, e.g., std::span<int>, the layout is:
48 //
49 // (std::__1::span<const int, 18446744073709551615>) s = {
50 // __data = 0x000000016fdff494
51 // __size = 6
52 // }
53 //
54 // This function checks for a '__size' member to determine the number
55 // of elements in the span. If no such member exists, we get the size
56 // from the only other place it can be: the template argument.
58
59 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
60
61private:
62 ValueObject *m_start = nullptr; ///< First element of span. Held, not owned.
63 CompilerType m_element_type{}; ///< Type of span elements.
64 size_t m_num_elements = 0; ///< Number of elements in span.
65 uint32_t m_element_size = 0; ///< Size in bytes of each span element.
66};
67
74
79
82 uint32_t idx) {
83 if (!m_start)
84 return {};
85
86 uint64_t offset = idx * m_element_size;
87 offset = offset + m_start->GetValueAsUnsigned(0);
88 StreamString name;
89 name.Printf("[%" PRIu64 "]", (uint64_t)idx);
90 return CreateValueObjectFromAddress(name.GetString(), offset,
91 m_backend.GetExecutionContextRef(),
93}
94
97 // Get element type.
98 ValueObjectSP data_type_finder_sp = GetChildMemberWithName(
99 m_backend, {ConstString("__data_"), ConstString("__data")});
100 if (!data_type_finder_sp)
102
103 m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
104
105 // Get element size.
106 llvm::Expected<uint64_t> size_or_err = m_element_type.GetByteSize(nullptr);
107 if (!size_or_err)
108 LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), size_or_err.takeError(),
109 "{0}");
110 else {
111 m_element_size = *size_or_err;
112
113 // Get data.
114 if (m_element_size > 0) {
115 m_start = data_type_finder_sp.get();
116 }
117
118 // Get number of elements.
119 if (auto size_sp = GetChildMemberWithName(
120 m_backend, {ConstString("__size_"), ConstString("__size")})) {
121 m_num_elements = size_sp->GetValueAsUnsigned(0);
122 } else if (auto arg =
123 m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) {
124
125 m_num_elements = arg->value.GetAPSInt().getLimitedValue();
126 }
127 }
128
130}
131
132llvm::Expected<size_t> lldb_private::formatters::
134 if (!m_start)
135 return llvm::createStringErrorV("type has no child named '{0}'", name);
136 auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());
137 if (!optional_idx) {
138 return llvm::createStringErrorV("type has no child named '{0}'", name);
139 }
140 return *optional_idx;
141}
142
145 lldb::ValueObjectSP valobj_sp) {
146 if (!valobj_sp)
147 return nullptr;
148 CompilerType type = valobj_sp->GetCompilerType();
149 if (!type.IsValid() || type.GetNumTemplateArguments() != 2)
150 return nullptr;
151 return new LibcxxStdSpanSyntheticFrontEnd(valobj_sp);
152}
153
154} // namespace formatters
155} // namespace lldb_private
#define LLDB_LOG_ERRORV(log, error,...)
Definition Log.h:410
Generic representation of a type in a programming language.
size_t GetNumTemplateArguments(bool expand_pack=false) const
Return the number of template arguments the type has.
A uniqued constant string class.
Definition ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:132
SyntheticChildrenFrontEnd(ValueObject &backend)
lldb::ValueObjectSP CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
CompilerType m_element_type
Type of span elements.
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Determine the index of a named child.
lldb::ChildCacheState Update() override
Determines properties of the std::span<> associated with this object.
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
ValueObject * m_start
First element of span. Held, not owned.
llvm::Expected< uint32_t > CalculateNumChildren() override
uint32_t m_element_size
Size in bytes of each span element.
SyntheticChildrenFrontEnd * LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
lldb::ValueObjectSP GetChildMemberWithName(ValueObject &obj, llvm::ArrayRef< ConstString > alternative_names)
Find a child member of obj_sp, trying all alternative names in order.
Definition LibCxx.cpp:63
std::optional< size_t > ExtractIndexFromString(const char *item_name)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
@ eReuse
Children did not change and don't need to be recomputed; re-use what we computed the last time we cal...
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP