Skip to content

Commit c9c0df2

Browse files
authored
[Driver] Address Brian G's feedback on 848b3eb. (#4046)
No functionality change.
1 parent 47898c5 commit c9c0df2

File tree

3 files changed

+77
-62
lines changed

3 files changed

+77
-62
lines changed

lib/Driver/Compilation.cpp

+64-49
Original file line numberDiff line numberDiff line change
@@ -464,57 +464,72 @@ int Compilation::performJobsImpl() {
464464
const CommandOutput &Output = FinishedCmd->getOutput();
465465
StringRef DependenciesFile =
466466
Output.getAdditionalOutputForType(types::TY_SwiftDeps);
467-
if (!DependenciesFile.empty() &&
468-
(ReturnCode == EXIT_SUCCESS || ReturnCode == EXIT_FAILURE)) {
469-
bool wasCascading = DepGraph.isMarked(FinishedCmd);
470467

471-
switch (DepGraph.loadFromPath(FinishedCmd, DependenciesFile)) {
472-
case DependencyGraphImpl::LoadResult::HadError:
473-
if (ReturnCode == EXIT_SUCCESS) {
474-
disableIncrementalBuild();
475-
for (const Job *Cmd : DeferredCommands)
476-
scheduleCommandIfNecessaryAndPossible(Cmd);
477-
DeferredCommands.clear();
478-
Dependents.clear();
479-
} // else, let the next build handle it.
480-
break;
481-
case DependencyGraphImpl::LoadResult::UpToDate:
482-
if (!wasCascading)
483-
break;
484-
SWIFT_FALLTHROUGH;
485-
case DependencyGraphImpl::LoadResult::AffectsDownstream:
486-
DepGraph.markTransitive(Dependents, FinishedCmd);
487-
break;
488-
}
468+
if (DependenciesFile.empty()) {
469+
// If this job doesn't track dependencies, it must always be run.
470+
// Note: In theory CheckDependencies makes sense as well (for a leaf
471+
// node in the dependency graph), and maybe even NewlyAdded (for very
472+
// coarse dependencies that always affect downstream nodes), but we're
473+
// not using either of those right now, and this logic should probably
474+
// be revisited when we are.
475+
assert(FinishedCmd->getCondition() == Job::Condition::Always);
489476
} else {
490-
// If there's a crash, assume the worst.
491-
switch (FinishedCmd->getCondition()) {
492-
case Job::Condition::NewlyAdded:
493-
// The job won't be treated as newly added next time. Conservatively
494-
// mark it as affecting other jobs, because some of them may have
495-
// completed already.
496-
DepGraph.markTransitive(Dependents, FinishedCmd);
497-
break;
498-
case Job::Condition::Always:
499-
// This applies to non-incremental tasks as well, but any incremental
500-
// task that shows up here has already been marked.
501-
break;
502-
case Job::Condition::RunWithoutCascading:
503-
// If this file changed, it might have been a non-cascading change and
504-
// it might not. Unfortunately, the interface hash has been updated or
505-
// compromised, so we don't actually know anymore; we have to
506-
// conservatively assume the changes could affect other files.
507-
DepGraph.markTransitive(Dependents, FinishedCmd);
508-
break;
509-
case Job::Condition::CheckDependencies:
510-
// If the only reason we're running this is because something else
511-
// changed, then we can trust the dependency graph as to whether it's
512-
// a cascading or non-cascading change. That is, if whatever /caused/
513-
// the error isn't supposed to affect other files, and whatever
514-
// /fixes/ the error isn't supposed to affect other files, then
515-
// there's no need to recompile any other inputs. If either of those
516-
// are false, we /do/ need to recompile other inputs.
517-
break;
477+
// If we have a dependency file /and/ the frontend task exited normally,
478+
// we can be discerning about what downstream files to rebuild.
479+
if (ReturnCode == EXIT_SUCCESS || ReturnCode == EXIT_FAILURE) {
480+
bool wasCascading = DepGraph.isMarked(FinishedCmd);
481+
482+
switch (DepGraph.loadFromPath(FinishedCmd, DependenciesFile)) {
483+
case DependencyGraphImpl::LoadResult::HadError:
484+
if (ReturnCode == EXIT_SUCCESS) {
485+
disableIncrementalBuild();
486+
for (const Job *Cmd : DeferredCommands)
487+
scheduleCommandIfNecessaryAndPossible(Cmd);
488+
DeferredCommands.clear();
489+
Dependents.clear();
490+
} // else, let the next build handle it.
491+
break;
492+
case DependencyGraphImpl::LoadResult::UpToDate:
493+
if (!wasCascading)
494+
break;
495+
SWIFT_FALLTHROUGH;
496+
case DependencyGraphImpl::LoadResult::AffectsDownstream:
497+
DepGraph.markTransitive(Dependents, FinishedCmd);
498+
break;
499+
}
500+
} else {
501+
// If there's an abnormal exit (a crash), assume the worst.
502+
switch (FinishedCmd->getCondition()) {
503+
case Job::Condition::NewlyAdded:
504+
// The job won't be treated as newly added next time. Conservatively
505+
// mark it as affecting other jobs, because some of them may have
506+
// completed already.
507+
DepGraph.markTransitive(Dependents, FinishedCmd);
508+
break;
509+
case Job::Condition::Always:
510+
// Any incremental task that shows up here has already been marked;
511+
// we didn't need to wait for it to finish to start downstream
512+
// tasks.
513+
assert(DepGraph.isMarked(FinishedCmd));
514+
break;
515+
case Job::Condition::RunWithoutCascading:
516+
// If this file changed, it might have been a non-cascading change
517+
// and it might not. Unfortunately, the interface hash has been
518+
// updated or compromised, so we don't actually know anymore; we
519+
// have to conservatively assume the changes could affect other
520+
// files.
521+
DepGraph.markTransitive(Dependents, FinishedCmd);
522+
break;
523+
case Job::Condition::CheckDependencies:
524+
// If the only reason we're running this is because something else
525+
// changed, then we can trust the dependency graph as to whether
526+
// it's a cascading or non-cascading change. That is, if whatever
527+
// /caused/ the error isn't supposed to affect other files, and
528+
// whatever /fixes/ the error isn't supposed to affect other files,
529+
// then there's no need to recompile any other inputs. If either of
530+
// those are false, we /do/ need to recompile other inputs.
531+
break;
532+
}
518533
}
519534
}
520535
}

lib/Driver/Driver.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -1612,20 +1612,13 @@ handleCompileJobCondition(Job *J, CompileJobAction::InputInfo inputInfo,
16121612
}
16131613

16141614
Job::Condition condition;
1615-
if (!hasValidModTime || J->getInputModTime() != inputInfo.previousModTime) {
1616-
if (alwaysRebuildDependents ||
1617-
inputInfo.status == CompileJobAction::InputInfo::NeedsCascadingBuild) {
1618-
condition = Job::Condition::Always;
1619-
} else {
1620-
condition = Job::Condition::RunWithoutCascading;
1621-
}
1622-
} else {
1615+
if (hasValidModTime && J->getInputModTime() == inputInfo.previousModTime) {
16231616
switch (inputInfo.status) {
16241617
case CompileJobAction::InputInfo::UpToDate:
1625-
if (!llvm::sys::fs::exists(J->getOutput().getPrimaryOutputFilename()))
1626-
condition = Job::Condition::RunWithoutCascading;
1627-
else
1618+
if (llvm::sys::fs::exists(J->getOutput().getPrimaryOutputFilename()))
16281619
condition = Job::Condition::CheckDependencies;
1620+
else
1621+
condition = Job::Condition::RunWithoutCascading;
16291622
break;
16301623
case CompileJobAction::InputInfo::NeedsCascadingBuild:
16311624
condition = Job::Condition::Always;
@@ -1636,6 +1629,13 @@ handleCompileJobCondition(Job *J, CompileJobAction::InputInfo inputInfo,
16361629
case CompileJobAction::InputInfo::NewlyAdded:
16371630
llvm_unreachable("handled above");
16381631
}
1632+
} else {
1633+
if (alwaysRebuildDependents ||
1634+
inputInfo.status == CompileJobAction::InputInfo::NeedsCascadingBuild) {
1635+
condition = Job::Condition::Always;
1636+
} else {
1637+
condition = Job::Condition::RunWithoutCascading;
1638+
}
16391639
}
16401640

16411641
J->setCondition(condition);

test/Driver/Dependencies/Inputs/update-dependencies-bad.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@
4444
else:
4545
sys.exit(129)
4646

47-
dir = os.path.dirname(os.path.abspath(__file__))
48-
execfile(os.path.join(dir, "update-dependencies.py"))
47+
execDir = os.path.dirname(os.path.abspath(__file__))
48+
execfile(os.path.join(execDir, "update-dependencies.py"))

0 commit comments

Comments
 (0)