diff --git a/include/swift/APIDigester/ModuleAnalyzerNodes.h b/include/swift/APIDigester/ModuleAnalyzerNodes.h index 6783c068ece..c1a09bda0b7 100644 --- a/include/swift/APIDigester/ModuleAnalyzerNodes.h +++ b/include/swift/APIDigester/ModuleAnalyzerNodes.h @@ -816,7 +816,7 @@ int dumpSDKContent(const CompilerInvocation &InitInvok, const llvm::StringSet<> &ModuleNames, StringRef OutputFile, CheckerOptions Opts); -void dumpModuleContent(ModuleDecl *MD, StringRef OutputFile, bool ABI); +void dumpModuleContent(ModuleDecl *MD, StringRef OutputFile, bool ABI, bool Empty); /// Mostly for testing purposes, this function de-serializes the SDK dump in /// dumpPath and re-serialize them to OutputPath. If the tool performs correctly, diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 5aff1c0fef3..9248cc4700b 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -447,6 +447,11 @@ public: /// to encode the actual paths into the .swiftmodule file. PathObfuscator serializedPathObfuscator; + /// Avoid printing actual module content into the ABI descriptor file. + /// This should only be used as a workaround when emitting ABI descriptor files + /// crashes the compiler. + bool emptyABIDescriptor = false; + private: static bool canActionEmitDependencies(ActionType); static bool canActionEmitReferenceDependencies(ActionType); diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 600258f42e4..f3b29cf5f00 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -169,6 +169,9 @@ def serialize_debugging_options : Flag<["-"], "serialize-debugging-options">, def serialized_path_obfuscate : Separate<["-"], "serialized-path-obfuscate">, HelpText<"Remap source paths in debug info">, MetaVarName<"">; +def empty_abi_descriptor : Flag<["-"], "empty-abi-descriptor">, + HelpText<"Avoid printing actual module content into ABI descriptor file">; + def no_serialize_debugging_options : Flag<["-"], "no-serialize-debugging-options">, HelpText<"Never serialize options for debugging (default: only for apps)">; diff --git a/include/swift/Serialization/SerializationOptions.h b/include/swift/Serialization/SerializationOptions.h index bd53a15ebbb..a07d726913c 100644 --- a/include/swift/Serialization/SerializationOptions.h +++ b/include/swift/Serialization/SerializationOptions.h @@ -33,6 +33,7 @@ namespace swift { const char *DocOutputPath = nullptr; const char *SourceInfoOutputPath = nullptr; std::string ABIDescriptorPath; + bool emptyABIDescriptor = false; llvm::VersionTuple UserModuleVersion; std::string SDKName; diff --git a/lib/APIDigester/ModuleAnalyzerNodes.cpp b/lib/APIDigester/ModuleAnalyzerNodes.cpp index 275b77051c5..b3cfed48fd9 100644 --- a/lib/APIDigester/ModuleAnalyzerNodes.cpp +++ b/lib/APIDigester/ModuleAnalyzerNodes.cpp @@ -2498,7 +2498,7 @@ int swift::ide::api::deserializeSDKDump(StringRef dumpPath, StringRef OutputPath } void swift::ide::api::dumpModuleContent(ModuleDecl *MD, StringRef OutputFile, - bool ABI) { + bool ABI, bool Empty) { CheckerOptions opts; opts.ABI = ABI; opts.SwiftOnly = true; @@ -2509,12 +2509,17 @@ void swift::ide::api::dumpModuleContent(ModuleDecl *MD, StringRef OutputFile, opts.Verbose = false; SDKContext ctx(opts); SwiftDeclCollector collector(ctx); - collector.lookupVisibleDecls({MD}); ConstExtractor extractor(ctx, MD->getASTContext()); - extractor.extract(MD); PayLoad payload; - payload.allContsValues = &extractor.getAllConstValues(); - dumpSDKRoot(collector.getSDKRoot(), payload, OutputFile); + SWIFT_DEFER { + payload.allContsValues = &extractor.getAllConstValues(); + dumpSDKRoot(collector.getSDKRoot(), payload, OutputFile); + }; + if (Empty) { + return; + } + collector.lookupVisibleDecls({MD}); + extractor.extract(MD); } int swift::ide::api::findDeclUsr(StringRef dumpPath, CheckerOptions Opts) { diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 36e59a145a4..0526af38d1a 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -297,6 +297,7 @@ bool ArgsToFrontendOptionsConverter::convert( auto SplitMap = StringRef(A).split('='); Opts.serializedPathObfuscator.addMapping(SplitMap.first, SplitMap.second); } + Opts.emptyABIDescriptor = Args.hasArg(OPT_empty_abi_descriptor); return false; } diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index c4268d4593c..f8a5ee1b462 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -158,7 +158,8 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( getIRGenOptions().PublicLinkLibraries; serializationOpts.SDKName = getLangOptions().SDKName; serializationOpts.ABIDescriptorPath = outs.ABIDescriptorOutputPath.c_str(); - + serializationOpts.emptyABIDescriptor = opts.emptyABIDescriptor; + if (!getIRGenOptions().ForceLoadSymbolName.empty()) serializationOpts.AutolinkForceLoad = true; diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index db2c4c535f8..484339c15b3 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -5802,10 +5802,11 @@ bool Serializer::allowCompilerErrors() const { static void emitABIDescriptor(ModuleOrSourceFile DC, const SerializationOptions &options) { + using namespace swift::ide::api; if (!options.ABIDescriptorPath.empty()) { if (DC.is()) { - swift::ide::api::dumpModuleContent(DC.get(), - options.ABIDescriptorPath, true); + dumpModuleContent(DC.get(), options.ABIDescriptorPath, true, + options.emptyABIDescriptor); } } } diff --git a/test/api-digester/empty-abi-descriptor.swift b/test/api-digester/empty-abi-descriptor.swift new file mode 100644 index 00000000000..91ed2ae3817 --- /dev/null +++ b/test/api-digester/empty-abi-descriptor.swift @@ -0,0 +1,6 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -emit-module -o %t/Foo.swiftmodule -emit-abi-descriptor-path %t/abi.json %S/Inputs/ConstExtraction/SimpleReferences.swift -empty-abi-descriptor +// RUN: %api-digester -deserialize-sdk -input-paths %t/abi.json -o %t/abi.result.json +// RUN: %api-digester -generate-empty-baseline -o %t/abi-tool.json -avoid-tool-args -abi +// RUN: diff -u %t/abi-tool.json %t/abi.result.json