Skip to content

Commit 71ec06e

Browse files
committed
Cache visible Clang modules for interface printing in 'ModuleDecl'
Instead of caching the collection of visible Clang modules in the 'TypePrinter', compute and cache them in the 'ModuleDecl'. When printing a textual interface, the compiler will instantiate many new instances of 'TypePrinter', which means caching them there is not useful.
1 parent 5dbf31a commit 71ec06e

File tree

3 files changed

+63
-56
lines changed

3 files changed

+63
-56
lines changed

include/swift/AST/Module.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/Support/ErrorHandling.h"
4040
#include "llvm/Support/MD5.h"
4141
#include <optional>
42+
#include <unordered_map>
4243
#include <set>
4344

4445
namespace clang {
@@ -537,6 +538,11 @@ class ModuleDecl
537538
std::optional<std::pair<ModuleDecl *, Identifier>>
538539
declaringModuleAndBystander;
539540

541+
/// A cache of this module's visible Clang modules
542+
/// parameterized by the Swift interface print mode.
543+
using VisibleClangModuleSet = llvm::DenseMap<const clang::Module *, ModuleDecl *>;
544+
std::unordered_map<PrintOptions::InterfaceMode, VisibleClangModuleSet> CachedVisibleClangModuleSet;
545+
540546
/// If this module is an underscored cross import overlay, gets the underlying
541547
/// module that declared it (which may itself be a cross-import overlay),
542548
/// along with the name of the required bystander module. Used by tooling to
@@ -578,6 +584,14 @@ class ModuleDecl
578584
bool getRequiredBystandersIfCrossImportOverlay(
579585
ModuleDecl *declaring, SmallVectorImpl<Identifier> &bystanderNames);
580586

587+
/// Computes all Clang modules that are visible from this moule.
588+
/// This includes any modules that are imported transitively through public
589+
/// (`@_exported`) imports.
590+
///
591+
/// The computed map associates each visible Clang module with the
592+
/// corresponding Swift module.
593+
const VisibleClangModuleSet &
594+
getVisibleClangModules(PrintOptions::InterfaceMode contentMode);
581595

582596
/// Walks and loads the declared, underscored cross-import overlays of this
583597
/// module and its underlying clang module, transitively, to find all cross

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5724,8 +5724,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
57245724

57255725
ASTPrinter &Printer;
57265726
const PrintOptions &Options;
5727-
std::optional<llvm::DenseMap<const clang::Module *, ModuleDecl *>>
5728-
VisibleClangModules;
57295727

57305728
void printGenericArgs(ArrayRef<Type> flatArgs) {
57315729
Printer << "<";
@@ -5799,56 +5797,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
57995797
return T->hasSimpleTypeRepr();
58005798
}
58015799

5802-
/// Computes the map that is cached by `getVisibleClangModules()`.
5803-
/// Do not call directly.
5804-
llvm::DenseMap<const clang::Module *, ModuleDecl *>
5805-
computeVisibleClangModules() {
5806-
assert(Options.CurrentModule &&
5807-
"CurrentModule needs to be set to determine imported Clang modules");
5808-
5809-
llvm::DenseMap<const clang::Module *, ModuleDecl *> Result;
5810-
5811-
// For the current module, consider both private and public imports.
5812-
ModuleDecl::ImportFilter Filter = ModuleDecl::ImportFilterKind::Exported;
5813-
Filter |= ModuleDecl::ImportFilterKind::Default;
5814-
5815-
// For private or package swiftinterfaces, also look through @_spiOnly imports.
5816-
if (!Options.printPublicInterface())
5817-
Filter |= ModuleDecl::ImportFilterKind::SPIOnly;
5818-
// Consider package import for package interface
5819-
if (Options.printPackageInterface())
5820-
Filter |= ModuleDecl::ImportFilterKind::PackageOnly;
5821-
5822-
SmallVector<ImportedModule, 4> Imports;
5823-
Options.CurrentModule->getImportedModules(Imports, Filter);
5824-
5825-
SmallVector<ModuleDecl *, 4> ModulesToProcess;
5826-
for (const auto &Import : Imports) {
5827-
ModulesToProcess.push_back(Import.importedModule);
5828-
}
5829-
5830-
SmallPtrSet<ModuleDecl *, 4> Processed;
5831-
while (!ModulesToProcess.empty()) {
5832-
ModuleDecl *Mod = ModulesToProcess.back();
5833-
ModulesToProcess.pop_back();
5834-
5835-
if (!Processed.insert(Mod).second)
5836-
continue;
5837-
5838-
if (const clang::Module *ClangModule = Mod->findUnderlyingClangModule())
5839-
Result[ClangModule] = Mod;
5840-
5841-
// For transitive imports, consider only public imports.
5842-
Imports.clear();
5843-
Mod->getImportedModules(Imports, ModuleDecl::ImportFilterKind::Exported);
5844-
for (const auto &Import : Imports) {
5845-
ModulesToProcess.push_back(Import.importedModule);
5846-
}
5847-
}
5848-
5849-
return Result;
5850-
}
5851-
58525800
/// Returns all Clang modules that are visible from `Options.CurrentModule`.
58535801
/// This includes any modules that are imported transitively through public
58545802
/// (`@_exported`) imports.
@@ -5857,10 +5805,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
58575805
/// corresponding Swift module.
58585806
const llvm::DenseMap<const clang::Module *, ModuleDecl *> &
58595807
getVisibleClangModules() {
5860-
if (!VisibleClangModules) {
5861-
VisibleClangModules = computeVisibleClangModules();
5862-
}
5863-
return *VisibleClangModules;
5808+
return Options.CurrentModule->getVisibleClangModules(Options.InterfaceContentKind);
58645809
}
58655810

58665811
template <typename T>

lib/AST/Module.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,54 @@ void ModuleDecl::getMissingImportedModules(
17191719
FORWARD(getMissingImportedModules, (imports));
17201720
}
17211721

1722+
const llvm::DenseMap<const clang::Module *, ModuleDecl *> &
1723+
ModuleDecl::getVisibleClangModules(PrintOptions::InterfaceMode contentMode) {
1724+
if (CachedVisibleClangModuleSet.find(contentMode) != CachedVisibleClangModuleSet.end())
1725+
return CachedVisibleClangModuleSet[contentMode];
1726+
else
1727+
CachedVisibleClangModuleSet.emplace(contentMode, VisibleClangModuleSet{});
1728+
VisibleClangModuleSet &result = CachedVisibleClangModuleSet[contentMode];
1729+
1730+
// For the current module, consider both private and public imports.
1731+
ModuleDecl::ImportFilter Filter = ModuleDecl::ImportFilterKind::Exported;
1732+
Filter |= ModuleDecl::ImportFilterKind::Default;
1733+
1734+
// For private or package swiftinterfaces, also look through @_spiOnly imports.
1735+
if (contentMode != PrintOptions::InterfaceMode::Public)
1736+
Filter |= ModuleDecl::ImportFilterKind::SPIOnly;
1737+
// Consider package import for package interface
1738+
if (contentMode == PrintOptions::InterfaceMode::Package)
1739+
Filter |= ModuleDecl::ImportFilterKind::PackageOnly;
1740+
1741+
SmallVector<ImportedModule, 32> Imports;
1742+
getImportedModules(Imports, Filter);
1743+
1744+
SmallVector<ModuleDecl *, 32> ModulesToProcess;
1745+
for (const auto &Import : Imports)
1746+
ModulesToProcess.push_back(Import.importedModule);
1747+
1748+
SmallPtrSet<ModuleDecl *, 32> Processed;
1749+
while (!ModulesToProcess.empty()) {
1750+
ModuleDecl *Mod = ModulesToProcess.back();
1751+
ModulesToProcess.pop_back();
1752+
1753+
if (!Processed.insert(Mod).second)
1754+
continue;
1755+
1756+
if (const clang::Module *ClangModule = Mod->findUnderlyingClangModule())
1757+
result[ClangModule] = Mod;
1758+
1759+
// For transitive imports, consider only public imports.
1760+
Imports.clear();
1761+
Mod->getImportedModules(Imports, ModuleDecl::ImportFilterKind::Exported);
1762+
for (const auto &Import : Imports) {
1763+
ModulesToProcess.push_back(Import.importedModule);
1764+
}
1765+
}
1766+
1767+
return result;
1768+
}
1769+
17221770
void
17231771
SourceFile::getImportedModules(SmallVectorImpl<ImportedModule> &modules,
17241772
ModuleDecl::ImportFilter filter) const {

0 commit comments

Comments
 (0)