Skip to content

Commit b6c5830

Browse files
committed
[Request-evaluator] Add GraphViz output option -output-request-graphviz.
Introduce a command-line option to visualize the complete set of output request dependencies evaluated by a particular compile action. This is exposing existing visualization facilities to the (-frontend) command line.
1 parent 833cd01 commit b6c5830

File tree

6 files changed

+34
-2
lines changed

6 files changed

+34
-2
lines changed

include/swift/Frontend/FrontendOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ class FrontendOptions {
7070
/// The path to which we should store indexing data, if any.
7171
std::string IndexStorePath;
7272

73+
/// The path to which we should emit GraphViz output for the complete
74+
/// request-evaluator graph.
75+
std::string RequestEvaluatorGraphVizPath;
76+
7377
/// Emit index data for imported serialized swift system modules.
7478
bool IndexSystemModules = false;
7579

include/swift/Option/FrontendOptions.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ def debug_forbid_typecheck_prefix : Separate<["-"], "debug-forbid-typecheck-pref
169169

170170
def debug_cycles : Flag<["-"], "debug-cycles">,
171171
HelpText<"Print out debug dumps when cycles are detected in evaluation">;
172+
def output_request_graphviz : Separate<["-"], "output-request-graphviz">,
173+
HelpText<"Emit GraphViz output visualizing the request graph">;
172174

173175
def debug_time_compilation : Flag<["-"], "debug-time-compilation">,
174176
HelpText<"Prints the time taken by each compilation phase">;

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ bool ArgsToFrontendOptionsConverter::convert(
6060
if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
6161
Opts.IndexStorePath = A->getValue();
6262
}
63+
if (const Arg *A = Args.getLastArg(OPT_output_request_graphviz)) {
64+
Opts.RequestEvaluatorGraphVizPath = A->getValue();
65+
}
66+
6367
Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);
6468

6569
Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);

lib/FrontendTool/FrontendTool.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,13 @@ emitIndexData(CompilerInvocation &Invocation, CompilerInstance &Instance) {
855855
return hadEmitIndexDataError;
856856
}
857857

858+
/// Emits the request-evaluator graph to the given file in GraphViz format.
859+
void emitRequestEvaluatorGraphViz(ASTContext &ctx, StringRef graphVizPath) {
860+
std::error_code error;
861+
llvm::raw_fd_ostream out(graphVizPath, error, llvm::sys::fs::F_Text);
862+
ctx.evaluator.printDependenciesGraphviz(out);
863+
}
864+
858865
static bool performCompileStepsPostSILGen(
859866
CompilerInstance &Instance, CompilerInvocation &Invocation,
860867
std::unique_ptr<SILModule> SM, bool astGuaranteedToCorrespondToSIL,
@@ -894,6 +901,17 @@ static bool performCompile(CompilerInstance &Instance,
894901
else
895902
Instance.performSema();
896903

904+
SWIFT_DEFER {
905+
// Emit request-evaluator graph via GraphViz, if requested.
906+
if (!Invocation.getFrontendOptions().RequestEvaluatorGraphVizPath.empty() &&
907+
Instance.hasASTContext()) {
908+
ASTContext &ctx = Instance.getASTContext();
909+
emitRequestEvaluatorGraphViz(
910+
ctx,
911+
Invocation.getFrontendOptions().RequestEvaluatorGraphVizPath);
912+
}
913+
};
914+
897915
if (Action == FrontendOptions::ActionType::Parse)
898916
return Instance.getASTContext().hadError();
899917

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,4 +702,4 @@ SerializedASTFile::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
702702
Identifier discriminator = File.getDiscriminatorForPrivateValue(D);
703703
assert(!discriminator.empty() && "no discriminator found for value");
704704
return discriminator;
705-
}
705+
}

test/decl/class/circular_inheritance.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-typecheck-verify-swift
2-
// RUN: not %target-swift-frontend -typecheck -debug-cycles %s 2> %t.cycles
2+
// RUN: not %target-swift-frontend -typecheck -debug-cycles %s -output-request-graphviz %t.dot 2> %t.cycles
33
// RUN: %FileCheck %s < %t.cycles
4+
// RUN: %FileCheck -check-prefix CHECK-DOT %s < %t.dot
45

56
class C : B { } // expected-error{{circular class inheritance 'C' -> 'B' -> 'A' -> 'C'}}
67
class B : A { } // expected-note{{class 'B' declared here}}
@@ -46,3 +47,6 @@ class Outer3
4647
// CHECK-NEXT: `--{{.*}}SuperclassTypeRequest
4748
// CHECK-NEXT: `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Right@
4849
// CHECK-NEXT: `--{{.*}}SuperclassTypeRequest{{.*(cyclic dependency)}}
50+
51+
// CHECK-DOT: digraph Dependencies
52+
// CHECK-DOT: label="InheritedTypeRequest

0 commit comments

Comments
 (0)