Skip to content

Commit d43dc84

Browse files
author
David Ungar
authored
Merge pull request swiftlang#29126 from davidungar/fine-grained-fixes-rb2-w-dbg
[Incremental] Dependency fixes in preparation for fine-grained dependencies
2 parents d623bb9 + 631c2d4 commit d43dc84

19 files changed

+877
-370
lines changed

include/swift/AST/FineGrainedDependencies.h

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ class BiIndexedTwoStageMap {
325325
/// Write out the .swiftdeps file for a frontend compilation of a primary file.
326326
bool emitReferenceDependencies(DiagnosticEngine &diags, SourceFile *SF,
327327
const DependencyTracker &depTracker,
328-
StringRef outputPath);
328+
StringRef outputPath, bool alsoEmitDotFile);
329329
//==============================================================================
330330
// MARK: Enums
331331
//==============================================================================
@@ -438,8 +438,8 @@ class DependencyKey {
438438
name() {}
439439

440440
/// For constructing a key in the frontend.
441-
DependencyKey(NodeKind kind, DeclAspect aspect, std::string context,
442-
std::string name)
441+
DependencyKey(NodeKind kind, DeclAspect aspect, const std::string &context,
442+
const std::string &name)
443443
: kind(kind), aspect(aspect), context(context), name(name) {
444444
assert(verify());
445445
}
@@ -449,7 +449,7 @@ class DependencyKey {
449449
StringRef getContext() const { return context; }
450450
StringRef getName() const { return name; }
451451

452-
StringRef getSwiftDepsFromSourceFileProvide() const {
452+
StringRef getSwiftDepsFromASourceFileProvideNodeKey() const {
453453
assert(getKind() == NodeKind::sourceFileProvide &&
454454
"Receiver must be sourceFileProvide.");
455455
return getName();
@@ -494,11 +494,19 @@ class DependencyKey {
494494
static std::string computeNameForProvidedEntity(Entity);
495495

496496
/// Given some type of depended-upon entity create the key.
497-
template <NodeKind kind, typename Entity>
498-
static DependencyKey createDependedUponKey(const Entity &);
497+
static DependencyKey createDependedUponKey(StringRef mangledHolderName,
498+
StringRef memberBaseName);
499+
500+
template <NodeKind kind>
501+
static DependencyKey createDependedUponKey(StringRef);
502+
503+
static DependencyKey
504+
createTransitiveKeyForWholeSourceFile(StringRef swiftDeps);
499505

500506
std::string humanReadableName() const;
501507

508+
StringRef aspectName() const { return DeclAspectNames[size_t(aspect)]; }
509+
502510
void dump(llvm::raw_ostream &os) const { os << asString() << "\n"; }
503511
SWIFT_DEBUG_DUMP { dump(llvm::errs()); }
504512

@@ -535,6 +543,13 @@ struct std::hash<typename swift::fine_grained_dependencies::DeclAspect> {
535543
}
536544
};
537545

546+
namespace swift {
547+
namespace fine_grained_dependencies {
548+
using ContextNameFingerprint =
549+
std::tuple<std::string, std::string, Optional<std::string>>;
550+
}
551+
} // namespace swift
552+
538553
//==============================================================================
539554
// MARK: DepGraphNode
540555
//==============================================================================
@@ -684,6 +699,9 @@ class SourceFileDepGraphNode : public DepGraphNode {
684699
}
685700

686701
/// Record the sequence number, \p n, of another use.
702+
/// The relationship between an interface and its implementation is NOT
703+
/// included here. See \c
704+
/// SourceFileDepGraph::findExistingNodePairOrCreateAndAddIfNew.
687705
void addDefIDependUpon(size_t n) {
688706
if (n != getSequenceNumber())
689707
defsIDependUpon.insert(n);
@@ -696,8 +714,29 @@ class SourceFileDepGraphNode : public DepGraphNode {
696714
bool verify() const {
697715
DepGraphNode::verify();
698716
assert(getIsProvides() || isDepends());
717+
assert(verifySequenceNumber());
699718
return true;
700719
}
720+
721+
bool verifySequenceNumber() const {
722+
const auto &k = getKey();
723+
if (k.getKind() != NodeKind::sourceFileProvide)
724+
return true;
725+
switch (k.getAspect()) {
726+
case DeclAspect::interface:
727+
assert(getSequenceNumber() == sourceFileProvidesInterfaceSequenceNumber);
728+
return true;
729+
case DeclAspect::implementation:
730+
assert(getSequenceNumber() ==
731+
sourceFileProvidesImplementationSequenceNumber);
732+
return true;
733+
default:
734+
llvm_unreachable("neither interface nor implementation");
735+
}
736+
}
737+
static constexpr const size_t sourceFileProvidesInterfaceSequenceNumber = 0;
738+
static constexpr const size_t sourceFileProvidesImplementationSequenceNumber =
739+
1;
701740
};
702741

703742
//==============================================================================
@@ -727,6 +766,25 @@ class SourceFileDepGraph {
727766
SourceFileDepGraph(const SourceFileDepGraph &g) = delete;
728767
SourceFileDepGraph(SourceFileDepGraph &&g) = default;
729768

769+
/// Simulate loading for unit testing:
770+
/// \param swiftDepsFileName The name of the swiftdeps file of the phony job
771+
/// \param includePrivateDeps Whether the graph includes intra-file arcs
772+
/// \param hadCompilationError Simulate a compilation error
773+
/// \param interfaceHash The interface hash of the simulated graph
774+
/// \param simpleNamesByRDK A map of vectors of names keyed by reference
775+
/// dependency key \param compoundNamesByRDK A map of (mangledHolder,
776+
/// baseName) pairs keyed by reference dependency key. For single-name
777+
/// dependencies, an initial underscore indicates that the name does not
778+
/// cascade. For compound names, it is the first name, the holder which
779+
/// indicates non-cascading. For member names, an initial underscore indicates
780+
/// file-privacy.
781+
static SourceFileDepGraph
782+
simulateLoad(std::string swiftDepsFileName, const bool includePrivateDeps,
783+
const bool hadCompilationError, std::string interfaceHash,
784+
llvm::StringMap<std::vector<std::string>> simpleNamesByRDK,
785+
llvm::StringMap<std::vector<std::pair<std::string, std::string>>>
786+
compoundNamesByRDK);
787+
730788
/// Nodes are owned by the graph.
731789
~SourceFileDepGraph() {
732790
forEachNode([&](SourceFileDepGraphNode *n) { delete n; });
@@ -746,7 +804,7 @@ class SourceFileDepGraph {
746804
InterfaceAndImplementationPair<SourceFileDepGraphNode>
747805
getSourceFileNodePair() const;
748806

749-
StringRef getSwiftDepsFromSourceFileProvide() const;
807+
StringRef getSwiftDepsOfJobThatProducedThisGraph() const;
750808

751809
std::string getGraphID() const {
752810
return getSourceFileNodePair().getInterface()->getKey().humanReadableName();
@@ -770,12 +828,13 @@ class SourceFileDepGraph {
770828
/// The frontend creates a pair of nodes for every tracked Decl and the source
771829
/// file itself.
772830
InterfaceAndImplementationPair<SourceFileDepGraphNode>
773-
findExistingNodePairOrCreateAndAddIfNew(NodeKind k, StringRef context,
774-
StringRef name,
775-
Optional<std::string> fingerprint);
831+
findExistingNodePairOrCreateAndAddIfNew(
832+
NodeKind k, const ContextNameFingerprint &contextNameFingerprint);
776833

777-
SourceFileDepGraphNode *findExistingNodeOrCreateIfNew(
778-
DependencyKey key, Optional<std::string> fingerprint, bool isProvides);
834+
SourceFileDepGraphNode *
835+
findExistingNodeOrCreateIfNew(DependencyKey key,
836+
const Optional<std::string> &fingerprint,
837+
bool isProvides);
779838

780839
/// \p Use is the Node that must be rebuilt when \p def changes.
781840
/// Record that fact in the graph.
@@ -800,14 +859,14 @@ class SourceFileDepGraph {
800859
/// Ensure that when read, the graph is the same as what was written.
801860
bool verifyReadsWhatIsWritten(StringRef path) const;
802861

862+
bool verifySequenceNumber() const;
863+
803864
private:
804865
void addNode(SourceFileDepGraphNode *n) {
805866
n->setSequenceNumber(allNodes.size());
806-
assert(allNodes.size() < 2 ==
807-
(n->getKey().getKind() == NodeKind::sourceFileProvide) &&
808-
"First two and only first two nodes should be sourceFileProvide "
809-
"nodes.");
810867
allNodes.push_back(n);
868+
assert(n->verifySequenceNumber() &&
869+
"Certain nodes must be in certain places");
811870
}
812871
};
813872

@@ -892,7 +951,7 @@ template <typename GraphT> class DotFileEmitter {
892951
}
893952
void emitArcs() {
894953
g.forEachArc([&](const NodeT *def, const NodeT *use) {
895-
if (includeGraphArc(use, def))
954+
if (includeGraphArc(def, use))
896955
emitGraphArc(def, use);
897956
});
898957
}

include/swift/Basic/LangOptions.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,14 @@ namespace swift {
285285
/// Whether to verify the parsed syntax tree and emit related diagnostics.
286286
bool VerifySyntaxTree = false;
287287

288-
/// Scaffolding to permit experimentation with finer-grained dependencies
289-
/// and faster rebuilds.
288+
/// Emit the newer, finer-grained swiftdeps file. Eventually will support
289+
/// faster rebuilds.
290290
bool EnableFineGrainedDependencies = false;
291-
291+
292+
/// When using fine-grained dependencies, emit dot files for every swiftdeps
293+
/// file.
294+
bool EmitFineGrainedDependencySourcefileDotFiles = false;
295+
292296
/// To mimic existing system, set to false.
293297
/// To experiment with including file-private and private dependency info,
294298
/// set to true.

include/swift/Driver/Action.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,23 @@ class CompileJobAction : public JobAction {
168168
static bool classof(const Action *A) {
169169
return A->getKind() == Action::Kind::CompileJob;
170170
}
171+
172+
/// Return a _single_ TY_Swift InputAction, if one exists;
173+
/// if 0 or >1 such inputs exist, return nullptr.
174+
const InputAction *findSingleSwiftInput() const {
175+
auto Inputs = getInputs();
176+
auto isSwiftInput = [](const Action *A) -> const InputAction* {
177+
if (auto const *S = dyn_cast<InputAction>(A))
178+
return S->getType() == file_types::TY_Swift ? S : nullptr;
179+
return nullptr;
180+
};
181+
const auto loc1 = std::find_if(Inputs.begin(), Inputs.end(), isSwiftInput);
182+
if (loc1 == Inputs.end())
183+
return nullptr; // none found
184+
// Ensure uniqueness
185+
const auto loc2 = std::find_if(loc1 + 1, Inputs.end(), isSwiftInput);
186+
return loc2 == Inputs.end() ? dyn_cast<InputAction>(*loc1) : nullptr;
187+
}
171188
};
172189

173190
class InterpretJobAction : public JobAction {

include/swift/Driver/Compilation.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,18 @@ class Compilation {
521521
/// How many .swift input files?
522522
unsigned countSwiftInputs() const;
523523

524+
/// Unfortunately the success or failure of a Swift compilation is currently
525+
/// sensitive to the order in which files are processed, at least in terms of
526+
/// the order of processing extensions (and likely other ways we haven't
527+
/// discovered yet). So long as this is true, we need to make sure any batch
528+
/// job we build names its inputs in an order that's a subsequence of the
529+
/// sequence of inputs the driver was initially invoked with.
530+
///
531+
/// Also use to write out information in a consistent order.
532+
void sortJobsToMatchCompilationInputs(
533+
ArrayRef<const Job *> unsortedJobs,
534+
SmallVectorImpl<const Job *> &sortedJobs) const;
535+
524536
private:
525537
/// Perform all jobs.
526538
///

0 commit comments

Comments
 (0)