Skip to content

Commit 27fb4d2

Browse files
committed
[lldb][DataFormatter] Clean up LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair
This patch cleans up the core of the `std::map` libc++ formatter. Depends on #97544 and #97549. Changes: * Renamed `m_skip_size` to `m_value_type_offset` to better describe what it's actually for. * Made updating `m_skip_size` (now `m_value_type_offset`) isolated to `GetKeyValuePair` (instead of doing so in the `GetValueOffset` helper). * We don't need special logic for the 0th index, so I merged the two `need_to_skip` branches.
1 parent a017653 commit 27fb4d2

File tree

1 file changed

+55
-78
lines changed

1 file changed

+55
-78
lines changed

lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp

Lines changed: 55 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "lldb/Utility/Status.h"
1919
#include "lldb/Utility/Stream.h"
2020
#include "lldb/lldb-forward.h"
21+
#include <cstdint>
22+
#include <optional>
2123

2224
using namespace lldb;
2325
using namespace lldb_private;
@@ -183,7 +185,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
183185
private:
184186
bool GetDataType();
185187

186-
void GetValueOffset(const lldb::ValueObjectSP &node);
188+
std::optional<uint32_t> GetValueOffset();
187189

188190
/// Returns the ValueObject for the __tree_node type that
189191
/// holds the key/value pair of the node at index \ref idx.
@@ -204,7 +206,7 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
204206
ValueObject *m_tree = nullptr;
205207
ValueObject *m_root_node = nullptr;
206208
CompilerType m_element_type;
207-
uint32_t m_skip_size = UINT32_MAX;
209+
uint32_t m_value_type_offset = UINT32_MAX;
208210
size_t m_count = UINT32_MAX;
209211
std::map<size_t, MapIterator> m_iterators;
210212
};
@@ -274,109 +276,84 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() {
274276
}
275277
}
276278

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;
317316
}
318317

319318
ValueObjectSP
320319
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetKeyValuePair(
321320
size_t idx, size_t max_depth) {
322321
MapIterator iterator(m_root_node, max_depth);
323322

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) {
327325
// If we have already created the iterator for the previous
328326
// index, we can start from there and advance by 1.
329327
auto cached_iterator = m_iterators.find(idx - 1);
330328
if (cached_iterator != m_iterators.end()) {
331329
iterator = cached_iterator->second;
332-
actual_advance = 1;
330+
advance_by = 1;
333331
}
334332
}
335333

336-
ValueObjectSP iterated_sp(iterator.advance(actual_advance));
334+
ValueObjectSP iterated_sp(iterator.advance(advance_by));
337335
if (!iterated_sp)
338336
// this tree is garbage - stop
339337
return nullptr;
340338

341339
if (!GetDataType())
342340
return nullptr;
343341

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
361346
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+
}
367348

368-
if (m_skip_size == UINT32_MAX)
369-
return nullptr;
349+
assert(m_value_type_offset != UINT32_MAX);
370350

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;
376355

377356
m_iterators[idx] = iterator;
378-
assert(iterated_sp != nullptr &&
379-
"Cached MapIterator for invalid ValueObject");
380357

381358
return iterated_sp;
382359
}

0 commit comments

Comments
 (0)