From aaa54304ccb49bf25b9a02a4822d73a72bf9b657 Mon Sep 17 00:00:00 2001 From: xensik Date: Sat, 22 Jan 2022 22:27:06 +0100 Subject: [PATCH] decompile do-while statements --- src/h1/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/h1/xsk/decompiler.hpp | 1 + src/h2/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/h2/xsk/decompiler.hpp | 1 + src/iw5/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/iw5/xsk/decompiler.hpp | 1 + src/iw6/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/iw6/xsk/decompiler.hpp | 1 + src/iw7/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/iw7/xsk/decompiler.hpp | 1 + src/iw8/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/iw8/xsk/decompiler.hpp | 1 + src/s1/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/s1/xsk/decompiler.hpp | 1 + src/s2/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/s2/xsk/decompiler.hpp | 1 + src/s4/xsk/decompiler.cpp | 51 +++++++++++++++++++++++++++++++++++--- src/s4/xsk/decompiler.hpp | 1 + 18 files changed, 432 insertions(+), 36 deletions(-) diff --git a/src/h1/xsk/decompiler.cpp b/src/h1/xsk/decompiler.cpp index 487de514..f406c2ab 100644 --- a/src/h1/xsk/decompiler.cpp +++ b/src/h1/xsk/decompiler.cpp @@ -1794,7 +1794,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1818,10 +1822,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2202,6 +2214,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/h1/xsk/decompiler.hpp b/src/h1/xsk/decompiler.hpp index 6d3bc1cc..9c050de8 100644 --- a/src/h1/xsk/decompiler.hpp +++ b/src/h1/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/h2/xsk/decompiler.cpp b/src/h2/xsk/decompiler.cpp index cac833ea..7d760edb 100644 --- a/src/h2/xsk/decompiler.cpp +++ b/src/h2/xsk/decompiler.cpp @@ -1794,7 +1794,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1818,10 +1822,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2202,6 +2214,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/h2/xsk/decompiler.hpp b/src/h2/xsk/decompiler.hpp index 0d2c8fe4..ba287c60 100644 --- a/src/h2/xsk/decompiler.hpp +++ b/src/h2/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/iw5/xsk/decompiler.cpp b/src/iw5/xsk/decompiler.cpp index 74d5f067..86b3818c 100644 --- a/src/iw5/xsk/decompiler.cpp +++ b/src/iw5/xsk/decompiler.cpp @@ -1788,7 +1788,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1812,10 +1816,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2196,6 +2208,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/iw5/xsk/decompiler.hpp b/src/iw5/xsk/decompiler.hpp index 5f443c95..3bc72e9b 100644 --- a/src/iw5/xsk/decompiler.hpp +++ b/src/iw5/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/iw6/xsk/decompiler.cpp b/src/iw6/xsk/decompiler.cpp index 325eb4a0..9475cd8d 100644 --- a/src/iw6/xsk/decompiler.cpp +++ b/src/iw6/xsk/decompiler.cpp @@ -1788,7 +1788,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1812,10 +1816,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2196,6 +2208,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/iw6/xsk/decompiler.hpp b/src/iw6/xsk/decompiler.hpp index 03adc52a..3d09c52f 100644 --- a/src/iw6/xsk/decompiler.hpp +++ b/src/iw6/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/iw7/xsk/decompiler.cpp b/src/iw7/xsk/decompiler.cpp index 82105bae..1f14af60 100644 --- a/src/iw7/xsk/decompiler.cpp +++ b/src/iw7/xsk/decompiler.cpp @@ -1788,7 +1788,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1812,10 +1816,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2196,6 +2208,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/iw7/xsk/decompiler.hpp b/src/iw7/xsk/decompiler.hpp index e90eb754..44b31df5 100644 --- a/src/iw7/xsk/decompiler.hpp +++ b/src/iw7/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/iw8/xsk/decompiler.cpp b/src/iw8/xsk/decompiler.cpp index 9efcee6b..a920d1d8 100644 --- a/src/iw8/xsk/decompiler.cpp +++ b/src/iw8/xsk/decompiler.cpp @@ -1825,7 +1825,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1849,10 +1853,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2233,6 +2245,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/iw8/xsk/decompiler.hpp b/src/iw8/xsk/decompiler.hpp index 8dda6574..32412de3 100644 --- a/src/iw8/xsk/decompiler.hpp +++ b/src/iw8/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/s1/xsk/decompiler.cpp b/src/s1/xsk/decompiler.cpp index 8c0e0e17..a16ecf16 100644 --- a/src/s1/xsk/decompiler.cpp +++ b/src/s1/xsk/decompiler.cpp @@ -1794,7 +1794,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1818,10 +1822,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2202,6 +2214,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/s1/xsk/decompiler.hpp b/src/s1/xsk/decompiler.hpp index b1844a91..63f39ef2 100644 --- a/src/s1/xsk/decompiler.hpp +++ b/src/s1/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/s2/xsk/decompiler.cpp b/src/s2/xsk/decompiler.cpp index 844c3d37..46028fcf 100644 --- a/src/s2/xsk/decompiler.cpp +++ b/src/s2/xsk/decompiler.cpp @@ -1801,7 +1801,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1825,10 +1829,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2209,6 +2221,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/s2/xsk/decompiler.hpp b/src/s2/xsk/decompiler.hpp index cab32009..72c5fda8 100644 --- a/src/s2/xsk/decompiler.hpp +++ b/src/s2/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin); diff --git a/src/s4/xsk/decompiler.cpp b/src/s4/xsk/decompiler.cpp index 9070300b..144be4b6 100644 --- a/src/s4/xsk/decompiler.cpp +++ b/src/s4/xsk/decompiler.cpp @@ -1825,7 +1825,11 @@ void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) auto break_loc = last_location_index(stmt, i) ? blocks_.back().loc_end : stmt->list.at(i + 1).loc().label(); auto start = find_location_index(stmt, stmt->list.at(i).as_jump_back->value); - if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) + if (i > 0 && stmt->list.at(i - 1).as_node->kind() == ast::kind::asm_jump_cond) + { + continue; + } + else if (stmt->list.at(start).as_node->kind() != ast::kind::asm_jump_cond) { decompile_infinite(stmt, start, i); i = start; @@ -1849,10 +1853,18 @@ void decompiler::decompile_loops(const ast::stmt_list::ptr& stmt) { auto j = (entry.as_cond->value == blocks_.back().loc_end) ? (stmt->list.size() - 1) : (find_location_index(stmt, entry.as_cond->value) - 1); - if (stmt->list.at(j) == ast::kind::asm_jump_back && stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + if (stmt->list.at(j) == ast::kind::asm_jump_back) { - decompile_loop(stmt, i, j); - i = 0; + if (j == i + 1) + { + decompile_dowhile(stmt, i, j); + i = 0; + } + else if (stmt->list.at(i).loc().label() == stmt->list.at(j).as_jump_back->value) + { + decompile_loop(stmt, i, j); + i = 0; + } } } } @@ -2233,6 +2245,37 @@ void decompiler::decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); } +void decompiler::decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) +{ + block blk; + blk.loc_break = stmt->list.at(begin).as_cond->value; + blk.loc_end = stmt->list.at(begin).loc().label(); + blk.loc_continue = stmt->list.at(begin).loc().label(); + + auto test = std::move(stmt->list.at(begin).as_cond->expr); + begin = find_location_index(stmt, stmt->list.at(end).as_jump_back->value); + auto loc = stmt->list.at(begin).loc(); + + end--; + stmt->list.erase(stmt->list.begin() + end); // remove 'test' + stmt->list.erase(stmt->list.begin() + end); // remove 'jumpback' + + auto while_stmt = std::make_unique(loc); + + for (auto i = begin; i < end; i++) + { + while_stmt->list.push_back(std::move(stmt->list[begin])); + stmt->list.erase(stmt->list.begin() + begin); + } + + blocks_.push_back(blk); + decompile_statements(while_stmt); + blocks_.pop_back(); + + auto new_stmt = ast::stmt(std::make_unique(loc, std::move(test), ast::stmt(std::move(while_stmt)))); + stmt->list.insert(stmt->list.begin() + begin, std::move(new_stmt)); +} + void decompiler::decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end) { block blk; diff --git a/src/s4/xsk/decompiler.hpp b/src/s4/xsk/decompiler.hpp index 6e93d471..bc5dfb80 100644 --- a/src/s4/xsk/decompiler.hpp +++ b/src/s4/xsk/decompiler.hpp @@ -40,6 +40,7 @@ private: void decompile_infinite(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_loop(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_while(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); + void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_for(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_foreach(const ast::stmt_list::ptr& stmt, std::uint32_t begin, std::uint32_t end); void decompile_switch(const ast::stmt_list::ptr& stmt, std::uint32_t begin);