From f8d439aeee6048b7365d1cb3bcd2578ec27a0288 Mon Sep 17 00:00:00 2001 From: Wiseguy <68165316+Mr-Wiseguy@users.noreply.github.com> Date: Thu, 15 Aug 2024 00:17:09 -0400 Subject: [PATCH] Add option to output multiple functions per file, defaults to 50 (#88) --- include/recomp_port.h | 1 + src/config.cpp | 11 ++++++++++ src/main.cpp | 47 ++++++++++++++++++++++++++++++++++--------- src/recompilation.cpp | 2 +- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/include/recomp_port.h b/include/recomp_port.h index 80e50c0..ad7f271 100644 --- a/include/recomp_port.h +++ b/include/recomp_port.h @@ -64,6 +64,7 @@ namespace RecompPort { struct Config { int32_t entrypoint; + int32_t functions_per_output_file; bool has_entrypoint; bool uses_mips3_float_mode; bool single_file_output; diff --git a/src/config.cpp b/src/config.cpp index 8933d26..2bce7fe 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -416,6 +416,17 @@ RecompPort::Config::Config(const char* path) { recomp_include = "#include \"librecomp/recomp.h\""; } + std::optional funcs_per_file_opt = input_data["functions_per_output_file"].value(); + if (funcs_per_file_opt.has_value()) { + functions_per_output_file = funcs_per_file_opt.value(); + if (functions_per_output_file <= 0) { + throw toml::parse_error("Invalid functions_per_output_file value", input_data["functions_per_output_file"].node()->source()); + } + } + else { + functions_per_output_file = 50; + } + // Patches section (optional) toml::node_view patches_data = config_data["patches"]; if (patches_data.is_table()) { diff --git a/src/main.cpp b/src/main.cpp index 615ae88..02b41b8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1780,16 +1780,33 @@ int main(int argc, char** argv) { func.function_hooks[instruction_index] = patch.text; } - std::ofstream single_output_file; - - if (config.single_file_output) { - single_output_file.open(config.output_func_path / config.elf_path.stem().replace_extension(".c")); + std::ofstream current_output_file; + size_t output_file_count = 0; + size_t cur_file_function_count = 0; + + auto open_new_output_file = [&config, ¤t_output_file, &output_file_count, &cur_file_function_count]() { + current_output_file = std::ofstream{config.output_func_path / fmt::format("funcs_{}.c", output_file_count)}; // Write the file header - fmt::print(single_output_file, + fmt::print(current_output_file, "{}\n" "#include \"funcs.h\"\n" "\n", config.recomp_include); + cur_file_function_count = 0; + output_file_count++; + }; + + if (config.single_file_output) { + current_output_file.open(config.output_func_path / config.elf_path.stem().replace_extension(".c")); + // Write the file header + fmt::print(current_output_file, + "{}\n" + "#include \"funcs.h\"\n" + "\n", + config.recomp_include); + } + else if (config.functions_per_output_file > 1) { + open_new_output_file(); } //#pragma omp parallel for @@ -1800,8 +1817,14 @@ int main(int argc, char** argv) { fmt::print(func_header_file, "void {}(uint8_t* rdram, recomp_context* ctx);\n", func.name); bool result; - if (config.single_file_output) { - result = RecompPort::recompile_function(context, config, func, single_output_file, static_funcs_by_section, false); + if (config.single_file_output || config.functions_per_output_file > 1) { + result = RecompPort::recompile_function(context, config, func, current_output_file, static_funcs_by_section, false); + if (!config.single_file_output) { + cur_file_function_count++; + if (cur_file_function_count >= config.functions_per_output_file) { + open_new_output_file(); + } + } } else { result = recompile_single_function(context, config, func, config.output_func_path / (func.name + ".c"), static_funcs_by_section); @@ -1873,8 +1896,14 @@ int main(int argc, char** argv) { bool result; size_t prev_num_statics = static_funcs_by_section[func.section_index].size(); - if (config.single_file_output) { - result = RecompPort::recompile_function(context, config, func, single_output_file, static_funcs_by_section, false); + if (config.single_file_output || config.functions_per_output_file > 1) { + result = RecompPort::recompile_function(context, config, func, current_output_file, static_funcs_by_section, false); + if (!config.single_file_output) { + cur_file_function_count++; + if (cur_file_function_count >= config.functions_per_output_file) { + open_new_output_file(); + } + } } else { result = recompile_single_function(context, config, func, config.output_func_path / (func.name + ".c"), static_funcs_by_section); diff --git a/src/recompilation.cpp b/src/recompilation.cpp index e39133e..22b8233 100644 --- a/src/recompilation.cpp +++ b/src/recompilation.cpp @@ -1246,7 +1246,7 @@ bool RecompPort::recompile_function(const RecompPort::Context& context, const Re } fmt::print(output_file, - "void {}(uint8_t* rdram, recomp_context* ctx) {{\n" + "RECOMP_FUNC void {}(uint8_t* rdram, recomp_context* ctx) {{\n" // these variables shouldn't need to be preserved across function boundaries, so make them local for more efficient output " uint64_t hi = 0, lo = 0, result = 0;\n" " unsigned int rounding_mode = DEFAULT_ROUNDING_MODE;\n"