mirror of
https://github.com/open-goal/jak-project
synced 2026-07-09 23:01:56 -04:00
wip: better stack var support (#4222)
Closes #736 --------- Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,26 @@
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
|
||||
namespace decompiler {
|
||||
namespace {
|
||||
bool nonempty_intersection(const RegSet& a, const RegSet& b) {
|
||||
for (auto x : a) {
|
||||
if (b.find(x) != b.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool can_inline_non_seq_source(const RegisterAccess& src, const Env& env) {
|
||||
if (!is_stack_slot_access(src)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto& use_def = env.get_use_def_info(src);
|
||||
return use_def.use_count() == 1 && use_def.def_count() == 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string FormStack::StackEntry::print(const Env& env) const {
|
||||
if (destination.has_value()) {
|
||||
ASSERT(source && !elt);
|
||||
@@ -116,19 +136,61 @@ Form* FormStack::pop_reg(const RegisterAccess& var,
|
||||
const Env& env,
|
||||
bool allow_side_effects,
|
||||
int begin_idx) {
|
||||
return pop_reg(var.reg(), barrier, env, allow_side_effects, begin_idx);
|
||||
}
|
||||
RegSet modified;
|
||||
size_t begin = m_stack.size();
|
||||
if (begin_idx >= 0) {
|
||||
begin = begin_idx;
|
||||
}
|
||||
for (size_t i = begin; i-- > 0;) {
|
||||
auto& entry = m_stack.at(i);
|
||||
if (entry.active) {
|
||||
if (entry.destination.has_value() && same_expression_var(*entry.destination, var)) {
|
||||
entry.source->get_modified_regs(modified);
|
||||
if (!allow_side_effects && entry.source->has_side_effects()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (nonempty_intersection(modified, barrier)) {
|
||||
return nullptr;
|
||||
}
|
||||
entry.active = false;
|
||||
ASSERT(entry.source);
|
||||
if (entry.non_seq_source.has_value()) {
|
||||
ASSERT(entry.sequence_point == false);
|
||||
if (can_inline_non_seq_source(*entry.non_seq_source, env)) {
|
||||
auto result = pop_reg(*entry.non_seq_source, barrier, env, allow_side_effects, i);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool nonempty_intersection(const RegSet& a, const RegSet& b) {
|
||||
for (auto x : a) {
|
||||
if (b.find(x) != b.end()) {
|
||||
return true;
|
||||
return entry.source;
|
||||
} else {
|
||||
if (entry.sequence_point) {
|
||||
return nullptr;
|
||||
}
|
||||
if (entry.source) {
|
||||
ASSERT(!entry.elt);
|
||||
entry.source->get_modified_regs(modified);
|
||||
if (!allow_side_effects) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
ASSERT(entry.elt);
|
||||
entry.elt->get_modified_regs(modified);
|
||||
if (!allow_side_effects && entry.elt->has_side_effects()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (entry.destination.has_value() && same_expression_var(*entry.destination, var)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Form* FormStack::pop_reg(Register reg,
|
||||
const RegSet& barrier,
|
||||
@@ -164,13 +226,15 @@ Form* FormStack::pop_reg(Register reg,
|
||||
ASSERT(entry.source);
|
||||
if (entry.non_seq_source.has_value()) {
|
||||
ASSERT(entry.sequence_point == false);
|
||||
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env, allow_side_effects, i);
|
||||
if (result) {
|
||||
if (found_orig_out) {
|
||||
*found_orig_out = true;
|
||||
*orig_out = *entry.destination;
|
||||
if (can_inline_non_seq_source(*entry.non_seq_source, env)) {
|
||||
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env, allow_side_effects, i);
|
||||
if (result) {
|
||||
if (found_orig_out) {
|
||||
*found_orig_out = true;
|
||||
*orig_out = *entry.destination;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +389,7 @@ std::vector<FormElement*> FormStack::rewrite(FormPool& pool, const Env& env) con
|
||||
while (keep_going && !result.empty()) {
|
||||
keep_going = false;
|
||||
auto last_op_as_set = dynamic_cast<SetVarElement*>(result.back());
|
||||
if (last_op_as_set && last_op_as_set->dst().reg() == var_to_get.reg()) {
|
||||
if (last_op_as_set && same_expression_var(last_op_as_set->dst(), var_to_get)) {
|
||||
result.pop_back();
|
||||
auto as_one = dynamic_cast<SimpleExpressionElement*>(
|
||||
last_op_as_set->src()->try_as_single_element());
|
||||
@@ -384,7 +448,7 @@ std::optional<RegisterAccess> rewrite_to_get_var(std::vector<FormElement*>& defa
|
||||
while (keep_going && !default_result.empty()) {
|
||||
keep_going = false;
|
||||
auto last_op_as_set = dynamic_cast<SetVarElement*>(default_result.back());
|
||||
if (last_op_as_set && last_op_as_set->dst().reg() == var_to_get.reg() &&
|
||||
if (last_op_as_set && same_expression_var(last_op_as_set->dst(), var_to_get) &&
|
||||
(first || last_op_as_set->info().is_compactable)) {
|
||||
default_result.pop_back();
|
||||
auto as_one =
|
||||
|
||||
Reference in New Issue
Block a user