Add -debug-constraints-on-line flag

This commit is contained in:
Brent Royal-Gordon
2019-04-19 11:03:52 -07:00
parent 334b76a237
commit 79cee8daad
4 changed files with 58 additions and 0 deletions

View File

@@ -166,6 +166,10 @@ namespace swift {
/// solver should be debugged. /// solver should be debugged.
unsigned DebugConstraintSolverAttempt = 0; unsigned DebugConstraintSolverAttempt = 0;
/// Line numbers to activate the constraint solver debugger.
/// Should be stored sorted.
llvm::SmallVector<unsigned, 4> DebugConstraintSolverOnLines;
/// Enable named lazy member loading. /// Enable named lazy member loading.
bool NamedLazyMemberLoading = true; bool NamedLazyMemberLoading = true;

View File

@@ -189,6 +189,12 @@ def debug_constraints : Flag<["-"], "debug-constraints">,
def debug_constraints_attempt : Separate<["-"], "debug-constraints-attempt">, def debug_constraints_attempt : Separate<["-"], "debug-constraints-attempt">,
HelpText<"Debug the constraint solver at a given attempt">; HelpText<"Debug the constraint solver at a given attempt">;
def debug_constraints_on_line : Separate<["-"], "debug-constraints-on-line">,
HelpText<"Debug the constraint solver for expressions on <line>">,
MetaVarName<"<line>">;
def debug_constraints_on_line_EQ : Joined<["-"], "debug-constraints-on-line=">,
Alias<debug_constraints_on_line>;
def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">, def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
HelpText<"Disable per-name lazy member loading">; HelpText<"Disable per-name lazy member loading">;

View File

@@ -339,6 +339,17 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.DebugConstraintSolverAttempt = attempt; Opts.DebugConstraintSolverAttempt = attempt;
} }
for (const Arg *A : Args.filtered(OPT_debug_constraints_on_line)) {
unsigned line;
if (StringRef(A->getValue()).getAsInteger(10, line)) {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
A->getAsString(Args), A->getValue());
return true;
}
Opts.DebugConstraintSolverOnLines.push_back(line);
}
llvm::sort(Opts.DebugConstraintSolverOnLines);
if (const Arg *A = Args.getLastArg(OPT_debug_forbid_typecheck_prefix)) { if (const Arg *A = Args.getLastArg(OPT_debug_forbid_typecheck_prefix)) {
Opts.DebugForbidTypecheckPrefix = A->getValue(); Opts.DebugForbidTypecheckPrefix = A->getValue();

View File

@@ -1020,11 +1020,48 @@ void ConstraintSystem::shrink(Expr *expr) {
} }
} }
static bool debugConstraintSolverForExpr(ASTContext &C, Expr *expr) {
if (C.LangOpts.DebugConstraintSolver)
return true;
if (C.LangOpts.DebugConstraintSolverOnLines.empty())
// No need to compute the line number to find out it's not present.
return false;
// Get the lines on which the expression starts and ends.
unsigned startLine = 0, endLine = 0;
if (expr->getSourceRange().isValid()) {
auto range =
Lexer::getCharSourceRangeFromSourceRange(C.SourceMgr,
expr->getSourceRange());
startLine = C.SourceMgr.getLineNumber(range.getStart());
endLine = C.SourceMgr.getLineNumber(range.getEnd());
}
assert(startLine <= endLine && "expr ends before it starts?");
auto &lines = C.LangOpts.DebugConstraintSolverOnLines;
assert(std::is_sorted(lines.begin(), lines.end()) &&
"DebugConstraintSolverOnLines sorting invariant violated");
// Check if `lines` contains at least one line `L` where
// `startLine <= L <= endLine`. If it does, `lower_bound(startLine)` and
// `upper_bound(endLine)` will be different.
auto startBound = llvm::lower_bound(lines, startLine);
auto endBound = std::upper_bound(startBound, lines.end(), endLine);
return startBound != endBound;
}
bool ConstraintSystem::solve(Expr *&expr, bool ConstraintSystem::solve(Expr *&expr,
Type convertType, Type convertType,
ExprTypeCheckListener *listener, ExprTypeCheckListener *listener,
SmallVectorImpl<Solution> &solutions, SmallVectorImpl<Solution> &solutions,
FreeTypeVariableBinding allowFreeTypeVariables) { FreeTypeVariableBinding allowFreeTypeVariables) {
llvm::SaveAndRestore<bool>
debugForExpr(TC.getLangOpts().DebugConstraintSolver,
debugConstraintSolverForExpr(TC.Context, expr));
// Attempt to solve the constraint system. // Attempt to solve the constraint system.
auto solution = solveImpl(expr, auto solution = solveImpl(expr,
convertType, convertType,