From c44c54f8157c5346a66c162f2df8331d741369e2 Mon Sep 17 00:00:00 2001 From: xensik Date: Sun, 17 Jul 2022 13:49:31 +0200 Subject: [PATCH] decompiler support for tuples --- src/h1/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/h1/xsk/decompiler.hpp | 8 +-- src/h2/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/h2/xsk/decompiler.hpp | 8 +-- src/iw5/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/iw5/xsk/decompiler.hpp | 8 +-- src/iw6/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/iw6/xsk/decompiler.hpp | 8 +-- src/iw7/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/iw7/xsk/decompiler.hpp | 8 +-- src/iw8/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/iw8/xsk/decompiler.hpp | 8 +-- src/s1/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/s1/xsk/decompiler.hpp | 8 +-- src/s2/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/s2/xsk/decompiler.hpp | 8 +-- src/s4/xsk/decompiler.cpp | 99 +++++++++++++++++++++++++++++----- src/s4/xsk/decompiler.hpp | 8 +-- src/utils/xsk/gsc/nodetree.cpp | 17 ++++++ src/utils/xsk/gsc/nodetree.hpp | 15 ++++++ 20 files changed, 860 insertions(+), 135 deletions(-) diff --git a/src/h1/xsk/decompiler.cpp b/src/h1/xsk/decompiler.cpp index 456ae268..26447230 100644 --- a/src/h1/xsk/decompiler.cpp +++ b/src/h1/xsk/decompiler.cpp @@ -1338,7 +1338,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1607,7 +1607,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1783,6 +1783,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -1987,6 +1988,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3077,17 +3139,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3316,18 +3381,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/h1/xsk/decompiler.hpp b/src/h1/xsk/decompiler.hpp index 55cf689e..be5080d9 100644 --- a/src/h1/xsk/decompiler.hpp +++ b/src/h1/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/h2/xsk/decompiler.cpp b/src/h2/xsk/decompiler.cpp index e7a07083..80e7b70d 100644 --- a/src/h2/xsk/decompiler.cpp +++ b/src/h2/xsk/decompiler.cpp @@ -1338,7 +1338,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1607,7 +1607,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1783,6 +1783,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -1987,6 +1988,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3077,17 +3139,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3316,18 +3381,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/h2/xsk/decompiler.hpp b/src/h2/xsk/decompiler.hpp index cc09f43c..61fb3ee6 100644 --- a/src/h2/xsk/decompiler.hpp +++ b/src/h2/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/iw5/xsk/decompiler.cpp b/src/iw5/xsk/decompiler.cpp index 51f48aa2..38bcb6d5 100644 --- a/src/iw5/xsk/decompiler.cpp +++ b/src/iw5/xsk/decompiler.cpp @@ -1332,7 +1332,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1601,7 +1601,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1777,6 +1777,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -1981,6 +1982,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3071,17 +3133,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3310,18 +3375,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/iw5/xsk/decompiler.hpp b/src/iw5/xsk/decompiler.hpp index 9b973206..9b739090 100644 --- a/src/iw5/xsk/decompiler.hpp +++ b/src/iw5/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/iw6/xsk/decompiler.cpp b/src/iw6/xsk/decompiler.cpp index 32a52619..039cbce8 100644 --- a/src/iw6/xsk/decompiler.cpp +++ b/src/iw6/xsk/decompiler.cpp @@ -1332,7 +1332,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1601,7 +1601,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1777,6 +1777,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -1981,6 +1982,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3071,17 +3133,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3310,18 +3375,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/iw6/xsk/decompiler.hpp b/src/iw6/xsk/decompiler.hpp index 05ab0ee4..6d4378cf 100644 --- a/src/iw6/xsk/decompiler.hpp +++ b/src/iw6/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/iw7/xsk/decompiler.cpp b/src/iw7/xsk/decompiler.cpp index 4232735a..057165aa 100644 --- a/src/iw7/xsk/decompiler.cpp +++ b/src/iw7/xsk/decompiler.cpp @@ -1332,7 +1332,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1601,7 +1601,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1777,6 +1777,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -1981,6 +1982,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3071,17 +3133,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3310,18 +3375,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/iw7/xsk/decompiler.hpp b/src/iw7/xsk/decompiler.hpp index 477ef884..8541a610 100644 --- a/src/iw7/xsk/decompiler.hpp +++ b/src/iw7/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/iw8/xsk/decompiler.cpp b/src/iw8/xsk/decompiler.cpp index 9c6e098b..04c69c8f 100644 --- a/src/iw8/xsk/decompiler.cpp +++ b/src/iw8/xsk/decompiler.cpp @@ -1338,7 +1338,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1607,7 +1607,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1814,6 +1814,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -2018,6 +2019,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3114,17 +3176,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3353,18 +3418,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/iw8/xsk/decompiler.hpp b/src/iw8/xsk/decompiler.hpp index de57be0d..fa1b5903 100644 --- a/src/iw8/xsk/decompiler.hpp +++ b/src/iw8/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/s1/xsk/decompiler.cpp b/src/s1/xsk/decompiler.cpp index 4abbeb8a..97a25c93 100644 --- a/src/s1/xsk/decompiler.cpp +++ b/src/s1/xsk/decompiler.cpp @@ -1338,7 +1338,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1607,7 +1607,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1783,6 +1783,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -1987,6 +1988,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3077,17 +3139,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3316,18 +3381,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/s1/xsk/decompiler.hpp b/src/s1/xsk/decompiler.hpp index 7662e7b1..9c1bc4ef 100644 --- a/src/s1/xsk/decompiler.hpp +++ b/src/s1/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/s2/xsk/decompiler.cpp b/src/s2/xsk/decompiler.cpp index d677548d..95768bfb 100644 --- a/src/s2/xsk/decompiler.cpp +++ b/src/s2/xsk/decompiler.cpp @@ -1338,7 +1338,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1607,7 +1607,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1790,6 +1790,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -1994,6 +1995,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3084,17 +3146,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3323,18 +3388,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/s2/xsk/decompiler.hpp b/src/s2/xsk/decompiler.hpp index daf9445c..6d950973 100644 --- a/src/s2/xsk/decompiler.hpp +++ b/src/s2/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/s4/xsk/decompiler.cpp b/src/s4/xsk/decompiler.cpp index 20e9adf6..d0248ce8 100644 --- a/src/s4/xsk/decompiler.cpp +++ b/src/s4/xsk/decompiler.cpp @@ -1338,7 +1338,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) auto obj = ast::expr(std::move(stack_.top())); stack_.pop(); auto event = ast::expr(std::move(stack_.top())); stack_.pop(); loc = event.as_node->loc(); - auto stmt = std::make_unique(loc, std::move(obj) , std::move(event)); + auto stmt = std::make_unique(loc, std::move(obj), std::move(event)); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1607,7 +1607,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) break; case opcode::OP_ClearLocalVariableFieldCached0: { - auto stmt = std::make_unique(loc,"0"); + auto stmt = std::make_unique(loc, "0"); func_->stmt->list.push_back(ast::stmt(std::move(stmt))); } break; @@ -1814,6 +1814,7 @@ void decompiler::decompile_statements(const ast::stmt_list::ptr& stmt) decompile_switches(stmt); decompile_ifelses(stmt); decompile_aborts(stmt); + decompile_tuples(stmt); } void decompiler::decompile_infinites(const ast::stmt_list::ptr& stmt) @@ -2018,6 +2019,67 @@ void decompiler::decompile_aborts(const ast::stmt_list::ptr& block) } } +void decompiler::decompile_tuples(const ast::stmt_list::ptr& block) +{ + for (auto i = 1u; i < block->list.size(); i++) + { + if (block->list.at(i) == ast::kind::asm_clear) + { + auto j = i - 1; + auto found = false, done = false; + + while (j >= 0 && block->list.at(j) == ast::kind::stmt_assign) + { + auto& expr = block->list.at(j).as_assign->expr; + + if (expr != ast::kind::expr_assign_equal) + break; + + if (!done) + { + if (expr.as_assign_equal->rvalue != ast::kind::expr_array) + break; + + if (expr.as_assign_equal->rvalue.as_array->key != ast::kind::expr_integer) + break; + + if (expr.as_assign_equal->rvalue.as_array->key.as_integer->value == "0") + done = true; + + j--; + } + else + { + if (expr.as_assign_equal->lvalue == ast::kind::asm_create || expr.as_assign_equal->lvalue == ast::kind::asm_access) + found = true; + + break; + } + } + + if (found) + { + auto& stmt = block->list.at(j); // temp = expr; + auto new_expr = std::make_unique(stmt.loc()); + new_expr->temp = std::move(stmt.as_assign->expr.as_assign_equal->lvalue); + j++; + + while (j < i) + { + new_expr->list.push_back(std::move(block->list.at(j).as_assign->expr.as_assign_equal->lvalue)); + block->list.erase(block->list.begin() + j); + i--; + } + + block->list.erase(block->list.begin() + j); // clear temp array + i--; + + stmt.as_assign->expr.as_assign_equal->lvalue = ast::expr(std::move(new_expr)); + } + } + } +} + void decompiler::decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end) { block blk; @@ -3114,17 +3176,20 @@ void decompiler::process_expr(ast::expr& expr, const block::ptr& blk) case ast::kind::expr_add_array: process_expr_add_array(expr.as_add_array, blk); break; - case ast::kind::expr_array: - process_array_variable(expr.as_array, blk); - break; - case ast::kind::expr_field: - process_field_variable(expr.as_field, blk); - break; case ast::kind::expr_size: process_expr_size(expr.as_size, blk); break; + case ast::kind::expr_tuple: + process_expr_tuple(expr.as_tuple, blk); + break; + case ast::kind::expr_array: + process_expr_array(expr.as_array, blk); + break; + case ast::kind::expr_field: + process_expr_field(expr.as_field, blk); + break; case ast::kind::expr_identifier: - process_local_variable(expr.as_identifier, blk); + process_expr_local(expr.as_identifier, blk); break; case ast::kind::expr_vector: process_expr_vector(expr.as_vector, blk); @@ -3353,18 +3418,28 @@ void decompiler::process_expr_size(const ast::expr_size::ptr& expr, const block: process_expr(expr->obj, blk); } -void decompiler::process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk) +{ + process_expr(expr->temp, blk); + + for (auto& entry : expr->list) + { + process_expr(entry, blk); + } +} + +void decompiler::process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk) { process_expr(expr->key, blk); process_expr(expr->obj, blk); } -void decompiler::process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk) +void decompiler::process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk) { process_expr(expr->obj, blk); } -void decompiler::process_local_variable(const ast::expr_identifier::ptr&, const block::ptr&) +void decompiler::process_expr_local(const ast::expr_identifier::ptr&, const block::ptr&) { return; } diff --git a/src/s4/xsk/decompiler.hpp b/src/s4/xsk/decompiler.hpp index 3bdd91b8..74068e0f 100644 --- a/src/s4/xsk/decompiler.hpp +++ b/src/s4/xsk/decompiler.hpp @@ -34,6 +34,7 @@ private: void decompile_switches(const ast::stmt_list::ptr& stmt); void decompile_ifelses(const ast::stmt_list::ptr& stmt); void decompile_aborts(const ast::stmt_list::ptr& stmt); + void decompile_tuples(const ast::stmt_list::ptr& stmt); void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); void decompile_last_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end); @@ -89,9 +90,10 @@ private: void process_expr_arguments(const ast::expr_arguments::ptr& expr, const block::ptr& blk); void process_expr_add_array(const ast::expr_add_array::ptr& expr, const block::ptr& blk); void process_expr_size(const ast::expr_size::ptr& expr, const block::ptr& blk); - void process_array_variable(const ast::expr_array::ptr& expr, const block::ptr& blk); - void process_field_variable(const ast::expr_field::ptr& expr, const block::ptr& blk); - void process_local_variable(const ast::expr_identifier::ptr& expr, const block::ptr& blk); + void process_expr_tuple(const ast::expr_tuple::ptr& expr, const block::ptr& blk); + void process_expr_array(const ast::expr_array::ptr& expr, const block::ptr& blk); + void process_expr_field(const ast::expr_field::ptr& expr, const block::ptr& blk); + void process_expr_local(const ast::expr_identifier::ptr& expr, const block::ptr& blk); void process_expr_vector(const ast::expr_vector::ptr& vec, const block::ptr& blk); void process_var_create(ast::expr& expr, const block::ptr& blk, bool fromstmt = false); void process_var_access(ast::expr& expr, const block::ptr& blk); diff --git a/src/utils/xsk/gsc/nodetree.cpp b/src/utils/xsk/gsc/nodetree.cpp index fce10b8f..ddd0ef7a 100644 --- a/src/utils/xsk/gsc/nodetree.cpp +++ b/src/utils/xsk/gsc/nodetree.cpp @@ -206,6 +206,9 @@ expr_field::expr_field(const location& loc, expr obj, expr_identifier::ptr field expr_array::expr_array(expr obj, expr key) : node(kind::expr_array), obj(std::move(obj)), key(std::move(key)) {} expr_array::expr_array(const location& loc, expr obj, expr key) : node(kind::expr_array, loc), obj(std::move(obj)), key(std::move(key)) {} +expr_tuple::expr_tuple() : node(kind::expr_tuple) {} +expr_tuple::expr_tuple(const location& loc) : node(kind::expr_tuple, loc) {} + expr_reference::expr_reference(expr_path::ptr path, expr_identifier::ptr name) : node(kind::expr_reference), path(std::move(path)), name(std::move(name)) {} expr_reference::expr_reference(const location& loc, expr_path::ptr path, expr_identifier::ptr name) : node(kind::expr_reference, loc), path(std::move(path)), name(std::move(name)) {} @@ -606,6 +609,19 @@ auto expr_array::print() const -> std::string return obj.print() + "[" + key.print() + "]"; } +auto expr_tuple::print() const -> std::string +{ + std::string data = "["; + + for (const auto& entry : list) + { + data += " " + entry.print(); + data += (&entry != &list.back()) ? "," : " "; + } + + return data += "]"; +} + auto expr_reference::print() const -> std::string { return path->print() + "::" + name->print(); @@ -1576,6 +1592,7 @@ expr::~expr() case kind::expr_size: as_size.~unique_ptr(); return; case kind::expr_field: as_field.~unique_ptr(); return; case kind::expr_array: as_array.~unique_ptr(); return; + case kind::expr_tuple: as_tuple.~unique_ptr(); return; case kind::expr_reference: as_reference.~unique_ptr(); return; case kind::expr_arguments: as_arguments.~unique_ptr(); return; case kind::expr_parameters: as_parameters.~unique_ptr(); return; diff --git a/src/utils/xsk/gsc/nodetree.hpp b/src/utils/xsk/gsc/nodetree.hpp index dca9d6f6..e83d6780 100644 --- a/src/utils/xsk/gsc/nodetree.hpp +++ b/src/utils/xsk/gsc/nodetree.hpp @@ -33,6 +33,7 @@ enum class kind expr_size, expr_field, expr_array, + expr_tuple, expr_reference, expr_istrue, expr_isdefined, @@ -152,6 +153,7 @@ struct expr_paren; struct expr_size; struct expr_field; struct expr_array; +struct expr_tuple; struct expr_reference; struct expr_istrue; struct expr_isdefined; @@ -292,6 +294,7 @@ union expr std::unique_ptr as_size; std::unique_ptr as_field; std::unique_ptr as_array; + std::unique_ptr as_tuple; std::unique_ptr as_reference; std::unique_ptr as_istrue; std::unique_ptr as_isdefined; @@ -718,6 +721,18 @@ struct expr_array : public node friend bool operator==(const expr_array& lhs, const expr_array& rhs); }; +struct expr_tuple : public node +{ + using ptr = std::unique_ptr; + + std::vector list; + ast::expr temp; + + expr_tuple(); + expr_tuple(const location& loc); + auto print() const -> std::string override; +}; + struct expr_reference : public node { using ptr = std::unique_ptr;