diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 85df234..ecddf1b 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -34,3 +34,4 @@ jobs: ./generate.sh ./build.sh ./build/bb test + ./build/bb reproduce diff --git a/src/compiler.bbb b/src/compiler.bbb index e1099b8..0c1a5c8 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -984,6 +984,7 @@ CompilerCommand = enum { compile, test, + reproduce, } BuildMode = enum @@ -18558,7 +18559,10 @@ names: [_][]u8 = return 1; } + >debug_info_array: [_]u1 = [1, 0]; + >command = command_string_to_enum.enum_value; + switch (command) { .compile => @@ -18620,7 +18624,6 @@ names: [_][]u8 = report_error(); } - >debug_info_array: [_]u1 = [1, 0]; for (name: names) { for (build_mode: #enum_values(BuildMode)) @@ -18656,6 +18659,43 @@ names: [_][]u8 = } } }, + .reproduce => + { + for (build_mode: #enum_values(BuildMode)) + { + for (has_debug_info: debug_info_array) + { + >position = arena.position; + + // Produce the compiler + >relative_file_path = "src/compiler.bbb"; + >executable_path = compile_file(arena, { + .relative_file_path = relative_file_path, + .build_mode = build_mode, + .has_debug_info = has_debug_info, + .silent = 1, + }, envp); + + // Test the compiler + >arguments: [_]&u8 = [ + executable_path.pointer, + "test", + zero, + ]; + >args = arguments[..arguments.length - 1]; + >execution = os_execute(arena, args, envp, zero); + + >success = execution.termination_kind == .exit and execution.termination_code == 0; + + if (!success) + { + #trap(); + } + + arena.position = position; + } + } + }, } return 0; diff --git a/src/compiler.cpp b/src/compiler.cpp index 8ba2702..6f61d12 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -619,6 +619,24 @@ void entry_point(Slice arguments, Slice envp) print(compiler_has_debug_info ? string_literal(" with debug info\n") : string_literal(" with no debug info\n")); bb_fail(); } + + char* const reproduce_arguments[] = + { + (char*)compiler.pointer, + (char*)"reproduce", + 0, + }; + arg_slice = array_to_slice(reproduce_arguments); + arg_slice.length -= 1; + execution = os_execute(arena, arg_slice, environment, {}); + success = execution.termination_kind == TerminationKind::exit && execution.termination_code == 0; + if (!success) + { + print(string_literal("Self-hosted reproduction failed: ")); + print(build_mode_to_string(compiler_build_mode)); + print(compiler_has_debug_info ? string_literal(" with debug info\n") : string_literal(" with no debug info\n")); + bb_fail(); + } } } } break;