mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2026-04-27 04:21:51 +00:00
Handle tail calls in the middle of functions
This commit is contained in:
parent
be29c979c8
commit
a5eaea94cb
3 changed files with 39 additions and 6 deletions
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/clang",
|
||||||
|
"intelliSenseMode": "linux-clang-x64",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++20",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
|
|
@ -503,7 +503,6 @@ std::unordered_set<std::string> ignored_funcs {
|
||||||
|
|
||||||
// libgcc math routines (these throw off the recompiler)
|
// libgcc math routines (these throw off the recompiler)
|
||||||
"__divdi3",
|
"__divdi3",
|
||||||
"__udivdi3",
|
|
||||||
"__moddi3",
|
"__moddi3",
|
||||||
|
|
||||||
// ido math routines
|
// ido math routines
|
||||||
|
|
@ -626,6 +625,7 @@ std::unordered_set<std::string> renamed_funcs{
|
||||||
"flush_window",
|
"flush_window",
|
||||||
|
|
||||||
"__muldi3",
|
"__muldi3",
|
||||||
|
"__udivdi3",
|
||||||
"__umoddi3",
|
"__umoddi3",
|
||||||
"div64_64",
|
"div64_64",
|
||||||
"div64_32",
|
"div64_32",
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
|
||||||
fmt::print(output_file, ";\n }}\n");
|
fmt::print(output_file, ";\n }}\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
auto print_func_call = [&](uint32_t target_func_vram) {
|
auto print_func_call = [&](uint32_t target_func_vram, bool link_branch = true) {
|
||||||
const auto matching_funcs_find = context.functions_by_vram.find(target_func_vram);
|
const auto matching_funcs_find = context.functions_by_vram.find(target_func_vram);
|
||||||
std::string jal_target_name;
|
std::string jal_target_name;
|
||||||
uint32_t section_vram_start = section.ram_addr;
|
uint32_t section_vram_start = section.ram_addr;
|
||||||
|
|
@ -190,7 +190,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
needs_link_branch = true;
|
needs_link_branch = link_branch;
|
||||||
print_unconditional_branch("{}(rdram, ctx)", jal_target_name);
|
print_unconditional_branch("{}(rdram, ctx)", jal_target_name);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
@ -511,7 +511,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
|
||||||
{
|
{
|
||||||
uint32_t branch_target = instr.getBranchVramGeneric();
|
uint32_t branch_target = instr.getBranchVramGeneric();
|
||||||
if (branch_target == instr_vram) {
|
if (branch_target == instr_vram) {
|
||||||
print_line("void pause_self(uint8_t *rdram); pause_self(rdram)");
|
print_line("pause_self(rdram)");
|
||||||
}
|
}
|
||||||
// Check if the branch is within this function
|
// Check if the branch is within this function
|
||||||
else if (branch_target >= func.vram && branch_target < func_vram_end) {
|
else if (branch_target >= func.vram && branch_target < func_vram_end) {
|
||||||
|
|
@ -522,6 +522,23 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
|
||||||
fmt::print("Tail call in {}\n", func.name);
|
fmt::print("Tail call in {}\n", func.name);
|
||||||
print_func_call(branch_target);
|
print_func_call(branch_target);
|
||||||
}
|
}
|
||||||
|
// This may be a tail call in the middle of the control flow due to a previous check
|
||||||
|
// For example:
|
||||||
|
// ```c
|
||||||
|
// void test() {
|
||||||
|
// if (SOME_CONDITION) {
|
||||||
|
// do_a();
|
||||||
|
// } else {
|
||||||
|
// do_b();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
// FIXME: how to deal with static functions?
|
||||||
|
else if (context.functions_by_vram.find(branch_target) != context.functions_by_vram.end()) {
|
||||||
|
fmt::print("Tail call in {}\n", func.name);
|
||||||
|
print_func_call(branch_target, false);
|
||||||
|
print_line("return");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
fmt::print(stderr, "Unhandled branch in {} at 0x{:08X} to 0x{:08X}\n", func.name, instr_vram, branch_target);
|
fmt::print(stderr, "Unhandled branch in {} at 0x{:08X} to 0x{:08X}\n", func.name, instr_vram, branch_target);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue