AST: Introduce ModuleDecl::ImportFilter::ForLinking

ModuleDecl::forAllVisibleModules() now has a includeLinkOnlyModules
parameter. This is intended to be used when computing the set of
libraries to autolink.
This commit is contained in:
Slava Pestov
2018-04-26 22:00:30 -07:00
parent 753967411a
commit cfa0ab3dbe
5 changed files with 77 additions and 12 deletions

View File

@@ -345,9 +345,17 @@ public:
/// \sa getImportedModules
enum class ImportFilter {
// Everything.
All,
// @_exported only.
Public,
Private
// Not @_exported only. Also includes @_usableFromInline.
Private,
// @_usableFromInline and @_exported only.
ForLinking
};
/// Looks up which modules are imported by this module.
@@ -360,11 +368,16 @@ public:
/// Looks up which modules are imported by this module, ignoring any that
/// won't contain top-level decls.
///
/// This is a performance hack. Do not use for anything but name lookup.
/// May go away in the future.
/// This is a performance hack for the ClangImporter. Do not use for
/// anything but name lookup. May go away in the future.
void
getImportedModulesForLookup(SmallVectorImpl<ImportedModule> &imports) const;
/// Extension of the above hack. Identical to getImportedModulesForLookup()
/// for imported modules, otherwise also includes @usableFromInline imports.
void
getImportedModulesForLinking(SmallVectorImpl<ImportedModule> &imports) const;
/// Finds all top-level decls of this module.
///
/// This does a simple local lookup, not recursively looking through imports.
@@ -402,11 +415,16 @@ public:
/// results, with the given access path.
/// \param fn A callback of type bool(ImportedModule) or void(ImportedModule).
/// Return \c false to abort iteration.
/// \param includeLinkOnlyModules Include modules that are not visible to
/// name lookup but must be linked in because inlinable code can
/// reference their symbols.
///
/// \return True if the traversal ran to completion, false if it ended early
/// due to the callback.
bool forAllVisibleModules(AccessPathTy topLevelAccessPath,
llvm::function_ref<bool(ImportedModule)> fn);
llvm::function_ref<bool(ImportedModule)> fn,
bool includeLinkOnlyModules = false);
/// @}
@@ -638,6 +656,12 @@ public:
return getImportedModules(imports, ModuleDecl::ImportFilter::Public);
}
/// \see ModuleDecl::getImportedModulesForLinking
virtual void getImportedModulesForLinking(
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const {
return getImportedModules(imports, ModuleDecl::ImportFilter::ForLinking);
}
/// Generates the list of libraries needed to link this file, based on its
/// imports.
virtual void
@@ -649,11 +673,15 @@ public:
///
/// \param fn A callback of type bool(ImportedModule) or void(ImportedModule).
/// Return \c false to abort iteration.
/// \param includeLinkOnlyModules Include modules that are not visible to
/// name lookup but must be linked in because inlinable code can
/// reference their symbols.
///
/// \return True if the traversal ran to completion, false if it ended early
/// due to the callback.
bool
forAllVisibleModules(llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn);
forAllVisibleModules(llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn,
bool includeLinkOnlyModules = false);
/// @}

View File

@@ -97,6 +97,12 @@ public:
virtual void getImportedModulesForLookup(
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const override;
virtual void getImportedModulesForLinking(
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const override {
// In C, anything that's linkable is visible to the source language.
return getImportedModulesForLookup(imports);
}
virtual void
collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const override;

View File

@@ -974,6 +974,11 @@ SourceFile::getImportedModules(SmallVectorImpl<ModuleDecl::ImportedModule> &modu
if (importPair.second.contains(ImportFlags::Exported))
continue;
break;
case ModuleDecl::ImportFilter::ForLinking:
if (!importPair.second.contains(ImportFlags::UsableFromInline) &&
!importPair.second.contains(ImportFlags::Exported))
continue;
break;
}
modules.push_back(importPair.first);
@@ -985,6 +990,11 @@ void ModuleDecl::getImportedModulesForLookup(
FORWARD(getImportedModulesForLookup, (modules));
}
void ModuleDecl::getImportedModulesForLinking(
SmallVectorImpl<ImportedModule> &modules) const {
FORWARD(getImportedModulesForLinking, (modules));
}
bool ModuleDecl::isSameAccessPath(AccessPathTy lhs, AccessPathTy rhs) {
using AccessPathElem = std::pair<Identifier, SourceLoc>;
if (lhs.size() != rhs.size())
@@ -1128,10 +1138,14 @@ bool ModuleDecl::isSystemModule() const {
}
bool ModuleDecl::forAllVisibleModules(AccessPathTy thisPath,
llvm::function_ref<bool(ImportedModule)> fn) {
llvm::function_ref<bool(ImportedModule)> fn,
bool includeLinkOnlyModules) {
llvm::SmallSet<ImportedModule, 32, ModuleDecl::OrderImportedModules> visited;
SmallVector<ImportedModule, 32> stack;
if (includeLinkOnlyModules)
getImportedModules(stack, ModuleDecl::ImportFilter::ForLinking);
else
getImportedModules(stack, ModuleDecl::ImportFilter::Public);
// Make sure the top-level module is first; we want pre-order-ish traversal.
@@ -1158,6 +1172,9 @@ bool ModuleDecl::forAllVisibleModules(AccessPathTy thisPath,
if (!fn(next))
return false;
if (includeLinkOnlyModules)
next.second->getImportedModulesForLinking(stack);
else
next.second->getImportedModulesForLookup(stack);
}
@@ -1165,8 +1182,10 @@ bool ModuleDecl::forAllVisibleModules(AccessPathTy thisPath,
}
bool FileUnit::forAllVisibleModules(
llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn) {
if (!getParentModule()->forAllVisibleModules(ModuleDecl::AccessPathTy(), fn))
llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn,
bool includeLinkOnlyModules) {
if (!getParentModule()->forAllVisibleModules(ModuleDecl::AccessPathTy(), fn,
includeLinkOnlyModules))
return false;
if (auto SF = dyn_cast<SourceFile>(this)) {
@@ -1175,7 +1194,8 @@ bool FileUnit::forAllVisibleModules(
SmallVector<ModuleDecl::ImportedModule, 4> imports;
SF->getImportedModules(imports, ModuleDecl::ImportFilter::Private);
for (auto importPair : imports)
if (!importPair.second->forAllVisibleModules(importPair.first, fn))
if (!importPair.second->forAllVisibleModules(importPair.first, fn,
includeLinkOnlyModules))
return false;
}
@@ -1198,7 +1218,8 @@ SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const
next->collectLinkLibraries(callback);
return true;
});
},
/*includeLinkOnlyModules=*/true);
}
bool ModuleDecl::walk(ASTWalker &Walker) {

View File

@@ -3049,6 +3049,7 @@ void ClangModuleUnit::getImportedModules(
imports.push_back({ModuleDecl::AccessPathTy(), owner.getStdlibModule()});
break;
case ModuleDecl::ImportFilter::Public:
case ModuleDecl::ImportFilter::ForLinking:
break;
}
@@ -3058,6 +3059,7 @@ void ClangModuleUnit::getImportedModules(
switch (filter) {
case ModuleDecl::ImportFilter::All:
case ModuleDecl::ImportFilter::Public:
case ModuleDecl::ImportFilter::ForLinking:
imported.append(owner.ImportedHeaderExports.begin(),
owner.ImportedHeaderExports.end());
break;
@@ -3106,6 +3108,7 @@ void ClangModuleUnit::getImportedModules(
}
case ModuleDecl::ImportFilter::Public:
case ModuleDecl::ImportFilter::ForLinking:
break;
}
}

View File

@@ -1598,6 +1598,13 @@ void ModuleFile::getImportedModules(
continue;
break;
case ModuleDecl::ImportFilter::ForLinking:
// FIXME
if (!dep.isExported())
continue;
break;
}
assert(dep.isLoaded());