Skip to content

Commit 8e0e51a

Browse files
authored
Merge pull request #63697 from artemcm/SeparateExplicitModuleInputMaps
Separate parsing out Swift and Clang modules from the explicit modulemap
2 parents 815e8cc + a0b5dd4 commit 8e0e51a

File tree

5 files changed

+105
-51
lines changed

5 files changed

+105
-51
lines changed

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -176,24 +176,49 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
176176
~ExplicitSwiftModuleLoader();
177177
};
178178

179-
/// Information about explicitly specified Swift and Clang module files.
180-
struct ExplicitModuleInfo {
181-
// Path of the .swiftmodule file. Empty for pure Clang modules.
179+
180+
// Explicitly-specified Swift module inputs
181+
struct ExplicitSwiftModuleInputInfo {
182+
ExplicitSwiftModuleInputInfo(std::string modulePath,
183+
llvm::Optional<std::string> moduleDocPath,
184+
llvm::Optional<std::string> moduleSourceInfoPath,
185+
bool isFramework = false,
186+
bool isSystem = false)
187+
: modulePath(modulePath),
188+
moduleDocPath(moduleDocPath),
189+
moduleSourceInfoPath(moduleSourceInfoPath),
190+
isFramework(isFramework),
191+
isSystem(isSystem) {}
192+
// Path of the .swiftmodule file.
193+
std::string modulePath;
194+
// Path of the .swiftmoduledoc file.
195+
llvm::Optional<std::string> moduleDocPath;
196+
// Path of the .swiftsourceinfo file.
197+
llvm::Optional<std::string> moduleSourceInfoPath;
198+
// A flag that indicates whether this module is a framework
199+
bool isFramework = false;
200+
// A flag that indicates whether this module is a system module
201+
bool isSystem = false;
202+
};
203+
204+
// Explicitly-specified Clang module inputs
205+
struct ExplicitClangModuleInputInfo {
206+
ExplicitClangModuleInputInfo(std::string moduleMapPath,
207+
std::string modulePath,
208+
bool isFramework = false,
209+
bool isSystem = false)
210+
: moduleMapPath(moduleMapPath),
211+
modulePath(modulePath),
212+
isFramework(isFramework),
213+
isSystem(isSystem) {}
214+
// Path of the Clang module map file.
215+
std::string moduleMapPath;
216+
// Path of a compiled Clang explicit module file (pcm).
182217
std::string modulePath;
183-
// Path of the .swiftmoduledoc file. Empty for pure Clang modules.
184-
std::string moduleDocPath;
185-
// Path of the .swiftsourceinfo file. Empty for pure Clang modules.
186-
std::string moduleSourceInfoPath;
187218
// A flag that indicates whether this module is a framework
188219
bool isFramework = false;
189220
// A flag that indicates whether this module is a system module
190-
// Set the default to be false.
191221
bool isSystem = false;
192-
// Path of the Clang module map file. Empty for pure Swift modules.
193-
std::string clangModuleMapPath;
194-
// Path of a compiled Clang explicit module file. Empty for pure Swift
195-
// modules.
196-
std::string clangModulePath;
197222
};
198223

199224
/// Parser of explicit module maps passed into the compiler.
@@ -223,7 +248,8 @@ class ExplicitModuleMapParser {
223248

224249
std::error_code
225250
parseSwiftExplicitModuleMap(llvm::StringRef fileName,
226-
llvm::StringMap<ExplicitModuleInfo> &moduleMap) {
251+
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
252+
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap) {
227253
using namespace llvm::yaml;
228254
// Load the input file.
229255
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
@@ -240,7 +266,7 @@ class ExplicitModuleMapParser {
240266
assert(DI != Stream.end() && "Failed to read a document");
241267
if (auto *MN = dyn_cast_or_null<SequenceNode>(DI->getRoot())) {
242268
for (auto &entry : *MN) {
243-
if (parseSingleModuleEntry(entry, moduleMap)) {
269+
if (parseSingleModuleEntry(entry, swiftModuleMap, clangModuleMap)) {
244270
return std::make_error_code(std::errc::invalid_argument);
245271
}
246272
}
@@ -269,40 +295,65 @@ class ExplicitModuleMapParser {
269295
}
270296

271297
bool parseSingleModuleEntry(llvm::yaml::Node &node,
272-
llvm::StringMap<ExplicitModuleInfo> &moduleMap) {
298+
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
299+
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap) {
273300
using namespace llvm::yaml;
274301
auto *mapNode = dyn_cast<MappingNode>(&node);
275302
if (!mapNode)
276303
return true;
277304
StringRef moduleName;
278-
ExplicitModuleInfo result;
305+
llvm::Optional<std::string> swiftModulePath, swiftModuleDocPath,
306+
swiftModuleSourceInfoPath;
307+
std::string clangModuleMapPath = "", clangModulePath = "";
308+
bool isFramework = false, isSystem = false;
279309
for (auto &entry : *mapNode) {
280310
auto key = getScalaNodeText(entry.getKey());
281311
auto val = getScalaNodeText(entry.getValue());
282312
if (key == "moduleName") {
283313
moduleName = val;
284314
} else if (key == "modulePath") {
285-
result.modulePath = val.str();
315+
swiftModulePath = val.str();
286316
} else if (key == "docPath") {
287-
result.moduleDocPath = val.str();
317+
swiftModuleDocPath = val.str();
288318
} else if (key == "sourceInfoPath") {
289-
result.moduleSourceInfoPath = val.str();
319+
swiftModuleSourceInfoPath = val.str();
290320
} else if (key == "isFramework") {
291-
result.isFramework = parseBoolValue(val);
321+
isFramework = parseBoolValue(val);
292322
} else if (key == "isSystem") {
293-
result.isSystem = parseBoolValue(val);
323+
isSystem = parseBoolValue(val);
294324
} else if (key == "clangModuleMapPath") {
295-
result.clangModuleMapPath = val.str();
325+
clangModuleMapPath = val.str();
296326
} else if (key == "clangModulePath") {
297-
result.clangModulePath = val.str();
327+
clangModulePath = val.str();
298328
} else {
299329
// Being forgiving for future fields.
300330
continue;
301331
}
302332
}
303333
if (moduleName.empty())
304334
return true;
305-
moduleMap[moduleName] = std::move(result);
335+
336+
if (swiftModulePath.has_value()) {
337+
assert((clangModuleMapPath.empty() &&
338+
clangModulePath.empty()) &&
339+
"Unexpected Clang dependency details for Swift module");
340+
ExplicitSwiftModuleInputInfo entry(swiftModulePath.value(),
341+
swiftModuleDocPath,
342+
swiftModuleSourceInfoPath,
343+
isFramework,
344+
isSystem);
345+
swiftModuleMap.try_emplace(moduleName, std::move(entry));
346+
} else {
347+
assert((!clangModuleMapPath.empty() ||
348+
!clangModulePath.empty()) &&
349+
"Expected Clang dependency module");
350+
ExplicitClangModuleInputInfo entry(clangModuleMapPath,
351+
clangModulePath,
352+
isFramework,
353+
isSystem);
354+
clangModuleMap.try_emplace(moduleName, std::move(entry));
355+
}
356+
306357
return false;
307358
}
308359

include/swift/Serialization/ModuleDependencyScanner.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@ namespace swift {
8484
/// Scan the given placeholder module map
8585
void parsePlaceholderModuleMap(StringRef fileName) {
8686
ExplicitModuleMapParser parser(Allocator);
87+
llvm::StringMap<ExplicitClangModuleInputInfo> ClangDependencyModuleMap;
8788
auto result =
88-
parser.parseSwiftExplicitModuleMap(fileName, PlaceholderDependencyModuleMap);
89+
parser.parseSwiftExplicitModuleMap(fileName, PlaceholderDependencyModuleMap,
90+
ClangDependencyModuleMap);
8991
if (result == std::errc::invalid_argument) {
9092
Ctx.Diags.diagnose(SourceLoc(),
9193
diag::placeholder_dependency_module_map_corrupted,
@@ -98,7 +100,7 @@ namespace swift {
98100
}
99101
}
100102

101-
llvm::StringMap<ExplicitModuleInfo> PlaceholderDependencyModuleMap;
103+
llvm::StringMap<ExplicitSwiftModuleInputInfo> PlaceholderDependencyModuleMap;
102104
llvm::BumpPtrAllocator Allocator;
103105

104106
public:

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,13 +1888,15 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
18881888
struct ExplicitSwiftModuleLoader::Implementation {
18891889
ASTContext &Ctx;
18901890
llvm::BumpPtrAllocator Allocator;
1891-
llvm::StringMap<ExplicitModuleInfo> ExplicitModuleMap;
1891+
llvm::StringMap<ExplicitSwiftModuleInputInfo> ExplicitModuleMap;
18921892
Implementation(ASTContext &Ctx) : Ctx(Ctx) {}
18931893

18941894
void parseSwiftExplicitModuleMap(StringRef fileName) {
18951895
ExplicitModuleMapParser parser(Allocator);
1896+
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
18961897
auto result =
1897-
parser.parseSwiftExplicitModuleMap(fileName, ExplicitModuleMap);
1898+
parser.parseSwiftExplicitModuleMap(fileName, ExplicitModuleMap,
1899+
ExplicitClangModuleMap);
18981900
if (result == std::errc::invalid_argument)
18991901
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
19001902
fileName);
@@ -1906,16 +1908,16 @@ struct ExplicitSwiftModuleLoader::Implementation {
19061908
// we've seen so that we don't generate duplicate flags.
19071909
std::set<std::string> moduleMapsSeen;
19081910
std::vector<std::string> &extraClangArgs = Ctx.ClangImporterOpts.ExtraArgs;
1909-
for (auto &entry : ExplicitModuleMap) {
1910-
const auto &moduleMapPath = entry.getValue().clangModuleMapPath;
1911+
for (auto &entry : ExplicitClangModuleMap) {
1912+
const auto &moduleMapPath = entry.getValue().moduleMapPath;
19111913
if (!moduleMapPath.empty() &&
19121914
moduleMapsSeen.find(moduleMapPath) == moduleMapsSeen.end()) {
19131915
moduleMapsSeen.insert(moduleMapPath);
19141916
extraClangArgs.push_back(
19151917
(Twine("-fmodule-map-file=") + moduleMapPath).str());
19161918
}
19171919

1918-
const auto &modulePath = entry.getValue().clangModulePath;
1920+
const auto &modulePath = entry.getValue().modulePath;
19191921
if (!modulePath.empty()) {
19201922
extraClangArgs.push_back(
19211923
(Twine("-fmodule-file=") + entry.getKey() + "=" + modulePath)
@@ -1928,8 +1930,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
19281930
const std::vector<std::pair<std::string, std::string>>
19291931
&commandLineExplicitInputs) {
19301932
for (const auto &moduleInput : commandLineExplicitInputs) {
1931-
ExplicitModuleInfo entry;
1932-
entry.modulePath = moduleInput.second;
1933+
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {});
19331934
ExplicitModuleMap.try_emplace(moduleInput.first, std::move(entry));
19341935
}
19351936
}
@@ -1968,16 +1969,6 @@ bool ExplicitSwiftModuleLoader::findModule(
19681969
}
19691970
auto &moduleInfo = it->getValue();
19701971

1971-
// If this is only a Clang module with no paired Swift module, return false
1972-
// now so that we don't emit diagnostics about it being missing. This gives
1973-
// ClangImporter an opportunity to import it.
1974-
bool hasClangModule = !moduleInfo.clangModuleMapPath.empty() ||
1975-
!moduleInfo.clangModulePath.empty();
1976-
bool hasSwiftModule = !moduleInfo.modulePath.empty();
1977-
if (hasClangModule && !hasSwiftModule) {
1978-
return false;
1979-
}
1980-
19811972
// Set IsFramework bit according to the moduleInfo
19821973
IsFramework = moduleInfo.isFramework;
19831974
IsSystemModule = moduleInfo.isSystem;
@@ -2019,14 +2010,14 @@ bool ExplicitSwiftModuleLoader::findModule(
20192010
*ModuleBuffer = std::move(moduleBuf.get());
20202011

20212012
// Open .swiftdoc file
2022-
if (!moduleInfo.moduleDocPath.empty()) {
2023-
auto moduleDocBuf = fs.getBufferForFile(moduleInfo.moduleDocPath);
2013+
if (moduleInfo.moduleDocPath.has_value()) {
2014+
auto moduleDocBuf = fs.getBufferForFile(moduleInfo.moduleDocPath.value());
20242015
if (moduleBuf)
20252016
*ModuleDocBuffer = std::move(moduleDocBuf.get());
20262017
}
20272018
// Open .swiftsourceinfo file
2028-
if (!moduleInfo.moduleSourceInfoPath.empty()) {
2029-
auto moduleSourceInfoBuf = fs.getBufferForFile(moduleInfo.moduleSourceInfoPath);
2019+
if (moduleInfo.moduleSourceInfoPath.has_value()) {
2020+
auto moduleSourceInfoBuf = fs.getBufferForFile(moduleInfo.moduleSourceInfoPath.value());
20302021
if (moduleSourceInfoBuf)
20312022
*ModuleSourceInfoBuffer = std::move(moduleSourceInfoBuf.get());
20322023
}

lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,11 @@ bool PlaceholderSwiftModuleScanner::findModule(
8383
}
8484
auto &moduleInfo = it->getValue();
8585
auto dependencies = ModuleDependencyInfo::forPlaceholderSwiftModuleStub(
86-
moduleInfo.modulePath, moduleInfo.moduleDocPath,
87-
moduleInfo.moduleSourceInfoPath);
86+
moduleInfo.modulePath,
87+
moduleInfo.moduleDocPath.has_value() ?
88+
moduleInfo.moduleDocPath.value() : "",
89+
moduleInfo.moduleSourceInfoPath.has_value() ?
90+
moduleInfo.moduleSourceInfoPath.value() : "");
8891
this->dependencies = std::move(dependencies);
8992
return true;
9093
}

test/ScanDependencies/explicit-module-map-clang-and-swift.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
// RUN: mkdir -p %t/inputs
44
// RUN: echo "public func anotherFuncA() {}" > %t/A.swift
55
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/inputs/A.swiftmodule -emit-module-doc-path %t/inputs/A.swiftdoc -emit-module-source-info -emit-module-source-info-path %t/inputs/A.swiftsourceinfo -import-underlying-module -I%S/Inputs/CHeaders -module-cache-path %t.module-cache %t/A.swift -module-name A
6+
// RUN: %target-swift-emit-pcm -module-name A -o %t/inputs/A.pcm %S/Inputs/CHeaders/module.modulemap
67

78
// RUN: echo "[{" > %/t/inputs/map.json
89
// RUN: echo "\"moduleName\": \"A\"," >> %/t/inputs/map.json
910
// RUN: echo "\"modulePath\": \"%/t/inputs/A.swiftmodule\"," >> %/t/inputs/map.json
1011
// RUN: echo "\"docPath\": \"%/t/inputs/A.swiftdoc\"," >> %/t/inputs/map.json
1112
// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/A.swiftsourceinfo\"," >> %/t/inputs/map.json
1213
// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json
14+
// RUN: echo "}," >> %/t/inputs/map.json
15+
// RUN: echo "{" >> %/t/inputs/map.json
16+
// RUN: echo "\"moduleName\": \"A\"," >> %/t/inputs/map.json
17+
// RUN: echo "\"clangModulePath\": \"%/t/inputs/A.pcm\"," >> %/t/inputs/map.json
1318
// RUN: echo "\"clangModuleMapPath\": \"%/S/Inputs/CHeaders/module.modulemap\"" >> %/t/inputs/map.json
1419
// RUN: echo "}," >> %/t/inputs/map.json
1520
// RUN: echo "{" >> %/t/inputs/map.json
@@ -33,7 +38,9 @@
3338
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
3439
// RUN: echo "}]" >> %/t/inputs/map.json
3540

36-
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/Foo.swiftmodule -module-cache-path %t.module-cache -explicit-swift-module-map-file %t/inputs/map.json %s
41+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/Foo.swiftmodule -disable-implicit-swift-modules -module-cache-path %t.module-cache -explicit-swift-module-map-file %t/inputs/map.json -Rmodule-loading -Xcc -Rmodule-import %s 2>&1 | %FileCheck %s
42+
43+
// CHECK: <unknown>:0: remark: importing module 'A' from {{.*}}{{/|\\}}explicit-module-map-clang-and-swift.swift.tmp{{/|\\}}inputs{{/|\\}}A.pcm'
3744

3845
import A
3946

0 commit comments

Comments
 (0)