]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
Update to bmake-20171028
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Language / CPlusPlus / LibCxxUnorderedMap.cpp
1 //===-- LibCxxUnorderedMap.cpp ----------------------------------*- C++ -*-===//
2 //
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
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "LibCxx.h"
15
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"
25
26 using namespace lldb;
27 using namespace lldb_private;
28 using namespace lldb_private::formatters;
29
30 namespace lldb_private {
31 namespace formatters {
32 class LibcxxStdUnorderedMapSyntheticFrontEnd
33     : public SyntheticChildrenFrontEnd {
34 public:
35   LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
36
37   ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
38
39   size_t CalculateNumChildren() override;
40
41   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
49 private:
50   CompilerType m_element_type;
51   CompilerType m_node_type;
52   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
58 } // namespace lldb_private
59
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() {
64   if (valobj_sp)
65     Update();
66 }
67
68 size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
69     CalculateNumChildren() {
70   if (m_num_elements != UINT32_MAX)
71     return m_num_elements;
72   return 0;
73 }
74
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();
81
82   while (idx >= m_elements_cache.size()) {
83     if (m_next_element == nullptr)
84       return lldb::ValueObjectSP();
85
86     Status error;
87     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);
95     if (!hash_sp || !value_sp) {
96       if (!m_element_type) {
97         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
121         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     }
142     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;
156   Status error;
157   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);
163   return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
164                                    val_hash.first->GetCompilerType());
165 }
166
167 bool 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)
175     return false;
176
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
202   if (!num_elements_sp)
203     return false;
204   m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
205   m_tree = table_sp->GetChildAtNamePath(next_path).get();
206   if (m_num_elements > 0)
207     m_next_element =
208         table_sp->GetChildAtNamePath(next_path).get();
209   return false;
210 }
211
212 bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
213     MightHaveChildren() {
214   return true;
215 }
216
217 size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
218     GetIndexOfChildWithName(const ConstString &name) {
219   return ExtractIndexFromString(name.GetCString());
220 }
221
222 SyntheticChildrenFrontEnd *
223 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator(
224     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
225   return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)
226                     : nullptr);
227 }