From cb4efa0839a421e0573b3ccb586bef6f62f37dbe Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Thu, 23 Oct 2025 16:56:59 -0700 Subject: [PATCH] Add a -debug-module-path frontend option This new option allows the Driver to pass the path to a compilation job's own binary swiftmodule artifact to the frontend. The compiler then stores this path in the debug info, to allow clients like LLDB to unambiguously know which binary Swift module belongs to which compile unit. rdar://163302154 --- include/swift/AST/IRGenOptions.h | 3 +++ include/swift/Option/Options.td | 6 ++++++ lib/Frontend/CompilerInvocation.cpp | 3 +++ lib/IRGen/IRGenDebugInfo.cpp | 10 +++++++--- test/DebugInfo/ebm_module_path.swift | 4 ++++ 5 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 test/DebugInfo/ebm_module_path.swift diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index e31ac132a0dfa..226eded7f12ec 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -270,6 +270,9 @@ class IRGenOptions { public: std::string ModuleName; + /// The path to the main binary swiftmodule for the debug info. + std::string DebugModulePath; + /// The compilation directory for the debug info. std::string DebugCompilationDir; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 85a11d114d03b..f3cd8bd24aeff 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -643,6 +643,12 @@ def project_name : Separate<["-"], "project-name">, def module_name_EQ : Joined<["-"], "module-name=">, Flags<[FrontendOption]>, Alias; +def debug_module_path : Separate<["-"], "debug-module-path">, + Flags<[FrontendOption]>, + HelpText<"Path to this module's binary swiftmodule artifact (required by debug info)">; +def debug_module_path_EQ : Joined<["-"], "debug-module-path=">, Flags<[FrontendOption]>, + Alias; + def module_alias : Separate<["-"], "module-alias">, Flags<[FrontendOption, ModuleInterfaceOption]>, MetaVarName<"">, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 98134b74aeb5e..ad52fc68a6c5d 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -3460,6 +3460,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, A->getAsString(Args), A->getValue()); } + if (const Arg *A = Args.getLastArg(options::OPT_debug_module_path)) + Opts.DebugModulePath = A->getValue(); + for (auto A : Args.getAllArgValues(options::OPT_file_prefix_map)) { auto SplitMap = StringRef(A).split('='); Opts.FilePrefixMap.addMapping(SplitMap.first, SplitMap.second); diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index aa48bdea6b9a3..c6e649f0cac9e 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -864,7 +864,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { llvm::DIModule *getOrCreateModule(const void *Key, llvm::DIScope *Parent, StringRef Name, StringRef IncludePath, uint64_t Signature = ~1ULL, - StringRef ASTFile = StringRef()) { + StringRef ASTFile = {}) { // Look in the cache first. auto Val = DIModuleCache.find(Key); if (Val != DIModuleCache.end()) @@ -2823,8 +2823,12 @@ IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts, // Create a module for the current compile unit. auto *MDecl = IGM.getSwiftModule(); - llvm::sys::path::remove_filename(SourcePath); - MainModule = getOrCreateModule(MDecl, TheCU, Opts.ModuleName, SourcePath); + StringRef Path = Opts.DebugModulePath; + if (Path.empty()) { + llvm::sys::path::remove_filename(SourcePath); + Path = SourcePath; + } + MainModule = getOrCreateModule(MDecl, TheCU, Opts.ModuleName, Path); DBuilder.createImportedModule(MainFile, MainModule, MainFile, 0); // Macro definitions that were defined by the user with "-Xcc -D" on the diff --git a/test/DebugInfo/ebm_module_path.swift b/test/DebugInfo/ebm_module_path.swift new file mode 100644 index 0000000000000..a48a85017b101 --- /dev/null +++ b/test/DebugInfo/ebm_module_path.swift @@ -0,0 +1,4 @@ +// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -module-name=A -debug-module-path %t/MY_MODULE_PATH.swiftmodule -emit-ir -o - | %FileCheck %s + +// CHECK: DIModule(scope: null, name: "A", includePath: "{{.*}}MY_MODULE_PATH.swiftmodule") +