Do cleanup on explorer fuzzing infrastructure. (#2790)

I'm partly doing this because the current setup would be difficult to share with the toolchain. e.g., ProtoToCarbon isn't explorer-specific, but the only way to run it via CLI is the explorer's fuzzverter. I want a separate tool.

This change:

- Adds a //common/fuzzing:proto_to_carbon tool.
  - The rest of fuzzverter is now just //explorer/fuzzing:ast_to_proto.
  - The change simplifies overall handling and removes a LLVM CLI dependency.
- Stops allowing unknown fields in the proto.
  - This has mostly led to forgetting to remove fuzzer inputs that were for removed features.
- Moves more non-explorer-specific bits to //common/fuzzing.
- Cleans up remaining pieces in //explorer/fuzzing
  - Merges the //explorer/fuzzing proto tests, which deduplicates AstToString copies.
    - These tests also had duplicate dependencies, etc -- and all complete in ~6s.
  - Updates and fixes regen_corpus which was previously broken by other changes.
  - Updates the README to reflect changes.
- Removes obsolete proto-fuzzer build configuration (AFAICT this is no longer needed).
This commit is contained in:
Jon Ross-Perkins
2023-04-21 08:23:58 -07:00
committed by GitHub
parent c9f0ef9e2c
commit d12583fc08
21 changed files with 432 additions and 527 deletions
+4 -40
View File
@@ -19,16 +19,7 @@
namespace Carbon {
// Appended to fuzzer-generated Carbon source when the source is missing
// `Main()` definition, to prevent early error return in semantic analysis.
static constexpr char EmptyMain[] = R"(
fn Main() -> i32 {
return 0;
}
)";
auto Internal::GetRunfilesFile(const std::string& file)
-> ErrorOr<std::string> {
auto GetRunfilesFile(const std::string& file) -> ErrorOr<std::string> {
using bazel::tools::cpp::runfiles::Runfiles;
std::string error;
// `Runfiles::Create()` fails if passed an empty `argv0`.
@@ -44,42 +35,15 @@ auto Internal::GetRunfilesFile(const std::string& file)
return full_path;
}
auto ParseCarbonTextProto(const std::string& contents, bool allow_unknown)
-> ErrorOr<Fuzzing::Carbon> {
google::protobuf::TextFormat::Parser parser;
if (allow_unknown) {
parser.AllowUnknownField(true);
parser.AllowUnknownExtension(true);
}
Fuzzing::Carbon carbon_proto;
if (!parser.ParseFromString(contents, &carbon_proto)) {
return ErrorBuilder() << "Couldn't parse Carbon text proto";
}
return carbon_proto;
}
auto ProtoToCarbonWithMain(const Fuzzing::CompilationUnit& compilation_unit)
-> std::string {
const bool has_main = std::any_of(
compilation_unit.declarations().begin(),
compilation_unit.declarations().end(),
[](const Fuzzing::Declaration& decl) {
return decl.kind_case() == Fuzzing::Declaration::kFunction &&
decl.function().name().name() == "Main";
});
return Carbon::ProtoToCarbon(compilation_unit) + (has_main ? "" : EmptyMain);
}
auto ParseAndExecute(const Fuzzing::CompilationUnit& compilation_unit)
-> ErrorOr<int> {
const std::string source = ProtoToCarbonWithMain(compilation_unit);
auto ParseAndExecute(const Fuzzing::Carbon& carbon) -> ErrorOr<int> {
const std::string source = ProtoToCarbon(carbon, /*maybe_add_main=*/true);
Arena arena;
CARBON_ASSIGN_OR_RETURN(AST ast,
ParseFromString(&arena, "Fuzzer.carbon", source,
/*parser_debug=*/false));
const ErrorOr<std::string> prelude_path =
Internal::GetRunfilesFile("carbon/explorer/data/prelude.carbon");
GetRunfilesFile("carbon/explorer/data/prelude.carbon");
// Can't do anything without a prelude, so it's a fatal error.
CARBON_CHECK(prelude_path.ok()) << prelude_path.error();