Skip to content

Commit cc89dad

Browse files
author
David Ungar
committed
Fine-grained and driver fixes.
Restructure fine-grained-dependencies to enable unit testing Get frontend to emit correct swiftdeps file (fine-grained when needed) and only emit dot file for -emit-fine-grained-dependency-sourcefile-dot-files Use deterministic order for more information outputs. Set EnableFineGrainedDependencies consistently in frontend. Tolerate errors that result in null getExtendedNominal() Fix memory issue by removing node everywhere. Break up print routine Be more verbose so it will compile on Linux. Sort batchable jobs, too.
1 parent 0d87a14 commit cc89dad

18 files changed

+828
-347
lines changed

include/swift/AST/FineGrainedDependencies.h

Lines changed: 51 additions & 13 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);
@@ -727,6 +745,25 @@ class SourceFileDepGraph {
727745
SourceFileDepGraph(const SourceFileDepGraph &g) = delete;
728746
SourceFileDepGraph(SourceFileDepGraph &&g) = default;
729747

748+
/// Simulate loading for unit testing:
749+
/// \param swiftDepsFileName The name of the swiftdeps file of the phony job
750+
/// \param includePrivateDeps Whether the graph includes intra-file arcs
751+
/// \param hadCompilationError Simulate a compilation error
752+
/// \param interfaceHash The interface hash of the simulated graph
753+
/// \param simpleNamesByRDK A map of vectors of names keyed by reference
754+
/// dependency key \param compoundNamesByRDK A map of (mangledHolder,
755+
/// baseName) pairs keyed by reference dependency key. For single-name
756+
/// dependencies, an initial underscore indicates that the name does not
757+
/// cascade. For compound names, it is the first name, the holder which
758+
/// indicates non-cascading. For member names, an initial underscore indicates
759+
/// file-privacy.
760+
static SourceFileDepGraph
761+
simulateLoad(std::string swiftDepsFileName, const bool includePrivateDeps,
762+
const bool hadCompilationError, std::string interfaceHash,
763+
llvm::StringMap<std::vector<std::string>> simpleNamesByRDK,
764+
llvm::StringMap<std::vector<std::pair<std::string, std::string>>>
765+
compoundNamesByRDK);
766+
730767
/// Nodes are owned by the graph.
731768
~SourceFileDepGraph() {
732769
forEachNode([&](SourceFileDepGraphNode *n) { delete n; });
@@ -746,7 +783,7 @@ class SourceFileDepGraph {
746783
InterfaceAndImplementationPair<SourceFileDepGraphNode>
747784
getSourceFileNodePair() const;
748785

749-
StringRef getSwiftDepsFromSourceFileProvide() const;
786+
StringRef getSwiftDepsOfJobThatProducedThisGraph() const;
750787

751788
std::string getGraphID() const {
752789
return getSourceFileNodePair().getInterface()->getKey().humanReadableName();
@@ -770,12 +807,13 @@ class SourceFileDepGraph {
770807
/// The frontend creates a pair of nodes for every tracked Decl and the source
771808
/// file itself.
772809
InterfaceAndImplementationPair<SourceFileDepGraphNode>
773-
findExistingNodePairOrCreateAndAddIfNew(NodeKind k, StringRef context,
774-
StringRef name,
775-
Optional<std::string> fingerprint);
810+
findExistingNodePairOrCreateAndAddIfNew(
811+
NodeKind k, const ContextNameFingerprint &contextNameFingerprint);
776812

777-
SourceFileDepGraphNode *findExistingNodeOrCreateIfNew(
778-
DependencyKey key, Optional<std::string> fingerprint, bool isProvides);
813+
SourceFileDepGraphNode *
814+
findExistingNodeOrCreateIfNew(DependencyKey key,
815+
const Optional<std::string> &fingerprint,
816+
bool isProvides);
779817

780818
/// \p Use is the Node that must be rebuilt when \p def changes.
781819
/// Record that fact in the graph.
@@ -892,7 +930,7 @@ template <typename GraphT> class DotFileEmitter {
892930
}
893931
void emitArcs() {
894932
g.forEachArc([&](const NodeT *def, const NodeT *use) {
895-
if (includeGraphArc(use, def))
933+
if (includeGraphArc(def, use))
896934
emitGraphArc(def, use);
897935
});
898936
}

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)