From 0fc0834a83885a81d655f7d9f62d4fd36e27fba6 Mon Sep 17 00:00:00 2001 From: xensik Date: Tue, 19 Jul 2022 13:50:12 +0200 Subject: [PATCH] finish decompiler loop statements --- src/h1/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/h2/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/iw5/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/iw6/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/iw7/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/iw8/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/s1/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/s2/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- src/s4/xsk/decompiler.cpp | 55 ++++++++++++++++++++++++++++---------- 9 files changed, 369 insertions(+), 126 deletions(-) diff --git a/src/h1/xsk/decompiler.cpp b/src/h1/xsk/decompiler.cpp index 26447230..69f2a6cf 100644 --- a/src/h1/xsk/decompiler.cpp +++ b/src/h1/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1884,17 +1877,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1909,7 +1932,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -1984,6 +2007,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/h2/xsk/decompiler.cpp b/src/h2/xsk/decompiler.cpp index 80e7b70d..8466756f 100644 --- a/src/h2/xsk/decompiler.cpp +++ b/src/h2/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1884,17 +1877,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1909,7 +1932,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -1984,6 +2007,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/iw5/xsk/decompiler.cpp b/src/iw5/xsk/decompiler.cpp index 38bcb6d5..0b9fcaa0 100644 --- a/src/iw5/xsk/decompiler.cpp +++ b/src/iw5/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1878,17 +1871,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1903,7 +1926,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -1978,6 +2001,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/iw6/xsk/decompiler.cpp b/src/iw6/xsk/decompiler.cpp index 039cbce8..6bcbb8bb 100644 --- a/src/iw6/xsk/decompiler.cpp +++ b/src/iw6/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1878,17 +1871,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1903,7 +1926,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -1978,6 +2001,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/iw7/xsk/decompiler.cpp b/src/iw7/xsk/decompiler.cpp index 057165aa..35d5648b 100644 --- a/src/iw7/xsk/decompiler.cpp +++ b/src/iw7/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1878,17 +1871,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1903,7 +1926,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -1978,6 +2001,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/iw8/xsk/decompiler.cpp b/src/iw8/xsk/decompiler.cpp index 04c69c8f..65a10b50 100644 --- a/src/iw8/xsk/decompiler.cpp +++ b/src/iw8/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1915,17 +1908,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1940,7 +1963,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -2015,6 +2038,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/s1/xsk/decompiler.cpp b/src/s1/xsk/decompiler.cpp index 97a25c93..9a75244b 100644 --- a/src/s1/xsk/decompiler.cpp +++ b/src/s1/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1884,17 +1877,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1909,7 +1932,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -1984,6 +2007,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/s2/xsk/decompiler.cpp b/src/s2/xsk/decompiler.cpp index 95768bfb..351b5b38 100644 --- a/src/s2/xsk/decompiler.cpp +++ b/src/s2/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1891,17 +1884,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1916,7 +1939,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -1991,6 +2014,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } } diff --git a/src/s4/xsk/decompiler.cpp b/src/s4/xsk/decompiler.cpp index d0248ce8..e9824bfd 100644 --- a/src/s4/xsk/decompiler.cpp +++ b/src/s4/xsk/decompiler.cpp @@ -72,13 +72,6 @@ void decompiler::decompile_function(const function::ptr& func) // remove last return stmt->list.pop_back(); - // hotfix empty else block at func end - if (stmt->list.size() > 0 && stmt->list.back() == ast::kind::asm_jump) - { - if (stmt->list.back().as_jump->value == blk.loc_end) - stmt->list.pop_back(); - } - blocks_.push_back(blk); decompile_statements(stmt); @@ -1915,17 +1908,47 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) // if block is a loop check break, continue if (stmt->list.at(j).as_jump->value == blocks_.back().loc_continue) { - // last if/else inside a loop still trigger this :( - decompile_if(stmt, i, j); + // check for if/else or if/continue + if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::stmt_return) + { + // block ends with a return, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (j - i > 1 && stmt->list.at(j - 1) == ast::kind::asm_jump) + { + if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_break) + { + // block ends with a break, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + else if (stmt->list.at(j - 1).as_jump->value == blocks_.back().loc_continue) + { + // if { break/return } else { continue } at loop block end + if (j - i > 2 && (stmt->list.at(j - 2) == ast::kind::asm_jump || stmt->list.at(j - 2) == ast::kind::stmt_return)) + { + decompile_if(stmt, i, j); + } + else + { + // block ends with a continue, so jump belows to if/else + decompile_ifelse(stmt, i, j); + } + } + else + { + // jump belows to if/continue + decompile_if(stmt, i, j); + } + } + else + { // last if/else inside a loop still trigger this :( + decompile_if(stmt, i, j); + } } else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_break) { decompile_if(stmt, i, j); } - else if (stmt->list.at(j).as_jump->value == blocks_.back().loc_end) - { - decompile_ifelse(stmt, i, j); - } else if (stmt->list.at(j).as_jump->value == entry.as_cond->value) { if (find_location_reference(stmt, i + 1, j, entry.as_cond->value)) @@ -1940,7 +1963,7 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt) } else { - decompile_ifelse(stmt, i, j); // TODO: if else block is empty, convert it to only if! + decompile_ifelse(stmt, i, j); } } else if (stmt->list.at(j) == ast::kind::stmt_return && stmt->list.at(j).as_return->expr == ast::kind::null) @@ -2015,6 +2038,10 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) auto stmt = ast::stmt(std::make_unique(loc)); block->list.insert(block->list.begin() + i, std::move(stmt)); } + else + { + printf("WARNING: unresolved jump to '%s', maybe incomplete for loop\n", jump_loc.data()); + } } } }