diff --git a/src/h1/xsk/decompiler.cpp b/src/h1/xsk/decompiler.cpp index 487de51..f406c2a 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 6d3bc1c..9c050de 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 cac833e..7d760ed 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 0d2c8fe..ba287c6 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 74d5f06..86b3818 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 5f443c9..3bc72e9 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 325eb4a..9475cd8 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 03adc52..3d09c52 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 82105ba..1f14af6 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 e90eb75..44b31df 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 9efcee6..a920d1d 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 8dda657..32412de 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 8c0e0e1..a16ecf1 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 b1844a9..63f39ef 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 844c3d3..46028fc 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 cab3200..72c5fda 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 9070300..144be4b 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 6e93d47..bc5dfb8 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);