Skip to content

Commit 96a5c81

Browse files
authored
Merge pull request #32170 from nkcsgexi/explicit-module-loader
Front-end: add a new module loader that loads explicitly built Swift modules
2 parents 5808893 + bd782be commit 96a5c81

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)