Skip to content

Commit bd782be

Browse files
committed
Front-end: add a new module loader that loads explicitly built Swift modules
To support -disable-implicit-swift-modules, the explicitly built modules are passed down as compiler arguments. We need this new module loader to handle these modules. This patch also stops ModuleInterfaceLoader from building module from interface when -disable-implicit-swift-modules is set.
1 parent d992e04 commit bd782be

File tree

11 files changed

+176
-1
lines changed

11 files changed

+176
-1
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ ERROR(error_extracting_version_from_module_interface,none,
326326
ERROR(unsupported_version_of_module_interface,none,
327327
"unsupported version of module interface '%0': '%1'",
328328
(StringRef, llvm::VersionTuple))
329+
ERROR(error_opening_explicit_module_file,none,
330+
"failed to open explicit Swift module: %0", (StringRef))
329331
ERROR(error_extracting_flags_from_module_interface,none,
330332
"error extracting flags from module interface", ())
331333
REMARK(rebuilding_module_from_interface,none,

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,38 @@ class LangOptions;
127127
class SearchPathOptions;
128128
class CompilerInvocation;
129129

130+
/// A ModuleLoader that loads explicitly built Swift modules specified via
131+
/// -swift-module-file
132+
class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
133+
explicit ExplicitSwiftModuleLoader(ASTContext &ctx, DependencyTracker *tracker,
134+
ModuleLoadingMode loadMode,
135+
bool IgnoreSwiftSourceInfoFile);
136+
std::error_code findModuleFilesInDirectory(
137+
AccessPathElem ModuleID,
138+
const SerializedModuleBaseName &BaseName,
139+
SmallVectorImpl<char> *ModuleInterfacePath,
140+
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
141+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
142+
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer) override;
143+
144+
bool isCached(StringRef DepPath) override { return false; };
145+
146+
struct Implementation;
147+
Implementation &Impl;
148+
public:
149+
static std::unique_ptr<ExplicitSwiftModuleLoader>
150+
create(ASTContext &ctx,
151+
DependencyTracker *tracker, ModuleLoadingMode loadMode,
152+
ArrayRef<std::string> ExplicitModulePaths,
153+
bool IgnoreSwiftSourceInfoFile);
154+
155+
/// Append visible module names to \p names. Note that names are possibly
156+
/// duplicated, and not guaranteed to be ordered in any way.
157+
void collectVisibleTopLevelModuleNames(
158+
SmallVectorImpl<Identifier> &names) const override;
159+
~ExplicitSwiftModuleLoader();
160+
};
161+
130162
struct ModuleInterfaceLoaderOptions {
131163
bool remarkOnRebuildFromInterface = false;
132164
bool disableInterfaceLock = false;
@@ -137,6 +169,7 @@ struct ModuleInterfaceLoaderOptions {
137169
disableImplicitSwiftModule(Opts.DisableImplicitModules) {}
138170
ModuleInterfaceLoaderOptions() = default;
139171
};
172+
140173
/// A ModuleLoader that runs a subordinate \c CompilerInvocation and
141174
/// \c CompilerInstance to convert .swiftinterface files to .swiftmodule
142175
/// files on the fly, caching the resulting .swiftmodules in the module cache

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ class SerializedModuleLoaderBase : public ModuleLoader {
138138
/// Scan the given serialized module file to determine dependencies.
139139
llvm::ErrorOr<ModuleDependencies> scanModuleFile(Twine modulePath);
140140

141+
/// Load the module file into a buffer and also collect its module name.
142+
static std::unique_ptr<llvm::MemoryBuffer>
143+
getModuleName(ASTContext &Ctx, StringRef modulePath, std::string &Name);
141144
public:
142145
virtual ~SerializedModuleLoaderBase();
143146
SerializedModuleLoaderBase(const SerializedModuleLoaderBase &) = delete;

lib/Frontend/Frontend.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,16 @@ bool CompilerInstance::setUpModuleLoaders() {
450450
return true;
451451
}
452452

453+
// If implicit modules are disabled, we need to install an explicit module
454+
// loader.
455+
if (Invocation.getFrontendOptions().DisableImplicitModules) {
456+
auto ESML = ExplicitSwiftModuleLoader::create(
457+
*Context,
458+
getDependencyTracker(), MLM,
459+
Invocation.getSearchPathOptions().ExplicitSwiftModules,
460+
IgnoreSourceInfoFile);
461+
Context->addModuleLoader(std::move(ESML));
462+
}
453463
if (MLM != ModuleLoadingMode::OnlySerialized) {
454464
auto const &Clang = clangImporter->getClangInstance();
455465
std::string ModuleCachePath = getModuleCachePathFromClang(Clang);

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,10 @@ class ModuleInterfaceLoaderImpl {
880880

881881
return std::move(module.moduleBuffer);
882882
}
883+
// If implicit module is disabled, we are done.
884+
if (Opts.disableImplicitSwiftModule) {
885+
return std::make_error_code(std::errc::not_supported);
886+
}
883887

884888
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
885889

@@ -1397,3 +1401,81 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN
13971401
// Run the action under the sub compiler instance.
13981402
return action(info);
13991403
}
1404+
1405+
struct ExplicitSwiftModuleLoader::Implementation {
1406+
// Information about explicitly specified Swift module files.
1407+
struct ExplicitModuleInfo {
1408+
// Path of the module file.
1409+
StringRef path;
1410+
// Buffer of the module content.
1411+
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
1412+
};
1413+
llvm::StringMap<ExplicitModuleInfo> ExplicitModuleMap;
1414+
};
1415+
1416+
ExplicitSwiftModuleLoader::ExplicitSwiftModuleLoader(
1417+
ASTContext &ctx,
1418+
DependencyTracker *tracker,
1419+
ModuleLoadingMode loadMode,
1420+
bool IgnoreSwiftSourceInfoFile):
1421+
SerializedModuleLoaderBase(ctx, tracker, loadMode,
1422+
IgnoreSwiftSourceInfoFile),
1423+
Impl(*new Implementation()) {}
1424+
1425+
ExplicitSwiftModuleLoader::~ExplicitSwiftModuleLoader() { delete &Impl; }
1426+
1427+
std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory(
1428+
AccessPathElem ModuleID,
1429+
const SerializedModuleBaseName &BaseName,
1430+
SmallVectorImpl<char> *ModuleInterfacePath,
1431+
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
1432+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
1433+
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer) {
1434+
StringRef moduleName = ModuleID.Item.str();
1435+
auto it = Impl.ExplicitModuleMap.find(moduleName);
1436+
// If no explicit module path is given matches the name, return with an
1437+
// error code.
1438+
if (it == Impl.ExplicitModuleMap.end()) {
1439+
return std::make_error_code(std::errc::not_supported);
1440+
}
1441+
// We found an explicit module matches the given name, give the buffer
1442+
// back to the caller side.
1443+
*ModuleBuffer = std::move(it->getValue().moduleBuffer);
1444+
return std::error_code();
1445+
}
1446+
1447+
void ExplicitSwiftModuleLoader::collectVisibleTopLevelModuleNames(
1448+
SmallVectorImpl<Identifier> &names) const {
1449+
for (auto &entry: Impl.ExplicitModuleMap) {
1450+
names.push_back(Ctx.getIdentifier(entry.getKey()));
1451+
}
1452+
}
1453+
1454+
std::unique_ptr<ExplicitSwiftModuleLoader>
1455+
ExplicitSwiftModuleLoader::create(ASTContext &ctx,
1456+
DependencyTracker *tracker, ModuleLoadingMode loadMode,
1457+
ArrayRef<std::string> ExplicitModulePaths,
1458+
bool IgnoreSwiftSourceInfoFile) {
1459+
auto result = std::unique_ptr<ExplicitSwiftModuleLoader>(
1460+
new ExplicitSwiftModuleLoader(ctx, tracker, loadMode,
1461+
IgnoreSwiftSourceInfoFile));
1462+
auto &Impl = result->Impl;
1463+
for (auto path: ExplicitModulePaths) {
1464+
std::string name;
1465+
// Load the explicit module into a buffer and get its name.
1466+
std::unique_ptr<llvm::MemoryBuffer> buffer = getModuleName(ctx, path, name);
1467+
if (buffer) {
1468+
// Register this module for future loading.
1469+
auto &entry = Impl.ExplicitModuleMap[name];
1470+
entry.path = path;
1471+
entry.moduleBuffer = std::move(buffer);
1472+
} else {
1473+
// We cannot read the module content, diagnose.
1474+
ctx.Diags.diagnose(SourceLoc(),
1475+
diag::error_opening_explicit_module_file,
1476+
path);
1477+
}
1478+
}
1479+
1480+
return result;
1481+
}

lib/Serialization/ModuleFile.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,6 +2190,30 @@ TypeDecl *ModuleFile::lookupLocalType(StringRef MangledName) {
21902190
return cast<TypeDecl>(getDecl(*iter));
21912191
}
21922192

2193+
std::unique_ptr<llvm::MemoryBuffer>
2194+
ModuleFile::getModuleName(ASTContext &Ctx, StringRef modulePath,
2195+
std::string &Name) {
2196+
// Open the module file
2197+
auto &fs = *Ctx.SourceMgr.getFileSystem();
2198+
auto moduleBuf = fs.getBufferForFile(modulePath);
2199+
if (!moduleBuf)
2200+
return nullptr;
2201+
2202+
// Load the module file without validation.
2203+
std::unique_ptr<ModuleFile> loadedModuleFile;
2204+
ExtendedValidationInfo ExtInfo;
2205+
bool isFramework = false;
2206+
serialization::ValidationInfo loadInfo =
2207+
ModuleFile::load(modulePath.str(),
2208+
std::move(moduleBuf.get()),
2209+
nullptr,
2210+
nullptr,
2211+
/*isFramework*/isFramework, loadedModuleFile,
2212+
&ExtInfo);
2213+
Name = loadedModuleFile->Name;
2214+
return std::move(loadedModuleFile->ModuleInputBuffer);
2215+
}
2216+
21932217
OpaqueTypeDecl *ModuleFile::lookupOpaqueResultType(StringRef MangledName) {
21942218
PrettyStackTraceModuleFile stackEntry(*this);
21952219

lib/Serialization/ModuleFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ class ModuleFile
106106
StringRef MiscVersion;
107107

108108
public:
109+
static std::unique_ptr<llvm::MemoryBuffer> getModuleName(ASTContext &Ctx,
110+
StringRef modulePath,
111+
std::string &Name);
112+
109113
/// Represents another module that has been imported as a dependency.
110114
class Dependency {
111115
public:

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,12 @@ std::error_code SerializedModuleLoaderBase::openModuleDocFileIfPresent(
275275
return std::error_code();
276276
}
277277

278+
std::unique_ptr<llvm::MemoryBuffer>
279+
SerializedModuleLoaderBase::getModuleName(ASTContext &Ctx, StringRef modulePath,
280+
std::string &Name) {
281+
return ModuleFile::getModuleName(Ctx, modulePath, Name);
282+
}
283+
278284
std::error_code
279285
SerializedModuleLoaderBase::openModuleSourceInfoFileIfPresent(
280286
AccessPathElem ModuleID,

test/ScanDependencies/Inputs/BuildModulesFromGraph.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ let moduleDependencyGraph = try! decoder.decode(
2222

2323
func findModuleBuildingCommand(_ moduleName: String) -> [String]? {
2424
for (_, dep) in moduleDependencyGraph.modules {
25-
if dep.modulePath.hasSuffix(moduleName) {
25+
if URL(fileURLWithPath: dep.modulePath).lastPathComponent == moduleName {
2626
switch dep.details {
2727
case .swift(let details):
2828
return details.commandLine
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name SubE
3+
import Swift
4+
import E
5+
public func funcSubE() {}

0 commit comments

Comments
 (0)