Merge remote-tracking branch 'origin/main' into rebranch

This commit is contained in:
swift-ci
2024-10-18 10:41:34 -07:00
21 changed files with 450 additions and 208 deletions

View File

@@ -184,6 +184,7 @@ public:
APIDigester, // swift-api-digester
CacheTool, // swift-cache-tool
ParseTest, // swift-parse-test
SynthesizeInterface, // swift-synthesize-interface
};
class InputInfoMap;

View File

@@ -29,7 +29,7 @@ namespace options {
DoesNotAffectIncrementalBuild = (1 << 8),
AutolinkExtractOption = (1 << 9),
ModuleWrapOption = (1 << 10),
// 1 << 11 was previously `SwiftIndentOption`
SwiftSynthesizeInterfaceOption = (1 << 11),
ArgumentIsPath = (1 << 12),
ModuleInterfaceOption = (1 << 13),
SupplementaryOutput = (1 << 14),

View File

@@ -60,6 +60,9 @@ def SupplementaryOutput : OptionFlag;
// The option should be accepted by swift-symbolgraph-extract.
def SwiftSymbolGraphExtractOption : OptionFlag;
// The option should be accepted by swift-synthesize-interface.
def SwiftSynthesizeInterfaceOption : OptionFlag;
// The option should be accepted by swift-api-digester.
def SwiftAPIDigesterOption : OptionFlag;
@@ -215,7 +218,8 @@ def driver_mode : Joined<["--"], "driver-mode=">, Flags<[HelpHidden]>,
def help : Flag<["-", "--"], "help">,
Flags<[FrontendOption, AutolinkExtractOption, ModuleWrapOption,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"Display available options">;
def h : Flag<["-"], "h">, Alias<help>;
def help_hidden : Flag<["-", "--"], "help-hidden">,
@@ -223,7 +227,8 @@ def help_hidden : Flag<["-", "--"], "help-hidden">,
HelpText<"Display available options, including hidden options">;
def v : Flag<["-"], "v">,
Flags<[DoesNotAffectIncrementalBuild, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
Flags<[DoesNotAffectIncrementalBuild, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Show commands to run and use verbose output">;
def version : Flag<["-", "--"], "version">, Flags<[FrontendOption]>,
HelpText<"Print version information and exit">;
@@ -236,26 +241,30 @@ def parseable_output : Flag<["-"], "parseable-output">,
def windows_sdk_root : Separate<["-"], "windows-sdk-root">,
Flags<[ArgumentIsPath, FrontendOption,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"Windows SDK Root">, MetaVarName<"<root>">;
def windows_sdk_version : Separate<["-"], "windows-sdk-version">,
Flags<[FrontendOption,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"Windows SDK Version">, MetaVarName<"<version>">;
def visualc_tools_root : Separate<["-"], "visualc-tools-root">,
Flags<[ArgumentIsPath, FrontendOption,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"VisualC++ Tools Root">, MetaVarName<"<root>">;
def visualc_tools_version : Separate<["-"], "visualc-tools-version">,
Flags<[FrontendOption,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"VisualC++ ToolSet Version">, MetaVarName<"<version>">;
// Android Options
def sysroot : Separate<["-"], "sysroot">,
Flags<[ArgumentIsPath, FrontendOption, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption]>,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Native Platform sysroot">, MetaVarName<"<sysroot>">;
// Standard Options
@@ -265,7 +274,7 @@ def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>,
def o : JoinedOrSeparate<["-"], "o">,
Flags<[FrontendOption, AutolinkExtractOption, ModuleWrapOption,
NoInteractiveOption, ArgumentIsPath, SwiftAPIDigesterOption,
CacheInvariant]>,
SwiftSynthesizeInterfaceOption, CacheInvariant]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
def j : JoinedOrSeparate<["-"], "j">, Flags<[DoesNotAffectIncrementalBuild]>,
@@ -273,18 +282,18 @@ def j : JoinedOrSeparate<["-"], "j">, Flags<[DoesNotAffectIncrementalBuild]>,
def sdk : Separate<["-"], "sdk">,
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption]>,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Compile against <sdk>">, MetaVarName<"<sdk>">;
def swift_version : Separate<["-"], "swift-version">,
Flags<[FrontendOption, ModuleInterfaceOption, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption]>,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Interpret input according to a specific Swift language version number">,
MetaVarName<"<vers>">;
def language_mode : Separate<["-"], "language-mode">,
Flags<[FrontendOption, ModuleInterfaceOption, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption]>,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Interpret input according to a specific Swift language mode">,
MetaVarName<"<mode>">,
Alias<swift_version>;
@@ -306,17 +315,20 @@ def e : Separate<["-"], "e">, Flags<[NewDriverOnlyOption]>,
HelpText<"Executes a line of code provided on the command line">;
def F : JoinedOrSeparate<["-"], "F">,
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Add directory to framework search path">;
def F_EQ : Joined<["-"], "F=">, Flags<[FrontendOption, ArgumentIsPath]>,
Alias<F>;
def Fsystem : Separate<["-"], "Fsystem">,
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption]>,
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"Add directory to system framework search path">;
def I : JoinedOrSeparate<["-"], "I">,
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Add directory to the import search path">;
def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption, ArgumentIsPath]>,
Alias<I>;
@@ -495,7 +507,8 @@ def localization_path : Separate<["-"], "localization-path">,
def module_cache_path : Separate<["-"], "module-cache-path">,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"Specifies the module cache path">;
def enable_library_evolution : Flag<["-"], "enable-library-evolution">,
@@ -559,11 +572,11 @@ def library_level_EQ : Joined<["-"], "library-level=">,
def module_name : Separate<["-"], "module-name">,
Flags<[FrontendOption, ModuleInterfaceOption,
SwiftSymbolGraphExtractOption]>,
SwiftSymbolGraphExtractOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Name of the module to build">;
def project_name : Separate<["-"], "project-name">,
Flags<[FrontendOption, ModuleInterfaceOptionIgnorable,
SwiftSymbolGraphExtractOption]>,
SwiftSymbolGraphExtractOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Name of the project this module to build belongs to">;
def module_name_EQ : Joined<["-"], "module-name=">, Flags<[FrontendOption]>,
@@ -790,7 +803,8 @@ def enable_experimental_cxx_interop :
def cxx_interoperability_mode :
Joined<["-"], "cxx-interoperability-mode=">,
Flags<[FrontendOption, ModuleInterfaceOption, SwiftSymbolGraphExtractOption]>,
Flags<[FrontendOption, ModuleInterfaceOption, SwiftSymbolGraphExtractOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"Enables C++ interoperability; pass 'default' to enable or 'off' to disable">;
def experimental_c_foreign_reference_types :
@@ -1384,7 +1398,9 @@ def num_threads : Separate<["-"], "num-threads">,
def Xfrontend : Separate<["-"], "Xfrontend">, Flags<[HelpHidden]>,
MetaVarName<"<arg>">, HelpText<"Pass <arg> to the Swift frontend">;
def Xcc : Separate<["-"], "Xcc">, Flags<[FrontendOption, SwiftSymbolGraphExtractOption]>,
def Xcc : Separate<["-"], "Xcc">,
Flags<[FrontendOption, SwiftSymbolGraphExtractOption,
SwiftSynthesizeInterfaceOption]>,
MetaVarName<"<arg>">,
HelpText<"Pass <arg> to the C/C++/Objective-C compiler">;
@@ -1396,13 +1412,16 @@ def Xllvm : Separate<["-"], "Xllvm">,
MetaVarName<"<arg>">, HelpText<"Pass <arg> to LLVM.">;
def resource_dir : Separate<["-"], "resource-dir">,
Flags<[FrontendOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption, HelpHidden, ArgumentIsPath]>,
Flags<[FrontendOption, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption,
HelpHidden, ArgumentIsPath]>,
MetaVarName<"</usr/lib/swift>">,
HelpText<"The directory that holds the compiler resource files">;
def target : Separate<["-"], "target">,
Flags<[FrontendOption, ModuleWrapOption, ModuleInterfaceOption, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption]>,
Flags<[FrontendOption, ModuleWrapOption, ModuleInterfaceOption,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption,
SwiftSynthesizeInterfaceOption]>,
HelpText<"Generate code for the given target <triple>, such as x86_64-apple-macos10.9">, MetaVarName<"<triple>">;
def target_legacy_spelling : Joined<["--"], "target=">,
Flags<[FrontendOption]>, Alias<target>;
@@ -1419,7 +1438,8 @@ def target_variant : Separate<["-"], "target-variant">,
" variant target triple in addition to the main -target triple">;
def clang_target : Separate<["-"], "clang-target">,
Flags<[FrontendOption, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
Flags<[FrontendOption, SwiftSymbolGraphExtractOption,
SwiftAPIDigesterOption, SwiftSynthesizeInterfaceOption]>,
HelpText<"Separately set the target we should use for internal Clang instance">;
def disable_clang_target : Flag<["-"], "disable-clang-target">,

View File

@@ -112,6 +112,7 @@ void Driver::parseDriverKind(ArrayRef<const char *> Args) {
.Case("swift-api-digester", DriverKind::APIDigester)
.Case("swift-cache-tool", DriverKind::CacheTool)
.Case("swift-parse-test", DriverKind::ParseTest)
.Case("swift-synthesize-interface", DriverKind::SynthesizeInterface)
.Default(std::nullopt);
if (Kind.has_value())
@@ -3122,6 +3123,7 @@ void Driver::printHelp(bool ShowHidden) const {
case DriverKind::APIDigester:
case DriverKind::CacheTool:
case DriverKind::ParseTest:
case DriverKind::SynthesizeInterface:
ExcludedFlagsBitmask |= options::NoBatchOption;
break;
}

View File

@@ -13,6 +13,7 @@ set(driver_sources_and_options
swift_cache_tool_main.cpp
swift_indent_main.cpp
swift_symbolgraph_extract_main.cpp
swift_synthesize_interface_main.cpp
swift_parse_test_main.cpp)
set(driver_common_libs

View File

@@ -98,6 +98,10 @@ extern int modulewrap_main(ArrayRef<const char *> Args, const char *Argv0,
extern int swift_symbolgraph_extract_main(ArrayRef<const char *> Args, const char *Argv0,
void *MainAddr);
/// Run 'swift-synthesize-interface'
extern int swift_synthesize_interface_main(ArrayRef<const char *> Args,
const char *Argv0, void *MainAddr);
/// Run 'swift-api-digester'
extern int swift_api_digester_main(ArrayRef<const char *> Args,
const char *Argv0, void *MainAddr);
@@ -387,6 +391,10 @@ static int run_driver(StringRef ExecName,
argv[0], (void *)(intptr_t)getExecutablePath);
case Driver::DriverKind::SymbolGraph:
return swift_symbolgraph_extract_main(TheDriver.getArgsWithoutProgramNameAndDriverMode(argv), argv[0], (void *)(intptr_t)getExecutablePath);
case Driver::DriverKind::SynthesizeInterface:
return swift_synthesize_interface_main(
TheDriver.getArgsWithoutProgramNameAndDriverMode(argv), argv[0],
(void *)(intptr_t)getExecutablePath);
case Driver::DriverKind::APIDigester:
return swift_api_digester_main(
TheDriver.getArgsWithoutProgramNameAndDriverMode(argv), argv[0],

View File

@@ -0,0 +1,211 @@
//===--- swift_synthesize_interface_main.cpp - Swift interface synthesis --===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Prints the synthesized Swift interface for a Clang module.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/Version.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
#include "swift/Option/Options.h"
#include "swift/Parse/ParseVersion.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
using namespace options;
int swift_synthesize_interface_main(ArrayRef<const char *> Args,
const char *Argv0, void *MainAddr) {
INITIALIZE_LLVM();
CompilerInvocation Invocation;
CompilerInstance CI;
PrintingDiagnosticConsumer DiagPrinter;
auto &Diags = CI.getDiags();
Diags.addConsumer(DiagPrinter);
std::unique_ptr<llvm::opt::OptTable> Table = createSwiftOptTable();
unsigned MissingIndex;
unsigned MissingCount;
llvm::opt::InputArgList ParsedArgs = Table->ParseArgs(
Args, MissingIndex, MissingCount, SwiftSynthesizeInterfaceOption);
if (MissingCount) {
Diags.diagnose(SourceLoc(), diag::error_missing_arg_value,
ParsedArgs.getArgString(MissingIndex), MissingCount);
return EXIT_FAILURE;
}
if (ParsedArgs.hasArg(OPT_UNKNOWN)) {
for (const auto *A : ParsedArgs.filtered(OPT_UNKNOWN)) {
Diags.diagnose(SourceLoc(), diag::error_unknown_arg,
A->getAsString(ParsedArgs));
}
return EXIT_FAILURE;
}
auto MainExecutablePath = llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
if (ParsedArgs.getLastArg(OPT_help) || Args.empty()) {
std::string ExecutableName =
llvm::sys::path::stem(MainExecutablePath).str();
Table->printHelp(llvm::outs(), ExecutableName.c_str(),
"Swift Interface Synthesizer",
SwiftSynthesizeInterfaceOption, 0,
/*ShowAllAliases*/ false);
return EXIT_FAILURE;
}
std::string ModuleName;
if (auto *A = ParsedArgs.getLastArg(OPT_module_name)) {
ModuleName = A->getValue();
} else {
Diags.diagnose(SourceLoc(), diag::error_option_required, "-module-name");
return EXIT_FAILURE;
}
llvm::Triple Target;
if (auto *A = ParsedArgs.getLastArg(OPT_target)) {
Target = llvm::Triple(A->getValue());
} else {
Diags.diagnose(SourceLoc(), diag::error_option_required, "-target");
return EXIT_FAILURE;
}
std::string OutputFile;
if (auto *A = ParsedArgs.getLastArg(OPT_o)) {
OutputFile = A->getValue();
} else {
OutputFile = "-";
}
Invocation.setMainExecutablePath(MainExecutablePath);
Invocation.setModuleName("swift_synthesize_interface");
if (auto *A = ParsedArgs.getLastArg(OPT_resource_dir)) {
Invocation.setRuntimeResourcePath(A->getValue());
}
std::string SDK = "";
if (auto *A = ParsedArgs.getLastArg(OPT_sdk)) {
SDK = A->getValue();
}
Invocation.setSDKPath(SDK);
Invocation.setTargetTriple(Target);
for (const auto *A : ParsedArgs.filtered(OPT_Xcc)) {
Invocation.getClangImporterOptions().ExtraArgs.push_back(A->getValue());
}
std::vector<SearchPathOptions::FrameworkSearchPath> FrameworkSearchPaths;
for (const auto *A : ParsedArgs.filtered(OPT_F)) {
FrameworkSearchPaths.push_back({A->getValue(), /*isSystem*/ false});
}
for (const auto *A : ParsedArgs.filtered(OPT_Fsystem)) {
FrameworkSearchPaths.push_back({A->getValue(), /*isSystem*/ true});
}
Invocation.setFrameworkSearchPaths(FrameworkSearchPaths);
Invocation.getSearchPathOptions().LibrarySearchPaths =
ParsedArgs.getAllArgValues(OPT_L);
Invocation.setImportSearchPaths(ParsedArgs.getAllArgValues(OPT_I));
Invocation.getLangOptions().EnableObjCInterop = Target.isOSDarwin();
Invocation.getLangOptions().setCxxInteropFromArgs(ParsedArgs, Diags);
std::string ModuleCachePath = "";
if (auto *A = ParsedArgs.getLastArg(OPT_module_cache_path)) {
ModuleCachePath = A->getValue();
}
Invocation.setClangModuleCachePath(ModuleCachePath);
Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
Invocation.getClangImporterOptions().ImportForwardDeclarations = true;
Invocation.setDefaultPrebuiltCacheIfNecessary();
if (auto *A = ParsedArgs.getLastArg(OPT_swift_version)) {
using version::Version;
auto SwiftVersion = A->getValue();
bool isValid = false;
if (auto Version = VersionParser::parseVersionString(
SwiftVersion, SourceLoc(), nullptr)) {
if (auto Effective = Version.value().getEffectiveLanguageVersion()) {
Invocation.getLangOptions().EffectiveLanguageVersion = *Effective;
isValid = true;
}
}
if (!isValid) {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
"-swift-version", SwiftVersion);
return EXIT_FAILURE;
}
}
std::string InstanceSetupError;
if (CI.setup(Invocation, InstanceSetupError)) {
llvm::outs() << InstanceSetupError << '\n';
return EXIT_FAILURE;
}
auto M = CI.getASTContext().getModuleByName(ModuleName);
if (!M) {
llvm::errs() << "Couldn't load module '" << ModuleName << '\''
<< " in the current SDK and search paths.\n";
SmallVector<Identifier, 32> VisibleModuleNames;
CI.getASTContext().getVisibleTopLevelModuleNames(VisibleModuleNames);
if (VisibleModuleNames.empty()) {
llvm::errs() << "Could not find any modules.\n";
} else {
std::sort(VisibleModuleNames.begin(), VisibleModuleNames.end(),
[](const Identifier &A, const Identifier &B) -> bool {
return A.str() < B.str();
});
llvm::errs() << "Current visible modules:\n";
for (const auto &ModuleName : VisibleModuleNames) {
llvm::errs() << ModuleName.str() << "\n";
}
}
return EXIT_FAILURE;
}
if (M->failedToLoad()) {
llvm::errs() << "Error: Failed to load the module '" << ModuleName
<< "'. Are you missing build dependencies or "
"include/framework directories?\n"
<< "See the previous error messages for details. Aborting.\n";
return EXIT_FAILURE;
}
std::error_code EC;
llvm::raw_fd_ostream fs(OutputFile, EC);
if (EC) {
llvm::errs() << "Cannot open output file: " << OutputFile << "\n";
return EXIT_FAILURE;
}
StreamPrinter printer(fs);
PrintOptions printOpts =
PrintOptions::printModuleInterface(/*printFullConvention=*/true);
ide::printModuleInterface(M, /*GroupNames=*/{},
/*TraversalOptions=*/std::nullopt, printer,
printOpts, /*PrintSynthesizedExtensions=*/false);
return EXIT_SUCCESS;
}

View File

@@ -1076,6 +1076,7 @@ static void printSingleFrontendOpt(llvm::opt::OptTable &table, options::ID id,
table.getOption(id).hasFlag(options::AutolinkExtractOption) ||
table.getOption(id).hasFlag(options::ModuleWrapOption) ||
table.getOption(id).hasFlag(options::SwiftSymbolGraphExtractOption) ||
table.getOption(id).hasFlag(options::SwiftSynthesizeInterfaceOption) ||
table.getOption(id).hasFlag(options::SwiftAPIDigesterOption)) {
auto name = StringRef(table.getOptionName(id));
if (!name.empty()) {

View File

@@ -53,7 +53,7 @@ namespace {
class CrossModuleOptimization {
friend class InstructionVisitor;
llvm::DenseMap<CanType, bool> canTypesChecked;
llvm::DenseMap<SILType, bool> typesChecked;
llvm::SmallPtrSet<TypeBase *, 16> typesHandled;
SILModule &M;
@@ -90,18 +90,14 @@ private:
void trySerializeFunctions(ArrayRef<SILFunction *> functions);
bool canSerializeFunction(SILFunction *function,
FunctionFlags &canSerializeFlags,
int maxDepth);
FunctionFlags &canSerializeFlags, int maxDepth);
bool canSerializeFieldsByInstructionKind(SILInstruction *inst,
FunctionFlags &canSerializeFlags,
int maxDepth);
bool canSerializeInstruction(SILInstruction *inst,
FunctionFlags &canSerializeFlags, int maxDepth);
bool canSerializeGlobal(SILGlobalVariable *global);
bool canSerializeType(SILType type);
bool canSerializeType(CanType type);
bool canSerializeDecl(NominalTypeDecl *decl);
bool canUseFromInline(DeclContext *declCtxt);
@@ -122,10 +118,11 @@ private:
void makeDeclUsableFromInline(ValueDecl *decl);
void makeTypeUsableFromInline(CanType type);
void makeSubstUsableFromInline(const SubstitutionMap &substs);
};
/// Visitor for detecting if an instruction can be serialized and also making used
/// types of an instruction inlinable if so.
/// Visitor for making used types of an instruction inlinable.
///
/// We use the SILCloner for visiting types, though it sucks that we allocate
/// instructions just to delete them immediately. But it's better than to
@@ -137,22 +134,12 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
friend class SILInstructionVisitor<InstructionVisitor>;
friend class CrossModuleOptimization;
public:
/// This visitor is used for 2 passes, 1st pass that detects whether the instruction
/// visited can be serialized, and 2nd pass that does the serializing.
enum class VisitMode {
DetectSerializableInst,
SerializeInst
};
private:
CrossModuleOptimization &CMS;
VisitMode mode;
bool isInstSerializable = true;
public:
InstructionVisitor(SILFunction &F, CrossModuleOptimization &CMS, VisitMode visitMode) :
SILCloner(F), CMS(CMS), mode(visitMode) {}
InstructionVisitor(SILFunction &F, CrossModuleOptimization &CMS) :
SILCloner(F), CMS(CMS) {}
SILType remapType(SILType Ty) {
if (Ty.hasLocalArchetype()) {
@@ -162,15 +149,7 @@ public:
SubstFlags::SubstituteLocalArchetypes);
}
switch (mode) {
case VisitMode::DetectSerializableInst:
if (!CMS.canSerializeType(Ty))
isInstSerializable = false;
break;
case VisitMode::SerializeInst:
CMS.makeTypeUsableFromInline(Ty.getASTType());
break;
}
CMS.makeTypeUsableFromInline(Ty.getASTType());
return Ty;
}
@@ -181,15 +160,7 @@ public:
SubstFlags::SubstituteLocalArchetypes)->getCanonicalType();
}
switch (mode) {
case VisitMode::DetectSerializableInst:
if (!CMS.canSerializeType(Ty))
isInstSerializable = false;
break;
case VisitMode::SerializeInst:
CMS.makeTypeUsableFromInline(Ty);
break;
}
CMS.makeTypeUsableFromInline(Ty);
return Ty;
}
@@ -200,32 +171,7 @@ public:
SubstFlags::SubstituteLocalArchetypes);
}
for (Type replType : Subs.getReplacementTypes()) {
switch (mode) {
case VisitMode::DetectSerializableInst:
CMS.canSerializeType(replType->getCanonicalType());
break;
case VisitMode::SerializeInst:
/// Ensure that all replacement types of \p Subs are usable from serialized
/// functions.
CMS.makeTypeUsableFromInline(replType->getCanonicalType());
break;
}
}
for (ProtocolConformanceRef pref : Subs.getConformances()) {
if (pref.isConcrete()) {
ProtocolConformance *concrete = pref.getConcrete();
switch (mode) {
case VisitMode::DetectSerializableInst:
if (!CMS.canSerializeDecl(concrete->getProtocol()))
isInstSerializable = false;
break;
case VisitMode::SerializeInst:
CMS.makeDeclUsableFromInline(concrete->getProtocol());
break;
}
}
}
CMS.makeSubstUsableFromInline(Subs);
return Subs;
}
@@ -234,36 +180,9 @@ public:
Cloned->eraseFromParent();
}
// This method retrieves the operand passed as \p Value as mapped
// in a previous instruction.
SILValue getMappedValue(SILValue Value) {
switch (mode) {
case VisitMode::DetectSerializableInst:
// Typically, the type of the operand (\p Value) is already checked
// and remapped as the resulting type of a previous instruction, so
// rechecking the type isn't necessary. However, certain instructions
// have operands that werent previously mapped, such as:
//
// ```
// bb0(%0 : $*Foo):
// %1 = struct_element_addr %0 : $*Foo, #Foo.bar
// ```
// where the operand of the first instruction is the argument of the
// basic block. In such case, an explicit check for the operand's type
// is required to ensure serializability.
remapType(Value->getType());
break;
case VisitMode::SerializeInst:
break;
}
return Value;
}
SILValue getMappedValue(SILValue Value) { return Value; }
SILBasicBlock *remapBasicBlock(SILBasicBlock *BB) { return BB; }
bool canSerializeTypesInInst(SILInstruction *inst) {
return isInstSerializable;
}
};
static bool isPackageCMOEnabled(ModuleDecl *mod) {
@@ -537,36 +456,32 @@ bool CrossModuleOptimization::canSerializeFunction(
}
// Check if any instruction prevents serializing the function.
InstructionVisitor visitor(*function, *this, InstructionVisitor::VisitMode::DetectSerializableInst);
for (SILBasicBlock &block : *function) {
for (SILInstruction &inst : block) {
visitor.getBuilder().setInsertionPoint(&inst);
// First, visit each instruction and see if its
// canonical or substituted types are serializalbe.
visitor.visit(&inst);
if (!visitor.canSerializeTypesInInst(&inst)) {
M.reclaimUnresolvedLocalArchetypeDefinitions();
return false;
}
// Next, check for any fields that weren't visited.
if (!canSerializeFieldsByInstructionKind(&inst, canSerializeFlags, maxDepth)) {
M.reclaimUnresolvedLocalArchetypeDefinitions();
if (!canSerializeInstruction(&inst, canSerializeFlags, maxDepth)) {
return false;
}
}
}
M.reclaimUnresolvedLocalArchetypeDefinitions();
canSerializeFlags[function] = true;
return true;
}
/// Returns true if \p inst can be serialized by checking its fields per instruction kind.
/// Returns true if \p inst can be serialized.
///
/// If \p inst is a function_ref, recursively visits the referenced function.
bool CrossModuleOptimization::canSerializeFieldsByInstructionKind(
bool CrossModuleOptimization::canSerializeInstruction(
SILInstruction *inst, FunctionFlags &canSerializeFlags, int maxDepth) {
// First check if any result or operand types prevent serialization.
for (SILValue result : inst->getResults()) {
if (!canSerializeType(result->getType()))
return false;
}
for (Operand &op : inst->getAllOperands()) {
if (!canSerializeType(op.get()->getType()))
return false;
}
if (auto *FRI = dyn_cast<FunctionRefBaseInst>(inst)) {
SILFunction *callee = FRI->getReferencedFunctionOrNull();
if (!callee)
@@ -658,45 +573,6 @@ bool CrossModuleOptimization::canSerializeFieldsByInstructionKind(
return true;
}
bool CrossModuleOptimization::canSerializeType(SILType type) {
return canSerializeType(type.getASTType());
}
bool CrossModuleOptimization::canSerializeType(CanType type) {
auto iter = canTypesChecked.find(type);
if (iter != canTypesChecked.end())
return iter->getSecond();
bool success = type.findIf(
[this](Type rawSubType) {
CanType subType = rawSubType->getCanonicalType();
if (auto nominal = subType->getNominalOrBoundGenericNominal()) {
return canSerializeDecl(nominal);
}
// If reached here, the type is a Builtin type or similar,
// e.g. Builtin.Int64, Builtin.Word, Builtin.NativeObject, etc.
return true;
});
canTypesChecked[type] = success;
return success;
}
bool CrossModuleOptimization::canSerializeDecl(NominalTypeDecl *decl) {
assert(decl && "Decl should not be null when checking if it can be serialized");
// In conservative mode we don't want to change the access level of types.
if (conservative && decl->getEffectiveAccess() < AccessLevel::Package) {
return false;
}
// Exclude types which are defined in an @_implementationOnly imported
// module. Such modules are not transitively available.
if (!canUseFromInline(decl)) {
return false;
}
return true;
}
bool CrossModuleOptimization::canSerializeGlobal(SILGlobalVariable *global) {
// Check for referenced functions in the initializer.
for (const SILInstruction &initInst : *global) {
@@ -718,6 +594,32 @@ bool CrossModuleOptimization::canSerializeGlobal(SILGlobalVariable *global) {
return true;
}
bool CrossModuleOptimization::canSerializeType(SILType type) {
auto iter = typesChecked.find(type);
if (iter != typesChecked.end())
return iter->getSecond();
bool success = !type.getASTType().findIf(
[this](Type rawSubType) {
CanType subType = rawSubType->getCanonicalType();
if (NominalTypeDecl *subNT = subType->getNominalOrBoundGenericNominal()) {
if (conservative && subNT->getEffectiveAccess() < AccessLevel::Package) {
return true;
}
// Exclude types which are defined in an @_implementationOnly imported
// module. Such modules are not transitively available.
if (!canUseFromInline(subNT)) {
return true;
}
}
return false;
});
typesChecked[type] = success;
return success;
}
/// Returns true if the function in \p funcCtxt could be linked statically to
/// this module.
static bool couldBeLinkedStatically(DeclContext *funcCtxt, SILModule &module) {
@@ -811,7 +713,7 @@ void CrossModuleOptimization::serializeFunction(SILFunction *function,
}
function->setSerializedKind(getRightSerializedKind(M));
InstructionVisitor visitor(*function, *this, InstructionVisitor::VisitMode::SerializeInst);
InstructionVisitor visitor(*function, *this);
for (SILBasicBlock &block : *function) {
for (SILInstruction &inst : block) {
visitor.getBuilder().setInsertionPoint(&inst);
@@ -1010,6 +912,21 @@ void CrossModuleOptimization::makeTypeUsableFromInline(CanType type) {
});
}
/// Ensure that all replacement types of \p substs are usable from serialized
/// functions.
void CrossModuleOptimization::makeSubstUsableFromInline(
const SubstitutionMap &substs) {
for (Type replType : substs.getReplacementTypes()) {
makeTypeUsableFromInline(replType->getCanonicalType());
}
for (ProtocolConformanceRef pref : substs.getConformances()) {
if (pref.isConcrete()) {
ProtocolConformance *concrete = pref.getConcrete();
makeDeclUsableFromInline(concrete->getProtocol());
}
}
}
class CrossModuleOptimizationPass: public SILModuleTransform {
void run() override {
auto &M = *getModule();

View File

@@ -55,7 +55,7 @@ function(_add_target_variant_c_compile_link_flags)
if("${CFLAGS_SDK}" IN_LIST SWIFT_DARWIN_PLATFORMS)
# Check if there's a specific OS deployment version needed for this invocation
if("${CFLAGS_SDK}" STREQUAL "OSX")
if(DEFINED maccatalyst_build_flavor)
if(DEFINED maccatalyst_build_flavor AND DEFINED CFLAGS_DEPLOYMENT_VERSION_MACCATALYST)
set(DEPLOYMENT_VERSION ${CFLAGS_DEPLOYMENT_VERSION_MACCATALYST})
else()
set(DEPLOYMENT_VERSION ${CFLAGS_DEPLOYMENT_VERSION_OSX})

View File

@@ -1,7 +1,10 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -target %target-cpu-apple-macosx12 %s -o %t/linking_direct
// RUN: %target-build-swift -target %target-cpu-apple-macosx11 %s -o %t/linking_rpath
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 %s -o %t/linking_rpath_old
// RUN: %target-build-swift -target %target-cpu-apple-macosx12 %s -o %t/linking_direct 2>&1 | %FileCheck -allow-empty -check-prefix CHECK-BUILD-ERRORS %s
// RUN: %target-build-swift -target %target-cpu-apple-macosx11 %s -o %t/linking_rpath 2>&1 | %FileCheck -allow-empty -check-prefix CHECK-BUILD-ERRORS %s
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 %s -o %t/linking_rpath_old 2>&1 | %FileCheck -allow-empty -check-prefix CHECK-BUILD-ERRORS %s
// Make sure the linker didn't emit any version mismatch warnings.
// CHECK-BUILD-ERRORS-NOT: was built for newer 'macOS' version
// RUN: otool -L %t/linking_direct | %FileCheck -check-prefix CHECK-DIRECT %s
// RUN: otool -L %t/linking_rpath | %FileCheck -check-prefix CHECK-RPATH %s

View File

@@ -1,29 +0,0 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-swift-frontend -emit-sil %t/Lib.swift -package-name pkg \
// RUN: -wmo -allow-non-resilient-access -package-cmo \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -Xllvm -sil-print-function=topFunc -o %t/Lib.sil
// RUN: %FileCheck %s < %t/Lib.sil
/// Verify that `InternalKlass` is visited and the instruction containing it is not serialized.
// CHECK: sil @$s3Lib7topFuncySiAA3PubCF : $@convention(thin) (@guaranteed Pub) -> Int {
// CHECK: checked_cast_br Pub in %0 : $Pub to InternalKlass
//--- Lib.swift
public class Pub {
public var pubVar: Int
public init(_ arg: Int) {
pubVar = arg
}
}
class InternalKlass: Pub {}
public func topFunc(_ arg: Pub) -> Int {
let x = arg as? InternalKlass
return x != nil ? 1 : 0
}

View File

@@ -0,0 +1,6 @@
struct MyStruct {
int value;
};
void printvalue_mystruct(const struct MyStruct *m)
__attribute__((swift_name("MyStruct.printValue(self:)")));

View File

@@ -0,0 +1,10 @@
class MyClass {
private:
int value;
public:
MyClass(int v) : value(v) {}
MyClass() : MyClass(0) {}
void printValue() const {}
};

View File

@@ -0,0 +1,8 @@
module m1 {
header "m1.h"
}
module mcxx {
requires cplusplus
header "mcxx.h"
}

View File

@@ -0,0 +1,7 @@
// RUN: %target-swift-synthesize-interface -cxx-interoperability-mode=default -module-name mcxx -I %S/Inputs -o - | %FileCheck %s
// CHECK: public struct MyClass {
// CHECK-DAG: public init(_ v: Int32)
// CHECK-DAG: public init()
// CHECK-DAG: public func printValue()
// CHECK-DAG: }

View File

@@ -0,0 +1,15 @@
// Emit the explicit module.
// RUN: %empty-directory(%t)
// RUN: %target-swift-emit-pcm -module-name m1 -o %t/m1.pcm %S/Inputs/module.modulemap
// Invoke the frontend with the PCM as an input.
// RUN: %target-swift-synthesize-interface %windows_vfs_overlay_opt -module-name m1 -Xcc -fmodule-file=%t/m1.pcm -o - | %FileCheck %s
// CHECK: public struct MyStruct {
// CHECK-DAG: public init()
// CHECK-DAG: public init(value: Int32)
// CHECK-DAG: public var value: Int32
// CHECK-DAG: }
// CHECK-DAG: extension MyStruct {
// CHECK-DAG: public func printValue()
// CHECK-DAG: }

View File

@@ -0,0 +1,23 @@
// Emit the Swift module.
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -module-name MyModule -o %t/MyModule.swiftmodule %s
// Invoke the frontend with the module on the import path.
// RUN: %target-swift-synthesize-interface -module-name MyModule -I %t -o - | %FileCheck %s
public struct MyStruct {
// CHECK: public struct MyStruct {
public private(set) var value: Int
// CHECK-DAG: public private(set) var value: Int { get }
public init(value: Int = 0) {
// CHECK-DAG: public init(value: Int = 0)
self.value = value
}
public func printValue() {
// CHECK-DAG: public func printValue()
print(self.value)
}
}
// CHECK-DAG: }

View File

@@ -0,0 +1,10 @@
// RUN: %target-swift-synthesize-interface -module-name m1 -I %S/Inputs -o - | %FileCheck %s
// CHECK: public struct MyStruct {
// CHECK-DAG: public init()
// CHECK-DAG: public init(value: Int32)
// CHECK-DAG: public var value: Int32
// CHECK-DAG: }
// CHECK-DAG: extension MyStruct {
// CHECK-DAG: public func printValue()
// CHECK-DAG: }

View File

@@ -324,6 +324,7 @@ config.swift_dependency_tool = inferSwiftBinary('swift-dependency-tool')
config.swift_reflection_dump = inferSwiftBinary('swift-reflection-dump')
config.swift_remoteast_test = inferSwiftBinary('swift-remoteast-test')
config.swift_symbolgraph_extract = inferSwiftBinary('swift-symbolgraph-extract')
config.swift_synthesize_interface = inferSwiftBinary('swift-synthesize-interface')
config.clang = inferSwiftBinary('clang')
config.clangxx = inferSwiftBinary('clang++')
config.llvm_link = inferSwiftBinary('llvm-link')
@@ -1546,6 +1547,9 @@ if run_vendor == 'apple':
config.target_swift_symbolgraph_extract = (
"%s %s %s" %
(xcrun_prefix, config.swift_symbolgraph_extract, target_options))
config.target_swift_synthesize_interface = (
"%s %s %s" %
(xcrun_prefix, config.swift_synthesize_interface, target_options))
config.target_swift_ide_test = (
"%s %s %s %s %s" %
(xcrun_prefix, config.swift_ide_test, target_options, ccp_opt,
@@ -1689,6 +1693,10 @@ elif run_os in ['windows-msvc']:
('%r -target %s %s' % (config.swift_symbolgraph_extract, \
config.variant_triple, \
mcp_opt))
config.target_swift_synthesize_interface = \
('%r -target %s %s' % (config.swift_synthesize_interface, \
config.variant_triple, \
mcp_opt))
config.target_swift_ide_test = \
('%r -target %s %s %s %s %s' % (config.swift_ide_test, \
config.variant_triple, \
@@ -1820,6 +1828,9 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows-
config.target_swift_symbolgraph_extract = (
'%s -target %s %s' %
(config.swift_symbolgraph_extract, config.variant_triple, mcp_opt))
config.target_swift_synthesize_interface = (
'%s -target %s %s' %
(config.swift_synthesize_interface, config.variant_triple, mcp_opt))
config.target_swift_ide_test = (
'%s -target %s %s %s %s %s' %
(config.swift_ide_test, config.variant_triple, config.resource_dir_opt,
@@ -1928,6 +1939,10 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android':
config.swift_symbolgraph_extract,
'-target', config.variant_triple,
mcp_opt])
config.target_swift_synthesize_interface = ' '.join([
config.swift_synthesize_interface,
'-target', config.variant_triple,
mcp_opt])
config.target_swift_ide_test = ' '.join([
'env', 'SDKROOT={}'.format(shell_quote(config.variant_sdk)),
config.swift_ide_test,
@@ -2007,6 +2022,10 @@ elif run_os == 'wasi':
config.swift_symbolgraph_extract,
'-target', config.variant_triple,
mcp_opt])
config.target_swift_synthesize_interface = ' '.join([
config.swift_synthesize_interface,
'-target', config.variant_triple,
mcp_opt])
config.target_swift_ide_test = (
'%s -target %s %s %s %s %s' %
(config.swift_ide_test, config.variant_triple, config.resource_dir_opt,
@@ -2768,6 +2787,7 @@ config.substitutions.append(('%target-swift-ide-test',
config.clang_system_overlay_opt)))
config.substitutions.append(('%target-swift-symbolgraph-extract', config.target_swift_symbolgraph_extract))
config.substitutions.append(('%target-swift-synthesize-interface', config.target_swift_synthesize_interface))
config.substitutions.append(('%empty-directory\(([^)]+)\)',
SubstituteCaptures(r'rm -rf "\1" && mkdir -p "\1"')))

View File

@@ -173,6 +173,11 @@ swift_create_post_build_symlink(swift-frontend
DESTINATION "swift-parse-test${CMAKE_EXECUTABLE_SUFFIX}"
WORKING_DIRECTORY "${SWIFT_RUNTIME_OUTPUT_INTDIR}")
swift_create_post_build_symlink(swift-frontend
SOURCE "swift-frontend${CMAKE_EXECUTABLE_SUFFIX}"
DESTINATION "swift-synthesize-interface${CMAKE_EXECUTABLE_SUFFIX}"
WORKING_DIRECTORY "${SWIFT_RUNTIME_OUTPUT_INTDIR}")
add_dependencies(compiler swift-frontend)
swift_install_in_component(FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift${CMAKE_EXECUTABLE_SUFFIX}"
DESTINATION "bin"
@@ -189,6 +194,9 @@ swift_install_in_component(FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift-api-diges
swift_install_in_component(FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift-cache-tool${CMAKE_EXECUTABLE_SUFFIX}"
DESTINATION "bin"
COMPONENT compiler)
swift_install_in_component(FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift-synthesize-interface${CMAKE_EXECUTABLE_SUFFIX}"
DESTINATION "bin"
COMPONENT compiler)
add_dependencies(autolink-driver swift-frontend)
swift_install_in_component(FILES "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift-autolink-extract${CMAKE_EXECUTABLE_SUFFIX}"
DESTINATION "bin"