Skip to content

Commit 8e8d195

Browse files
author
David Ungar
authored
Merge pull request #29722 from davidungar/unit-test-users-v2
[NFC Incremental] Small changes to fine-grained unit test framework
2 parents 68f3341 + 3ac5ceb commit 8e8d195

File tree

5 files changed

+171
-97
lines changed

5 files changed

+171
-97
lines changed

include/swift/AST/FineGrainedDependencies.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,8 @@ class SourceFileDepGraphNode : public DepGraphNode {
721721
}
722722

723723
std::string humanReadableName() const {
724-
return DepGraphNode::humanReadableName("here");
724+
return DepGraphNode::humanReadableName(getIsProvides() ? "here"
725+
: "somewhere else");
725726
}
726727

727728
bool verify() const {
@@ -883,6 +884,8 @@ class SourceFileDepGraph {
883884

884885
bool verifySequenceNumber() const;
885886

887+
void emitDotFile(StringRef outputPath, DiagnosticEngine &diags);
888+
886889
private:
887890
void addNode(SourceFileDepGraphNode *n) {
888891
n->setSequenceNumber(allNodes.size());

include/swift/Driver/FineGrainedDependencyDriverGraph.h

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class ModuleDepGraphNode : public DepGraphNode {
123123
return DepGraphNode::humanReadableName(where);
124124
}
125125

126+
void dump(raw_ostream &) const;
127+
126128
SWIFT_DEBUG_DUMP;
127129
};
128130

@@ -312,9 +314,11 @@ class ModuleDepGraph {
312314
}
313315

314316
/// For unit tests.
315-
ModuleDepGraph(const bool EnableTypeFingerprints)
316-
: ModuleDepGraph(true, false, EnableTypeFingerprints, false, nullptr) {}
317-
317+
ModuleDepGraph(const bool EnableTypeFingerprints,
318+
const bool EmitDotFilesForDebugging = false)
319+
: ModuleDepGraph(
320+
true, /*emitFineGrainedDependencyDotFileAfterEveryImport=*/
321+
EmitDotFilesForDebugging, EnableTypeFingerprints, false, nullptr) {}
318322

319323
//============================================================================
320324
// MARK: ModuleDepGraph - updating from a switdeps file
@@ -328,26 +332,27 @@ class ModuleDepGraph {
328332
/// compensates.
329333
Changes loadFromPath(const driver::Job *, StringRef, DiagnosticEngine &);
330334

331-
332335
Changes loadFromSourceFileDepGraph(const driver::Job *cmd,
333-
const SourceFileDepGraph &);
336+
const SourceFileDepGraph &,
337+
DiagnosticEngine &);
334338

335-
/// Also for unit tests
336-
Changes
337-
simulateLoad(const driver::Job *cmd,
338-
llvm::StringMap<std::vector<std::string>> simpleNames,
339-
llvm::StringMap<std::vector<std::pair<std::string, std::string>>>
340-
compoundNames = {},
341-
const bool includePrivateDeps = false,
342-
const bool hadCompilationError = false);
339+
/// Also for unit tests
340+
Changes
341+
simulateLoad(const driver::Job *cmd,
342+
llvm::StringMap<std::vector<std::string>> simpleNames,
343+
llvm::StringMap<std::vector<std::pair<std::string, std::string>>>
344+
compoundNames = {},
345+
const bool includePrivateDeps = false,
346+
const bool hadCompilationError = false);
343347

344348

345349
private:
346350
/// Read a SourceFileDepGraph belonging to \p job from \p buffer
347351
/// and integrate it into the ModuleDepGraph.
348352
/// Used both the first time, and to reload the SourceFileDepGraph.
349353
/// If any changes were observed, indicate same in the return vale.
350-
Changes loadFromBuffer(const driver::Job *, llvm::MemoryBuffer &);
354+
Changes loadFromBuffer(const driver::Job *, llvm::MemoryBuffer &,
355+
DiagnosticEngine &);
351356

352357
/// Integrate a SourceFileDepGraph into the receiver.
353358
/// Integration happens when the driver needs to read SourceFileDepGraph.
@@ -365,8 +370,9 @@ class ModuleDepGraph {
365370
const SourceFileDepGraphNode *integrand) const;
366371

367372
/// Integrate the \p integrand into the receiver.
368-
/// Return the changed node if any..
369-
NullablePtr<ModuleDepGraphNode>
373+
/// If an illegal value was found, return \c None, otherwise
374+
/// return the changed node if any..
375+
Optional<NullablePtr<ModuleDepGraphNode>>
370376
integrateSourceFileDepGraphNode(const SourceFileDepGraph &g,
371377
const SourceFileDepGraphNode *integrand,
372378
const PreexistingNodeIfAny preexistingMatch,
@@ -392,6 +398,12 @@ class ModuleDepGraph {
392398
/// After importing a provides node from the frontend, record its
393399
/// dependencies.
394400
/// Return true if moduleUseNode picks up a new external-dependency
401+
///
402+
/// \param g The source file graph being integrated into the module graph
403+
/// \param sourceFileUseNode The source file node just integrated, which may
404+
/// also be a use (i.e. a "depends", a declaration used by something else)
405+
/// \param moduleUseNode The module file node corresponding to the \c
406+
/// sourceFileUseNode
395407
bool recordWhatUseDependsUpon(const SourceFileDepGraph &g,
396408
const SourceFileDepGraphNode *sourceFileUseNode,
397409
ModuleDepGraphNode *moduleUseNode);
@@ -486,17 +498,8 @@ class ModuleDepGraph {
486498

487499
bool haveAnyNodesBeenTraversedIn(const driver::Job *) const;
488500

489-
/// Given a "cascading" job, that is a job whose dependents must be recompiled
490-
/// when this job is recompiled, Compute two sets of jobs:
491-
/// 1. Return value (via visited) is the set of jobs needing recompilation
492-
/// after this one, and
493-
/// 2. Jobs not previously known to need dependencies reexamined after they
494-
/// are recompiled.
495-
///
496-
/// Returns jobs to be run because of changes to any/ever node in the
497-
/// argument. Only return jobs marked that were previously unmarked, assuming
498-
/// previously marked jobs are already scheduled.
499-
/// TODO: rewrite above comment
501+
/// Find all jobs (possibly including the argument) requiring recompilation
502+
/// assuming that every entity in \p jobToBeRecompiled has changed.
500503
std::vector<const driver::Job *>
501504
findJobsToRecompileWhenWholeJobChanges(const driver::Job *jobToBeRecompiled);
502505

lib/AST/FineGrainedDependencies.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@
1515
#include "swift/AST/FineGrainedDependencies.h"
1616

1717
// may not all be needed
18+
#include "swift/AST/DiagnosticEngine.h"
19+
#include "swift/AST/DiagnosticsCommon.h"
20+
#include "swift/AST/DiagnosticsFrontend.h"
21+
#include "swift/AST/FileSystem.h"
1822
#include "swift/Basic/FileSystem.h"
1923
#include "swift/Basic/LLVM.h"
2024
#include "swift/Demangling/Demangle.h"
2125
#include "swift/Frontend/FrontendOptions.h"
26+
2227
#include "llvm/ADT/MapVector.h"
2328
#include "llvm/ADT/SetVector.h"
2429
#include "llvm/ADT/SmallVector.h"
@@ -34,6 +39,28 @@
3439
using namespace swift;
3540
using namespace fine_grained_dependencies;
3641

42+
//==============================================================================
43+
// MARK: Emitting and reading SourceFileDepGraph
44+
//==============================================================================
45+
46+
Optional<SourceFileDepGraph> SourceFileDepGraph::loadFromPath(StringRef path) {
47+
auto bufferOrError = llvm::MemoryBuffer::getFile(path);
48+
if (!bufferOrError)
49+
return None;
50+
return loadFromBuffer(*bufferOrError.get());
51+
}
52+
53+
Optional<SourceFileDepGraph>
54+
SourceFileDepGraph::loadFromBuffer(llvm::MemoryBuffer &buffer) {
55+
SourceFileDepGraph fg;
56+
llvm::yaml::Input yamlReader(llvm::MemoryBufferRef(buffer), nullptr);
57+
yamlReader >> fg;
58+
if (yamlReader.error())
59+
return None;
60+
// return fg; compiles for Mac but not Linux, because it cannot be copied.
61+
return Optional<SourceFileDepGraph>(std::move(fg));
62+
}
63+
3764
//==============================================================================
3865
// MARK: SourceFileDepGraph access
3966
//==============================================================================
@@ -229,6 +256,23 @@ raw_ostream &fine_grained_dependencies::operator<<(raw_ostream &out,
229256
bool DependencyKey::verify() const {
230257
assert((getKind() != NodeKind::externalDepend || isInterface()) &&
231258
"All external dependencies must be interfaces.");
259+
switch (getKind()) {
260+
case NodeKind::topLevel:
261+
case NodeKind::dynamicLookup:
262+
case NodeKind::externalDepend:
263+
case NodeKind::sourceFileProvide:
264+
assert(context.empty() && !name.empty() && "Must only have a name");
265+
break;
266+
case NodeKind::nominal:
267+
case NodeKind::potentialMember:
268+
assert(!context.empty() && name.empty() && "Must only have a context");
269+
break;
270+
case NodeKind::member:
271+
assert(!context.empty() && !name.empty() && "Must have both");
272+
break;
273+
case NodeKind::kindCount:
274+
llvm_unreachable("impossible");
275+
}
232276
return true;
233277
}
234278

@@ -300,6 +344,15 @@ void SourceFileDepGraph::verifySame(const SourceFileDepGraph &other) const {
300344
#endif
301345
}
302346

347+
void SourceFileDepGraph::emitDotFile(StringRef outputPath,
348+
DiagnosticEngine &diags) {
349+
std::string dotFileName = outputPath.str() + ".dot";
350+
withOutputFile(diags, dotFileName, [&](llvm::raw_pwrite_stream &out) {
351+
DotFileEmitter<SourceFileDepGraph>(out, *this, false, false).emit();
352+
return false;
353+
});
354+
}
355+
303356
//==============================================================================
304357
// MARK: SourceFileDepGraph YAML reading & writing
305358
//==============================================================================

lib/AST/SourceFileDepGraphConstructor.cpp

Lines changed: 29 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -46,32 +46,6 @@
4646
using namespace swift;
4747
using namespace fine_grained_dependencies;
4848

49-
//==============================================================================
50-
// MARK: Emitting and reading SourceFileDepGraph
51-
//==============================================================================
52-
53-
Optional<SourceFileDepGraph> SourceFileDepGraph::loadFromPath(StringRef path) {
54-
auto bufferOrError = llvm::MemoryBuffer::getFile(path);
55-
if (!bufferOrError)
56-
return None;
57-
return loadFromBuffer(*bufferOrError.get());
58-
}
59-
60-
Optional<SourceFileDepGraph>
61-
SourceFileDepGraph::loadFromBuffer(llvm::MemoryBuffer &buffer) {
62-
SourceFileDepGraph fg;
63-
llvm::yaml::Input yamlReader(llvm::MemoryBufferRef(buffer), nullptr);
64-
yamlReader >> fg;
65-
if (yamlReader.error())
66-
return None;
67-
// return fg; compiles for Mac but not Linux, because it cannot be copied.
68-
return Optional<SourceFileDepGraph>(std::move(fg));
69-
}
70-
71-
//==============================================================================
72-
// MARK: Start of SourceFileDepGraph building, specific to status quo
73-
//==============================================================================
74-
7549
//==============================================================================
7650
// MARK: Helpers for key construction that must be in frontend
7751
//==============================================================================
@@ -501,7 +475,7 @@ class SourceFileDepGraphConstructor {
501475
/// a flag indicating if the member is private to its enclosing file, and
502476
/// a flag indicating if the dependency cascades.
503477
const std::vector<std::pair<std::tuple<std::string, std::string, bool>, bool>>
504-
memberDepends;
478+
dependsWithContexts;
505479

506480
/// The base name of a class member depended-upon for dynamic lookup, and a
507481
/// cascades flag.
@@ -534,7 +508,8 @@ class SourceFileDepGraphConstructor {
534508
bool hadCompilationError,
535509
const std::string &interfaceHash,
536510
ArrayRef<std::pair<std::string, bool>> topLevelDepends,
537-
ArrayRef<std::pair<std::tuple<std::string, std::string, bool>, bool>> memberDepends,
511+
ArrayRef<std::pair<std::tuple<std::string, std::string, bool>, bool>>
512+
dependsWithContexts,
538513
ArrayRef<std::pair<std::string, bool>> dynamicLookupDepends,
539514
ArrayRef<std::string> externalDependencies,
540515

@@ -554,7 +529,7 @@ class SourceFileDepGraphConstructor {
554529

555530
interfaceHash(interfaceHash),
556531
topLevelDepends(topLevelDepends),
557-
memberDepends(memberDepends),
532+
dependsWithContexts(dependsWithContexts),
558533
dynamicLookupDepends(dynamicLookupDepends),
559534
externalDependencies(externalDependencies),
560535

@@ -569,11 +544,15 @@ class SourceFileDepGraphConstructor {
569544
classMembers(classMembers)
570545
{}
571546

572-
SourceFileDepGraphConstructor static forSourceFile(SourceFile *SF,
573-
const DependencyTracker &depTracker,
574-
StringRef swiftDeps,
575-
const bool includePrivateDeps,
576-
const bool hadCompilationError) {
547+
// clang-format off
548+
static SourceFileDepGraphConstructor
549+
forSourceFile(
550+
SourceFile *SF,
551+
const DependencyTracker &depTracker,
552+
StringRef swiftDeps,
553+
const bool includePrivateDeps,
554+
const bool hadCompilationError) {
555+
// clang-format on
577556

578557
SourceFileDeclFinder declFinder(SF, includePrivateDeps);
579558
std::vector<std::pair<std::string, bool>> topLevelDepends;
@@ -584,11 +563,11 @@ class SourceFileDepGraphConstructor {
584563
for (const auto &p: SF->getReferencedNameTracker()->getDynamicLookupNames())
585564
dynamicLookupDepends.push_back(std::make_pair(p.getFirst().userFacingName(), p.getSecond()));
586565

587-
std::vector<std::pair<std::tuple<std::string, std::string, bool>, bool>> memberDepends;
566+
std::vector<std::pair<std::tuple<std::string, std::string, bool>, bool>> dependsWithContexts;
588567
for (const auto &p: SF->getReferencedNameTracker()->getUsedMembers()) {
589568
const auto &member = p.getFirst().second;
590569
StringRef emptyOrUserFacingName = member.empty() ? "" : member.userFacingName();
591-
memberDepends.push_back(
570+
dependsWithContexts.push_back(
592571
std::make_pair(
593572
std::make_tuple(
594573
mangleTypeAsContext(p.getFirst().first),
@@ -604,7 +583,7 @@ class SourceFileDepGraphConstructor {
604583

605584
getInterfaceHash(SF),
606585
topLevelDepends,
607-
memberDepends,
586+
dependsWithContexts,
608587
dynamicLookupDepends,
609588
depTracker.getDependencies(),
610589

@@ -782,7 +761,7 @@ void SourceFileDepGraphConstructor::addDependencyArcsToGraph() {
782761
// TODO: express the multiple provides and depends streams with variadic
783762
// templates
784763
addAllDependenciesFrom<NodeKind::topLevel>(topLevelDepends);
785-
addAllDependenciesFrom(memberDepends);
764+
addAllDependenciesFrom(dependsWithContexts);
786765
addAllDependenciesFrom<NodeKind::dynamicLookup>(dynamicLookupDepends);
787766
addAllDependenciesFrom(externalDependencies);
788767
}
@@ -798,7 +777,7 @@ void SourceFileDepGraphConstructor::recordThatThisWholeFileDependsOn(
798777
// Entry point from the Frontend to this whole system
799778
//==============================================================================
800779

801-
bool swift::fine_grained_dependencies::emitReferenceDependencies(
780+
bool fine_grained_dependencies::emitReferenceDependencies(
802781
DiagnosticEngine &diags, SourceFile *const SF,
803782
const DependencyTracker &depTracker, StringRef outputPath,
804783
const bool alsoEmitDotFile) {
@@ -814,8 +793,9 @@ bool swift::fine_grained_dependencies::emitReferenceDependencies(
814793
// we force the inclusion of private declarations when fingerprints
815794
// are enabled.
816795
const bool includeIntrafileDeps =
817-
SF->getASTContext().LangOpts.FineGrainedDependenciesIncludeIntrafileOnes ||
818-
SF->getASTContext().LangOpts.EnableTypeFingerprints;
796+
SF->getASTContext()
797+
.LangOpts.FineGrainedDependenciesIncludeIntrafileOnes ||
798+
SF->getASTContext().LangOpts.EnableTypeFingerprints;
819799
const bool hadCompilationError = SF->getASTContext().hadError();
820800
auto gc = SourceFileDepGraphConstructor::forSourceFile(
821801
SF, depTracker, outputPath, includeIntrafileDeps, hadCompilationError);
@@ -832,13 +812,9 @@ bool swift::fine_grained_dependencies::emitReferenceDependencies(
832812
// If path is stdout, cannot read it back, so check for "-"
833813
assert(outputPath == "-" || g.verifyReadsWhatIsWritten(outputPath));
834814

835-
if (alsoEmitDotFile) {
836-
std::string dotFileName = outputPath.str() + ".dot";
837-
withOutputFile(diags, dotFileName, [&](llvm::raw_pwrite_stream &out) {
838-
DotFileEmitter<SourceFileDepGraph>(out, g, false, false).emit();
839-
return false;
840-
});
841-
}
815+
if (alsoEmitDotFile)
816+
g.emitDotFile(outputPath, diags);
817+
842818
return hadError;
843819
}
844820

@@ -952,7 +928,10 @@ SourceFileDepGraph SourceFileDepGraph::simulateLoad(
952928

953929
// clang-format off
954930
SourceFileDepGraphConstructor c(
955-
swiftDepsFilename, includePrivateDeps, hadCompilationError, interfaceHash,
931+
swiftDepsFilename,
932+
includePrivateDeps,
933+
hadCompilationError,
934+
interfaceHash,
956935
getSimpleDepends(simpleNamesByRDK[dependsTopLevel]),
957936
getCompoundDepends(simpleNamesByRDK[dependsNominal],
958937
compoundNamesByRDK[dependsMember]),
@@ -961,7 +940,7 @@ SourceFileDepGraph SourceFileDepGraph::simulateLoad(
961940
{}, // precedence groups
962941
{}, // memberOperatorDecls
963942
{}, // operators
964-
getMangledHolderProvides(simpleNamesByRDK[providesNominal]), // topNominals
943+
{}, // topNominals
965944
getBaseNameProvides(simpleNamesByRDK[providesTopLevel]), // topValues
966945
getMangledHolderProvides(simpleNamesByRDK[providesNominal]), // allNominals
967946
getMangledHolderProvides(simpleNamesByRDK[providesNominal]), // potentialMemberHolders

0 commit comments

Comments
 (0)