Skip to content

[lldb] Enable auto-detection of Swift/C++ interop #6509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lldb/include/lldb/Core/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,8 @@ class Module : public std::enable_shared_from_this<Module>,
void
ReportWarningToolchainMismatch(CompileUnit &comp_unit,
llvm::Optional<lldb::user_id_t> debugger_id);

bool IsSwiftCxxInteropEnabled();
#endif

// Return true if the file backing this module has changed since the module
Expand Down Expand Up @@ -1174,6 +1176,10 @@ class Module : public std::enable_shared_from_this<Module>,

Module(const Module &) = delete;
const Module &operator=(const Module &) = delete;

#ifdef LLDB_ENABLE_SWIFT
LazyBool m_is_swift_cxx_interop_enabled = eLazyBoolCalculate;
#endif
};

} // namespace lldb_private
Expand Down
12 changes: 12 additions & 0 deletions lldb/include/lldb/Symbol/SymbolFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <mutex>
#include <vector>
#include <unordered_map>

#if defined(LLDB_CONFIGURATION_DEBUG)
#define ASSERT_MODULE_LOCK(expr) (expr->AssertModuleLock())
Expand Down Expand Up @@ -471,9 +472,20 @@ class SymbolFile : public PluginInterface {

virtual lldb::TypeSP CopyType(const lldb::TypeSP &other_type) = 0;

/// Returns a map of compilation unit to the compile option arguments
/// associated with that compilation unit.
std::unordered_map<lldb::CompUnitSP, Args> GetCompileOptions() {
std::unordered_map<lldb::CompUnitSP, Args> args;
GetCompileOptions(args);
return args;
}

protected:
void AssertModuleLock();

virtual void GetCompileOptions(
std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) {}

private:
SymbolFile(const SymbolFile &) = delete;
const SymbolFile &operator=(const SymbolFile &) = delete;
Expand Down
8 changes: 7 additions & 1 deletion lldb/include/lldb/Target/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class TargetProperties : public Properties {

bool GetSwiftEnableBareSlashRegex() const;

bool GetSwiftEnableCxxInterop() const;
EnableSwiftCxxInterop GetEnableSwiftCxxInterop() const;

bool GetSwiftAutoImportFrameworks() const;

Expand Down Expand Up @@ -1260,6 +1260,7 @@ class Target : public std::enable_shared_from_this<Target>,
/// Return whether this is the Swift REPL.
bool IsSwiftREPL();

bool IsSwiftCxxInteropEnabled();
private:
void DisplayFallbackSwiftContextErrors(
SwiftASTContextForExpressions *swift_ast_ctx);
Expand Down Expand Up @@ -1736,6 +1737,11 @@ class Target : public std::enable_shared_from_this<Target>,

Target(const Target &) = delete;
const Target &operator=(const Target &) = delete;

#ifdef LLDB_ENABLE_SWIFT
LazyBool m_is_swift_cxx_interop_enabled = eLazyBoolCalculate;
#endif // LLDB_ENABLE_SWIFT

};

} // namespace lldb_private
Expand Down
8 changes: 8 additions & 0 deletions lldb/include/lldb/lldb-private-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ typedef enum SwiftModuleLoadingMode {
eSwiftModuleLoadingModeOnlyInterface, // Load via .swiftinterface only
} SwiftModuleLoadingMode;

// BEGIN SWIFT
enum EnableSwiftCxxInterop {
eAutoDetectSwiftCxxInterop,
eEnableSwiftCxxInterop,
eDisableSwiftCxxInterop
};
// END SWIFT

// Loading modules from memory
enum MemoryModuleLoadLevel {
eMemoryModuleLoadLevelMinimal, // Load sections only
Expand Down
42 changes: 42 additions & 0 deletions lldb/source/Core/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,48 @@ void Module::ReportWarningToolchainMismatch(
}
}
}

bool Module::IsSwiftCxxInteropEnabled() {
switch (m_is_swift_cxx_interop_enabled) {
case eLazyBoolYes:
return true;
case eLazyBoolNo:
return false;
case eLazyBoolCalculate:
break;
}
EnableSwiftCxxInterop interop_enabled =
Target::GetGlobalProperties().GetEnableSwiftCxxInterop();
switch (interop_enabled) {
case eEnableSwiftCxxInterop:
m_is_swift_cxx_interop_enabled = eLazyBoolYes;
break;
case eDisableSwiftCxxInterop:
m_is_swift_cxx_interop_enabled = eLazyBoolNo;
break;
case eAutoDetectSwiftCxxInterop: {
// Look for the "-enable-experimental-cxx-interop" compile flag in the args
// of the compile units this module is composed of.
auto *sym_file = GetSymbolFile();
if (sym_file) {
auto options = sym_file->GetCompileOptions();
for (auto &[_, args] : options) {
for (const char *arg : args.GetArgumentArrayRef()) {
if (strcmp(arg, "-enable-experimental-cxx-interop") == 0) {
m_is_swift_cxx_interop_enabled = eLazyBoolYes;
break;
}
}
if (m_is_swift_cxx_interop_enabled == eLazyBoolYes)
break;
}
}
if (m_is_swift_cxx_interop_enabled == eLazyBoolCalculate)
m_is_swift_cxx_interop_enabled = eLazyBoolNo;
}
}
return m_is_swift_cxx_interop_enabled == eLazyBoolYes;
}
#endif

void Module::ReportErrorIfModifyDetected(const char *format, ...) {
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Language/Swift/SwiftLanguage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ SwiftLanguage::GetHardcodedSynthetics() {

Log *log(GetLog(LLDBLog::DataFormatters));

if (!valobj.GetTargetSP()->GetSwiftEnableCxxInterop())
if (!valobj.GetTargetSP()->IsSwiftCxxInteropEnabled())
return nullptr;

CompilerType type(valobj.GetCompilerType());
Expand Down
27 changes: 27 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4282,3 +4282,30 @@ Status SymbolFileDWARF::CalculateFrameVariableError(StackFrame &frame) {
return Status("no variable information is available in debug info for this "
"compile unit");
}

void SymbolFileDWARF::GetCompileOptions(
std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) {

const uint32_t num_compile_units = GetNumCompileUnits();

for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
lldb::CompUnitSP comp_unit = GetCompileUnitAtIndex(cu_idx);
if (!comp_unit)
continue;

DWARFUnit *dwarf_cu = GetDWARFCompileUnit(comp_unit.get());
if (!dwarf_cu)
continue;

const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
if (!die)
continue;

const char *flags = die.GetAttributeValueAsString(DW_AT_APPLE_flags, NULL);

if (!flags)
continue;
args.insert({comp_unit, Args(flags)});
}
}

3 changes: 3 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,9 @@ class SymbolFileDWARF : public lldb_private::SymbolFileCommon,

void InitializeFirstCodeAddress();

void GetCompileOptions(
std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) override;

lldb::ModuleWP m_debug_map_module_wp;
SymbolFileDWARFDebugMap *m_debug_map_symfile;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1642,3 +1642,12 @@ Status SymbolFileDWARFDebugMap::CalculateFrameVariableError(StackFrame &frame) {
}
return Status();
}

void SymbolFileDWARFDebugMap::GetCompileOptions(
std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) {

ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
oso_dwarf->GetCompileOptions(args);
return false;
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFileCommon {
// Statistics overrides.
lldb_private::ModuleList GetDebugInfoModules() override;

void GetCompileOptions(
std::unordered_map<lldb::CompUnitSP, lldb_private::Args> &args) override;

protected:
enum { kHaveInitializedOSOs = (1 << 0), kNumFlags };

Expand Down
7 changes: 5 additions & 2 deletions lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1564,7 +1564,8 @@ SwiftASTContext::CreateInstance(lldb::LanguageType language, Module &module,
swift_ast_sp->m_module = &module;
swift_ast_sp->GetLanguageOptions().EnableAccessControl = false;
swift_ast_sp->GetLanguageOptions().EnableCXXInterop =
Target::GetGlobalProperties().GetSwiftEnableCxxInterop();
module.IsSwiftCxxInteropEnabled();

bool found_swift_modules = false;
SymbolFile *sym_file = module.GetSymbolFile();

Expand Down Expand Up @@ -1950,7 +1951,7 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(
swift_ast_sp->m_is_scratch_context = true;

swift_ast_sp->GetLanguageOptions().EnableCXXInterop =
target.GetSwiftEnableCxxInterop();
target.IsSwiftCxxInteropEnabled();
bool handled_sdk_path = false;
const size_t num_images = target.GetImages().GetSize();

Expand Down Expand Up @@ -4825,6 +4826,8 @@ void SwiftASTContext::LogConfiguration() {
for (std::string &extra_arg : clang_importer_options.ExtraArgs) {
HEALTH_LOG_PRINTF(" %s", extra_arg.c_str());
}
HEALTH_LOG_PRINTF(" Swift/C++ interop mode: %s",
m_ast_context_ap->LangOpts.EnableCXXInterop ? "on" : "off");
}

bool SwiftASTContext::HasTarget() {
Expand Down
54 changes: 45 additions & 9 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2860,6 +2860,37 @@ bool Target::IsSwiftREPL() {
GetProcessLaunchInfo().GetArg0().endswith("repl_swift");
}

bool Target::IsSwiftCxxInteropEnabled() {
switch (m_is_swift_cxx_interop_enabled) {
case eLazyBoolYes:
return true;
case eLazyBoolNo:
return false;
case eLazyBoolCalculate:
break;
}

EnableSwiftCxxInterop interop_enabled = GetEnableSwiftCxxInterop();
switch (interop_enabled) {
case eEnableSwiftCxxInterop:
m_is_swift_cxx_interop_enabled = eLazyBoolYes;
break;
case eDisableSwiftCxxInterop:
m_is_swift_cxx_interop_enabled = eLazyBoolNo;
break;
case eAutoDetectSwiftCxxInterop: {
if (GetImages().IsEmpty())
m_is_swift_cxx_interop_enabled = eLazyBoolNo;
else
m_is_swift_cxx_interop_enabled =
GetImages().GetModuleAtIndex(0)->IsSwiftCxxInteropEnabled()
? eLazyBoolYes
: eLazyBoolNo;
}
}
return m_is_swift_cxx_interop_enabled == eLazyBoolYes;
}

#endif // LLDB_ENABLE_SWIFT

void Target::SettingsInitialize() { Process::SettingsInitialize(); }
Expand Down Expand Up @@ -4385,6 +4416,13 @@ static constexpr OptionEnumValueElement g_memory_module_load_level_values[] = {
},
};

static constexpr OptionEnumValueElement g_enable_swift_cxx_interop_values[] = {
{eAutoDetectSwiftCxxInterop, "auto",
"Automatically detect if C++ interop mode should be enabled."},
{eEnableSwiftCxxInterop, "true", "Enable C++ interop."},
{eDisableSwiftCxxInterop, "false", "Disable C++ interop."},
};

#define LLDB_PROPERTIES_target
#include "TargetProperties.inc"

Expand Down Expand Up @@ -4605,16 +4643,14 @@ bool TargetProperties::GetSwiftEnableBareSlashRegex() const {
return true;
}

bool TargetProperties::GetSwiftEnableCxxInterop() const {
const Property *exp_property = m_collection_sp->GetPropertyAtIndex(
nullptr, false, ePropertyExperimental);
OptionValueProperties *exp_values =
exp_property->GetValue()->GetAsProperties();
if (exp_values)
return exp_values->GetPropertyAtIndexAsBoolean(
nullptr, ePropertySwiftEnableCxxInterop, false);
EnableSwiftCxxInterop TargetProperties::GetEnableSwiftCxxInterop() const {
const uint32_t idx = ePropertySwiftEnableCxxInterop;

return false;
EnableSwiftCxxInterop enable_interop =
(EnableSwiftCxxInterop)m_experimental_properties_up->GetValueProperties()
->GetPropertyAtIndexAsEnumeration(
nullptr, idx, g_target_properties[idx].default_uint_value);
return enable_interop;
}

bool TargetProperties::GetSwiftAutoImportFrameworks() const {
Expand Down
5 changes: 3 additions & 2 deletions lldb/source/Target/TargetProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ let Definition = "target_experimental" in {
def SwiftEnableBareSlashRegex: Property<"swift-enable-bare-slash-regex", "Boolean">,
DefaultFalse,
Desc<"Passes the -enable-bare-slash-regex compiler flag to the swift compiler.">;
def SwiftEnableCxxInterop: Property<"swift-enable-cxx-interop", "Boolean">,
DefaultFalse,
def SwiftEnableCxxInterop: Property<"swift-enable-cxx-interop", "Enum">,
DefaultEnumValue<"eAutoDetectSwiftCxxInterop">,
EnumValues<"OptionEnumValues(g_enable_swift_cxx_interop_values)">,
Desc<"Passes the -enable-cxx-interop flag to the swift compiler.">;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class TestSwiftBackwardInteropFormatActors(TestBase):
@swiftTest
def test_class(self):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')

_, _, _, _= lldbutil.run_to_source_breakpoint(
self, 'Set breakpoint here', lldb.SBFileSpec('main.cpp'))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class TestSwiftBackwardInteropFormatSwiftStdlibTypes(TestBase):
def setup(self, bkpt_str):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')

_, _, _, _= lldbutil.run_to_source_breakpoint(
self, bkpt_str, lldb.SBFileSpec('main.cpp'))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TestSwiftBackwardInteropFormatSwiftTypesInCxx(TestBase):

def setup(self, bkpt_str):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')

_, _, _, _= lldbutil.run_to_source_breakpoint(
self, bkpt_str, lldb.SBFileSpec('main.cpp'))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TestSwiftBackwardInteropStepping(TestBase):

def setup(self, bkpt_str):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')

_, _, thread, _ = lldbutil.run_to_source_breakpoint(
self, bkpt_str, lldb.SBFileSpec('main.cpp'))
return thread
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class TestSwiftForwardInteropClassInNamespace(TestBase):
@swiftTest
def test_class(self):
self.build()
self.runCmd('settings set target.experimental.swift-enable-cxx-interop true')
_, _, _, _= lldbutil.run_to_source_breakpoint(
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class TestSwiftForwardInteropCxxClassAsExistential(TestBase):
@swiftTest
def test(self):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')

_, _, _, _= lldbutil.run_to_source_breakpoint(
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class TestSwiftForwardInteropCxxClass(TestBase):
@swiftTest
def test_class(self):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')
_, _, _, _= lldbutil.run_to_source_breakpoint(
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))

Expand Down
Loading