blob: 190b5f64381ea1f53421dc2922ce668739755374 [file] [log] [blame]
Eugene Zelenko8d15f332015-10-20 01:10:59 +00001//===-- LibCxxUnorderedMap.cpp ----------------------------------*- C++ -*-===//
Enrico Granatae2e220a2013-09-12 00:48:47 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenko8d15f332015-10-20 01:10:59 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Enrico Granata33e97e62015-09-04 21:01:18 +000014#include "LibCxx.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000015
Enrico Granatae2e220a2013-09-12 00:48:47 +000016#include "lldb/Core/ValueObject.h"
17#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000018#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000019#include "lldb/Symbol/ClangASTContext.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000020#include "lldb/Target/Target.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000021#include "lldb/Utility/DataBufferHeap.h"
Zachary Turner01c32432017-02-14 19:06:07 +000022#include "lldb/Utility/Endian.h"
Zachary Turner97206d52017-05-12 04:51:55 +000023#include "lldb/Utility/Status.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000024#include "lldb/Utility/Stream.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000025
26using namespace lldb;
27using namespace lldb_private;
28using namespace lldb_private::formatters;
29
Enrico Granatae85fe3a2014-10-22 20:34:38 +000030namespace lldb_private {
Kate Stoneb9c1b512016-09-06 20:57:50 +000031namespace formatters {
32class LibcxxStdUnorderedMapSyntheticFrontEnd
33 : public SyntheticChildrenFrontEnd {
34public:
35 LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
Eugene Zelenko8d15f332015-10-20 01:10:59 +000036
Kate Stoneb9c1b512016-09-06 20:57:50 +000037 ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000038
Kate Stoneb9c1b512016-09-06 20:57:50 +000039 size_t CalculateNumChildren() override;
Eugene Zelenko8d15f332015-10-20 01:10:59 +000040
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
42
43 bool Update() override;
44
45 bool MightHaveChildren() override;
46
47 size_t GetIndexOfChildWithName(const ConstString &name) override;
48
49private:
Enrico Granatad22a9432016-10-05 22:04:43 +000050 CompilerType m_element_type;
51 CompilerType m_node_type;
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 ValueObject *m_tree;
53 size_t m_num_elements;
54 ValueObject *m_next_element;
55 std::vector<std::pair<ValueObject *, uint64_t>> m_elements_cache;
56};
57} // namespace formatters
Eugene Zelenko8d15f332015-10-20 01:10:59 +000058} // namespace lldb_private
Enrico Granatae85fe3a2014-10-22 20:34:38 +000059
Kate Stoneb9c1b512016-09-06 20:57:50 +000060lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
61 LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Enrico Granatad22a9432016-10-05 22:04:43 +000062 : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_tree(nullptr),
63 m_num_elements(0), m_next_element(nullptr), m_elements_cache() {
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 if (valobj_sp)
65 Update();
Enrico Granatae2e220a2013-09-12 00:48:47 +000066}
67
Kate Stoneb9c1b512016-09-06 20:57:50 +000068size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
69 CalculateNumChildren() {
70 if (m_num_elements != UINT32_MAX)
71 return m_num_elements;
72 return 0;
Enrico Granatae2e220a2013-09-12 00:48:47 +000073}
74
Kate Stoneb9c1b512016-09-06 20:57:50 +000075lldb::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();
81
82 while (idx >= m_elements_cache.size()) {
83 if (m_next_element == nullptr)
84 return lldb::ValueObjectSP();
85
Zachary Turner97206d52017-05-12 04:51:55 +000086 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +000087 ValueObjectSP node_sp = m_next_element->Dereference(error);
88 if (!node_sp || error.Fail())
89 return lldb::ValueObjectSP();
90
91 ValueObjectSP value_sp =
92 node_sp->GetChildMemberWithName(ConstString("__value_"), true);
93 ValueObjectSP hash_sp =
94 node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
Enrico Granatad22a9432016-10-05 22:04:43 +000095 if (!hash_sp || !value_sp) {
96 if (!m_element_type) {
Lang Hames6cc33542017-04-26 23:29:59 +000097 auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
98 ConstString("__p1_")});
99 if (!p1_sp)
100 return nullptr;
101
102 ValueObjectSP first_sp = nullptr;
103 switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) {
104 case 1:
105 // Assume a pre llvm r300140 __compressed_pair implementation:
106 first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"),
107 true);
108 break;
109 case 2: {
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_"),
114 true);
115 break;
116 }
117 default:
118 return nullptr;
119 }
120
Enrico Granatad22a9432016-10-05 22:04:43 +0000121 if (!first_sp)
122 return nullptr;
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);
129 std::string name;
130 m_element_type =
131 m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);
132 m_element_type = m_element_type.GetTypedefedType();
133 }
134 if (!m_node_type)
135 return nullptr;
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)
140 return nullptr;
141 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142 m_elements_cache.push_back(
143 {value_sp.get(), hash_sp->GetValueAsUnsigned(0)});
144 m_next_element =
145 node_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
146 if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
147 m_next_element = nullptr;
148 }
149
150 std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx];
151 if (!val_hash.first)
152 return lldb::ValueObjectSP();
153 StreamString stream;
154 stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
155 DataExtractor data;
Zachary Turner97206d52017-05-12 04:51:55 +0000156 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 val_hash.first->GetData(data, error);
158 if (error.Fail())
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);
Zachary Turnerc1564272016-11-16 21:15:24 +0000163 return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164 val_hash.first->GetCompilerType());
Enrico Granatae2e220a2013-09-12 00:48:47 +0000165}
166
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
168 Update() {
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);
174 if (!table_sp)
Enrico Granatae2e220a2013-09-12 00:48:47 +0000175 return false;
Lang Hames6cc33542017-04-26 23:29:59 +0000176
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()) {
182 case 1:
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_")});
188 break;
189 case 2: {
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_")});
196 break;
197 }
198 default:
199 return false;
200 }
201
Kate Stoneb9c1b512016-09-06 20:57:50 +0000202 if (!num_elements_sp)
203 return false;
204 m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
Lang Hames6cc33542017-04-26 23:29:59 +0000205 m_tree = table_sp->GetChildAtNamePath(next_path).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206 if (m_num_elements > 0)
207 m_next_element =
Lang Hames6cc33542017-04-26 23:29:59 +0000208 table_sp->GetChildAtNamePath(next_path).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209 return false;
Enrico Granatae2e220a2013-09-12 00:48:47 +0000210}
211
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
213 MightHaveChildren() {
214 return true;
Enrico Granatae2e220a2013-09-12 00:48:47 +0000215}
216
Kate Stoneb9c1b512016-09-06 20:57:50 +0000217size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
218 GetIndexOfChildWithName(const ConstString &name) {
219 return ExtractIndexFromString(name.GetCString());
Enrico Granatae2e220a2013-09-12 00:48:47 +0000220}
221
Kate Stoneb9c1b512016-09-06 20:57:50 +0000222SyntheticChildrenFrontEnd *
223lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator(
224 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
225 return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)
226 : nullptr);
Enrico Granatae2e220a2013-09-12 00:48:47 +0000227}