diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index 6b4c1639d00c5..a44752905b787 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -185,6 +185,7 @@ class SerializedModuleLoaderBase : public ModuleLoader { bool isFramework, bool isRequiredOSSAModules, StringRef SDKName, + const llvm::Triple &target, StringRef packageName, llvm::vfs::FileSystem *fileSystem, PathObfuscator &recoverer); diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h index 7d5eeb4c635df..0e5b9d7d53933 100644 --- a/include/swift/Serialization/Validation.h +++ b/include/swift/Serialization/Validation.h @@ -23,10 +23,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" - -namespace llvm { -class Triple; -} +#include "llvm/TargetParser/Triple.h" namespace swift { @@ -296,6 +293,8 @@ struct SearchPath { /// compiled with -enable-ossa-modules. /// \param requiredSDK If not empty, only accept modules built with /// a compatible SDK. The StringRef represents the canonical SDK name. +/// \param target The target triple of the current compilation for +/// validating that the module we are attempting to load is compatible. /// \param[out] extendedInfo If present, will be populated with additional /// compilation options serialized into the AST at build time that may be /// necessary to load it properly. @@ -307,7 +306,8 @@ ValidationInfo validateSerializedAST( ExtendedValidationInfo *extendedInfo = nullptr, SmallVectorImpl *dependencies = nullptr, - SmallVectorImpl *searchPaths = nullptr); + SmallVectorImpl *searchPaths = nullptr, + std::optional target = std::nullopt); /// Emit diagnostics explaining a failure to load a serialized AST. /// diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 2f175f020e318..3b8131199edbf 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -427,8 +427,8 @@ ModuleFile::getModuleName(ASTContext &Ctx, StringRef modulePath, serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( "", "", std::move(newBuf), nullptr, nullptr, /*isFramework=*/isFramework, Ctx.SILOpts.EnableOSSAModules, - Ctx.LangOpts.SDKName, Ctx.SearchPathOpts.DeserializedPathRecoverer, - loadedModuleFile); + Ctx.LangOpts.SDKName, Ctx.LangOpts.Target, + Ctx.SearchPathOpts.DeserializedPathRecoverer, loadedModuleFile); Name = loadedModuleFile->Name.str(); return std::move(moduleBuf.get()); } diff --git a/lib/Serialization/ModuleFileSharedCore.cpp b/lib/Serialization/ModuleFileSharedCore.cpp index 64f9f801b7820..7d2ba92da4c95 100644 --- a/lib/Serialization/ModuleFileSharedCore.cpp +++ b/lib/Serialization/ModuleFileSharedCore.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/TargetParser/Triple.h" using namespace swift; using namespace swift::serialization; @@ -241,6 +242,7 @@ static ValidationInfo validateControlBlock( bool requiresOSSAModules, bool requiresRevisionMatch, StringRef requiredSDK, + std::optional target, ExtendedValidationInfo *extendedInfo, PathObfuscator &pathRecoverer) { // The control block is malformed until we've at least read a major version @@ -376,9 +378,17 @@ static ValidationInfo validateControlBlock( case control_block::MODULE_NAME: result.name = blobData; break; - case control_block::TARGET: + case control_block::TARGET: { result.targetTriple = blobData; + if (target && + !areCompatible(*target, llvm::Triple(llvm::Triple::normalize( + result.targetTriple)))) { + result.status = Status::TargetIncompatible; + return result; + } + break; + } case control_block::ALLOWABLE_CLIENT_NAME: result.allowableClients.push_back(blobData); break; @@ -606,7 +616,8 @@ ValidationInfo serialization::validateSerializedAST( StringRef requiredSDK, ExtendedValidationInfo *extendedInfo, SmallVectorImpl *dependencies, - SmallVectorImpl *searchPaths) { + SmallVectorImpl *searchPaths, + std::optional target) { ValidationInfo result; // Check 32-bit alignment. @@ -649,7 +660,7 @@ ValidationInfo serialization::validateSerializedAST( {SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR}, requiresOSSAModules, /*requiresRevisionMatch=*/true, - requiredSDK, + requiredSDK, target, extendedInfo, localObfuscator); if (result.status != Status::Valid) return result; @@ -1201,7 +1212,8 @@ bool ModuleFileSharedCore::readModuleDocIfPresent(PathObfuscator &pathRecoverer) docCursor, scratch, {SWIFTDOC_VERSION_MAJOR, SWIFTDOC_VERSION_MINOR}, RequiresOSSAModules, /*requiresRevisionMatch*/false, - /*requiredSDK*/StringRef(), /*extendedInfo*/nullptr, pathRecoverer); + /*requiredSDK*/StringRef(), /*target*/std::nullopt, + /*extendedInfo*/nullptr, pathRecoverer); if (info.status != Status::Valid) return false; // Check that the swiftdoc is actually for this module. @@ -1346,7 +1358,8 @@ bool ModuleFileSharedCore::readModuleSourceInfoIfPresent(PathObfuscator &pathRec {SWIFTSOURCEINFO_VERSION_MAJOR, SWIFTSOURCEINFO_VERSION_MINOR}, RequiresOSSAModules, /*requiresRevisionMatch*/false, - /*requiredSDK*/StringRef(), /*extendedInfo*/nullptr, pathRecoverer); + /*requiredSDK*/StringRef(), /*target*/std::nullopt, + /*extendedInfo*/nullptr, pathRecoverer); if (info.status != Status::Valid) return false; // Check that the swiftsourceinfo is actually for this module. @@ -1423,6 +1436,7 @@ ModuleFileSharedCore::ModuleFileSharedCore( bool isFramework, bool requiresOSSAModules, StringRef requiredSDK, + std::optional target, serialization::ValidationInfo &info, PathObfuscator &pathRecoverer) : ModuleInputBuffer(std::move(moduleInputBuffer)), ModuleDocInputBuffer(std::move(moduleDocInputBuffer)), @@ -1475,7 +1489,7 @@ ModuleFileSharedCore::ModuleFileSharedCore( cursor, scratch, {SWIFTMODULE_VERSION_MAJOR, SWIFTMODULE_VERSION_MINOR}, RequiresOSSAModules, - /*requiresRevisionMatch=*/true, requiredSDK, + /*requiresRevisionMatch=*/true, requiredSDK, target, &extInfo, pathRecoverer); if (info.status != Status::Valid) { error(info.status); diff --git a/lib/Serialization/ModuleFileSharedCore.h b/lib/Serialization/ModuleFileSharedCore.h index b9f00f2680b0a..418a8634c69f4 100644 --- a/lib/Serialization/ModuleFileSharedCore.h +++ b/lib/Serialization/ModuleFileSharedCore.h @@ -444,6 +444,7 @@ class ModuleFileSharedCore { bool isFramework, bool requiresOSSAModules, StringRef requiredSDK, + std::optional target, serialization::ValidationInfo &info, PathObfuscator &pathRecoverer); /// Change the status of the current module. @@ -571,6 +572,10 @@ class ModuleFileSharedCore { /// linking purposes. /// \param requiresOSSAModules If true, this requires dependent modules to be /// compiled with -enable-ossa-modules. + /// \param requiredSDK A string denoting the name of the currently-used SDK, + /// to ensure that the loaded module was built with a compatible SDK. + /// \param target The target triple of the current compilation for + /// validating that the module we are attempting to load is compatible. /// \param[out] theModule The loaded module. /// \returns Whether the module was successfully loaded, or what went wrong /// if it was not. @@ -580,13 +585,14 @@ class ModuleFileSharedCore { std::unique_ptr moduleDocInputBuffer, std::unique_ptr moduleSourceInfoInputBuffer, bool isFramework, bool requiresOSSAModules, - StringRef requiredSDK, PathObfuscator &pathRecoverer, + StringRef requiredSDK, std::optional target, + PathObfuscator &pathRecoverer, std::shared_ptr &theModule) { serialization::ValidationInfo info; auto *core = new ModuleFileSharedCore( std::move(moduleInputBuffer), std::move(moduleDocInputBuffer), std::move(moduleSourceInfoInputBuffer), isFramework, - requiresOSSAModules, requiredSDK, info, + requiresOSSAModules, requiredSDK, target, info, pathRecoverer); if (!moduleInterfacePath.empty()) { ArrayRef path; diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index 1fc077f433b76..868bea6ee72cd 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -214,8 +214,8 @@ SwiftModuleScanner::scanInterfaceFile(Identifier moduleID, auto adjacentBinaryModulePackageOnlyImports = getMatchingPackageOnlyImportsOfModule( *adjacentBinaryModule, isFramework, isRequiredOSSAModules(), - Ctx.LangOpts.SDKName, ScannerPackageName, - Ctx.SourceMgr.getFileSystem().get(), + Ctx.LangOpts.SDKName, Ctx.LangOpts.Target, + ScannerPackageName, Ctx.SourceMgr.getFileSystem().get(), Ctx.SearchPathOpts.DeserializedPathRecoverer); if (!adjacentBinaryModulePackageOnlyImports) @@ -255,7 +255,7 @@ llvm::ErrorOr SwiftModuleScanner::scanBinaryModuleFile( std::shared_ptr loadedModuleFile; serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( "", "", std::move(moduleBuf.get()), nullptr, nullptr, isFramework, - isRequiredOSSAModules(), Ctx.LangOpts.SDKName, + isRequiredOSSAModules(), Ctx.LangOpts.SDKName, Ctx.LangOpts.Target, Ctx.SearchPathOpts.DeserializedPathRecoverer, loadedModuleFile); if (Ctx.SearchPathOpts.ScannerModuleValidation) { diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index a7e46e9e793e1..3cc5d940f54bc 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -344,8 +344,8 @@ std::optional SerializedModuleLoaderBase::invalidModuleReason(seria llvm::ErrorOr> SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule( Twine modulePath, bool isFramework, bool isRequiredOSSAModules, - StringRef SDKName, StringRef packageName, llvm::vfs::FileSystem *fileSystem, - PathObfuscator &recoverer) { + StringRef SDKName, const llvm::Triple &target, StringRef packageName, + llvm::vfs::FileSystem *fileSystem, PathObfuscator &recoverer) { auto moduleBuf = fileSystem->getBufferForFile(modulePath); if (!moduleBuf) return moduleBuf.getError(); @@ -355,7 +355,7 @@ SerializedModuleLoaderBase::getMatchingPackageOnlyImportsOfModule( std::shared_ptr loadedModuleFile; serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( "", "", std::move(moduleBuf.get()), nullptr, nullptr, isFramework, - isRequiredOSSAModules, SDKName, recoverer, loadedModuleFile); + isRequiredOSSAModules, SDKName, target, recoverer, loadedModuleFile); if (loadedModuleFile->getModulePackageName() != packageName) return importedModuleNames; @@ -940,7 +940,7 @@ LoadedFile *SerializedModuleLoaderBase::loadAST( std::move(moduleInputBuffer), std::move(moduleDocInputBuffer), std::move(moduleSourceInfoInputBuffer), isFramework, isRequiredOSSAModules(), - Ctx.LangOpts.SDKName, + Ctx.LangOpts.SDKName, Ctx.LangOpts.Target, Ctx.SearchPathOpts.DeserializedPathRecoverer, loadedModuleFileCore); SerializedASTFile *fileUnit = nullptr; @@ -1482,6 +1482,7 @@ std::string swift::extractEmbeddedBridgingHeaderContent( serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( "", "", std::move(file), nullptr, nullptr, false, Context.SILOpts.EnableOSSAModules, Context.LangOpts.SDKName, + Context.LangOpts.Target, Context.SearchPathOpts.DeserializedPathRecoverer, loadedModuleFile); diff --git a/test/ScanDependencies/wrong_target_candidate_diagnostic.swift b/test/ScanDependencies/wrong_target_candidate_diagnostic.swift new file mode 100644 index 0000000000000..53f755eccf436 --- /dev/null +++ b/test/ScanDependencies/wrong_target_candidate_diagnostic.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/module-cache) +// RUN: %empty-directory(%t/moduleInputs) +// RUN: split-file %s %t + +// ERROR: error: unable to resolve Swift module dependency to a compatible module: 'FooBar' +// ERROR: note: found incompatible module '{{.*}}{{/|\\}}moduleInputs{{/|\\}}FooBar.swiftmodule': compiled for a different target platform + +// RUN: %target-swift-frontend -emit-module %t/FooBar.swift -emit-module-path %t/moduleInputs/FooBar.swiftmodule -module-name FooBar -target x86_64-unknown-linux-gnu -parse-stdlib +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %t/main.swift -o %t/deps.json -I %t/moduleInputs -I %t/moduleInputs2 -diagnostic-style llvm -scanner-module-validation -target arm64e-apple-macosx11.0 2>&1 | %FileCheck %s -check-prefix=ERROR + +//--- main.swift +import FooBar + +//--- FooBar.swift +public func fooBar() {}