3636#include " llvm/Support/Path.h"
3737#include " llvm/Support/Errc.h"
3838#include " llvm/Support/YAMLTraits.h"
39+ #include " llvm/Support/YAMLParser.h"
3940#include " ModuleInterfaceBuilder.h"
4041
4142using namespace swift ;
@@ -1218,6 +1219,15 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
12181219 GenericArgs.push_back (" -swift-module-file" );
12191220 GenericArgs.push_back (ArgSaver.save (EM));
12201221 }
1222+ // Pass down -explicit-swift-module-map-file
1223+ // FIXME: we shouldn't need this. Remove it?
1224+ StringRef explictSwiftModuleMap = searchPathOpts.ExplicitSwiftModuleMap ;
1225+ subInvocation.getSearchPathOptions ().ExplicitSwiftModuleMap =
1226+ explictSwiftModuleMap;
1227+ if (!explictSwiftModuleMap.empty ()) {
1228+ GenericArgs.push_back (" -explicit-swift-module-map-file" );
1229+ GenericArgs.push_back (explictSwiftModuleMap);
1230+ }
12211231 if (clangImporter) {
12221232 // We need to add these extra clang flags because explict module building
12231233 // related flags are all there: -fno-implicit-modules, -fmodule-map-file=,
@@ -1418,14 +1428,99 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN
14181428}
14191429
14201430struct ExplicitSwiftModuleLoader ::Implementation {
1431+
14211432 // Information about explicitly specified Swift module files.
14221433 struct ExplicitModuleInfo {
1423- // Path of the module file.
1424- StringRef path;
1425- // Buffer of the module content.
1434+ // Path of the .swiftmodule file.
1435+ StringRef modulePath;
1436+ // Path of the .swiftmoduledoc file.
1437+ StringRef moduleDocPath;
1438+ // Path of the .swiftsourceinfo file.
1439+ StringRef moduleSourceInfoPath;
1440+ // Opened buffer for the .swiftmodule file.
14261441 std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
14271442 };
1443+ ASTContext &Ctx;
1444+ llvm::BumpPtrAllocator Allocator;
1445+ llvm::StringSaver Saver;
14281446 llvm::StringMap<ExplicitModuleInfo> ExplicitModuleMap;
1447+ Implementation (ASTContext &Ctx): Ctx(Ctx), Saver(Allocator) {}
1448+
1449+ StringRef getScalaNodeText (llvm::yaml::Node *N) {
1450+ SmallString<32 > Buffer;
1451+ return Saver.save (cast<llvm::yaml::ScalarNode>(N)->getValue (Buffer));
1452+ }
1453+
1454+ bool parseSingleModuleEntry (llvm::yaml::KeyValueNode &node) {
1455+ using namespace llvm ::yaml;
1456+ auto moduleName = getScalaNodeText (node.getKey ());
1457+ auto insertRes = ExplicitModuleMap.insert ({moduleName,
1458+ ExplicitModuleInfo ()});
1459+ if (!insertRes.second ) {
1460+ return true ;
1461+ }
1462+ auto moduleDetails = dyn_cast<MappingNode>(node.getValue ());
1463+ if (!moduleDetails)
1464+ return true ;
1465+ for (auto &entry: *moduleDetails) {
1466+ auto key = getScalaNodeText (entry.getKey ());
1467+ auto val = getScalaNodeText (entry.getValue ());
1468+ if (key == " SwiftModulePath" ) {
1469+ insertRes.first ->second .modulePath = val;
1470+ } else if (key == " SwiftDocPath" ) {
1471+ insertRes.first ->second .moduleDocPath = val;
1472+ } else if (key == " SwiftSourceInfoPath" ) {
1473+ insertRes.first ->second .moduleSourceInfoPath = val;
1474+ } else {
1475+ return true ;
1476+ }
1477+ }
1478+ return false ;
1479+ }
1480+ // {
1481+ // "A": {
1482+ // "SwiftModulePath": "A.swiftmodule",
1483+ // "SwiftDocPath": "A.swiftdoc",
1484+ // "SwiftSourceInfoPath": "A.swiftsourceinfo"
1485+ // },
1486+ // "B": {
1487+ // "SwiftModulePath": "B.swiftmodule",
1488+ // "SwiftDocPath": "B.swiftdoc",
1489+ // "SwiftSourceInfoPath": "B.swiftsourceinfo"
1490+ // }
1491+ // }
1492+ void parseSwiftExplicitModuleMap (StringRef fileName) {
1493+ using namespace llvm ::yaml;
1494+ // Load the input file.
1495+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
1496+ llvm::MemoryBuffer::getFile (fileName);
1497+ if (!fileBufOrErr) {
1498+ Ctx.Diags .diagnose (SourceLoc (), diag::explicit_swift_module_map_missing,
1499+ fileName);
1500+ return ;
1501+ }
1502+ StringRef Buffer = fileBufOrErr->get ()->getBuffer ();
1503+ Stream Stream (llvm::MemoryBufferRef (Buffer, fileName),
1504+ Ctx.SourceMgr .getLLVMSourceMgr ());
1505+ for (auto DI = Stream.begin (); DI != Stream.end (); ++ DI) {
1506+ assert (DI != Stream.end () && " Failed to read a document" );
1507+ if (auto *MN = dyn_cast_or_null<MappingNode>(DI->getRoot ())) {
1508+ for (auto &entry: *MN) {
1509+ if (parseSingleModuleEntry (entry)) {
1510+ Ctx.Diags .diagnose (SourceLoc (),
1511+ diag::explicit_swift_module_map_corrupted,
1512+ fileName);
1513+ return ;
1514+ }
1515+ }
1516+ } else {
1517+ Ctx.Diags .diagnose (SourceLoc (),
1518+ diag::explicit_swift_module_map_corrupted,
1519+ fileName);
1520+ return ;
1521+ }
1522+ }
1523+ }
14291524};
14301525
14311526ExplicitSwiftModuleLoader::ExplicitSwiftModuleLoader (
@@ -1435,7 +1530,7 @@ ExplicitSwiftModuleLoader::ExplicitSwiftModuleLoader(
14351530 bool IgnoreSwiftSourceInfoFile):
14361531 SerializedModuleLoaderBase(ctx, tracker, loadMode,
14371532 IgnoreSwiftSourceInfoFile),
1438- Impl(*new Implementation()) {}
1533+ Impl(*new Implementation(ctx )) {}
14391534
14401535ExplicitSwiftModuleLoader::~ExplicitSwiftModuleLoader () { delete &Impl; }
14411536
@@ -1453,9 +1548,33 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory(
14531548 if (it == Impl.ExplicitModuleMap .end ()) {
14541549 return std::make_error_code (std::errc::not_supported);
14551550 }
1456- // We found an explicit module matches the given name, give the buffer
1457- // back to the caller side.
1458- *ModuleBuffer = std::move (it->getValue ().moduleBuffer );
1551+ auto &moduleInfo = it->getValue ();
1552+ if (moduleInfo.moduleBuffer ) {
1553+ // We found an explicit module matches the given name, give the buffer
1554+ // back to the caller side.
1555+ *ModuleBuffer = std::move (moduleInfo.moduleBuffer );
1556+ return std::error_code ();
1557+ }
1558+
1559+ auto &fs = *Ctx.SourceMgr .getFileSystem ();
1560+ // Open .swiftmodule file
1561+ auto moduleBuf = fs.getBufferForFile (moduleInfo.modulePath );
1562+ if (!moduleBuf)
1563+ return moduleBuf.getError ();
1564+ *ModuleBuffer = std::move (moduleBuf.get ());
1565+
1566+ // Open .swiftdoc file
1567+ if (!moduleInfo.moduleDocPath .empty ()) {
1568+ auto moduleDocBuf = fs.getBufferForFile (moduleInfo.moduleDocPath );
1569+ if (moduleBuf)
1570+ *ModuleDocBuffer = std::move (moduleDocBuf.get ());
1571+ }
1572+ // Open .swiftsourceinfo file
1573+ if (!moduleInfo.moduleSourceInfoPath .empty ()) {
1574+ auto moduleSourceInfoBuf = fs.getBufferForFile (moduleInfo.moduleSourceInfoPath );
1575+ if (moduleSourceInfoBuf)
1576+ *ModuleSourceInfoBuffer = std::move (moduleSourceInfoBuf.get ());
1577+ }
14591578 return std::error_code ();
14601579}
14611580
@@ -1470,19 +1589,24 @@ std::unique_ptr<ExplicitSwiftModuleLoader>
14701589ExplicitSwiftModuleLoader::create (ASTContext &ctx,
14711590 DependencyTracker *tracker, ModuleLoadingMode loadMode,
14721591 ArrayRef<std::string> ExplicitModulePaths,
1592+ StringRef ExplicitSwiftModuleMap,
14731593 bool IgnoreSwiftSourceInfoFile) {
14741594 auto result = std::unique_ptr<ExplicitSwiftModuleLoader>(
14751595 new ExplicitSwiftModuleLoader (ctx, tracker, loadMode,
14761596 IgnoreSwiftSourceInfoFile));
14771597 auto &Impl = result->Impl ;
1598+ // Parse a JSON file to collect explicitly built modules.
1599+ Impl.parseSwiftExplicitModuleMap (ExplicitSwiftModuleMap);
1600+ // Collect .swiftmodule paths from -swift-module-path
1601+ // FIXME: remove these.
14781602 for (auto path: ExplicitModulePaths) {
14791603 std::string name;
14801604 // Load the explicit module into a buffer and get its name.
14811605 std::unique_ptr<llvm::MemoryBuffer> buffer = getModuleName (ctx, path, name);
14821606 if (buffer) {
14831607 // Register this module for future loading.
14841608 auto &entry = Impl.ExplicitModuleMap [name];
1485- entry.path = path;
1609+ entry.modulePath = path;
14861610 entry.moduleBuffer = std::move (buffer);
14871611 } else {
14881612 // We cannot read the module content, diagnose.
0 commit comments