From 1349b680dbd9cac4c8441d76934ef5ebd651a8a7 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Wed, 23 Jul 2025 14:32:49 -0700 Subject: [PATCH] [lldb] Speed up check if C++ interop and embedded are enabled Previously, we were parsing every compile unit to look up the flags that indicate whether the current compile unit had C++ interop and/or embedded Swift enabled. Change that to parse only the compile unit we're interested in. rdar://153198051 --- lldb/include/lldb/Symbol/SymbolFile.h | 9 +++ .../Swift/SwiftExpressionParser.cpp | 8 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 75 +++++++++---------- .../TypeSystem/Swift/TypeSystemSwift.cpp | 21 +++--- .../TestSwiftForwardInteropExpressions.py | 6 +- .../expr/TestSwiftEmbeddedExpression.py | 6 ++ 6 files changed, 71 insertions(+), 54 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 8d6f090605628..7a0ca8b19a3ee 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -387,6 +387,15 @@ class SymbolFile : public PluginInterface { /// for this module have been changed. virtual void SectionFileAddressesChanged() = 0; + /// Looks for the compile option specified by \p option, and sets \p value to + /// it's value. For example, for a flag such as -foo=bar, looking up \p option + /// "-foo" will set \p value to "bar". For a standalone flag such as -baz, \p + /// value will be empty. + /// + /// If \p cu is set, only that compile unit is searched. Otherwise, every + /// compile unit is searched until the option is found or failure. + /// + /// Returns true if the option is found. virtual bool GetCompileOption(const char *option, std::string &value, CompileUnit *cu = nullptr) { value.clear(); diff --git a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp index bd4d64a0522f5..f55b3964d6712 100644 --- a/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Swift/SwiftExpressionParser.cpp @@ -358,12 +358,12 @@ class LLDBExprNameLookup : public LLDBNameLookup { swift::Identifier getPreferredPrivateDiscriminator() override { if (m_sc.comp_unit) { if (lldb_private::Module *module = m_sc.module_sp.get()) { - if (lldb_private::SymbolFile *symbol_file = - module->GetSymbolFile()) { + if (lldb_private::SymbolFile *symbol_file = module->GetSymbolFile()) { std::string private_discriminator_string; if (symbol_file->GetCompileOption("-private-discriminator", - private_discriminator_string, - m_sc.comp_unit)) { + private_discriminator_string, + m_sc.comp_unit) && + !private_discriminator_string.empty()) { return m_source_file.getASTContext().getIdentifier( private_discriminator_string); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 83f4416b59d78..e02ec964f1124 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3253,6 +3253,36 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { return result; } +namespace { +const char *GetFlags(const char *option, DWARFUnit *dwarf_cu) { + if (!dwarf_cu) + return nullptr; + + const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly(); + if (!die) + return nullptr; + + const char *flags = die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL); + if (!flags) + return nullptr; + + if (strstr(flags, option)) + return flags; + + return nullptr; +} +bool FindOptionInDWARFCU(const char *option, DWARFUnit *dwarf_cu, + std::string &value) { + const char *flags = GetFlags(option, dwarf_cu); + if (!flags) + return false; + + Args compiler_args(flags); + OptionParsing::GetOptionValueAsString(compiler_args, option, value); + return true; +} +} // namespace + bool SymbolFileDWARF::GetCompileOption(const char *option, std::string &value, CompileUnit *cu) { value.clear(); @@ -3262,52 +3292,19 @@ bool SymbolFileDWARF::GetCompileOption(const char *option, std::string &value, const uint32_t num_compile_units = GetNumCompileUnits(); if (cu) { - auto *dwarf_cu = - llvm::dyn_cast_or_null(GetDWARFCompileUnit(cu)); - - if (dwarf_cu) { + if (auto *dwarf_cu = + llvm::dyn_cast_or_null(GetDWARFCompileUnit(cu))) { // GetDWARFCompileUnit() only looks up by CU#. Make sure that // this is actually the correct SymbolFile by converting it // back to a CompileUnit. if (GetCompUnitForDWARFCompUnit(*dwarf_cu) != cu) return false; - - const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly(); - if (die) { - const char *flags = - die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL); - - if (flags) { - if (strstr(flags, option)) { - Args compiler_args(flags); - - return OptionParsing::GetOptionValueAsString(compiler_args, - option, value); - } - } - } + return FindOptionInDWARFCU(option, dwarf_cu, value); } } else { - for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { - DWARFUnit *dwarf_cu = debug_info.GetUnitAtIndex(cu_idx); - - if (dwarf_cu) { - const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly(); - if (die) { - const char *flags = - die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL); - - if (flags) { - if (strstr(flags, option)) { - Args compiler_args(flags); - - return OptionParsing::GetOptionValueAsString(compiler_args, - option, value); - } - } - } - } - } + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + if (DWARFUnit *dwarf_cu = debug_info.GetUnitAtIndex(cu_idx)) + return FindOptionInDWARFCU(option, dwarf_cu, value); } return false; diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.cpp index cda4161a07d21..5d94360571398 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.cpp @@ -16,6 +16,7 @@ #include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h" #include "lldb/Core/PluginManager.h" #include "lldb/Symbol/CompileUnit.h" +#include "lldb/Utility/LLDBLog.h" #include #include @@ -74,7 +75,7 @@ void TypeSystemSwift::Terminate() { bool TypeSystemSwift::CheckFlagInCU(CompileUnit *cu, const char *flag) { AutoBool interop_enabled = - ModuleList::GetGlobalModuleListProperties().GetSwiftEnableCxxInterop(); + ModuleList::GetGlobalModuleListProperties().GetSwiftEnableCxxInterop(); switch (interop_enabled) { case AutoBool::True: return true; @@ -89,18 +90,18 @@ bool TypeSystemSwift::CheckFlagInCU(CompileUnit *cu, const char *flag) { auto *sym_file = module->GetSymbolFile(); if (!sym_file) return false; - auto options = sym_file->GetCompileOptions(); - for (auto &[unit, args] : options) { - if (unit.get() == cu) { - if (cu->GetLanguage() == eLanguageTypeSwift) - for (const char *arg : args.GetArgumentArrayRef()) - if (strcmp(arg, flag) == 0) - return true; - return false; - } + std::string value; + if (sym_file->GetCompileOption(flag, value, cu)) { + LLDB_LOGV(GetLog(LLDBLog::Types), + "[CheckFlagInCU] Found flag {0} in CU: {1}", flag, + cu->GetPrimaryFile().GetFilename().AsCString()); + return true; } } } + LLDB_LOGV(GetLog(LLDBLog::Types), + "[CheckFlagInCU] Did not find flag {0} in CU: {1}", flag, + cu->GetPrimaryFile().GetFilename().AsCString()); return false; } diff --git a/lldb/test/API/lang/swift/cxx_interop/forward/expressions/TestSwiftForwardInteropExpressions.py b/lldb/test/API/lang/swift/cxx_interop/forward/expressions/TestSwiftForwardInteropExpressions.py index c76b52a59ecd3..f278858085d74 100644 --- a/lldb/test/API/lang/swift/cxx_interop/forward/expressions/TestSwiftForwardInteropExpressions.py +++ b/lldb/test/API/lang/swift/cxx_interop/forward/expressions/TestSwiftForwardInteropExpressions.py @@ -15,13 +15,14 @@ def setup(self, bkpt_str): self, bkpt_str, lldb.SBFileSpec('main.swift')) return thread - @skipIf(bugnumber='rdar://152745034') @skipIfLinux # rdar://106871422" @skipIf(setting=('symbols.use-swift-clangimporter', 'false')) # rdar://106871275 @swiftTest def test(self): self.setup('Break here') + types_log = self.getBuildArtifact('types.log') + self.expect("log enable lldb types -v -f "+ types_log) # Check that we can call free functions. self.expect('expr returnsInt()', substrs=['Int32', '42']) @@ -54,6 +55,9 @@ def test(self): # Check that po prints the fields of a base class self.expect('po cxxClass', substrs=['CxxClass', 'a : 100', 'b : 101']) + self.filecheck('platform shell cat "%s"' % types_log, __file__) + # CHECK: [CheckFlagInCU] Found flag -enable-experimental-cxx-interop in CU: + @expectedFailureAll(bugnumber="rdar://106216567") @swiftTest def test_po_subclass(self): diff --git a/lldb/test/API/lang/swift/embedded/expr/TestSwiftEmbeddedExpression.py b/lldb/test/API/lang/swift/embedded/expr/TestSwiftEmbeddedExpression.py index a1d04ba6ee86f..a129d3c3d9e1f 100644 --- a/lldb/test/API/lang/swift/embedded/expr/TestSwiftEmbeddedExpression.py +++ b/lldb/test/API/lang/swift/embedded/expr/TestSwiftEmbeddedExpression.py @@ -14,4 +14,10 @@ def test(self): self, "break here", lldb.SBFileSpec("main.swift") ) + types_log = self.getBuildArtifact('types.log') + self.expect("log enable lldb types -v -f "+ types_log) + self.expect("expr a.foo()", substrs=["(Int)", " = 16"]) + + self.filecheck('platform shell cat "%s"' % types_log, __file__) + # CHECK: [CheckFlagInCU] Found flag -enable-embedded-swift in CU: