Skip to content

Commit 140c024

Browse files
authored
Add -prefix-serialized-debugging-options (#39555)
This commit adds a new frontend flag that applies debug path prefixing to the paths serialized in swiftmodule files. This makes it possible to use swiftmodule files that have been built on different machines by applying the inverse map when debugging, in a similar fashion to source path prefixing. The inverse mapping in LLDB will be handled in a follow up PR. Second pass at #39138 Tests updated to handle windows path separators. This reverts commit f5aa95b.
1 parent b8d7062 commit 140c024

File tree

13 files changed

+239
-31
lines changed

13 files changed

+239
-31
lines changed

include/swift/AST/SearchPathOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_AST_SEARCHPATHOPTIONS_H
1515

1616
#include "swift/Basic/ArrayRefView.h"
17+
#include "swift/Basic/PathRemapper.h"
1718
#include "llvm/ADT/Hashing.h"
1819

1920
#include <string>
@@ -97,6 +98,11 @@ class SearchPathOptions {
9798

9899
/// A file containing modules we should perform batch scanning.
99100
std::string BatchScanInputFilePath;
101+
102+
/// Debug path mappings to apply to serialized search paths. These are
103+
/// specified in LLDB from the target.source-map entries.
104+
PathRemapper SearchPathRemapper;
105+
100106
private:
101107
static StringRef
102108
pathStringFromFrameworkSearchPath(const FrameworkSearchPath &next) {

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,9 @@ namespace swift {
772772
DisableOverlayModules,
773773
EnableClangSPI);
774774
}
775+
776+
std::vector<std::string> getRemappedExtraArgs(
777+
std::function<std::string(StringRef)> pathRemapCallback) const;
775778
};
776779

777780
} // end namespace swift

include/swift/Frontend/FrontendOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ class FrontendOptions {
182182
/// module appears to not be a public module.
183183
Optional<bool> SerializeOptionsForDebugging;
184184

185+
/// When true the debug prefix map entries will be applied to debugging
186+
/// options before serialization. These can be reconstructed at debug time by
187+
/// applying the inverse map in SearchPathOptions.SearchPathRemapper.
188+
bool DebugPrefixSerializedDebuggingOptions = false;
189+
185190
/// When true, check if all required SwiftOnoneSupport symbols are present in
186191
/// the module.
187192
bool CheckOnoneSupportCompleteness = false;

include/swift/Option/Options.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ def disable_bridging_pch : Flag<["-"], "disable-bridging-pch">,
559559
def lto : Joined<["-"], "lto=">,
560560
Flags<[FrontendOption, NoInteractiveOption]>,
561561
HelpText<"Specify the LTO type to either 'llvm-thin' or 'llvm-full'">;
562-
562+
563563
def lto_library : Separate<["-"], "lto-library">,
564564
Flags<[FrontendOption, ArgumentIsPath, NoInteractiveOption]>,
565565
HelpText<"Perform LTO with <lto-library>">, MetaVarName<"<lto-library>">;
@@ -815,6 +815,10 @@ def debug_info_format : Joined<["-"], "debug-info-format=">,
815815
Flags<[FrontendOption]>,
816816
HelpText<"Specify the debug info format type to either 'dwarf' or 'codeview'">;
817817

818+
def prefix_serialized_debugging_options : Flag<["-"], "prefix-serialized-debugging-options">,
819+
Flags<[FrontendOption]>,
820+
HelpText<"Apply debug prefix mappings to serialized debug info in Swiftmodule files">;
821+
818822
// Verify debug info
819823
def verify_debug_info : Flag<["-"], "verify-debug-info">,
820824
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,

include/swift/Serialization/SerializationOptions.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_SERIALIZATION_SERIALIZATIONOPTIONS_H
1515

1616
#include "swift/Basic/LLVM.h"
17+
#include "swift/Basic/PathRemapper.h"
1718
#include "llvm/Support/VersionTuple.h"
1819

1920
namespace swift {
@@ -42,7 +43,10 @@ namespace swift {
4243
StringRef ImportedHeader;
4344
StringRef ModuleLinkName;
4445
StringRef ModuleInterface;
45-
ArrayRef<std::string> ExtraClangOptions;
46+
std::vector<std::string> ExtraClangOptions;
47+
48+
/// Path prefixes that should be rewritten in debug info.
49+
PathRemapper DebuggingOptionsPrefixMap;
4650

4751
/// Describes a single-file dependency for this module, along with the
4852
/// appropriate strategy for how to verify if it's up-to-date.

lib/Basic/LangOptions.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,56 @@ DiagnosticBehavior LangOptions::getAccessNoteFailureLimit() const {
408408
}
409409
llvm_unreachable("covered switch");
410410
}
411+
412+
std::vector<std::string> ClangImporterOptions::getRemappedExtraArgs(
413+
std::function<std::string(StringRef)> pathRemapCallback) const {
414+
auto consumeIncludeOption = [](StringRef &arg, StringRef &prefix) {
415+
static StringRef options[] = {"-I",
416+
"-F",
417+
"-fmodule-map-file=",
418+
"-iquote",
419+
"-idirafter",
420+
"-iframeworkwithsysroot",
421+
"-iframework",
422+
"-iprefix",
423+
"-iwithprefixbefore",
424+
"-iwithprefix",
425+
"-isystemafter",
426+
"-isystem",
427+
"-isysroot",
428+
"-ivfsoverlay",
429+
"-working-directory=",
430+
"-working-directory"};
431+
for (StringRef &option : options)
432+
if (arg.consume_front(option)) {
433+
prefix = option;
434+
return true;
435+
}
436+
return false;
437+
};
438+
439+
// true if the previous argument was the dash-option of an option pair
440+
bool remap_next = false;
441+
std::vector<std::string> args;
442+
for (auto A : ExtraArgs) {
443+
StringRef prefix;
444+
StringRef arg(A);
445+
446+
if (remap_next) {
447+
remap_next = false;
448+
args.push_back(pathRemapCallback(arg));
449+
} else if (consumeIncludeOption(arg, prefix)) {
450+
if (arg.empty()) {
451+
// Option pair
452+
remap_next = true;
453+
args.push_back(prefix.str());
454+
} else {
455+
// Combine prefix with remapped path value
456+
args.push_back(prefix.str() + pathRemapCallback(arg));
457+
}
458+
} else {
459+
args.push_back(A);
460+
}
461+
}
462+
return args;
463+
}

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ bool ArgsToFrontendOptionsConverter::convert(
258258
A->getOption().matches(OPT_serialize_debugging_options);
259259
}
260260

261+
Opts.DebugPrefixSerializedDebuggingOptions |=
262+
Args.hasArg(OPT_prefix_serialized_debugging_options);
261263
Opts.EnableSourceImport |= Args.hasArg(OPT_enable_source_import);
262264
Opts.ImportUnderlyingModule |= Args.hasArg(OPT_import_underlying_module);
263265
Opts.EnableIncrementalDependencyVerifier |= Args.hasArg(OPT_verify_incremental_dependencies);

lib/Frontend/Frontend.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ SerializationOptions CompilerInvocation::computeSerializationOptions(
147147
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
148148
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
149149
serializationOpts.UserModuleVersion = opts.UserModuleVersion;
150-
serializationOpts.ExtraClangOptions = getClangImporterOptions().ExtraArgs;
150+
151151
serializationOpts.PublicDependentLibraries =
152152
getIRGenOptions().PublicLinkLibraries;
153153
serializationOpts.SDKName = getLangOptions().SDKName;
@@ -176,6 +176,20 @@ SerializationOptions CompilerInvocation::computeSerializationOptions(
176176
opts.SerializeOptionsForDebugging.getValueOr(
177177
!module->isExternallyConsumed());
178178

179+
if (serializationOpts.SerializeOptionsForDebugging &&
180+
opts.DebugPrefixSerializedDebuggingOptions) {
181+
serializationOpts.DebuggingOptionsPrefixMap =
182+
getIRGenOptions().DebugPrefixMap;
183+
auto &remapper = serializationOpts.DebuggingOptionsPrefixMap;
184+
auto remapClangPaths = [&remapper](StringRef path) {
185+
return remapper.remapPath(path);
186+
};
187+
serializationOpts.ExtraClangOptions =
188+
getClangImporterOptions().getRemappedExtraArgs(remapClangPaths);
189+
} else {
190+
serializationOpts.ExtraClangOptions = getClangImporterOptions().ExtraArgs;
191+
}
192+
179193
serializationOpts.DisableCrossModuleIncrementalInfo =
180194
opts.DisableCrossModuleIncrementalBuild;
181195

lib/Serialization/ModuleFile.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,11 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
158158
return error(status);
159159
}
160160

161-
for (const auto &searchPath : Core->SearchPaths)
162-
ctx.addSearchPath(searchPath.Path, searchPath.IsFramework,
163-
searchPath.IsSystem);
161+
for (const auto &searchPath : Core->SearchPaths) {
162+
ctx.addSearchPath(
163+
ctx.SearchPathOpts.SearchPathRemapper.remapPath(searchPath.Path),
164+
searchPath.IsFramework, searchPath.IsSystem);
165+
}
164166

165167
auto clangImporter = static_cast<ClangImporter *>(ctx.getClangModuleLoader());
166168

lib/Serialization/Serialization.cpp

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "swift/Basic/Defer.h"
4141
#include "swift/Basic/Dwarf.h"
4242
#include "swift/Basic/FileSystem.h"
43+
#include "swift/Basic/PathRemapper.h"
4344
#include "swift/Basic/STLExtras.h"
4445
#include "swift/Basic/Version.h"
4546
#include "swift/ClangImporter/ClangImporter.h"
@@ -48,9 +49,9 @@
4849
#include "swift/Demangling/ManglingMacros.h"
4950
#include "swift/Serialization/SerializationOptions.h"
5051
#include "swift/Strings.h"
51-
#include "clang/AST/DeclTemplate.h"
52-
#include "swift/SymbolGraphGen/SymbolGraphOptions.h"
5352
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
53+
#include "swift/SymbolGraphGen/SymbolGraphOptions.h"
54+
#include "clang/AST/DeclTemplate.h"
5455
#include "llvm/ADT/SmallSet.h"
5556
#include "llvm/ADT/SmallString.h"
5657
#include "llvm/ADT/StringExtras.h"
@@ -511,7 +512,7 @@ static uint8_t getRawOpaqueReadOwnership(swift::OpaqueReadOwnership ownership) {
511512
CASE(OwnedOrBorrowed)
512513
#undef CASE
513514
}
514-
llvm_unreachable("bad kind");
515+
llvm_unreachable("bad kind");
515516
}
516517

517518
static uint8_t getRawReadImplKind(swift::ReadImplKind kind) {
@@ -1062,25 +1063,35 @@ void Serializer::writeHeader(const SerializationOptions &options) {
10621063
options_block::SDKPathLayout SDKPath(Out);
10631064
options_block::XCCLayout XCC(Out);
10641065

1065-
SDKPath.emit(ScratchRecord, M->getASTContext().SearchPathOpts.SDKPath);
1066+
const auto &PathRemapper = options.DebuggingOptionsPrefixMap;
1067+
SDKPath.emit(
1068+
ScratchRecord,
1069+
PathRemapper.remapPath(M->getASTContext().SearchPathOpts.SDKPath));
10661070
auto &Opts = options.ExtraClangOptions;
1067-
for (auto Arg = Opts.begin(), E = Opts.end(); Arg != E; ++Arg) {
1068-
// FIXME: This is a hack and calls for a better design.
1069-
//
1070-
// Filter out any -ivfsoverlay options that include an
1071-
// unextended-module-overlay.yaml overlay. By convention the Xcode
1072-
// buildsystem uses these while *building* mixed Objective-C and Swift
1073-
// frameworks; but they should never be used to *import* the module
1074-
// defined in the framework.
1075-
if (StringRef(*Arg).startswith("-ivfsoverlay")) {
1071+
for (auto Arg = Opts.begin(), E = Opts.end(); Arg != E; ++Arg) {
1072+
StringRef arg(*Arg);
1073+
if (arg.startswith("-ivfsoverlay")) {
1074+
// FIXME: This is a hack and calls for a better design.
1075+
//
1076+
// Filter out any -ivfsoverlay options that include an
1077+
// unextended-module-overlay.yaml overlay. By convention the Xcode
1078+
// buildsystem uses these while *building* mixed Objective-C and
1079+
// Swift frameworks; but they should never be used to *import* the
1080+
// module defined in the framework.
10761081
auto Next = std::next(Arg);
10771082
if (Next != E &&
10781083
StringRef(*Next).endswith("unextended-module-overlay.yaml")) {
10791084
++Arg;
10801085
continue;
10811086
}
1087+
} else if (arg.startswith("-fdebug-prefix-map=")) {
1088+
// We don't serialize the debug prefix map flags as these
1089+
// contain absoute paths that are not usable on different
1090+
// machines. These flags are not necessary to compile the
1091+
// clang modules again so are safe to remove.
1092+
continue;
10821093
}
1083-
XCC.emit(ScratchRecord, *Arg);
1094+
XCC.emit(ScratchRecord, arg);
10841095
}
10851096
}
10861097
}
@@ -1131,14 +1142,16 @@ void Serializer::writeInputBlock(const SerializationOptions &options) {
11311142
input_block::ModuleInterfaceLayout ModuleInterface(Out);
11321143

11331144
if (options.SerializeOptionsForDebugging) {
1145+
const auto &PathMapper = options.DebuggingOptionsPrefixMap;
11341146
const SearchPathOptions &searchPathOpts = M->getASTContext().SearchPathOpts;
11351147
// Put the framework search paths first so that they'll be preferred upon
11361148
// deserialization.
11371149
for (auto &framepath : searchPathOpts.FrameworkSearchPaths)
11381150
SearchPath.emit(ScratchRecord, /*framework=*/true, framepath.IsSystem,
1139-
framepath.Path);
1151+
PathMapper.remapPath(framepath.Path));
11401152
for (auto &path : searchPathOpts.ImportSearchPaths)
1141-
SearchPath.emit(ScratchRecord, /*framework=*/false, /*system=*/false, path);
1153+
SearchPath.emit(ScratchRecord, /*framework=*/false, /*system=*/false,
1154+
PathMapper.remapPath(path));
11421155
}
11431156

11441157
// Note: We're not using StringMap here because we don't need to own the
@@ -1472,7 +1485,7 @@ void Serializer::writeASTBlockEntity(const SILLayout *layout) {
14721485
typeRef |= 0x80000000U;
14731486
data.push_back(typeRef);
14741487
}
1475-
1488+
14761489
unsigned abbrCode
14771490
= DeclTypeAbbrCodes[SILLayoutLayout::Code];
14781491

@@ -1707,7 +1720,7 @@ static bool shouldSerializeMember(Decl *D) {
17071720

17081721
case DeclKind::OpaqueType:
17091722
return true;
1710-
1723+
17111724
case DeclKind::EnumElement:
17121725
case DeclKind::Protocol:
17131726
case DeclKind::Constructor:
@@ -1805,14 +1818,14 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
18051818
if (auto opaque = dyn_cast<OpaqueTypeDecl>(generic)) {
18061819
if (!opaque->hasName()) {
18071820
abbrCode = DeclTypeAbbrCodes[XRefOpaqueReturnTypePathPieceLayout::Code];
1808-
1821+
18091822
XRefOpaqueReturnTypePathPieceLayout::emitRecord(Out, ScratchRecord,
18101823
abbrCode,
18111824
addDeclBaseNameRef(opaque->getOpaqueReturnTypeIdentifier()));
18121825
break;
18131826
}
18141827
}
1815-
1828+
18161829
assert(generic->hasName());
18171830

18181831
abbrCode = DeclTypeAbbrCodes[XRefTypePathPieceLayout::Code];
@@ -1853,7 +1866,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
18531866
case DeclContextKind::SubscriptDecl: {
18541867
auto SD = cast<SubscriptDecl>(DC);
18551868
writeCrossReference(DC->getParent(), pathLen + 1);
1856-
1869+
18571870
Type ty = SD->getInterfaceType()->getCanonicalType();
18581871

18591872
abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
@@ -1864,7 +1877,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
18641877
SD->isStatic());
18651878
break;
18661879
}
1867-
1880+
18681881
case DeclContextKind::AbstractFunctionDecl: {
18691882
if (auto fn = dyn_cast<AccessorDecl>(DC)) {
18701883
auto storage = fn->getStorage();
@@ -1976,7 +1989,7 @@ void Serializer::writeCrossReference(const Decl *D) {
19761989
addDeclBaseNameRef(opaque->getOpaqueReturnTypeIdentifier()));
19771990
return;
19781991
}
1979-
1992+
19801993
if (auto genericParam = dyn_cast<GenericTypeParamDecl>(D)) {
19811994
assert(!D->getDeclContext()->isModuleScopeContext() &&
19821995
"Cannot cross reference a generic type decl at module scope.");
@@ -4677,7 +4690,7 @@ class ClangToSwiftBasicWriter :
46774690

46784691
Serializer &S;
46794692
SmallVectorImpl<uint64_t> &Record;
4680-
using TypeWriter =
4693+
using TypeWriter =
46814694
clang::serialization::AbstractTypeWriter<ClangToSwiftBasicWriter>;
46824695
TypeWriter Types;
46834696

@@ -5481,7 +5494,7 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
54815494
/*isLocal=*/true);
54825495
}
54835496
}
5484-
5497+
54855498
for (auto OTD : opaqueReturnTypeDecls) {
54865499
// FIXME: We should delay parsing function bodies so these type decls
54875500
// don't even get added to the file.

0 commit comments

Comments
 (0)