Skip to content

Commit 40d69ed

Browse files
committed
[LLDB] Refactored CPlusPlusLanguage::MethodName to break lldb-server dependencies
This patch addresses the issue #129543. After this patch the size of lldb-server is reduced by 9MB. Co-authored-by: @bulbazord Alex Langford
1 parent edc22c6 commit 40d69ed

File tree

17 files changed

+286
-259
lines changed

17 files changed

+286
-259
lines changed

lldb/include/lldb/Core/Mangled.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ class Mangled {
246246
/// for s, otherwise the enumerator for the mangling scheme detected.
247247
static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name);
248248

249+
static bool IsCPPMangledName(llvm::StringRef name);
250+
249251
/// Decode a serialized version of this object from data.
250252
///
251253
/// \param data

lldb/include/lldb/Core/RichManglingContext.h

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "lldb/lldb-forward.h"
1313
#include "lldb/lldb-private.h"
1414

15+
#include "lldb/Target/Language.h"
1516
#include "lldb/Utility/ConstString.h"
1617

1718
#include "llvm/ADT/Any.h"
@@ -67,11 +68,7 @@ class RichManglingContext {
6768
char *m_ipd_buf;
6869
size_t m_ipd_buf_size = 2048;
6970

70-
/// Members for PluginCxxLanguage
71-
/// Cannot forward declare inner class CPlusPlusLanguage::MethodName. The
72-
/// respective header is in Plugins and including it from here causes cyclic
73-
/// dependency. Instead keep a llvm::Any and cast it on-access in the cpp.
74-
llvm::Any m_cxx_method_parser;
71+
std::unique_ptr<Language::MethodName> m_cxx_method_parser;
7572

7673
/// Clean up memory when using PluginCxxLanguage
7774
void ResetCxxMethodParser();
@@ -81,15 +78,6 @@ class RichManglingContext {
8178

8279
/// Uniform handling of string buffers for ItaniumPartialDemangler.
8380
llvm::StringRef processIPDStrResult(char *ipd_res, size_t res_len);
84-
85-
/// Cast the given parser to the given type. Ideally we would have a type
86-
/// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we
87-
/// can't access CPlusPlusLanguage::MethodName from within the header.
88-
template <class ParserT> static ParserT *get(llvm::Any parser) {
89-
assert(parser.has_value());
90-
assert(llvm::any_cast<ParserT *>(&parser));
91-
return *llvm::any_cast<ParserT *>(&parser);
92-
}
9381
};
9482

9583
} // namespace lldb_private

lldb/include/lldb/Target/Language.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,104 @@ class Language : public PluginInterface {
214214
return std::vector<Language::MethodNameVariant>();
215215
};
216216

217+
class MethodName {
218+
public:
219+
MethodName() {}
220+
221+
MethodName(ConstString full)
222+
: m_full(full), m_basename(), m_context(), m_arguments(),
223+
m_qualifiers(), m_return_type(), m_scope_qualified(), m_parsed(false),
224+
m_parse_error(false) {}
225+
226+
virtual ~MethodName() {};
227+
228+
void Clear() {
229+
m_full.Clear();
230+
m_basename = llvm::StringRef();
231+
m_context = llvm::StringRef();
232+
m_arguments = llvm::StringRef();
233+
m_qualifiers = llvm::StringRef();
234+
m_return_type = llvm::StringRef();
235+
m_scope_qualified.clear();
236+
m_parsed = false;
237+
m_parse_error = false;
238+
}
239+
240+
bool IsValid() {
241+
if (!m_parsed)
242+
Parse();
243+
if (m_parse_error)
244+
return false;
245+
return (bool)m_full;
246+
}
247+
248+
ConstString GetFullName() const { return m_full; }
249+
250+
llvm::StringRef GetBasename() {
251+
if (!m_parsed)
252+
Parse();
253+
return m_basename;
254+
}
255+
256+
llvm::StringRef GetContext() {
257+
if (!m_parsed)
258+
Parse();
259+
return m_context;
260+
}
261+
262+
llvm::StringRef GetArguments() {
263+
if (!m_parsed)
264+
Parse();
265+
return m_arguments;
266+
}
267+
268+
llvm::StringRef GetQualifiers() {
269+
if (!m_parsed)
270+
Parse();
271+
return m_qualifiers;
272+
}
273+
274+
llvm::StringRef GetReturnType() {
275+
if (!m_parsed)
276+
Parse();
277+
return m_return_type;
278+
}
279+
280+
std::string GetScopeQualifiedName() {
281+
if (!m_parsed)
282+
Parse();
283+
return m_scope_qualified;
284+
}
285+
286+
protected:
287+
virtual void Parse() {
288+
m_parsed = true;
289+
m_parse_error = true;
290+
}
291+
292+
ConstString m_full; // Full name:
293+
// "size_t lldb::SBTarget::GetBreakpointAtIndex(unsigned
294+
// int) const"
295+
llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex"
296+
llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
297+
llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
298+
llvm::StringRef m_qualifiers; // Qualifiers: "const"
299+
llvm::StringRef m_return_type; // Return type: "size_t"
300+
std::string m_scope_qualified;
301+
bool m_parsed = false;
302+
bool m_parse_error = false;
303+
};
304+
305+
virtual std::unique_ptr<Language::MethodName>
306+
GetMethodName(ConstString name) const {
307+
return std::make_unique<Language::MethodName>(name);
308+
};
309+
310+
virtual std::pair<lldb::FunctionNameType, llvm::StringRef>
311+
GetFunctionNameInfo(ConstString name) const {
312+
return std::pair{lldb::eFunctionNameTypeNone, llvm::StringRef()};
313+
};
314+
217315
/// Returns true iff the given symbol name is compatible with the mangling
218316
/// scheme of this language.
219317
///

lldb/source/Core/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ add_lldb_library(lldbCore
7171
lldbUtility
7272
lldbValueObject
7373
lldbVersion
74-
lldbPluginCPlusPlusLanguage
75-
lldbPluginObjCLanguage
7674
${LLDB_CURSES_LIBS}
7775

7876
CLANG_LIBS

lldb/source/Core/Mangled.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ static inline bool cstring_is_mangled(llvm::StringRef s) {
3939

4040
#pragma mark Mangled
4141

42+
bool Mangled::IsCPPMangledName(llvm::StringRef name) {
43+
Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
44+
return (scheme != Mangled::eManglingSchemeNone);
45+
}
46+
4247
Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
4348
if (name.empty())
4449
return Mangled::eManglingSchemeNone;

lldb/source/Core/Module.cpp

Lines changed: 63 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@
5252
#include "lldb/Host/windows/PosixApi.h"
5353
#endif
5454

55-
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
56-
#include "Plugins/Language/ObjC/ObjCLanguage.h"
57-
5855
#include "llvm/ADT/STLExtras.h"
5956
#include "llvm/Support/Compiler.h"
6057
#include "llvm/Support/DJB.h"
@@ -641,98 +638,75 @@ void Module::FindCompileUnits(const FileSpec &path,
641638
Module::LookupInfo::LookupInfo(ConstString name,
642639
FunctionNameType name_type_mask,
643640
LanguageType language)
644-
: m_name(name), m_lookup_name(), m_language(language) {
645-
const char *name_cstr = name.GetCString();
641+
: m_name(name), m_lookup_name(name), m_language(language) {
646642
llvm::StringRef basename;
647-
llvm::StringRef context;
643+
644+
std::vector<Language *> languages;
645+
auto collect_language_plugins = [&languages](Language *lang) {
646+
languages.push_back(lang);
647+
return true;
648+
};
648649

649650
if (name_type_mask & eFunctionNameTypeAuto) {
650-
if (CPlusPlusLanguage::IsCPPMangledName(name_cstr))
651-
m_name_type_mask = eFunctionNameTypeFull;
652-
else if ((language == eLanguageTypeUnknown ||
653-
Language::LanguageIsObjC(language)) &&
654-
ObjCLanguage::IsPossibleObjCMethodName(name_cstr))
655-
m_name_type_mask = eFunctionNameTypeFull;
656-
else if (Language::LanguageIsC(language)) {
657-
m_name_type_mask = eFunctionNameTypeFull;
651+
if (language == eLanguageTypeUnknown) {
652+
Language::ForEach(collect_language_plugins);
653+
for (Language *lang : languages) {
654+
auto info = lang->GetFunctionNameInfo(name);
655+
if (info.first != eFunctionNameTypeNone) {
656+
m_name_type_mask |= info.first;
657+
basename = info.second;
658+
break;
659+
}
660+
}
658661
} else {
659-
if ((language == eLanguageTypeUnknown ||
660-
Language::LanguageIsObjC(language)) &&
661-
ObjCLanguage::IsPossibleObjCSelector(name_cstr))
662-
m_name_type_mask |= eFunctionNameTypeSelector;
663-
664-
CPlusPlusLanguage::MethodName cpp_method(name);
665-
basename = cpp_method.GetBasename();
666-
if (basename.empty()) {
667-
if (CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
668-
basename))
669-
m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
670-
else
671-
m_name_type_mask |= eFunctionNameTypeFull;
672-
} else {
673-
m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
662+
if (auto *lang = Language::FindPlugin(language)) {
663+
auto info = lang->GetFunctionNameInfo(name);
664+
m_name_type_mask = info.first;
665+
basename = info.second;
674666
}
675667
}
668+
669+
// NOTE: There are several ways to get here, but this is a fallback path in
670+
// case the above does not succeed at extracting any useful information from
671+
// the loaded language plugins.
672+
if (m_name_type_mask == eFunctionNameTypeNone)
673+
m_name_type_mask = eFunctionNameTypeFull;
674+
676675
} else {
677676
m_name_type_mask = name_type_mask;
678-
if (name_type_mask & eFunctionNameTypeMethod ||
679-
name_type_mask & eFunctionNameTypeBase) {
680-
// If they've asked for a CPP method or function name and it can't be
681-
// that, we don't even need to search for CPP methods or names.
682-
CPlusPlusLanguage::MethodName cpp_method(name);
683-
if (cpp_method.IsValid()) {
684-
basename = cpp_method.GetBasename();
685-
686-
if (!cpp_method.GetQualifiers().empty()) {
687-
// There is a "const" or other qualifier following the end of the
688-
// function parens, this can't be a eFunctionNameTypeBase
689-
m_name_type_mask &= ~(eFunctionNameTypeBase);
690-
if (m_name_type_mask == eFunctionNameTypeNone)
691-
return;
677+
if (language == eLanguageTypeUnknown) {
678+
Language::ForEach(collect_language_plugins);
679+
for (Language *lang : languages) {
680+
auto info = lang->GetFunctionNameInfo(name);
681+
if (info.first & m_name_type_mask) {
682+
m_name_type_mask &= info.first;
683+
basename = info.second;
684+
break;
692685
}
693-
} else {
694-
// If the CPP method parser didn't manage to chop this up, try to fill
695-
// in the base name if we can. If a::b::c is passed in, we need to just
696-
// look up "c", and then we'll filter the result later.
697-
CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
698-
basename);
699-
}
700-
}
701-
702-
if (name_type_mask & eFunctionNameTypeSelector) {
703-
if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) {
704-
m_name_type_mask &= ~(eFunctionNameTypeSelector);
705-
if (m_name_type_mask == eFunctionNameTypeNone)
706-
return;
707686
}
708-
}
709-
710-
// Still try and get a basename in case someone specifies a name type mask
711-
// of eFunctionNameTypeFull and a name like "A::func"
712-
if (basename.empty()) {
713-
if (name_type_mask & eFunctionNameTypeFull &&
714-
!CPlusPlusLanguage::IsCPPMangledName(name_cstr)) {
715-
CPlusPlusLanguage::MethodName cpp_method(name);
716-
basename = cpp_method.GetBasename();
717-
if (basename.empty())
718-
CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
719-
basename);
687+
} else {
688+
if (auto *lang = Language::FindPlugin(language)) {
689+
auto info = lang->GetFunctionNameInfo(name);
690+
if (info.first & m_name_type_mask) {
691+
// If the user asked for FunctionNameTypes that aren't possible,
692+
// then filter those out. (e.g. asking for Selectors on
693+
// C++ symbols, or even if the symbol given can't be a selector in
694+
// ObjC)
695+
m_name_type_mask &= info.first;
696+
basename = info.second;
697+
}
720698
}
721699
}
722700
}
723701

724702
if (!basename.empty()) {
725-
// The name supplied was a partial C++ path like "a::count". In this case
726-
// we want to do a lookup on the basename "count" and then make sure any
727-
// matching results contain "a::count" so that it would match "b::a::count"
728-
// and "a::count". This is why we set "match_name_after_lookup" to true
703+
// The name supplied was incomplete for lookup purposes. For example, in C++
704+
// we may have gotten something like "a::count". In this case, we want to do
705+
// a lookup on the basename "count" and then make sure any matching results
706+
// contain "a::count" so that it would match "b::a::count" and "a::count".
707+
// This is why we set match_name_after_lookup to true.
729708
m_lookup_name.SetString(basename);
730709
m_match_name_after_lookup = true;
731-
} else {
732-
// The name is already correct, just use the exact name as supplied, and we
733-
// won't need to check if any matches contain "name"
734-
m_lookup_name = name;
735-
m_match_name_after_lookup = false;
736710
}
737711
}
738712

@@ -791,7 +765,8 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list,
791765
// "func" and specified eFunctionNameTypeFull, but we might have found
792766
// "a::func()", "a::b::func()", "c::func()", "func()" and "func". Only
793767
// "func()" and "func" should end up matching.
794-
if (m_name_type_mask == eFunctionNameTypeFull) {
768+
auto *lang = Language::FindPlugin(eLanguageTypeC_plus_plus);
769+
if (lang && m_name_type_mask == eFunctionNameTypeFull) {
795770
SymbolContext sc;
796771
size_t i = start_idx;
797772
while (i < sc_list.GetSize()) {
@@ -802,20 +777,21 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list,
802777
ConstString mangled_name(sc.GetFunctionName(Mangled::ePreferMangled));
803778
ConstString full_name(sc.GetFunctionName());
804779
if (mangled_name != m_name && full_name != m_name) {
805-
CPlusPlusLanguage::MethodName cpp_method(full_name);
806-
if (cpp_method.IsValid()) {
807-
if (cpp_method.GetContext().empty()) {
808-
if (cpp_method.GetBasename().compare(m_name) != 0) {
780+
std::unique_ptr<Language::MethodName> cpp_method =
781+
lang->GetMethodName(full_name);
782+
if (cpp_method->IsValid()) {
783+
if (cpp_method->GetContext().empty()) {
784+
if (cpp_method->GetBasename().compare(m_name) != 0) {
809785
sc_list.RemoveContextAtIndex(i);
810786
continue;
811787
}
812788
} else {
813789
std::string qualified_name;
814790
llvm::StringRef anon_prefix("(anonymous namespace)");
815-
if (cpp_method.GetContext() == anon_prefix)
816-
qualified_name = cpp_method.GetBasename().str();
791+
if (cpp_method->GetContext() == anon_prefix)
792+
qualified_name = cpp_method->GetBasename().str();
817793
else
818-
qualified_name = cpp_method.GetScopeQualifiedName();
794+
qualified_name = cpp_method->GetScopeQualifiedName();
819795
if (qualified_name != m_name.GetCString()) {
820796
sc_list.RemoveContextAtIndex(i);
821797
continue;
@@ -988,8 +964,7 @@ DebuggersOwningModuleRequestingInterruption(Module &module) {
988964
for (auto debugger_sp : requestors) {
989965
if (!debugger_sp->InterruptRequested())
990966
continue;
991-
if (debugger_sp->GetTargetList()
992-
.AnyTargetContainsModule(module))
967+
if (debugger_sp->GetTargetList().AnyTargetContainsModule(module))
993968
interruptors.push_back(debugger_sp);
994969
}
995970
return interruptors;

0 commit comments

Comments
 (0)