blob: 2091c0b6b7400b7a5dafda3c4f177f3646cefd20 [file] [log] [blame]
Raphael Isemann80814282020-01-24 08:23:27 +01001//===-- LibCxxUnorderedMap.cpp --------------------------------------------===//
Enrico Granatae2e220a2013-09-12 00:48:47 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Enrico Granatae2e220a2013-09-12 00:48:47 +00006//
7//===----------------------------------------------------------------------===//
8
Enrico Granata33e97e62015-09-04 21:01:18 +00009#include "LibCxx.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000010
Enrico Granatae2e220a2013-09-12 00:48:47 +000011#include "lldb/Core/ValueObject.h"
12#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000013#include "lldb/DataFormatters/FormattersHelpers.h"
Raphael Isemann6e3b0cc2020-01-23 10:04:13 +010014#include "lldb/Symbol/TypeSystemClang.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000015#include "lldb/Target/Target.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000016#include "lldb/Utility/DataBufferHeap.h"
Zachary Turner01c32432017-02-14 19:06:07 +000017#include "lldb/Utility/Endian.h"
Zachary Turner97206d52017-05-12 04:51:55 +000018#include "lldb/Utility/Status.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000019#include "lldb/Utility/Stream.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000020
21using namespace lldb;
22using namespace lldb_private;
23using namespace lldb_private::formatters;
24
Enrico Granatae85fe3a2014-10-22 20:34:38 +000025namespace lldb_private {
Kate Stoneb9c1b512016-09-06 20:57:50 +000026namespace formatters {
27class LibcxxStdUnorderedMapSyntheticFrontEnd
28 : public SyntheticChildrenFrontEnd {
29public:
30 LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
Eugene Zelenko8d15f332015-10-20 01:10:59 +000031
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000033
Kate Stoneb9c1b512016-09-06 20:57:50 +000034 size_t CalculateNumChildren() override;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000035
Kate Stoneb9c1b512016-09-06 20:57:50 +000036 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
37
38 bool Update() override;
39
40 bool MightHaveChildren() override;
41
Adrian Prantl0e4c4822019-03-06 21:22:25 +000042 size_t GetIndexOfChildWithName(ConstString name) override;
Kate Stoneb9c1b512016-09-06 20:57:50 +000043
44private:
Enrico Granatad22a9432016-10-05 22:04:43 +000045 CompilerType m_element_type;
46 CompilerType m_node_type;
Kate Stoneb9c1b512016-09-06 20:57:50 +000047 ValueObject *m_tree;
48 size_t m_num_elements;
49 ValueObject *m_next_element;
50 std::vector<std::pair<ValueObject *, uint64_t>> m_elements_cache;
51};
52} // namespace formatters
Eugene Zelenko8d15f332015-10-20 01:10:59 +000053} // namespace lldb_private
Enrico Granatae85fe3a2014-10-22 20:34:38 +000054
Kate Stoneb9c1b512016-09-06 20:57:50 +000055lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
56 LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Enrico Granatad22a9432016-10-05 22:04:43 +000057 : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_tree(nullptr),
58 m_num_elements(0), m_next_element(nullptr), m_elements_cache() {
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 if (valobj_sp)
60 Update();
Enrico Granatae2e220a2013-09-12 00:48:47 +000061}
62
Kate Stoneb9c1b512016-09-06 20:57:50 +000063size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
64 CalculateNumChildren() {
65 if (m_num_elements != UINT32_MAX)
66 return m_num_elements;
67 return 0;
Enrico Granatae2e220a2013-09-12 00:48:47 +000068}
69
Kate Stoneb9c1b512016-09-06 20:57:50 +000070lldb::ValueObjectSP lldb_private::formatters::
71 LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
72 if (idx >= CalculateNumChildren())
73 return lldb::ValueObjectSP();
74 if (m_tree == nullptr)
75 return lldb::ValueObjectSP();
76
77 while (idx >= m_elements_cache.size()) {
78 if (m_next_element == nullptr)
79 return lldb::ValueObjectSP();
80
Zachary Turner97206d52017-05-12 04:51:55 +000081 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +000082 ValueObjectSP node_sp = m_next_element->Dereference(error);
83 if (!node_sp || error.Fail())
84 return lldb::ValueObjectSP();
85
86 ValueObjectSP value_sp =
87 node_sp->GetChildMemberWithName(ConstString("__value_"), true);
88 ValueObjectSP hash_sp =
89 node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
Enrico Granatad22a9432016-10-05 22:04:43 +000090 if (!hash_sp || !value_sp) {
91 if (!m_element_type) {
Lang Hames6cc33542017-04-26 23:29:59 +000092 auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
93 ConstString("__p1_")});
94 if (!p1_sp)
95 return nullptr;
96
97 ValueObjectSP first_sp = nullptr;
98 switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) {
99 case 1:
100 // Assume a pre llvm r300140 __compressed_pair implementation:
101 first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"),
102 true);
103 break;
104 case 2: {
105 // Assume a post llvm r300140 __compressed_pair implementation:
106 ValueObjectSP first_elem_parent_sp =
107 p1_sp->GetChildAtIndex(0, true);
108 first_sp = p1_sp->GetChildMemberWithName(ConstString("__value_"),
109 true);
110 break;
111 }
112 default:
113 return nullptr;
114 }
115
Enrico Granatad22a9432016-10-05 22:04:43 +0000116 if (!first_sp)
117 return nullptr;
118 m_element_type = first_sp->GetCompilerType();
Pavel Labath769b21e2017-11-13 14:26:21 +0000119 m_element_type = m_element_type.GetTypeTemplateArgument(0);
Enrico Granatad22a9432016-10-05 22:04:43 +0000120 m_element_type = m_element_type.GetPointeeType();
121 m_node_type = m_element_type;
Pavel Labath769b21e2017-11-13 14:26:21 +0000122 m_element_type = m_element_type.GetTypeTemplateArgument(0);
Enrico Granatad22a9432016-10-05 22:04:43 +0000123 std::string name;
124 m_element_type =
125 m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);
126 m_element_type = m_element_type.GetTypedefedType();
127 }
128 if (!m_node_type)
129 return nullptr;
130 node_sp = node_sp->Cast(m_node_type);
131 value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
132 hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
133 if (!value_sp || !hash_sp)
134 return nullptr;
135 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136 m_elements_cache.push_back(
137 {value_sp.get(), hash_sp->GetValueAsUnsigned(0)});
138 m_next_element =
139 node_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
140 if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
141 m_next_element = nullptr;
142 }
143
144 std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx];
145 if (!val_hash.first)
146 return lldb::ValueObjectSP();
147 StreamString stream;
148 stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
149 DataExtractor data;
Zachary Turner97206d52017-05-12 04:51:55 +0000150 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151 val_hash.first->GetData(data, error);
152 if (error.Fail())
153 return lldb::ValueObjectSP();
154 const bool thread_and_frame_only_if_stopped = true;
155 ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(
156 thread_and_frame_only_if_stopped);
Zachary Turnerc1564272016-11-16 21:15:24 +0000157 return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 val_hash.first->GetCompilerType());
Enrico Granatae2e220a2013-09-12 00:48:47 +0000159}
160
Kate Stoneb9c1b512016-09-06 20:57:50 +0000161bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
162 Update() {
163 m_num_elements = UINT32_MAX;
164 m_next_element = nullptr;
165 m_elements_cache.clear();
166 ValueObjectSP table_sp =
167 m_backend.GetChildMemberWithName(ConstString("__table_"), true);
168 if (!table_sp)
Enrico Granatae2e220a2013-09-12 00:48:47 +0000169 return false;
Lang Hames6cc33542017-04-26 23:29:59 +0000170
171 ValueObjectSP p2_sp = table_sp->GetChildMemberWithName(
172 ConstString("__p2_"), true);
173 ValueObjectSP num_elements_sp = nullptr;
174 llvm::SmallVector<ConstString, 3> next_path;
175 switch (p2_sp->GetCompilerType().GetNumDirectBaseClasses()) {
176 case 1:
177 // Assume a pre llvm r300140 __compressed_pair implementation:
178 num_elements_sp = p2_sp->GetChildMemberWithName(
179 ConstString("__first_"), true);
180 next_path.append({ConstString("__p1_"), ConstString("__first_"),
181 ConstString("__next_")});
182 break;
183 case 2: {
184 // Assume a post llvm r300140 __compressed_pair implementation:
185 ValueObjectSP first_elem_parent = p2_sp->GetChildAtIndex(0, true);
186 num_elements_sp = first_elem_parent->GetChildMemberWithName(
187 ConstString("__value_"), true);
188 next_path.append({ConstString("__p1_"), ConstString("__value_"),
189 ConstString("__next_")});
190 break;
191 }
192 default:
193 return false;
194 }
195
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 if (!num_elements_sp)
197 return false;
198 m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
Lang Hames6cc33542017-04-26 23:29:59 +0000199 m_tree = table_sp->GetChildAtNamePath(next_path).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200 if (m_num_elements > 0)
201 m_next_element =
Lang Hames6cc33542017-04-26 23:29:59 +0000202 table_sp->GetChildAtNamePath(next_path).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203 return false;
Enrico Granatae2e220a2013-09-12 00:48:47 +0000204}
205
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
207 MightHaveChildren() {
208 return true;
Enrico Granatae2e220a2013-09-12 00:48:47 +0000209}
210
Kate Stoneb9c1b512016-09-06 20:57:50 +0000211size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
Adrian Prantl0e4c4822019-03-06 21:22:25 +0000212 GetIndexOfChildWithName(ConstString name) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000213 return ExtractIndexFromString(name.GetCString());
Enrico Granatae2e220a2013-09-12 00:48:47 +0000214}
215
Kate Stoneb9c1b512016-09-06 20:57:50 +0000216SyntheticChildrenFrontEnd *
217lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator(
218 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
219 return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)
220 : nullptr);
Enrico Granatae2e220a2013-09-12 00:48:47 +0000221}