18
18
#include " lldb/Utility/Status.h"
19
19
#include " lldb/Utility/Stream.h"
20
20
#include " lldb/lldb-forward.h"
21
+ #include < cstdint>
22
+ #include < optional>
21
23
22
24
using namespace lldb ;
23
25
using namespace lldb_private ;
@@ -183,7 +185,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
183
185
private:
184
186
bool GetDataType ();
185
187
186
- void GetValueOffset ( const lldb::ValueObjectSP &node );
188
+ std::optional< uint32_t > GetValueOffset ( );
187
189
188
190
// / Returns the ValueObject for the __tree_node type that
189
191
// / holds the key/value pair of the node at index \ref idx.
@@ -204,7 +206,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
204
206
ValueObject *m_tree = nullptr ;
205
207
ValueObject *m_root_node = nullptr ;
206
208
CompilerType m_element_type;
207
- uint32_t m_skip_size = UINT32_MAX;
209
+ uint32_t m_value_type_offset = UINT32_MAX;
208
210
size_t m_count = UINT32_MAX;
209
211
std::map<size_t , MapIterator> m_iterators;
210
212
};
@@ -274,109 +276,84 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() {
274
276
}
275
277
}
276
278
277
- void lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (
278
- const lldb::ValueObjectSP &node) {
279
- if (m_skip_size != UINT32_MAX)
280
- return ;
281
- if (!node)
282
- return ;
283
- CompilerType node_type (node->GetCompilerType ());
284
- uint64_t bit_offset;
285
- if (node_type.GetIndexOfFieldWithName (" __value_" , nullptr , &bit_offset) !=
286
- UINT32_MAX) {
287
- // Old layout (pre d05b10ab4fc65)
288
- m_skip_size = bit_offset / 8u ;
289
- } else {
290
- auto ast_ctx = node_type.GetTypeSystem ().dyn_cast_or_null <TypeSystemClang>();
291
- if (!ast_ctx)
292
- return ;
293
- CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier (
294
- llvm::StringRef (),
295
- {{" ptr0" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
296
- {" ptr1" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
297
- {" ptr2" , ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
298
- {" cw" , ast_ctx->GetBasicType (lldb::eBasicTypeBool)},
299
- {" payload" , (m_element_type.GetCompleteType (), m_element_type)}});
300
- std::string child_name;
301
- uint32_t child_byte_size;
302
- int32_t child_byte_offset = 0 ;
303
- uint32_t child_bitfield_bit_size;
304
- uint32_t child_bitfield_bit_offset;
305
- bool child_is_base_class;
306
- bool child_is_deref_of_parent;
307
- uint64_t language_flags;
308
- auto child_type =
309
- llvm::expectedToStdOptional (tree_node_type.GetChildCompilerTypeAtIndex (
310
- nullptr , 4 , true , true , true , child_name, child_byte_size,
311
- child_byte_offset, child_bitfield_bit_size,
312
- child_bitfield_bit_offset, child_is_base_class,
313
- child_is_deref_of_parent, nullptr , language_flags));
314
- if (child_type && child_type->IsValid ())
315
- m_skip_size = (uint32_t )child_byte_offset;
316
- }
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;
317
316
}
318
317
319
318
ValueObjectSP
320
319
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair (
321
320
size_t idx, size_t max_depth) {
322
321
MapIterator iterator (m_root_node, max_depth);
323
322
324
- const bool need_to_skip = (idx > 0 );
325
- size_t actual_advance = idx;
326
- if (need_to_skip) {
323
+ size_t advance_by = idx;
324
+ if (idx > 0 ) {
327
325
// If we have already created the iterator for the previous
328
326
// index, we can start from there and advance by 1.
329
327
auto cached_iterator = m_iterators.find (idx - 1 );
330
328
if (cached_iterator != m_iterators.end ()) {
331
329
iterator = cached_iterator->second ;
332
- actual_advance = 1 ;
330
+ advance_by = 1 ;
333
331
}
334
332
}
335
333
336
- ValueObjectSP iterated_sp (iterator.advance (actual_advance ));
334
+ ValueObjectSP iterated_sp (iterator.advance (advance_by ));
337
335
if (!iterated_sp)
338
336
// this tree is garbage - stop
339
337
return nullptr ;
340
338
341
339
if (!GetDataType ())
342
340
return nullptr ;
343
341
344
- if (!need_to_skip) {
345
- Status error;
346
- iterated_sp = iterated_sp->Dereference (error);
347
- if (!iterated_sp || error.Fail ())
348
- return nullptr ;
349
-
350
- GetValueOffset (iterated_sp);
351
- auto child_sp = iterated_sp->GetChildMemberWithName (" __value_" );
352
- if (child_sp) {
353
- // Old layout (pre 089a7cc5dea)
354
- iterated_sp = child_sp;
355
- } else {
356
- iterated_sp = iterated_sp->GetSyntheticChildAtOffset (
357
- m_skip_size, m_element_type, true );
358
- }
359
-
360
- if (!iterated_sp)
342
+ if (m_value_type_offset == UINT32_MAX) {
343
+ if (auto offset = GetValueOffset ())
344
+ m_value_type_offset = *offset;
345
+ else
361
346
return nullptr ;
362
- } else {
363
- // because of the way our debug info is made, we need to read item 0
364
- // first so that we can cache information used to generate other elements
365
- if (m_skip_size == UINT32_MAX)
366
- GetChildAtIndex (0 );
347
+ }
367
348
368
- if (m_skip_size == UINT32_MAX)
369
- return nullptr ;
349
+ assert (m_value_type_offset != UINT32_MAX);
370
350
371
- iterated_sp = iterated_sp->GetSyntheticChildAtOffset (m_skip_size,
372
- m_element_type, true );
373
- if (!iterated_sp)
374
- return nullptr ;
375
- }
351
+ iterated_sp = iterated_sp->GetSyntheticChildAtOffset (m_value_type_offset,
352
+ m_element_type, true );
353
+ if (!iterated_sp)
354
+ return nullptr ;
376
355
377
356
m_iterators[idx] = iterator;
378
- assert (iterated_sp != nullptr &&
379
- " Cached MapIterator for invalid ValueObject" );
380
357
381
358
return iterated_sp;
382
359
}
0 commit comments