Skip to content

Commit 044f85a

Browse files
committed
Add ModuleDepGraphFactory
This completes the missing piece from swiftlang#34073 and means the frontend may now serialize moduledecl-based dependencies.
1 parent 1b01f21 commit 044f85a

File tree

3 files changed

+117
-3
lines changed

3 files changed

+117
-3
lines changed

lib/AST/FrontendSourceFileDepGraphFactory.cpp

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,10 @@ bool fine_grained_dependencies::withReferenceDependencies(
241241
const DependencyTracker &depTracker, StringRef outputPath,
242242
bool alsoEmitDotFile,
243243
llvm::function_ref<bool(SourceFileDepGraph &&)> cont) {
244-
if (MSF.dyn_cast<ModuleDecl *>()) {
245-
llvm_unreachable("Cannot construct dependency graph for modules!");
244+
if (auto *MD = MSF.dyn_cast<ModuleDecl *>()) {
245+
SourceFileDepGraph g =
246+
ModuleDepGraphFactory(MD, alsoEmitDotFile).construct();
247+
return cont(std::move(g));
246248
} else {
247249
auto *SF = MSF.get<SourceFile *>();
248250
SourceFileDepGraph g = FrontendSourceFileDepGraphFactory(
@@ -632,3 +634,75 @@ FrontendSourceFileDepGraphFactory::getFingerprintIfAny(const Decl *d) {
632634
}
633635
return None;
634636
}
637+
638+
//==============================================================================
639+
// MARK: ModuleDepGraphFactory
640+
//==============================================================================
641+
642+
ModuleDepGraphFactory::ModuleDepGraphFactory(ModuleDecl *Mod, bool emitDot)
643+
: AbstractSourceFileDepGraphFactory(
644+
/*include private*/ true, Mod->getASTContext().hadError(),
645+
Mod->getNameStr(), "0xBADBEEF", emitDot, Mod->getASTContext().Diags),
646+
Mod(Mod) {}
647+
648+
void ModuleDepGraphFactory::addAllDefinedDecls() {
649+
// TODO: express the multiple provides and depends streams with variadic
650+
// templates
651+
652+
// Many kinds of Decls become top-level depends.
653+
654+
SmallVector<Decl *, 32> TopLevelDecls;
655+
Mod->getTopLevelDecls(TopLevelDecls);
656+
DeclFinder declFinder(TopLevelDecls, includePrivateDeps,
657+
[this](VisibleDeclConsumer &consumer) {
658+
return Mod->lookupClassMembers({}, consumer);
659+
});
660+
661+
addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(
662+
declFinder.precedenceGroups);
663+
addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(
664+
declFinder.memberOperatorDecls);
665+
addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.operators);
666+
addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.topNominals);
667+
addAllDefinedDeclsOfAGivenType<NodeKind::topLevel>(declFinder.topValues);
668+
addAllDefinedDeclsOfAGivenType<NodeKind::nominal>(declFinder.allNominals);
669+
addAllDefinedDeclsOfAGivenType<NodeKind::potentialMember>(
670+
declFinder.potentialMemberHolders);
671+
addAllDefinedDeclsOfAGivenType<NodeKind::member>(
672+
declFinder.valuesInExtensions);
673+
addAllDefinedDeclsOfAGivenType<NodeKind::dynamicLookup>(
674+
declFinder.classMembers);
675+
}
676+
677+
/// Given an array of Decls or pairs of them in \p declsOrPairs
678+
/// create node pairs for context and name
679+
template <NodeKind kind, typename ContentsT>
680+
void ModuleDepGraphFactory::addAllDefinedDeclsOfAGivenType(
681+
std::vector<ContentsT> &contentsVec) {
682+
for (const auto &declOrPair : contentsVec) {
683+
Optional<std::string> fp = getFingerprintIfAny(declOrPair);
684+
addADefinedDecl(
685+
DependencyKey::createForProvidedEntityInterface<kind>(declOrPair),
686+
fp ? StringRef(fp.getValue()) : Optional<StringRef>());
687+
}
688+
}
689+
690+
//==============================================================================
691+
// MARK: ModuleDepGraphFactory - adding individual defined Decls
692+
//==============================================================================
693+
694+
/// At present, only \c NominalTypeDecls have (body) fingerprints
695+
Optional<std::string> ModuleDepGraphFactory::getFingerprintIfAny(
696+
std::pair<const NominalTypeDecl *, const ValueDecl *>) {
697+
return None;
698+
}
699+
Optional<std::string>
700+
ModuleDepGraphFactory::getFingerprintIfAny(const Decl *d) {
701+
if (const auto *idc = dyn_cast<IterableDeclContext>(d)) {
702+
auto result = idc->getBodyFingerprint();
703+
assert((!result || !result->empty()) &&
704+
"Fingerprint should never be empty");
705+
return result;
706+
}
707+
return None;
708+
}

lib/AST/FrontendSourceFileDepGraphFactory.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ class FrontendSourceFileDepGraphFactory
5454
static Optional<std::string> getFingerprintIfAny(const Decl *d);
5555
};
5656

57+
class ModuleDepGraphFactory : public AbstractSourceFileDepGraphFactory {
58+
ModuleDecl *const Mod;
59+
60+
public:
61+
ModuleDepGraphFactory(ModuleDecl *Mod, bool emitDot);
62+
63+
~ModuleDepGraphFactory() override = default;
64+
65+
private:
66+
void addAllDefinedDecls() override;
67+
void addAllUsedDecls() override {}
68+
69+
/// Given an array of Decls or pairs of them in \p declsOrPairs
70+
/// create node pairs for context and name
71+
template <NodeKind kind, typename ContentsT>
72+
void addAllDefinedDeclsOfAGivenType(std::vector<ContentsT> &contentsVec);
73+
74+
/// At present, only nominals, protocols, and extensions have (body)
75+
/// fingerprints
76+
static Optional<std::string> getFingerprintIfAny(
77+
std::pair<const NominalTypeDecl *, const ValueDecl *>);
78+
static Optional<std::string> getFingerprintIfAny(const Decl *d);
79+
};
80+
5781
} // namespace fine_grained_dependencies
5882
} // namespace swift
5983

lib/FrontendTool/FrontendTool.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2292,7 +2292,23 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
22922292

22932293
SerializationOptions serializationOpts =
22942294
Invocation.computeSerializationOptions(outs, Instance.getMainModule());
2295-
serialize(MSF, serializationOpts, SM.get());
2295+
if (serializationOpts.ExperimentalCrossModuleIncrementalInfo) {
2296+
const auto alsoEmitDotFile =
2297+
Instance.getInvocation()
2298+
.getLangOptions()
2299+
.EmitFineGrainedDependencySourcefileDotFiles;
2300+
2301+
using SourceFileDepGraph = fine_grained_dependencies::SourceFileDepGraph;
2302+
auto *Mod = MSF.get<ModuleDecl *>();
2303+
fine_grained_dependencies::withReferenceDependencies(
2304+
Mod, *Instance.getDependencyTracker(), Mod->getModuleFilename(),
2305+
alsoEmitDotFile, [](SourceFileDepGraph &&g) {
2306+
serialize(MSF, serializationOpts, SM.get(), &g);
2307+
return false;
2308+
});
2309+
} else {
2310+
serialize(MSF, serializationOpts, SM.get());
2311+
}
22962312
};
22972313

22982314
// Set the serialization action, so that the SIL module

0 commit comments

Comments
 (0)