Skip to content

[ScanDependency] Move binary module validation into scanner #72291

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 2 commits into from
Apr 5, 2024
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
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,9 @@ REMARK(module_api_import_aliases,none,
"%select{, which reexports definition from %2|}3",
(const Decl *, ModuleDecl *, ModuleDecl *, bool))

REMARK(skip_module_invalid,none,"skip invalid swiftmodule: %0", (StringRef))
REMARK(skip_module_testable,none,"skip swiftmodule built with '-enable-testing': %0", (StringRef))

REMARK(macro_loaded,none,
"loaded macro implementation module %0 from "
"%select{shared library '%2'|executable '%2'|"
Expand Down
6 changes: 6 additions & 0 deletions include/swift/AST/ModuleDependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,12 @@ class ModuleDependenciesCache {
std::optional<const ModuleDependencyInfo *>
findDependency(StringRef moduleName) const;

/// Look for known existing dependencies.
///
/// \returns the cached result.
const ModuleDependencyInfo &
findKnownDependency(const ModuleDependencyID &moduleID) const;

/// Record dependencies for the given module.
void recordDependency(StringRef moduleName,
ModuleDependencyInfo dependencies);
Expand Down
19 changes: 18 additions & 1 deletion include/swift/AST/SearchPathOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ enum class ModuleSearchPathKind {
RuntimeLibrary,
};

/// Specifies how to load modules when both a module interface and serialized
/// AST are present, or whether to disallow one format or the other altogether.
enum class ModuleLoadingMode {
PreferInterface,
PreferSerialized,
OnlyInterface,
OnlySerialized
};

/// A single module search path that can come from different sources, e.g.
/// framework search paths, import search path etc.
class ModuleSearchPath : public llvm::RefCountedBase<ModuleSearchPath> {
Expand Down Expand Up @@ -499,6 +508,12 @@ class SearchPathOptions {
/// original form.
PathObfuscator DeserializedPathRecoverer;

/// Specify the module loading behavior of the compilation.
ModuleLoadingMode ModuleLoadMode = ModuleLoadingMode::PreferSerialized;

/// Legacy scanner search behavior.
bool NoScannerModuleValidation = false;

/// Return all module search paths that (non-recursively) contain a file whose
/// name is in \p Filenames.
SmallVector<const ModuleSearchPath *, 4>
Expand Down Expand Up @@ -546,7 +561,9 @@ class SearchPathOptions {
RuntimeResourcePath,
hash_combine_range(RuntimeLibraryImportPaths.begin(),
RuntimeLibraryImportPaths.end()),
DisableModulesValidateSystemDependencies);
DisableModulesValidateSystemDependencies,
NoScannerModuleValidation,
ModuleLoadMode);
}

/// Return a hash code of any components from these options that should
Expand Down
6 changes: 6 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -1348,4 +1348,10 @@ def disable_strict_concurrency_region_based_isolation : Flag<["-"],
HelpText<"Disable region based isolation when running with strict concurrency enabled. Only enabled with asserts">,
Flags<[HelpHidden]>;

def no_scanner_module_validation: Flag<["-"], "no-scanner-module-validation">,
HelpText<"Do not validate binary modules in scanner and delegate the validation to swift-frontend">;
def module_load_mode: Separate<["-"], "module-load-mode">,
MetaVarName<"only-interface|prefer-interface|prefer-serialized|only-serialized">,
HelpText<"Module loading mode">;

} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]
3 changes: 2 additions & 1 deletion include/swift/Serialization/ScanningLoaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {

/// Scan the given interface file to determine dependencies.
llvm::ErrorOr<ModuleDependencyInfo>
scanInterfaceFile(Twine moduleInterfacePath, bool isFramework);
scanInterfaceFile(Twine moduleInterfacePath, bool isFramework,
bool isTestableImport);

InterfaceSubContextDelegate &astDelegate;

Expand Down
25 changes: 7 additions & 18 deletions include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,20 @@
#include "swift/AST/FileUnit.h"
#include "swift/AST/Module.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/SearchPathOptions.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrefixMapper.h"
#include "llvm/TargetParser/Triple.h"

namespace swift {
class ModuleFile;
class PathObfuscator;
class ModuleFileSharedCore;
enum class ModuleLoadingBehavior;
namespace file_types {
enum ID : uint8_t;
}

/// Specifies how to load modules when both a module interface and serialized
/// AST are present, or whether to disallow one format or the other altogether.
enum class ModuleLoadingMode {
PreferInterface,
PreferSerialized,
OnlyInterface,
OnlySerialized
};

/// How a dependency should be loaded.
///
/// \sa getTransitiveLoadingBehavior
Expand Down Expand Up @@ -170,22 +163,18 @@ class SerializedModuleLoaderBase : public ModuleLoader {
}

/// Scan the given serialized module file to determine dependencies.
llvm::ErrorOr<ModuleDependencyInfo> scanModuleFile(Twine modulePath, bool isFramework);
llvm::ErrorOr<ModuleDependencyInfo>
scanModuleFile(Twine modulePath, bool isFramework, bool isTestableImport);

struct BinaryModuleImports {
llvm::StringSet<> moduleImports;
std::string headerImport;
};

static llvm::ErrorOr<BinaryModuleImports>
getImportsOfModule(Twine modulePath,
static BinaryModuleImports
getImportsOfModule(const ModuleFileSharedCore &loadedModule,
ModuleLoadingBehavior transitiveBehavior,
bool isFramework,
bool isRequiredOSSAModules,
StringRef SDKName,
StringRef packageName,
llvm::vfs::FileSystem *fileSystem,
PathObfuscator &recoverer);
StringRef packageName);

/// Load the module file into a buffer and also collect its module name.
static std::unique_ptr<llvm::MemoryBuffer>
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/ModuleDependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,13 @@ ModuleDependenciesCache::findDependency(StringRef moduleName) const {
return std::nullopt;
}

const ModuleDependencyInfo &ModuleDependenciesCache::findKnownDependency(
const ModuleDependencyID &moduleID) const {
auto dep = findDependency(moduleID);
assert(dep && "dependency unknown");
return **dep;
}

bool ModuleDependenciesCache::hasDependency(const ModuleDependencyID &moduleID) const {
return hasDependency(moduleID.ModuleName, moduleID.Kind);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/DependencyScan/ModuleDependencyScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker(
ScanASTContext,
*static_cast<ModuleInterfaceCheckerImpl *>(
ScanASTContext.getModuleInterfaceChecker()),
&DependencyTracker, ModuleLoadingMode::OnlyInterface);
&DependencyTracker,
ScanCompilerInvocation.getSearchPathOptions().ModuleLoadMode);
}

ModuleDependencyVector
Expand Down
Loading