1 //===-- LibCxxUnorderedMap.cpp ----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/DataFormatters/FormattersHelpers.h"
19 #include "lldb/Symbol/ClangASTContext.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Utility/DataBufferHeap.h"
22 #include "lldb/Utility/Endian.h"
23 #include "lldb/Utility/Status.h"
24 #include "lldb/Utility/Stream.h"
27 using namespace lldb_private;
28 using namespace lldb_private::formatters;
30 namespace lldb_private {
31 namespace formatters {
32 class LibcxxStdUnorderedMapSyntheticFrontEnd
33 : public SyntheticChildrenFrontEnd {
35 LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
37 ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
39 size_t CalculateNumChildren() override;
41 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
43 bool Update() override;
45 bool MightHaveChildren() override;
47 size_t GetIndexOfChildWithName(const ConstString &name) override;
50 CompilerType m_element_type;
51 CompilerType m_node_type;
53 size_t m_num_elements;
54 ValueObject *m_next_element;
55 std::vector<std::pair<ValueObject *, uint64_t>> m_elements_cache;
57 } // namespace formatters
58 } // namespace lldb_private
60 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
61 LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
62 : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_tree(nullptr),
63 m_num_elements(0), m_next_element(nullptr), m_elements_cache() {
68 size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
69 CalculateNumChildren() {
70 if (m_num_elements != UINT32_MAX)
71 return m_num_elements;
75 lldb::ValueObjectSP lldb_private::formatters::
76 LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
77 if (idx >= CalculateNumChildren())
78 return lldb::ValueObjectSP();
79 if (m_tree == nullptr)
80 return lldb::ValueObjectSP();
82 while (idx >= m_elements_cache.size()) {
83 if (m_next_element == nullptr)
84 return lldb::ValueObjectSP();
87 ValueObjectSP node_sp = m_next_element->Dereference(error);
88 if (!node_sp || error.Fail())
89 return lldb::ValueObjectSP();
91 ValueObjectSP value_sp =
92 node_sp->GetChildMemberWithName(ConstString("__value_"), true);
93 ValueObjectSP hash_sp =
94 node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
95 if (!hash_sp || !value_sp) {
96 if (!m_element_type) {
97 auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
98 ConstString("__p1_")});
102 ValueObjectSP first_sp = nullptr;
103 switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) {
105 // Assume a pre llvm r300140 __compressed_pair implementation:
106 first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"),
110 // Assume a post llvm r300140 __compressed_pair implementation:
111 ValueObjectSP first_elem_parent_sp =
112 p1_sp->GetChildAtIndex(0, true);
113 first_sp = p1_sp->GetChildMemberWithName(ConstString("__value_"),
123 m_element_type = first_sp->GetCompilerType();
124 lldb::TemplateArgumentKind kind;
125 m_element_type = m_element_type.GetTemplateArgument(0, kind);
126 m_element_type = m_element_type.GetPointeeType();
127 m_node_type = m_element_type;
128 m_element_type = m_element_type.GetTemplateArgument(0, kind);
131 m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);
132 m_element_type = m_element_type.GetTypedefedType();
136 node_sp = node_sp->Cast(m_node_type);
137 value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
138 hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
139 if (!value_sp || !hash_sp)
142 m_elements_cache.push_back(
143 {value_sp.get(), hash_sp->GetValueAsUnsigned(0)});
145 node_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
146 if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
147 m_next_element = nullptr;
150 std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx];
152 return lldb::ValueObjectSP();
154 stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
157 val_hash.first->GetData(data, error);
159 return lldb::ValueObjectSP();
160 const bool thread_and_frame_only_if_stopped = true;
161 ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(
162 thread_and_frame_only_if_stopped);
163 return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
164 val_hash.first->GetCompilerType());
167 bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
169 m_num_elements = UINT32_MAX;
170 m_next_element = nullptr;
171 m_elements_cache.clear();
172 ValueObjectSP table_sp =
173 m_backend.GetChildMemberWithName(ConstString("__table_"), true);
177 ValueObjectSP p2_sp = table_sp->GetChildMemberWithName(
178 ConstString("__p2_"), true);
179 ValueObjectSP num_elements_sp = nullptr;
180 llvm::SmallVector<ConstString, 3> next_path;
181 switch (p2_sp->GetCompilerType().GetNumDirectBaseClasses()) {
183 // Assume a pre llvm r300140 __compressed_pair implementation:
184 num_elements_sp = p2_sp->GetChildMemberWithName(
185 ConstString("__first_"), true);
186 next_path.append({ConstString("__p1_"), ConstString("__first_"),
187 ConstString("__next_")});
190 // Assume a post llvm r300140 __compressed_pair implementation:
191 ValueObjectSP first_elem_parent = p2_sp->GetChildAtIndex(0, true);
192 num_elements_sp = first_elem_parent->GetChildMemberWithName(
193 ConstString("__value_"), true);
194 next_path.append({ConstString("__p1_"), ConstString("__value_"),
195 ConstString("__next_")});
202 if (!num_elements_sp)
204 m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
205 m_tree = table_sp->GetChildAtNamePath(next_path).get();
206 if (m_num_elements > 0)
208 table_sp->GetChildAtNamePath(next_path).get();
212 bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
213 MightHaveChildren() {
217 size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
218 GetIndexOfChildWithName(const ConstString &name) {
219 return ExtractIndexFromString(name.GetCString());
222 SyntheticChildrenFrontEnd *
223 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator(
224 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
225 return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)