19
19
#include " lldb/Utility/Stream.h"
20
20
#include " lldb/lldb-forward.h"
21
21
#include < cstdint>
22
+ #include < locale>
22
23
#include < optional>
23
24
24
25
using namespace lldb ;
25
26
using namespace lldb_private ;
26
27
using namespace lldb_private ::formatters;
27
28
29
+ // The flattened layout of the std::__tree_iterator::__ptr_ looks
30
+ // as follows:
31
+ //
32
+ // The following shows the contiguous block of memory:
33
+ //
34
+ // +-----------------------------+ class __tree_end_node
35
+ // __ptr_ | pointer __left_; |
36
+ // +-----------------------------+ class __tree_node_base
37
+ // | pointer __right_; |
38
+ // | __parent_pointer __parent_; |
39
+ // | bool __is_black_; |
40
+ // +-----------------------------+ class __tree_node
41
+ // | __node_value_type __value_; | <<< our key/value pair
42
+ // +-----------------------------+
43
+ //
44
+ // where __ptr_ has type __iter_pointer.
45
+
28
46
class MapEntry {
29
47
public:
30
48
MapEntry () = default ;
@@ -183,10 +201,6 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
183
201
size_t GetIndexOfChildWithName (ConstString name) override ;
184
202
185
203
private:
186
- bool GetDataType ();
187
-
188
- std::optional<uint32_t > GetValueOffset ();
189
-
190
204
// / Returns the ValueObject for the __tree_node type that
191
205
// / holds the key/value pair of the node at index \ref idx.
192
206
// /
@@ -205,8 +219,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
205
219
206
220
ValueObject *m_tree = nullptr ;
207
221
ValueObject *m_root_node = nullptr ;
208
- CompilerType m_element_type;
209
- uint32_t m_value_type_offset = UINT32_MAX;
222
+ CompilerType m_node_ptr_type;
210
223
size_t m_count = UINT32_MAX;
211
224
std::map<size_t , MapIterator> m_iterators;
212
225
};
@@ -215,7 +228,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
215
228
216
229
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
217
230
LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp)
218
- : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_iterators() {
231
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
219
232
if (valobj_sp)
220
233
Update ();
221
234
}
@@ -241,80 +254,6 @@ llvm::Expected<uint32_t> lldb_private::formatters::
241
254
return m_count;
242
255
}
243
256
244
- bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType () {
245
- if (m_element_type.IsValid ())
246
- return true ;
247
- m_element_type.Clear ();
248
- ValueObjectSP deref;
249
- Status error;
250
- deref = m_root_node->Dereference (error);
251
- if (!deref || error.Fail ())
252
- return false ;
253
- deref = deref->GetChildMemberWithName (" __value_" );
254
- if (deref) {
255
- m_element_type = deref->GetCompilerType ();
256
- return true ;
257
- }
258
- deref = m_backend.GetChildAtNamePath ({" __tree_" , " __pair3_" });
259
- if (!deref)
260
- return false ;
261
- m_element_type = deref->GetCompilerType ()
262
- .GetTypeTemplateArgument (1 )
263
- .GetTypeTemplateArgument (1 );
264
- if (m_element_type) {
265
- std::string name;
266
- uint64_t bit_offset_ptr;
267
- uint32_t bitfield_bit_size_ptr;
268
- bool is_bitfield_ptr;
269
- m_element_type = m_element_type.GetFieldAtIndex (
270
- 0 , name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
271
- m_element_type = m_element_type.GetTypedefedType ();
272
- return m_element_type.IsValid ();
273
- } else {
274
- m_element_type = m_backend.GetCompilerType ().GetTypeTemplateArgument (0 );
275
- return m_element_type.IsValid ();
276
- }
277
- }
278
-
279
- std::optional<uint32_t >
280
- lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset () {
281
- if (!m_tree)
282
- return std::nullopt;
283
-
284
- auto ast_ctx = m_tree->GetCompilerType ()
285
- .GetTypeSystem ()
286
- .dyn_cast_or_null <TypeSystemClang>();
287
- if (!ast_ctx)
288
- return std::nullopt;
289
-
290
- CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier (
291
- llvm::StringRef (),
292
- {{" ptr0" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
293
- {" ptr1" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
294
- {" ptr2" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
295
- {" cw" , ast_ctx->GetBasicType (lldb::eBasicTypeBool)},
296
- {" payload" , (m_element_type.GetCompleteType (), m_element_type)}});
297
- std::string child_name;
298
- uint32_t child_byte_size;
299
- int32_t child_byte_offset = 0 ;
300
- uint32_t child_bitfield_bit_size;
301
- uint32_t child_bitfield_bit_offset;
302
- bool child_is_base_class;
303
- bool child_is_deref_of_parent;
304
- uint64_t language_flags;
305
- auto child_type =
306
- llvm::expectedToStdOptional (tree_node_type.GetChildCompilerTypeAtIndex (
307
- nullptr , 4 , true , true , true , child_name, child_byte_size,
308
- child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
309
- child_is_base_class, child_is_deref_of_parent, nullptr ,
310
- language_flags));
311
-
312
- if (!child_type || !child_type->IsValid ())
313
- return std::nullopt;
314
-
315
- return child_byte_offset;
316
- }
317
-
318
257
ValueObjectSP
319
258
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair (
320
259
size_t idx, size_t max_depth) {
@@ -336,26 +275,31 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair(
336
275
// this tree is garbage - stop
337
276
return nullptr ;
338
277
339
- if (!GetDataType ())
278
+ if (!m_node_ptr_type. IsValid ())
340
279
return nullptr ;
341
280
342
- if (m_value_type_offset == UINT32_MAX) {
343
- if (auto offset = GetValueOffset ())
344
- m_value_type_offset = *offset;
345
- else
346
- return nullptr ;
347
- }
281
+ // iterated_sp is a __iter_pointer at this point.
282
+ // We can cast it to a __node_pointer (which is what libc++ does).
283
+ auto value_type_sp = iterated_sp->Cast (m_node_ptr_type);
284
+ if (!value_type_sp)
285
+ return nullptr ;
348
286
349
- assert (m_value_type_offset != UINT32_MAX);
287
+ // After dereferencing the __node_pointer, we will have a handle to
288
+ // a std::__1::__tree_node<void *>, which has the __value_ member
289
+ // we are looking for.
290
+ Status s;
291
+ value_type_sp = value_type_sp->Dereference (s);
292
+ if (!value_type_sp || s.Fail ())
293
+ return nullptr ;
350
294
351
- iterated_sp = iterated_sp-> GetSyntheticChildAtOffset (m_value_type_offset,
352
- m_element_type, true );
353
- if (!iterated_sp )
295
+ // Finally, get the key/value pair.
296
+ value_type_sp = value_type_sp-> GetChildMemberWithName ( " __value_ " );
297
+ if (!value_type_sp )
354
298
return nullptr ;
355
299
356
300
m_iterators[idx] = iterator;
357
301
358
- return iterated_sp ;
302
+ return value_type_sp ;
359
303
}
360
304
361
305
lldb::ValueObjectSP
@@ -415,6 +359,9 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update() {
415
359
if (!m_tree)
416
360
return lldb::ChildCacheState::eRefetch;
417
361
m_root_node = m_tree->GetChildMemberWithName (" __begin_node_" ).get ();
362
+ m_node_ptr_type =
363
+ m_tree->GetCompilerType ().GetDirectNestedTypeWithName (" __node_pointer" );
364
+
418
365
return lldb::ChildCacheState::eRefetch;
419
366
}
420
367
0 commit comments