Skip to content

[Request-evaluator] Add GraphViz output option -output-request-graphviz. #17391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ Types
KNOWN-TYPE-KIND ::= 'B' // Swift.BinaryFloatingPoint
KNOWN-TYPE-KIND ::= 'b' // Swift.Bool
KNOWN-TYPE-KIND ::= 'c' // Swift.UnicodeScalar
KNOWN-TYPE-KIND ::= 'd' // Swift.Dictionary
KNOWN-TYPE-KIND ::= 'D' // Swift.Dictionary
KNOWN-TYPE-KIND ::= 'd' // Swift.Float64
KNOWN-TYPE-KIND ::= 'E' // Swift.Encodable
KNOWN-TYPE-KIND ::= 'e' // Swift.Decodable
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ class FrontendOptions {
/// The path to which we should store indexing data, if any.
std::string IndexStorePath;

/// The path to which we should emit GraphViz output for the complete
/// request-evaluator graph.
std::string RequestEvaluatorGraphVizPath;

/// Emit index data for imported serialized swift system modules.
bool IndexSystemModules = false;

Expand Down
2 changes: 2 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ def debug_forbid_typecheck_prefix : Separate<["-"], "debug-forbid-typecheck-pref

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

def debug_time_compilation : Flag<["-"], "debug-time-compilation">,
HelpText<"Prints the time taken by each compilation phase">;
Expand Down
4 changes: 4 additions & 0 deletions lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ bool ArgsToFrontendOptionsConverter::convert(
if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
Opts.IndexStorePath = A->getValue();
}
if (const Arg *A = Args.getLastArg(OPT_output_request_graphviz)) {
Opts.RequestEvaluatorGraphVizPath = A->getValue();
}

Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);

Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
Expand Down
18 changes: 18 additions & 0 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,13 @@ emitIndexData(CompilerInvocation &Invocation, CompilerInstance &Instance) {
return hadEmitIndexDataError;
}

/// Emits the request-evaluator graph to the given file in GraphViz format.
void emitRequestEvaluatorGraphViz(ASTContext &ctx, StringRef graphVizPath) {
std::error_code error;
llvm::raw_fd_ostream out(graphVizPath, error, llvm::sys::fs::F_Text);
ctx.evaluator.printDependenciesGraphviz(out);
}

static bool performCompileStepsPostSILGen(
CompilerInstance &Instance, CompilerInvocation &Invocation,
std::unique_ptr<SILModule> SM, bool astGuaranteedToCorrespondToSIL,
Expand Down Expand Up @@ -894,6 +901,17 @@ static bool performCompile(CompilerInstance &Instance,
else
Instance.performSema();

SWIFT_DEFER {
// Emit request-evaluator graph via GraphViz, if requested.
if (!Invocation.getFrontendOptions().RequestEvaluatorGraphVizPath.empty() &&
Instance.hasASTContext()) {
ASTContext &ctx = Instance.getASTContext();
emitRequestEvaluatorGraphViz(
ctx,
Invocation.getFrontendOptions().RequestEvaluatorGraphVizPath);
}
};

if (Action == FrontendOptions::ActionType::Parse)
return Instance.getASTContext().hadError();

Expand Down
2 changes: 1 addition & 1 deletion lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,4 +702,4 @@ SerializedASTFile::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
Identifier discriminator = File.getDiscriminatorForPrivateValue(D);
assert(!discriminator.empty() && "no discriminator found for value");
return discriminator;
}
}
6 changes: 5 additions & 1 deletion test/decl/class/circular_inheritance.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// RUN: %target-typecheck-verify-swift
// RUN: not %target-swift-frontend -typecheck -debug-cycles %s 2> %t.cycles
// RUN: not %target-swift-frontend -typecheck -debug-cycles %s -output-request-graphviz %t.dot 2> %t.cycles
// RUN: %FileCheck %s < %t.cycles
// RUN: %FileCheck -check-prefix CHECK-DOT %s < %t.dot

class C : B { } // expected-error{{circular class inheritance 'C' -> 'B' -> 'A' -> 'C'}}
class B : A { } // expected-note{{class 'B' declared here}}
Expand Down Expand Up @@ -46,3 +47,6 @@ class Outer3
// CHECK-NEXT: `--{{.*}}SuperclassTypeRequest
// CHECK-NEXT: `--{{.*}}InheritedTypeRequest(circular_inheritance.(file).Right@
// CHECK-NEXT: `--{{.*}}SuperclassTypeRequest{{.*(cyclic dependency)}}

// CHECK-DOT: digraph Dependencies
// CHECK-DOT: label="InheritedTypeRequest