blob: 19cc7fb123447bc89c821aa8cbf29e96168203c9 [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
16#include "lldb/Core/DataBufferHeap.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000017#include "lldb/Core/ValueObject.h"
18#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000019#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000020#include "lldb/Host/Endian.h"
21#include "lldb/Symbol/ClangASTContext.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000022#include "lldb/Target/Target.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000023#include "lldb/Utility/Error.h"
24#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
Sean Callanan866e91c2014-02-28 22:27:53 +000086 Error 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) {
97 auto first_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
98 ConstString("__p1_"),
99 ConstString("__first_")});
100 if (!first_sp)
101 return nullptr;
102 m_element_type = first_sp->GetCompilerType();
103 lldb::TemplateArgumentKind kind;
104 m_element_type = m_element_type.GetTemplateArgument(0, kind);
105 m_element_type = m_element_type.GetPointeeType();
106 m_node_type = m_element_type;
107 m_element_type = m_element_type.GetTemplateArgument(0, kind);
108 std::string name;
109 m_element_type =
110 m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);
111 m_element_type = m_element_type.GetTypedefedType();
112 }
113 if (!m_node_type)
114 return nullptr;
115 node_sp = node_sp->Cast(m_node_type);
116 value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
117 hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
118 if (!value_sp || !hash_sp)
119 return nullptr;
120 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121 m_elements_cache.push_back(
122 {value_sp.get(), hash_sp->GetValueAsUnsigned(0)});
123 m_next_element =
124 node_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
125 if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
126 m_next_element = nullptr;
127 }
128
129 std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx];
130 if (!val_hash.first)
131 return lldb::ValueObjectSP();
132 StreamString stream;
133 stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
134 DataExtractor data;
135 Error error;
136 val_hash.first->GetData(data, error);
137 if (error.Fail())
138 return lldb::ValueObjectSP();
139 const bool thread_and_frame_only_if_stopped = true;
140 ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(
141 thread_and_frame_only_if_stopped);
Zachary Turnerc1564272016-11-16 21:15:24 +0000142 return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 val_hash.first->GetCompilerType());
Enrico Granatae2e220a2013-09-12 00:48:47 +0000144}
145
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
147 Update() {
148 m_num_elements = UINT32_MAX;
149 m_next_element = nullptr;
150 m_elements_cache.clear();
151 ValueObjectSP table_sp =
152 m_backend.GetChildMemberWithName(ConstString("__table_"), true);
153 if (!table_sp)
Enrico Granatae2e220a2013-09-12 00:48:47 +0000154 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath(
156 {ConstString("__p2_"), ConstString("__first_")});
157 if (!num_elements_sp)
158 return false;
159 m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
160 m_tree =
161 table_sp
162 ->GetChildAtNamePath({ConstString("__p1_"), ConstString("__first_"),
163 ConstString("__next_")})
164 .get();
165 if (m_num_elements > 0)
166 m_next_element =
167 table_sp
168 ->GetChildAtNamePath({ConstString("__p1_"), ConstString("__first_"),
169 ConstString("__next_")})
170 .get();
171 return false;
Enrico Granatae2e220a2013-09-12 00:48:47 +0000172}
173
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
175 MightHaveChildren() {
176 return true;
Enrico Granatae2e220a2013-09-12 00:48:47 +0000177}
178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
180 GetIndexOfChildWithName(const ConstString &name) {
181 return ExtractIndexFromString(name.GetCString());
Enrico Granatae2e220a2013-09-12 00:48:47 +0000182}
183
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184SyntheticChildrenFrontEnd *
185lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator(
186 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
187 return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)
188 : nullptr);
Enrico Granatae2e220a2013-09-12 00:48:47 +0000189}