Skip to content

Commit b06211e

Browse files
committed
Initial plumbing for private dependencies
Add a mode bit to the dependency collector that respects the frontend flag in the previous commit. Notably, we now write over the dependency files at the end of the compiler pipeline when this flag is on so that dependency from SILGen and IRGen are properly written to disk.
1 parent a42fa19 commit b06211e

27 files changed

+1150
-16
lines changed

include/swift/AST/Evaluator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ class Evaluator {
245245
/// diagnostics through the given diagnostics engine.
246246
Evaluator(DiagnosticEngine &diags,
247247
bool debugDumpCycles,
248-
bool buildDependencyGraph);
248+
bool buildDependencyGraph,
249+
bool enableExperimentalPrivateDeps);
249250

250251
/// Emit GraphViz output visualizing the request graph.
251252
void emitRequestEvaluatorGraphViz(llvm::StringRef graphVizPath);

include/swift/AST/EvaluatorDependencies.h

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,22 @@ struct DependencyCollector {
113113
llvm::SmallVector<evaluator::DependencySource, 8> dependencySources;
114114

115115
public:
116-
DependencyCollector() = default;
116+
enum class Mode {
117+
// Enables the current "status quo" behavior of the dependency collector.
118+
//
119+
// By default, the dependency collector moves to register dependencies in
120+
// the referenced name trackers at the top of the active dependency stack.
121+
StatusQuo,
122+
// Enables an experimental mode to only register private dependencies.
123+
//
124+
// This mode restricts the dependency collector to ignore changes of
125+
// scope. This has practical effect of charging all unqualified lookups to
126+
// the primary file being acted upon instead of to the destination file.
127+
ExperimentalPrivateDependencies,
128+
};
129+
Mode mode;
130+
131+
explicit DependencyCollector(Mode mode) : mode{mode} {};
117132

118133
public:
119134
/// Registers a named reference from the current dependency scope to a member
@@ -206,19 +221,43 @@ struct DependencyCollector {
206221
};
207222

208223
private:
224+
/// Returns the first dependency source registered with the tracker, or
225+
/// \c nullptr if no dependency sources have been registered.
226+
SourceFile *getFirstDependencySourceOrNull() const {
227+
if (dependencySources.empty())
228+
return nullptr;
229+
return dependencySources.front().getPointer();
230+
}
231+
209232
/// If there is an active dependency source, returns its
210233
/// \c ReferencedNameTracker. Else, returns \c nullptr.
211234
ReferencedNameTracker *getActiveDependencyTracker() const {
212-
if (auto *source = getActiveDependencySourceOrNull())
213-
return source->getRequestBasedReferencedNameTracker();
214-
return nullptr;
235+
SourceFile *source = nullptr;
236+
switch (mode) {
237+
case Mode::StatusQuo:
238+
source = getActiveDependencySourceOrNull();
239+
break;
240+
case Mode::ExperimentalPrivateDependencies:
241+
source = getFirstDependencySourceOrNull();
242+
break;
243+
}
244+
245+
if (!source)
246+
return nullptr;
247+
248+
return source->getRequestBasedReferencedNameTracker();
215249
}
216250

217251
/// Returns \c true if the scope of the current active source cascades.
218252
///
219253
/// If there is no active scope, the result always cascades.
220254
bool isActiveSourceCascading() const {
221-
return getActiveSourceScope() == evaluator::DependencyScope::Cascading;
255+
switch (mode) {
256+
case Mode::StatusQuo:
257+
return getActiveSourceScope() == evaluator::DependencyScope::Cascading;
258+
case Mode::ExperimentalPrivateDependencies:
259+
return false;
260+
}
222261
}
223262
};
224263
} // end namespace evaluator

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,8 @@ ASTContext::ASTContext(LangOptions &langOpts, TypeCheckerOptions &typeckOpts,
552552
SearchPathOpts(SearchPathOpts), SourceMgr(SourceMgr), Diags(Diags),
553553
evaluator(Diags,
554554
langOpts.DebugDumpCycles,
555-
langOpts.BuildRequestDependencyGraph),
555+
langOpts.BuildRequestDependencyGraph,
556+
langOpts.EnableExperientalPrivateIntransitiveDependencies),
556557
TheBuiltinModule(createBuiltinModule(*this)),
557558
StdlibModuleName(getIdentifier(STDLIB_NAME)),
558559
SwiftShimsModuleName(getIdentifier(SWIFT_SHIMS_NAME)),

lib/AST/Evaluator.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,22 @@ void Evaluator::registerRequestFunctions(
6060
requestFunctionsByZone.push_back({zoneID, functions});
6161
}
6262

63-
Evaluator::Evaluator(DiagnosticEngine &diags,
64-
bool debugDumpCycles,
65-
bool buildDependencyGraph)
66-
: diags(diags),
67-
debugDumpCycles(debugDumpCycles),
68-
buildDependencyGraph(buildDependencyGraph) { }
63+
static evaluator::DependencyCollector::Mode
64+
computeDependencyModeFromFlags(bool enableExperimentalPrivateDeps) {
65+
using Mode = evaluator::DependencyCollector::Mode;
66+
if (enableExperimentalPrivateDeps) {
67+
return Mode::ExperimentalPrivateDependencies;
68+
}
69+
return Mode::StatusQuo;
70+
}
71+
72+
Evaluator::Evaluator(DiagnosticEngine &diags, bool debugDumpCycles,
73+
bool buildDependencyGraph,
74+
bool enableExperimentalPrivateDeps)
75+
: diags(diags), debugDumpCycles(debugDumpCycles),
76+
buildDependencyGraph(buildDependencyGraph),
77+
collector{computeDependencyModeFromFlags(enableExperimentalPrivateDeps)} {
78+
}
6979

7080
void Evaluator::emitRequestEvaluatorGraphViz(llvm::StringRef graphVizPath) {
7181
std::error_code error;

lib/Driver/ToolChains.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,9 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
250250
options::OPT_enable_experimental_concise_pound_file);
251251
inputArgs.AddLastArg(arguments,
252252
options::OPT_verify_incremental_dependencies);
253-
253+
inputArgs.AddLastArg(arguments,
254+
options::OPT_experimental_private_intransitive_dependencies);
255+
254256
// Pass on any build config options
255257
inputArgs.AddAllArgs(arguments, options::OPT_D);
256258

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
434434
if (Args.hasArg(OPT_enable_experimental_additive_arithmetic_derivation))
435435
Opts.EnableExperimentalAdditiveArithmeticDerivedConformances = true;
436436

437+
if (Args.hasArg(OPT_experimental_private_intransitive_dependencies))
438+
Opts.EnableExperientalPrivateIntransitiveDependencies = true;
439+
437440
Opts.EnableExperimentalForwardModeDifferentiation |=
438441
Args.hasArg(OPT_enable_experimental_forward_mode_differentiation);
439442

lib/FrontendTool/FrontendTool.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,6 +2184,14 @@ int swift::performFrontend(ArrayRef<const char *> Args,
21842184
Invocation.getFrontendOptions().DumpAPIPath);
21852185
}
21862186

2187+
// If we're asked to enable private intransitive dependencies, we need to
2188+
// write over the dependency files we just emitted because we need to
2189+
// get the dependencies written post-Sema down on disk.
2190+
// FIXME: Evaluate the impact turning this on universally has.
2191+
if (Invocation.getLangOptions().EnableExperientalPrivateIntransitiveDependencies) {
2192+
emitReferenceDependenciesForAllPrimaryInputsIfNeeded(*Instance);
2193+
}
2194+
21872195
// Verify reference dependencies of the current compilation job *before*
21882196
// verifying diagnostics so that the former can be tested via the latter.
21892197
if (Invocation.getFrontendOptions().EnableIncrementalDependencyVerifier) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
protocol IntMaker {}
2+
extension IntMaker {
3+
func make() -> Int { return 0 }
4+
}
5+
6+
protocol DoubleMaker {}
7+
extension DoubleMaker {
8+
func make() -> Double { return 0 }
9+
}
10+
11+
12+
#if OLD
13+
typealias InterestingType = Int
14+
typealias InterestingProto = IntMaker
15+
16+
#elseif NEW
17+
typealias InterestingType = Double
18+
typealias InterestingProto = DoubleMaker
19+
20+
#else
21+
typealias InterestingType = ErrorMustSetOLDOrNew
22+
23+
#endif
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// REQUIRES: shell
2+
// Also uses awk:
3+
// XFAIL OS=windows
4+
5+
// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main -experimental-private-intransitive-dependencies | %FileCheck %s -check-prefix=CHECK-OLD
6+
// RUN: %S/../../Inputs/process_fine_grained_swiftdeps.sh <%t.swiftdeps >%t-processed.swiftdeps
7+
// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t-processed.swiftdeps
8+
9+
// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main -experimental-private-intransitive-dependencies | %FileCheck %s -check-prefix=CHECK-NEW
10+
// RUN: %S/../../Inputs/process_fine_grained_swiftdeps.sh <%t.swiftdeps >%t-processed.swiftdeps
11+
// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t-processed.swiftdeps
12+
13+
private func testParamType(_: InterestingType) {}
14+
15+
// CHECK-OLD: sil_global hidden @$s4main1x{{[^ ]+}} : ${{(@[a-zA-Z_]+ )?}}(Int) -> ()
16+
// CHECK-NEW: sil_global hidden @$s4main1x{{[^ ]+}} : ${{(@[a-zA-Z_]+ )?}}(Double) -> ()
17+
internal var x = testParamType
18+
19+
// CHECK-DEPS: topLevel interface '' InterestingType false
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// REQUIRES: shell
2+
// Also uses awk:
3+
// XFAIL OS=windows
4+
5+
// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main -experimental-private-intransitive-dependencies | %FileCheck %s -check-prefix=CHECK-OLD
6+
// RUN: %S/../../Inputs/process_fine_grained_swiftdeps.sh <%t.swiftdeps >%t-processed.swiftdeps
7+
// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t-processed.swiftdeps
8+
9+
// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main -experimental-private-intransitive-dependencies | %FileCheck %s -check-prefix=CHECK-NEW
10+
// RUN: %S/../../Inputs/process_fine_grained_swiftdeps.sh <%t.swiftdeps >%t-processed.swiftdeps
11+
// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t-processed.swiftdeps
12+
13+
private func testReturnType() -> InterestingType { fatalError() }
14+
15+
// CHECK-OLD: sil_global @$s4main1x{{[^ ]+}} : $Int
16+
// CHECK-NEW: sil_global @$s4main1x{{[^ ]+}} : $Double
17+
public var x = testReturnType() + 0
18+
19+
// CHECK-DEPS: topLevel interface '' InterestingType false

0 commit comments

Comments
 (0)