Suppress Print intrinsic output in the fuzzer. (#2784)

Related to #2780, but mostly an issue when running over the committed corpus since we use Print a lot.
This commit is contained in:
Jon Ross-Perkins
2023-04-19 16:56:02 -07:00
committed by GitHub
parent 39155d34ae
commit 62ee4a5c7a
8 changed files with 96 additions and 74 deletions
+5 -2
View File
@@ -86,8 +86,11 @@ auto ParseAndExecute(const Fuzzing::CompilationUnit& compilation_unit)
AddPrelude(*prelude_path, &arena, &ast.declarations,
&ast.num_prelude_declarations);
TraceStream trace_stream;
CARBON_ASSIGN_OR_RETURN(ast, AnalyzeProgram(&arena, ast, &trace_stream));
return ExecProgram(&arena, ast, &trace_stream);
// Use llvm::nulls() to suppress output from the Print intrinsic.
CARBON_ASSIGN_OR_RETURN(
ast, AnalyzeProgram(&arena, ast, &trace_stream, &llvm::nulls()));
return ExecProgram(&arena, ast, &trace_stream, &llvm::nulls());
}
} // namespace Carbon
+7 -4
View File
@@ -19,7 +19,8 @@
namespace Carbon {
auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
Nonnull<TraceStream*> trace_stream) -> ErrorOr<AST> {
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream) -> ErrorOr<AST> {
if (trace_stream->is_enabled()) {
*trace_stream << "********** source program **********\n";
for (int i = ast.num_prelude_declarations;
@@ -46,7 +47,8 @@ auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
if (trace_stream->is_enabled()) {
*trace_stream << "********** type checking **********\n";
}
CARBON_RETURN_IF_ERROR(TypeChecker(arena, trace_stream).TypeCheck(ast));
CARBON_RETURN_IF_ERROR(
TypeChecker(arena, trace_stream, print_stream).TypeCheck(ast));
if (trace_stream->is_enabled()) {
*trace_stream << "********** resolving unformed variables **********\n";
@@ -64,11 +66,12 @@ auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
}
auto ExecProgram(Nonnull<Arena*> arena, AST ast,
Nonnull<TraceStream*> trace_stream) -> ErrorOr<int> {
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream) -> ErrorOr<int> {
if (trace_stream->is_enabled()) {
*trace_stream << "********** starting execution **********\n";
}
return InterpProgram(ast, arena, trace_stream);
return InterpProgram(ast, arena, trace_stream, print_stream);
}
} // namespace Carbon
+4 -2
View File
@@ -17,11 +17,13 @@ namespace Carbon {
// Perform semantic analysis on the AST.
auto AnalyzeProgram(Nonnull<Arena*> arena, AST ast,
Nonnull<TraceStream*> trace_stream) -> ErrorOr<AST>;
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream) -> ErrorOr<AST>;
// Run the program's `Main` function.
auto ExecProgram(Nonnull<Arena*> arena, AST ast,
Nonnull<TraceStream*> trace_stream) -> ErrorOr<int>;
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream) -> ErrorOr<int>;
} // namespace Carbon
+18 -9
View File
@@ -59,11 +59,13 @@ class Interpreter {
// traces if `trace` is true. `phase` indicates whether it executes at
// compile time or run time.
Interpreter(Phase phase, Nonnull<Arena*> arena,
Nonnull<TraceStream*> trace_stream)
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream)
: arena_(arena),
heap_(arena),
todo_(MakeTodo(phase, &heap_)),
trace_stream_(trace_stream),
print_stream_(print_stream),
phase_(phase) {}
// Runs all the steps of `action`.
@@ -178,6 +180,10 @@ class Interpreter {
ActionStack todo_;
Nonnull<TraceStream*> trace_stream_;
// The stream for the Print intrinsic.
Nonnull<llvm::raw_ostream*> print_stream_;
Phase phase_;
};
@@ -1561,17 +1567,17 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
intrinsic.source_loc(), format_string, num_format_args));
switch (num_format_args) {
case 0:
llvm::outs() << llvm::formatv(format_string);
*print_stream_ << llvm::formatv(format_string);
break;
case 1:
llvm::outs() << llvm::formatv(format_string,
cast<IntValue>(*args[1]).value());
*print_stream_ << llvm::formatv(format_string,
cast<IntValue>(*args[1]).value());
break;
default:
CARBON_FATAL() << "Too many format args: " << num_format_args;
}
// Implicit newline; currently no way to disable it.
llvm::outs() << "\n";
*print_stream_ << "\n";
return todo_.FinishAction(TupleValue::Empty());
}
case IntrinsicExpression::Intrinsic::Assert: {
@@ -2438,8 +2444,9 @@ auto Interpreter::RunAllSteps(std::unique_ptr<Action> action)
}
auto InterpProgram(const AST& ast, Nonnull<Arena*> arena,
Nonnull<TraceStream*> trace_stream) -> ErrorOr<int> {
Interpreter interpreter(Phase::RunTime, arena, trace_stream);
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream) -> ErrorOr<int> {
Interpreter interpreter(Phase::RunTime, arena, trace_stream, print_stream);
if (trace_stream->is_enabled()) {
*trace_stream << "********** initializing globals **********\n";
}
@@ -2460,9 +2467,11 @@ auto InterpProgram(const AST& ast, Nonnull<Arena*> arena,
}
auto InterpExp(Nonnull<const Expression*> e, Nonnull<Arena*> arena,
Nonnull<TraceStream*> trace_stream)
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream)
-> ErrorOr<Nonnull<const Value*>> {
Interpreter interpreter(Phase::CompileTime, arena, trace_stream);
Interpreter interpreter(Phase::CompileTime, arena, trace_stream,
print_stream);
CARBON_RETURN_IF_ERROR(
interpreter.RunAllSteps(std::make_unique<ExpressionAction>(e)));
return interpreter.result();
+4 -2
View File
@@ -25,13 +25,15 @@ namespace Carbon {
// Interprets the program defined by `ast`, allocating values on `arena` and
// printing traces if `trace` is true.
auto InterpProgram(const AST& ast, Nonnull<Arena*> arena,
Nonnull<TraceStream*> trace_stream) -> ErrorOr<int>;
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream) -> ErrorOr<int>;
// Interprets `e` at compile-time, allocating values on `arena` and
// printing traces if `trace` is true. The caller must ensure that all the
// code this evaluates has been typechecked.
auto InterpExp(Nonnull<const Expression*> e, Nonnull<Arena*> arena,
Nonnull<TraceStream*> trace_stream)
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream)
-> ErrorOr<Nonnull<const Value*>>;
// Attempts to match `v` against the pattern `p`, returning whether matching
+38 -48
View File
@@ -756,7 +756,7 @@ auto TypeChecker::ImplicitlyConvert(std::string_view context,
ImplicitlyConvert(context, impl_scope, source,
arena_->New<TypeType>()));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> converted_value,
InterpExp(source_as_type, arena_, trace_stream_));
InterpExp(source_as_type));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const ConstraintType*> destination_constraint,
ConvertToConstraintType(source->source_loc(), "implicit conversion",
@@ -1363,7 +1363,7 @@ auto TypeChecker::ArgumentDeduction::Finish(
// Evaluate the argument to get the value.
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> value,
InterpExp(arg, type_checker.arena_, trace_stream_));
type_checker.InterpExp(arg));
if (trace_stream_->is_enabled()) {
*trace_stream_ << "evaluated generic parameter " << *binding << " as "
<< *value << "\n";
@@ -2717,9 +2717,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
ExpectExactType(index.offset().source_loc(), "tuple index",
arena_->New<IntType>(),
&index.offset().static_type(), impl_scope));
CARBON_ASSIGN_OR_RETURN(
auto offset_value,
InterpExp(&index.offset(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(auto offset_value,
InterpExp(&index.offset()));
int i = cast<IntValue>(*offset_value).value();
if (i < 0 || i >= static_cast<int>(tuple_type.elements().size())) {
return ProgramError(e->source_loc())
@@ -2936,9 +2935,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
// TODO: Per the language rules, we are supposed to also perform
// lookup into `type` and report an ambiguity if the name is found in
// both places.
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> type,
InterpExp(&access.object(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> type,
InterpExp(&access.object()));
CARBON_ASSIGN_OR_RETURN(
ConstraintLookupResult result,
LookupInConstraint(e->source_loc(), "member access", &object_type,
@@ -2987,9 +2985,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
case Value::Kind::TypeType: {
// This is member access into an unconstrained type. Evaluate it and
// perform lookup in the result.
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> type,
InterpExp(&access.object(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> type,
InterpExp(&access.object()));
CARBON_RETURN_IF_ERROR(
ExpectCompleteType(access.source_loc(), "member access", type));
switch (type->kind()) {
@@ -3119,7 +3116,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
// Evaluate the member name expression to determine which member we're
// accessing.
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> member_name_value,
InterpExp(&access.path(), arena_, trace_stream_));
InterpExp(&access.path()));
const auto& member_name = cast<MemberName>(*member_name_value);
access.set_member(&member_name);
bool is_instance_member = IsInstanceMember(&member_name.member());
@@ -3130,8 +3127,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
if (IsTypeOfType(&access.object().static_type())) {
// This is `Type.(member_name)`, where `member_name` doesn't specify
// a type. This access doesn't perform instance binding.
CARBON_ASSIGN_OR_RETURN(
base_type, InterpExp(&access.object(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(base_type, InterpExp(&access.object()));
has_instance = false;
} else {
// This is `value.(member_name)`, where `member_name` doesn't specify
@@ -3382,12 +3378,10 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
// `&` between type-of-types performs constraint combination.
// TODO: Should this be done via an intrinsic?
if (IsTypeOfType(ts[0]) && IsTypeOfType(ts[1])) {
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> lhs,
InterpExp(op.arguments()[0], arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> rhs,
InterpExp(op.arguments()[1], arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> lhs,
InterpExp(op.arguments()[0]));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> rhs,
InterpExp(op.arguments()[1]));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const ConstraintType*> lhs_constraint,
ConvertToConstraintType(op.arguments()[0]->source_loc(),
@@ -3568,9 +3562,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
dyn_cast<SimpleMemberAccessExpression>(&call.function());
if (member_access &&
isa<TypeType>(member_access->object().static_type())) {
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> type,
InterpExp(&member_access->object(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> type,
InterpExp(&member_access->object()));
if (isa<ChoiceType>(type)) {
return ProgramError(e->source_loc())
<< "alternative `" << *type << "."
@@ -3885,9 +3878,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> type,
TypeCheckTypeExp(&impls_clause.type(), inner_impl_scope));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> constraint,
InterpExp(&impls_clause.constraint(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> constraint,
InterpExp(&impls_clause.constraint()));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const ConstraintType*> constraint_type,
ConvertToConstraintType(impls_clause.source_loc(),
@@ -3904,12 +3896,10 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
}
case WhereClauseKind::EqualsWhereClause: {
const auto& equals_clause = cast<EqualsWhereClause>(*clause);
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> lhs,
InterpExp(&equals_clause.lhs(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> rhs,
InterpExp(&equals_clause.rhs(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> lhs,
InterpExp(&equals_clause.lhs()));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> rhs,
InterpExp(&equals_clause.rhs()));
if (!ValueEqual(lhs, rhs, std::nullopt)) {
builder.AddEqualityConstraint({.values = {lhs, rhs}});
}
@@ -3945,8 +3935,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
// type. This is the value we'll rewrite to when type-checking a
// member access.
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> replacement_value,
InterpExp(&rewrite_clause.replacement(),
arena_, trace_stream_));
InterpExp(&rewrite_clause.replacement()));
Nonnull<const Value*> replacement_type =
&rewrite_clause.replacement().static_type();
@@ -3964,9 +3953,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
Nonnull<Expression*> converted_expression,
ImplicitlyConvert("rewrite constraint", inner_impl_scope,
replacement_literal, constraint_type));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> converted_value,
InterpExp(converted_expression, arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> converted_value,
InterpExp(converted_expression));
// Add the rewrite constraint.
builder.AddRewriteConstraint(
@@ -3998,9 +3986,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
array_literal.size_expression().source_loc(), "array size",
arena_->New<IntType>(),
&array_literal.size_expression().static_type(), impl_scope));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> size_value,
InterpExp(&array_literal.size_expression(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> size_value,
InterpExp(&array_literal.size_expression()));
if (cast<IntValue>(size_value)->value() < 0) {
return ProgramError(array_literal.size_expression().source_loc())
<< "Array size cannot be negative";
@@ -4072,7 +4059,7 @@ auto TypeChecker::TypeCheckTypeExp(Nonnull<Expression*> type_expression,
ImplicitlyConvert("type expression", impl_scope, type_expression,
arena_->New<TypeType>()));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> type,
InterpExp(type_expression, arena_, trace_stream_));
InterpExp(type_expression));
CARBON_CHECK(IsType(type))
<< "type expression did not produce a type, got " << *type;
if (concrete) {
@@ -4180,8 +4167,7 @@ auto TypeChecker::TypeCheckPattern(
auto* converted,
ImplicitlyConvert("type of name binding", impl_scope, literal,
arena_->New<TypeType>()));
CARBON_ASSIGN_OR_RETURN(type,
InterpExp(converted, arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(type, InterpExp(converted));
}
CARBON_CHECK(IsType(type))
<< "conversion to type succeeded but didn't produce a type, got "
@@ -4306,7 +4292,7 @@ auto TypeChecker::TypeCheckPattern(
p->set_static_type(&expression.static_type());
// TODO: Per proposal #2188, we should form an `==` comparison here.
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> expr_value,
InterpExp(&expression, arena_, trace_stream_));
InterpExp(&expression));
p->set_value(expr_value);
return Success();
}
@@ -5910,7 +5896,7 @@ auto TypeChecker::DeclareAliasDeclaration(Nonnull<AliasDeclaration*> alias,
if (alias->target().static_type().kind() !=
Value::Kind::TypeOfNamespaceName) {
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> target,
InterpExp(&alias->target(), arena_, trace_stream_));
InterpExp(&alias->target()));
alias->set_constant_value(target);
}
return Success();
@@ -6091,9 +6077,8 @@ auto TypeChecker::DeclareDeclaration(Nonnull<Declaration*> d,
auto& mix_decl = cast<MixDeclaration>(*d);
CARBON_RETURN_IF_ERROR(
TypeCheckExp(&mix_decl.mixin(), *scope_info.innermost_scope));
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> mixin,
InterpExp(&mix_decl.mixin(), arena_, trace_stream_));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> mixin,
InterpExp(&mix_decl.mixin()));
if (const auto* mixin_value = dyn_cast<MixinPseudoType>(mixin)) {
mix_decl.set_mixin_value(mixin_value);
} else {
@@ -6333,4 +6318,9 @@ auto TypeChecker::InstantiateImplDeclaration(
return std::pair{impl, arena_->New<Bindings>(std::move(new_bindings))};
}
auto TypeChecker::InterpExp(Nonnull<const Expression*> e)
-> ErrorOr<Nonnull<const Value*>> {
return Carbon::InterpExp(e, arena_, trace_stream_, print_stream_);
}
} // namespace Carbon
+16 -5
View File
@@ -38,8 +38,11 @@ using GlobalMembersMap =
class TypeChecker {
public:
explicit TypeChecker(Nonnull<Arena*> arena,
Nonnull<TraceStream*> trace_stream)
: arena_(arena), trace_stream_(trace_stream) {}
Nonnull<TraceStream*> trace_stream,
Nonnull<llvm::raw_ostream*> print_stream)
: arena_(arena),
trace_stream_(trace_stream),
print_stream_(print_stream) {}
// Type-checks `ast` and sets properties such as `static_type`, as documented
// on the individual nodes.
@@ -523,9 +526,14 @@ class TypeChecker {
// Instantiate an impl with the given set of bindings, including one or more
// template bindings.
ErrorOr<std::pair<Nonnull<ImplDeclaration*>, Nonnull<Bindings*>>>
InstantiateImplDeclaration(Nonnull<const ImplDeclaration*> pattern,
Nonnull<const Bindings*> bindings) const;
auto InstantiateImplDeclaration(Nonnull<const ImplDeclaration*> pattern,
Nonnull<const Bindings*> bindings) const
-> ErrorOr<std::pair<Nonnull<ImplDeclaration*>, Nonnull<Bindings*>>>;
// Wraps the interpreter's InterpExp, forwarding TypeChecker members as
// arguments.
auto InterpExp(Nonnull<const Expression*> e)
-> ErrorOr<Nonnull<const Value*>>;
Nonnull<Arena*> arena_;
Builtins builtins_;
@@ -535,6 +543,9 @@ class TypeChecker {
Nonnull<TraceStream*> trace_stream_;
// The stream for the Print intrinsic.
Nonnull<llvm::raw_ostream*> print_stream_;
// The top-level ImplScope, containing `impl` declarations that should be
// usable from any context. This is used when we want to try to refine a
// symbolic witness into an impl witness during substitution.
+4 -2
View File
@@ -105,7 +105,8 @@ auto ExplorerMain(int argc, char** argv, void* static_for_main_addr,
auto time_after_prelude = std::chrono::system_clock::now();
// Semantically analyze the parsed program.
if (ErrorOr<AST> analyze_result = AnalyzeProgram(&arena, ast, &trace_stream);
if (ErrorOr<AST> analyze_result =
AnalyzeProgram(&arena, ast, &trace_stream, &llvm::outs());
analyze_result.ok()) {
ast = *std::move(analyze_result);
} else {
@@ -117,7 +118,8 @@ auto ExplorerMain(int argc, char** argv, void* static_for_main_addr,
// Run the program.
auto ret = EXIT_SUCCESS;
if (ErrorOr<int> exec_result = ExecProgram(&arena, ast, &trace_stream);
if (ErrorOr<int> exec_result =
ExecProgram(&arena, ast, &trace_stream, &llvm::outs());
exec_result.ok()) {
// Print the return code to stdout.
llvm::outs() << "result: " << *exec_result << "\n";