Skip to content

Commit 22b5d31

Browse files
committed
[lldb][DataFormatters] Support newer _LIBCPP_COMPRESSED_PAIR layouts
Starting with llvm#154686 the compressed_pair children are now wrapped in an anonymous structure. This patch adjusts the LLDB data-formatters to support that.
1 parent 7b22660 commit 22b5d31

File tree

6 files changed

+103
-75
lines changed

6 files changed

+103
-75
lines changed

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,18 @@ lldb::ChildCacheState LibCxxForwardListFrontEnd::Update() {
339339
if (err.Fail() || !backend_addr)
340340
return lldb::ChildCacheState::eRefetch;
341341

342-
ValueObjectSP impl_sp(m_backend.GetChildMemberWithName("__before_begin_"));
342+
auto list_base_sp = m_backend.GetChildAtIndex(0);
343+
if (!list_base_sp)
344+
return lldb::ChildCacheState::eRefetch;
345+
346+
// Anonymous strucutre index is in base class at index 0.
347+
auto [impl_sp, is_compressed_pair] =
348+
GetValueOrOldCompressedPair(*list_base_sp, /*anon_struct_idx=*/0,
349+
"__before_begin_", "__before_begin_");
343350
if (!impl_sp)
344351
return ChildCacheState::eRefetch;
345352

346-
if (isOldCompressedPairLayout(*impl_sp))
353+
if (is_compressed_pair)
347354
impl_sp = GetFirstValueOfLibCXXCompressedPair(*impl_sp);
348355

349356
if (!impl_sp)
@@ -366,17 +373,10 @@ llvm::Expected<uint32_t> LibCxxListFrontEnd::CalculateNumChildren() {
366373
if (!m_head || !m_tail || m_node_address == 0)
367374
return 0;
368375

369-
ValueObjectSP size_node_sp(m_backend.GetChildMemberWithName("__size_"));
370-
if (!size_node_sp) {
371-
size_node_sp = m_backend.GetChildMemberWithName(
372-
"__size_alloc_"); // pre-compressed_pair rework
373-
374-
if (!isOldCompressedPairLayout(*size_node_sp))
375-
return llvm::createStringError("Unexpected std::list layout: expected "
376-
"old __compressed_pair layout.");
377-
376+
auto [size_node_sp, is_compressed_pair] = GetValueOrOldCompressedPair(
377+
m_backend, /*anon_struct_idx=*/1, "__size_", "__size_alloc_");
378+
if (is_compressed_pair)
378379
size_node_sp = GetFirstValueOfLibCXXCompressedPair(*size_node_sp);
379-
}
380380

381381
if (size_node_sp)
382382
m_count = size_node_sp->GetValueAsUnsigned(UINT32_MAX);

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

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ static void consumeInlineNamespace(llvm::StringRef &name) {
4949
}
5050
}
5151

52-
bool lldb_private::formatters::isOldCompressedPairLayout(
53-
ValueObject &pair_obj) {
52+
static bool isOldCompressedPairLayout(ValueObject &pair_obj) {
5453
return isStdTemplate(pair_obj.GetTypeName(), "__compressed_pair");
5554
}
5655

@@ -105,6 +104,40 @@ lldb_private::formatters::GetSecondValueOfLibCXXCompressedPair(
105104
return value;
106105
}
107106

107+
std::pair<lldb::ValueObjectSP, bool>
108+
lldb_private::formatters::GetValueOrOldCompressedPair(
109+
ValueObject &obj, size_t anon_struct_idx, llvm::StringRef child_name,
110+
llvm::StringRef compressed_pair_name) {
111+
// Try searching the child member in an anonymous structure first.
112+
if (auto unwrapped = obj.GetChildAtIndex(anon_struct_idx)) {
113+
ValueObjectSP node_sp(obj.GetChildMemberWithName(child_name));
114+
if (node_sp)
115+
return {node_sp, isOldCompressedPairLayout(*node_sp)};
116+
}
117+
118+
// Older versions of libc++ don't wrap the children in anonymous structures.
119+
// Try that instead.
120+
ValueObjectSP node_sp(obj.GetChildMemberWithName(child_name));
121+
if (node_sp)
122+
return {node_sp, isOldCompressedPairLayout(*node_sp)};
123+
124+
// Try the even older __compressed_pair layout.
125+
126+
assert(!compressed_pair_name.empty());
127+
128+
node_sp = obj.GetChildMemberWithName(compressed_pair_name);
129+
130+
// Unrecognized layout (possibly older than LLDB supports).
131+
if (!node_sp)
132+
return {nullptr, false};
133+
134+
// Expected old compressed_pair layout, but got something else.
135+
if (!isOldCompressedPairLayout(*node_sp))
136+
return {nullptr, false};
137+
138+
return {node_sp, true};
139+
}
140+
108141
bool lldb_private::formatters::LibcxxFunctionSummaryProvider(
109142
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
110143

lldb/source/Plugins/Language/CPlusPlus/LibCxx.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,22 @@ GetChildMemberWithName(ValueObject &obj,
2525

2626
lldb::ValueObjectSP GetFirstValueOfLibCXXCompressedPair(ValueObject &pair);
2727
lldb::ValueObjectSP GetSecondValueOfLibCXXCompressedPair(ValueObject &pair);
28-
bool isOldCompressedPairLayout(ValueObject &pair_obj);
28+
29+
/// Returns the ValueObjectSP of the child of \c obj. If \c obj has no
30+
/// child named \c child_name, returns the __compressed_pair child instead
31+
/// with \c compressed_pair_name, if one exists.
32+
///
33+
/// Latest libc++ wrap the compressed children in an anonymous structure.
34+
/// The \c anon_struct_idx indicates the location of this struct.
35+
///
36+
/// The returned boolean is \c true if the returned child was has an old-style
37+
/// libc++ __compressed_pair layout.
38+
///
39+
/// If no child was found returns a nullptr.
40+
std::pair<lldb::ValueObjectSP, bool>
41+
GetValueOrOldCompressedPair(ValueObject &obj, size_t anon_struct_idx,
42+
llvm::StringRef child_name,
43+
llvm::StringRef compressed_pair_name);
2944
bool isStdTemplate(ConstString type_name, llvm::StringRef type);
3045

3146
bool LibcxxStringSummaryProviderASCII(

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

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
200200
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
201201

202202
private:
203-
llvm::Expected<uint32_t> CalculateNumChildrenForOldCompressedPairLayout();
203+
llvm::Expected<uint32_t>
204+
CalculateNumChildrenForOldCompressedPairLayout(ValueObject &pair);
204205

205206
/// Returns the ValueObject for the __tree_node type that
206207
/// holds the key/value pair of the node at index \ref idx.
@@ -254,16 +255,8 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
254255

255256
llvm::Expected<uint32_t>
256257
lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
257-
CalculateNumChildrenForOldCompressedPairLayout() {
258-
ValueObjectSP node_sp(m_tree->GetChildMemberWithName("__pair3_"));
259-
if (!node_sp)
260-
return 0;
261-
262-
if (!isOldCompressedPairLayout(*node_sp))
263-
return llvm::createStringError("Unexpected std::map layout: expected "
264-
"old __compressed_pair layout.");
265-
266-
node_sp = GetFirstValueOfLibCXXCompressedPair(*node_sp);
258+
CalculateNumChildrenForOldCompressedPairLayout(ValueObject &pair) {
259+
auto node_sp = GetFirstValueOfLibCXXCompressedPair(pair);
267260

268261
if (!node_sp)
269262
return 0;
@@ -281,12 +274,16 @@ llvm::Expected<uint32_t> lldb_private::formatters::
281274
if (m_tree == nullptr)
282275
return 0;
283276

284-
if (auto node_sp = m_tree->GetChildMemberWithName("__size_")) {
285-
m_count = node_sp->GetValueAsUnsigned(0);
286-
return m_count;
287-
}
277+
auto [size_sp, is_compressed_pair] = GetValueOrOldCompressedPair(
278+
*m_tree, /*anon_struct_idx=*/2, "__size_", "__pair3_");
279+
if (!size_sp)
280+
return llvm::createStringError("Unexpected std::map layout");
288281

289-
return CalculateNumChildrenForOldCompressedPairLayout();
282+
if (is_compressed_pair)
283+
return CalculateNumChildrenForOldCompressedPairLayout(*size_sp);
284+
285+
m_count = size_sp->GetValueAsUnsigned(0);
286+
return m_count;
290287
}
291288

292289
ValueObjectSP

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

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -130,22 +130,17 @@ CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
130130

131131
CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
132132
GetNodeType() {
133-
auto node_sp = m_backend.GetChildAtNamePath({"__table_", "__first_node_"});
134-
135-
if (!node_sp) {
136-
auto p1_sp = m_backend.GetChildAtNamePath({"__table_", "__p1_"});
137-
if (!p1_sp)
138-
return {};
133+
auto table_sp = m_backend.GetChildMemberWithName("__table_");
134+
if (!table_sp)
135+
return {};
139136

140-
if (!isOldCompressedPairLayout(*p1_sp))
141-
return {};
137+
auto [node_sp, is_compressed_pair] = GetValueOrOldCompressedPair(
138+
*table_sp, /*anon_struct_idx=*/1, "__first_node_", "__p1_");
139+
if (is_compressed_pair)
140+
node_sp = GetFirstValueOfLibCXXCompressedPair(*node_sp);
142141

143-
node_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp);
144-
if (!node_sp)
145-
return {};
146-
}
147-
148-
assert(node_sp);
142+
if (!node_sp)
143+
return {};
149144

150145
return node_sp->GetCompilerType().GetTypeTemplateArgument(0).GetPointeeType();
151146
}
@@ -223,19 +218,15 @@ lldb::ValueObjectSP lldb_private::formatters::
223218
llvm::Expected<size_t>
224219
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
225220
CalculateNumChildrenImpl(ValueObject &table) {
226-
if (auto size_sp = table.GetChildMemberWithName("__size_"))
221+
auto [size_sp, is_compressed_pair] = GetValueOrOldCompressedPair(
222+
table, /*anon_struct_idx=*/2, "__size_", "__p2_");
223+
if (!is_compressed_pair && size_sp)
227224
return size_sp->GetValueAsUnsigned(0);
228225

229-
ValueObjectSP p2_sp = table.GetChildMemberWithName("__p2_");
230-
if (!p2_sp)
231-
return llvm::createStringError(
232-
"Unexpected std::unordered_map layout: __p2_ member not found.");
226+
if (!is_compressed_pair)
227+
return llvm::createStringError("Unsupported std::unordered_map layout.");
233228

234-
if (!isOldCompressedPairLayout(*p2_sp))
235-
return llvm::createStringError("Unexpected std::unordered_map layout: old "
236-
"__compressed_pair layout not found.");
237-
238-
ValueObjectSP num_elements_sp = GetFirstValueOfLibCXXCompressedPair(*p2_sp);
229+
ValueObjectSP num_elements_sp = GetFirstValueOfLibCXXCompressedPair(*size_sp);
239230

240231
if (!num_elements_sp)
241232
return llvm::createStringError(
@@ -246,19 +237,13 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
246237
}
247238

248239
static ValueObjectSP GetTreePointer(ValueObject &table) {
249-
ValueObjectSP tree_sp = table.GetChildMemberWithName("__first_node_");
250-
if (!tree_sp) {
251-
ValueObjectSP p1_sp = table.GetChildMemberWithName("__p1_");
252-
if (!p1_sp)
253-
return nullptr;
254-
255-
if (!isOldCompressedPairLayout(*p1_sp))
256-
return nullptr;
257-
258-
tree_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp);
259-
if (!tree_sp)
260-
return nullptr;
261-
}
240+
auto [tree_sp, is_compressed_pair] = GetValueOrOldCompressedPair(
241+
table, /*anon_struct_idx=*/1, "__first_node_", "__p1_");
242+
if (is_compressed_pair)
243+
tree_sp = GetFirstValueOfLibCXXCompressedPair(*tree_sp);
244+
245+
if (!tree_sp)
246+
return nullptr;
262247

263248
return tree_sp->GetChildMemberWithName("__next_");
264249
}

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,15 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex(
126126
}
127127

128128
static ValueObjectSP GetDataPointer(ValueObject &root) {
129-
if (auto cap_sp = root.GetChildMemberWithName("__cap_"))
130-
return cap_sp;
131-
132-
ValueObjectSP cap_sp = root.GetChildMemberWithName("__end_cap_");
129+
auto [cap_sp, is_compressed_pair] = GetValueOrOldCompressedPair(
130+
root, /*anon_struct_idx=*/2, "__cap_", "__end_cap_");
133131
if (!cap_sp)
134132
return nullptr;
135133

136-
if (!isOldCompressedPairLayout(*cap_sp))
137-
return nullptr;
134+
if (is_compressed_pair)
135+
return GetFirstValueOfLibCXXCompressedPair(*cap_sp);
138136

139-
return GetFirstValueOfLibCXXCompressedPair(*cap_sp);
137+
return cap_sp;
140138
}
141139

142140
lldb::ChildCacheState

0 commit comments

Comments
 (0)