Skip to content

Commit 1c2e9e0

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 c129356 commit 1c2e9e0

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
@@ -5725,8 +5725,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
57255725

57265726
ASTPrinter &Printer;
57275727
const PrintOptions &Options;
5728-
std::optional<llvm::DenseMap<const clang::Module *, ModuleDecl *>>
5729-
VisibleClangModules;
57305728

57315729
void printGenericArgs(ArrayRef<Type> flatArgs) {
57325730
Printer << "<";
@@ -5800,56 +5798,6 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
58005798
return T->hasSimpleTypeRepr();
58015799
}
58025800

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

58675812
template <typename T>

lib/AST/Module.cpp

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

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

0 commit comments

Comments
 (0)