Skip to content

Commit 2e060b9

Browse files
Michael137IanWood1
authored andcommitted
[lldb][Mangled] Retrieve and cache demangled name info (llvm#131836)
Uses the `TrackingOutputBuffer` to populate the new member `Mangled::m_demangled_info`. `m_demangled_info` is lazily popluated by `GetDemangledInfo`. To ensure `m_demangled` and `m_demangled_info` are in-sync we clear `m_demangled_info` anytime `m_demangled` is set/cleared. llvm#131836
1 parent 20cecec commit 2e060b9

File tree

7 files changed

+243
-44
lines changed

7 files changed

+243
-44
lines changed

lldb/include/lldb/Core/DemangledNameInfo.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,20 @@ struct DemangledNameInfo {
4848
/// \endcode
4949
std::pair<size_t, size_t> ArgumentsRange;
5050

51+
/// Indicates the [start, end) of the function qualifiers
52+
/// (e.g., CV-qualifiers, reference qualifiers, requires clauses).
53+
///
54+
/// E.g.,
55+
/// \code{.cpp}
56+
/// void foo::bar<int>::qux<float>(int) const &&
57+
/// ^ ^
58+
/// start end
59+
/// \endcode
60+
std::pair<size_t, size_t> QualifiersRange;
61+
5162
/// Returns \c true if this object holds a valid basename range.
5263
bool hasBasename() const {
53-
return BasenameRange.first != BasenameRange.second &&
64+
return BasenameRange.second > BasenameRange.first &&
5465
BasenameRange.second > 0;
5566
}
5667

@@ -139,6 +150,8 @@ struct TrackingOutputBuffer : public llvm::itanium_demangle::OutputBuffer {
139150
void finalizeArgumentEnd();
140151
void finalizeStart();
141152
void finalizeEnd();
153+
void finalizeQualifiersStart();
154+
void finalizeQualifiersEnd();
142155

143156
/// Helper used in the finalize APIs.
144157
bool canFinalize() const;

lldb/include/lldb/Core/Mangled.h

+17-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
#ifndef LLDB_CORE_MANGLED_H
1010
#define LLDB_CORE_MANGLED_H
1111

12+
#include "lldb/Core/DemangledNameInfo.h"
13+
#include "lldb/Utility/ConstString.h"
1214
#include "lldb/lldb-enumerations.h"
1315
#include "lldb/lldb-forward.h"
1416
#include "lldb/lldb-types.h"
15-
#include "lldb/Utility/ConstString.h"
1617
#include "llvm/ADT/StringRef.h"
1718

1819
#include <cstddef>
@@ -134,9 +135,15 @@ class Mangled {
134135
/// A const reference to the display demangled name string object.
135136
ConstString GetDisplayDemangledName() const;
136137

137-
void SetDemangledName(ConstString name) { m_demangled = name; }
138+
void SetDemangledName(ConstString name) {
139+
m_demangled = name;
140+
m_demangled_info.reset();
141+
}
138142

139-
void SetMangledName(ConstString name) { m_mangled = name; }
143+
void SetMangledName(ConstString name) {
144+
m_mangled = name;
145+
m_demangled_info.reset();
146+
}
140147

141148
/// Mangled name get accessor.
142149
///
@@ -277,6 +284,9 @@ class Mangled {
277284
/// table offsets in the cache data.
278285
void Encode(DataEncoder &encoder, ConstStringTable &strtab) const;
279286

287+
/// Retrieve \c DemangledNameInfo of the demangled name held by this object.
288+
const std::optional<DemangledNameInfo> &GetDemangledInfo() const;
289+
280290
private:
281291
/// If \c force is \c false, this function will re-use the previously
282292
/// demangled name (if any). If \c force is \c true (or the mangled name
@@ -290,6 +300,10 @@ class Mangled {
290300
/// Mutable so we can get it on demand with
291301
/// a const version of this object.
292302
mutable ConstString m_demangled;
303+
304+
/// If available, holds information about where in \c m_demangled certain
305+
/// parts of the name (e.g., basename, arguments, etc.) begin and end.
306+
mutable std::optional<DemangledNameInfo> m_demangled_info = std::nullopt;
293307
};
294308

295309
Stream &operator<<(Stream &s, const Mangled &obj);

lldb/source/Core/DemangledNameInfo.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ void TrackingOutputBuffer::finalizeArgumentEnd() {
6666
NameInfo.ArgumentsRange.second = getCurrentPosition();
6767
}
6868

69+
void TrackingOutputBuffer::finalizeQualifiersStart() {
70+
if (!canFinalize())
71+
return;
72+
73+
NameInfo.QualifiersRange.first = getCurrentPosition();
74+
}
75+
76+
void TrackingOutputBuffer::finalizeQualifiersEnd() {
77+
if (!canFinalize())
78+
return;
79+
80+
NameInfo.QualifiersRange.second = getCurrentPosition();
81+
}
82+
6983
void TrackingOutputBuffer::finalizeStart() {
7084
if (!shouldTrack())
7185
return;
@@ -171,6 +185,8 @@ void TrackingOutputBuffer::printRightImpl(const FunctionEncoding &N) {
171185
if (Ret)
172186
printRight(*Ret);
173187

188+
finalizeQualifiersStart();
189+
174190
auto CVQuals = N.getCVQuals();
175191
auto RefQual = N.getRefQual();
176192
auto *Attrs = N.getAttrs();
@@ -193,6 +209,7 @@ void TrackingOutputBuffer::printRightImpl(const FunctionEncoding &N) {
193209
Requires->print(*this);
194210
}
195211

212+
finalizeQualifiersEnd();
196213
finalizeEnd();
197214
}
198215

lldb/source/Core/Mangled.cpp

+34-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "lldb/Core/Mangled.h"
1010

1111
#include "lldb/Core/DataFileCache.h"
12+
#include "lldb/Core/DemangledNameInfo.h"
1213
#include "lldb/Core/RichManglingContext.h"
1314
#include "lldb/Target/Language.h"
1415
#include "lldb/Utility/ConstString.h"
@@ -111,6 +112,7 @@ Mangled::operator bool() const { return m_mangled || m_demangled; }
111112
void Mangled::Clear() {
112113
m_mangled.Clear();
113114
m_demangled.Clear();
115+
m_demangled_info.reset();
114116
}
115117

116118
// Compare the string values.
@@ -124,13 +126,16 @@ void Mangled::SetValue(ConstString name) {
124126
if (IsMangledName(name.GetStringRef())) {
125127
m_demangled.Clear();
126128
m_mangled = name;
129+
m_demangled_info.reset();
127130
} else {
128131
m_demangled = name;
129132
m_mangled.Clear();
133+
m_demangled_info.reset();
130134
}
131135
} else {
132136
m_demangled.Clear();
133137
m_mangled.Clear();
138+
m_demangled_info.reset();
134139
}
135140
}
136141

@@ -152,20 +157,26 @@ static char *GetMSVCDemangledStr(llvm::StringRef M) {
152157
return demangled_cstr;
153158
}
154159

155-
static char *GetItaniumDemangledStr(const char *M) {
160+
static std::pair<char *, DemangledNameInfo>
161+
GetItaniumDemangledStr(const char *M) {
156162
char *demangled_cstr = nullptr;
157163

164+
DemangledNameInfo info;
158165
llvm::ItaniumPartialDemangler ipd;
159166
bool err = ipd.partialDemangle(M);
160167
if (!err) {
161-
// Default buffer and size (will realloc in case it's too small).
168+
// Default buffer and size (OutputBuffer will realloc in case it's too
169+
// small).
162170
size_t demangled_size = 80;
163-
demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
164-
demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size);
171+
demangled_cstr = static_cast<char *>(std::malloc(80));
172+
173+
TrackingOutputBuffer OB(demangled_cstr, demangled_size);
174+
demangled_cstr = ipd.finishDemangle(&OB);
175+
info = std::move(OB.NameInfo);
165176

166177
assert(demangled_cstr &&
167178
"finishDemangle must always succeed if partialDemangle did");
168-
assert(demangled_cstr[demangled_size - 1] == '\0' &&
179+
assert(demangled_cstr[OB.getCurrentPosition() - 1] == '\0' &&
169180
"Expected demangled_size to return length including trailing null");
170181
}
171182

@@ -174,9 +185,14 @@ static char *GetItaniumDemangledStr(const char *M) {
174185
LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr);
175186
else
176187
LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M);
188+
189+
if (!info.hasBasename())
190+
LLDB_LOGF(log,
191+
"demangled itanium: %s -> error: failed to retrieve name info",
192+
M);
177193
}
178194

179-
return demangled_cstr;
195+
return {demangled_cstr, std::move(info)};
180196
}
181197

182198
static char *GetRustV0DemangledStr(llvm::StringRef M) {
@@ -269,6 +285,13 @@ ConstString Mangled::GetDemangledName() const {
269285
return GetDemangledNameImpl(/*force=*/false);
270286
}
271287

288+
std::optional<DemangledNameInfo> const &Mangled::GetDemangledInfo() const {
289+
if (!m_demangled_info)
290+
GetDemangledNameImpl(/*force=*/true);
291+
292+
return m_demangled_info;
293+
}
294+
272295
// Generate the demangled name on demand using this accessor. Code in this
273296
// class will need to use this accessor if it wishes to decode the demangled
274297
// name. The result is cached and will be kept until a new string value is
@@ -293,7 +316,10 @@ ConstString Mangled::GetDemangledNameImpl(bool force) const {
293316
demangled_name = GetMSVCDemangledStr(m_mangled);
294317
break;
295318
case eManglingSchemeItanium: {
296-
demangled_name = GetItaniumDemangledStr(m_mangled.GetCString());
319+
std::pair<char *, DemangledNameInfo> demangled =
320+
GetItaniumDemangledStr(m_mangled.GetCString());
321+
demangled_name = demangled.first;
322+
m_demangled_info.emplace(std::move(demangled.second));
297323
break;
298324
}
299325
case eManglingSchemeRustV0:
@@ -452,6 +478,7 @@ bool Mangled::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
452478
const StringTableReader &strtab) {
453479
m_mangled.Clear();
454480
m_demangled.Clear();
481+
m_demangled_info.reset();
455482
MangledEncoding encoding = (MangledEncoding)data.GetU8(offset_ptr);
456483
switch (encoding) {
457484
case Empty:

0 commit comments

Comments
 (0)