decompiler fixes

This commit is contained in:
water111
2026-07-26 14:43:29 -04:00
parent e0dc11554d
commit e980b16d88
18 changed files with 45864 additions and 4826 deletions
+43 -3
View File
@@ -562,6 +562,18 @@ FunctionVariableDefinitions Env::local_var_type_list(const Form* top_level_form,
std::vector<goos::Object> elts;
elts.push_back(pretty_print::to_symbol("local-vars"));
int count = 0;
std::unordered_map<std::string, std::string> emitted_local_types;
// A user may deliberately give an argument and its saved stack copy the same preferred name.
// Treat the argument as the existing lexical binding so the spill is not emitted as a second
// local with the same name.
for (int i = 0; i < nargs_to_ignore; i++) {
auto remapped = m_var_remap.find(get_reg_name(i));
if (remapped != m_var_remap.end() && func && i < func->type.arg_count() - 1) {
emitted_local_types.emplace(remapped->second, func->type.get_arg(i).print());
}
}
for (auto& x : vars) {
if (x.reg_id.reg.get_kind() == Reg::GPR && x.reg_id.reg.get_gpr() < Reg::A0 + nargs_to_ignore &&
x.reg_id.reg.get_gpr() >= Reg::A0 && x.reg_id.id == 0) {
@@ -579,12 +591,27 @@ FunctionVariableDefinitions Env::local_var_type_list(const Form* top_level_form,
lookup_name = remapped->second;
}
if (m_vars_defined_in_let.find(lookup_name) != m_vars_defined_in_let.end()) {
if (m_vars_defined_in_let.find(x.name()) != m_vars_defined_in_let.end() ||
m_vars_defined_in_let.find(lookup_name) != m_vars_defined_in_let.end()) {
continue;
}
auto type_name = x.type.typespec().print();
auto retype = m_var_retype.find(x.name());
if (retype != m_var_retype.end()) {
type_name = retype->second.print();
}
const auto [existing, inserted] = emitted_local_types.emplace(lookup_name, type_name);
if (!inserted) {
if (existing->second != type_name) {
lg::warn("Local variable {} has conflicting remapped types {} and {}", lookup_name,
existing->second, type_name);
}
continue;
}
count++;
elts.push_back(pretty_print::build_list(lookup_name, x.type.typespec().print()));
elts.push_back(pretty_print::build_list(lookup_name, type_name));
}
// sort in increasing offset.
@@ -602,7 +629,20 @@ FunctionVariableDefinitions Env::local_var_type_list(const Form* top_level_form,
if (m_vars_defined_in_let.find(x.name()) != m_vars_defined_in_let.end()) {
continue;
}
elts.push_back(pretty_print::build_list(x.name(), x.typespec.print()));
auto type_name = x.typespec.print();
auto retype = m_var_retype.find(x.name());
if (retype != m_var_retype.end()) {
type_name = retype->second.print();
}
const auto [existing, inserted] = emitted_local_types.emplace(x.name(), type_name);
if (!inserted) {
if (existing->second != type_name) {
lg::warn("Local variable {} has conflicting remapped types {} and {}", x.name(),
existing->second, type_name);
}
continue;
}
elts.push_back(pretty_print::build_list(x.name(), type_name));
count++;
}
+7 -5
View File
@@ -131,11 +131,13 @@ FormElement* handle_get_property_data_or_structure(const std::vector<Form*>& for
time = nullptr;
}
// get the default value. It must be (the-as pointer #f)
// get the default value. The ordinary macro default can be omitted.
Form* default_value = forms.at(4);
// but let's see if it's 0, because that's the default in the macro
if (default_value->to_string(env) != expcted_default) {
lg::error("fail data: bad default {}", default_value->to_string(env));
if (default_value->to_string(env) == expcted_default) {
default_value = nullptr;
} else if (kind != ResLumpMacroElement::Kind::STRUCT ||
env.version != GameVersion::Jak1) {
// Only Jak 1's res-lump-struct macro currently exposes a custom default.
return nullptr;
}
@@ -153,7 +155,7 @@ FormElement* handle_get_property_data_or_structure(const std::vector<Form*>& for
}
return pool.alloc_element<ResLumpMacroElement>(kind, lump_object, property_name,
nullptr, // default, must be #f
default_value,
tag_pointer, time, default_type);
}
} // namespace
+1
View File
@@ -1555,6 +1555,7 @@ class StackSpillStoreElement : public FormElement {
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
const std::optional<TypeSpec>& cast_type() const { return m_cast_type; }
const RegisterAccess& access() const { return m_access; }
const SimpleAtom& value() const { return m_value; }
int stack_offset() const { return m_stack_offset; }
private:
+16 -5
View File
@@ -2746,13 +2746,19 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
if (src_as_se) {
if (src_as_se->expr().kind() == SimpleExpression::Kind::IDENTITY &&
src_as_se->expr().get_arg(0).is_var()) {
// this can happen late in the case of coloring moves which are also gpr -> fpr's
// so they don't get caught by SetVarOp::get_as_form's check.
if (env.op_id_is_eliminated_coloring_move(src_as_se->expr().get_arg(0).var().idx())) {
const auto src_var = src_as_se->expr().get_arg(0).var();
if (env.get_variable_name(m_dst) == env.get_variable_name(src_var) &&
env.get_variable_type(m_dst, true) == env.get_variable_type(src_var, true)) {
m_var_info.is_eliminated_coloring_move = true;
}
auto var = src_as_se->expr().get_arg(0).var();
// this can happen late in the case of coloring moves which are also gpr -> fpr's
// so they don't get caught by SetVarOp::get_as_form's check.
if (env.op_id_is_eliminated_coloring_move(src_var.idx())) {
m_var_info.is_eliminated_coloring_move = true;
}
auto var = src_var;
bool is_consumed_reg_move = false;
if (is_stack_slot_access(var)) {
auto& use_def = env.get_use_def_info(var);
@@ -2793,7 +2799,12 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
// stripped off by update_children_from_stack.
if (src_as_se->expr().kind() == SimpleExpression::Kind::IDENTITY &&
src_as_se->expr().get_arg(0).is_var()) {
if (env.op_id_is_eliminated_coloring_move(src_as_se->expr().get_arg(0).var().idx())) {
const auto src_var = src_as_se->expr().get_arg(0).var();
if (env.get_variable_name(m_dst) == env.get_variable_name(src_var) &&
env.get_variable_type(m_dst, true) == env.get_variable_type(src_var, true)) {
m_var_info.is_eliminated_coloring_move = true;
}
if (env.op_id_is_eliminated_coloring_move(src_var.idx())) {
m_var_info.is_eliminated_coloring_move = true;
}
}
+5 -1
View File
@@ -64,6 +64,7 @@ struct LetRewriteStats {
int abs2 = 0;
int unused = 0;
int ja = 0;
int ja_play = 0;
int case_no_else = 0;
int case_with_else = 0;
int set_vector = 0;
@@ -85,7 +86,7 @@ struct LetRewriteStats {
int light_trail_tracker_spawn = 0;
int total() const {
return dotimes + countdown + abs + abs2 + unused + ja + case_no_else + case_with_else +
return dotimes + countdown + abs + abs2 + unused + ja + ja_play + case_no_else + case_with_else +
set_vector + set_vector2 + send_event + font_context_meth + proc_new + attack_info +
vector_dot + rand_float_gen + set_let + with_dma_buf_add_bucket + dma_buffer_add_gs_set +
launch_particles + call_parent_state_handler + suspend_for + font_method +
@@ -100,6 +101,7 @@ struct LetRewriteStats {
out += fmt::format(" abs: {}\n", abs);
out += fmt::format(" abs2: {}\n", abs2);
out += fmt::format(" ja: {}\n", ja);
out += fmt::format(" ja-play: {}\n", ja_play);
out += fmt::format(" set_vector: {}\n", set_vector);
out += fmt::format(" set_vector2: {}\n", set_vector2);
out += fmt::format(" set_vector3: {}\n", set_vector3);
@@ -130,6 +132,7 @@ struct LetRewriteStats {
result.abs = abs + other.abs;
result.abs2 = abs2 + other.abs2;
result.ja = ja + other.ja;
result.ja_play = ja_play + other.ja_play;
result.set_vector = set_vector + other.set_vector;
result.set_vector2 = set_vector2 + other.set_vector2;
result.case_no_else = case_no_else + other.case_no_else;
@@ -156,6 +159,7 @@ struct LetRewriteStats {
abs += other.abs;
abs2 += other.abs2;
ja += other.ja;
ja_play += other.ja_play;
set_vector += other.set_vector;
set_vector2 += other.set_vector2;
case_no_else += other.case_no_else;
@@ -791,6 +791,11 @@ void ObjectFileDB::ir2_build_expressions(int seg, const Config& config, ObjectFi
func.ir2.env.types_succeeded) {
auto name = func.name();
auto arg_config = config.function_arg_names.find(name);
if (arg_config == config.function_arg_names.end() &&
func.guessed_name.kind == FunctionName::FunctionKind::UNIDENTIFIED) {
arg_config = config.function_arg_names.find(
fmt::format("(anon-function * {})", func.guessed_name.object_name));
}
auto var_config = config.function_var_overrides.find(name);
if (convert_to_expressions(func.ir2.top_form, *func.ir2.form_pool, func,
arg_config != config.function_arg_names.end()
+25 -26
View File
@@ -1171,12 +1171,9 @@ std::unique_ptr<AtomicOp> convert_slt_2(const Instruction& i0,
auto temp = i0.get_dst(0).get_reg();
auto left = i0.get_src(0).get_reg();
auto right = i0.get_src(1).get_reg();
if (temp == left) {
if (temp == left || temp == right || left == right) {
return nullptr;
}
ASSERT(temp != left);
ASSERT(temp != right);
ASSERT(left != right);
std::unique_ptr<AtomicOp> result;
SimpleExpression::Kind kind;
if (is_gpr_3(i1, InstructionKind::MOVZ, left, right, temp)) {
@@ -1338,12 +1335,12 @@ std::unique_ptr<AtomicOp> convert_dsubu_3(const Instruction& i0,
auto a = i0.get_src(0).get_reg();
auto b = i0.get_src(1).get_reg();
auto dest = i1.get_dst(0).get_reg();
ASSERT(i1.get_src(0).is_reg(rs7()));
ASSERT(i1.get_src(1).is_imm(true_symbol_offset(version)));
ASSERT(i2.get_dst(0).get_reg() == dest);
ASSERT(i2.get_src(0).is_reg(rs7()));
ASSERT(i2.get_src(1).get_reg() == temp);
ASSERT(temp != dest);
if (!i1.get_src(0).is_reg(rs7()) ||
!i1.get_src(1).is_imm(true_symbol_offset(version)) ||
i2.get_dst(0).get_reg() != dest || !i2.get_src(0).is_reg(rs7()) ||
i2.get_src(1).get_reg() != temp || temp == dest) {
return nullptr;
}
auto kind = i2.kind == InstructionKind::MOVN ? IR2_Condition::Kind::EQUAL
: IR2_Condition::Kind::NOT_EQUAL;
std::unique_ptr<AtomicOp> result;
@@ -1397,8 +1394,9 @@ std::unique_ptr<AtomicOp> convert_slt_3(const Instruction& i0,
// delay slot
auto temp = i0.get_dst(0).get_reg();
auto dest = i1.get_src(2).get_label();
ASSERT(i1.get_src(0).get_reg() == temp);
ASSERT(i1.get_src(1).is_reg(rr0()));
if (i1.get_src(0).get_reg() != temp || !i1.get_src(1).is_reg(rr0())) {
return nullptr;
}
IR2_Condition condition;
if (s1 == rr0()) {
@@ -1430,12 +1428,12 @@ std::unique_ptr<AtomicOp> convert_slt_3(const Instruction& i0,
// movz dest, s7, temp
auto temp = i0.get_dst(0).get_reg();
auto dest = i1.get_dst(0).get_reg();
ASSERT(i1.get_src(0).is_reg(rs7()));
ASSERT(i1.get_src(1).is_imm(true_symbol_offset(version)));
ASSERT(i2.get_dst(0).get_reg() == dest);
ASSERT(i2.get_src(0).is_reg(rs7()));
ASSERT(i2.get_src(1).get_reg() == temp);
ASSERT(temp != dest);
if (!i1.get_src(0).is_reg(rs7()) ||
!i1.get_src(1).is_imm(true_symbol_offset(version)) ||
i2.get_dst(0).get_reg() != dest || !i2.get_src(0).is_reg(rs7()) ||
i2.get_src(1).get_reg() != temp || temp == dest) {
return nullptr;
}
IR2_Condition condition;
if (s1 == rr0()) {
auto kind = is_signed ? IR2_Condition::Kind::LESS_THAN_ZERO_SIGNED
@@ -1477,8 +1475,9 @@ std::unique_ptr<AtomicOp> convert_slti_3(const Instruction& i0,
// delay slot
auto temp = i0.get_dst(0).get_reg();
auto dest = i1.get_src(2).get_label();
ASSERT(i1.get_src(0).get_reg() == temp);
ASSERT(i1.get_src(1).is_reg(rr0()));
if (i1.get_src(0).get_reg() != temp || !i1.get_src(1).is_reg(rr0())) {
return nullptr;
}
auto kind =
is_signed ? IR2_Condition::Kind::LESS_THAN_SIGNED : IR2_Condition::Kind::LESS_THAN_UNSIGNED;
auto condition = IR2_Condition(kind, make_src_atom(s0, idx), s1);
@@ -1496,12 +1495,12 @@ std::unique_ptr<AtomicOp> convert_slti_3(const Instruction& i0,
// movz dest, s7, temp
auto temp = i0.get_dst(0).get_reg();
auto dest = i1.get_dst(0).get_reg();
ASSERT(i1.get_src(0).is_reg(rs7()));
ASSERT(i1.get_src(1).is_imm(true_symbol_offset(version)));
ASSERT(i2.get_dst(0).get_reg() == dest);
ASSERT(i2.get_src(0).is_reg(rs7()));
ASSERT(i2.get_src(1).get_reg() == temp);
ASSERT(temp != dest);
if (!i1.get_src(0).is_reg(rs7()) ||
!i1.get_src(1).is_imm(true_symbol_offset(version)) ||
i2.get_dst(0).get_reg() != dest || !i2.get_src(0).is_reg(rs7()) ||
i2.get_src(1).get_reg() != temp || temp == dest) {
return nullptr;
}
IR2_Condition condition;
auto kind =
+30
View File
@@ -1,5 +1,7 @@
#include "expression_build.h"
#include <algorithm>
#include "common/goos/PrettyPrinter.h"
#include "common/log/log.h"
@@ -151,6 +153,34 @@ bool convert_to_expressions(
}
}
// A saved argument may intentionally share its preferred name with the argument itself. Once
// both accesses print as the same, the prologue spill assignment is a lexical self-assignment;
// subsequent spill loads already name the argument binding. Drop only exact, same-typed
// top-level aliases so independent same-named variables in nested scopes remain untouched.
new_entries.erase(
std::remove_if(new_entries.begin(), new_entries.end(), [&](FormElement* entry) {
auto* spill = dynamic_cast<StackSpillStoreElement*>(entry);
if (spill && spill->value().is_var()) {
const auto& source = spill->value().var();
const auto slot = f.ir2.env.stack_slot_entries.find(spill->stack_offset());
return slot != f.ir2.env.stack_slot_entries.end() &&
slot->second.name() == f.ir2.env.get_variable_name(source) &&
slot->second.typespec == f.ir2.env.get_variable_type(source, true);
}
auto* set = dynamic_cast<SetVarElement*>(entry);
if (!set) {
return false;
}
const auto source = form_element_as_atom(set->src()->try_as_single_element());
return source && source->is_var() &&
f.ir2.env.get_variable_name(set->dst()) ==
f.ir2.env.get_variable_name(source->var()) &&
f.ir2.env.get_variable_type(set->dst(), true) ==
f.ir2.env.get_variable_type(source->var(), true);
}),
new_entries.end());
// if we are a totally empty function, insert a placeholder so we don't have to handle
// the zero element case ever.
if (new_entries.empty()) {
+21 -11
View File
@@ -41,6 +41,15 @@ std::string fix_docstring_indent(const std::string& input) {
return result;
}
void set_metadata_docstring(std::vector<goos::Object>* body, const std::string& docstring) {
auto replacement = pretty_print::new_string(docstring);
if (!body->empty() && body->front().is_string()) {
body->front() = replacement;
} else {
body->insert(body->begin(), replacement);
}
}
void append_body_to_function_definition(goos::Object* top_form,
const std::vector<goos::Object>& inline_body,
const FunctionVariableDefinitions& var_dec,
@@ -106,6 +115,7 @@ goos::Object final_output_lambda(const Function& func, GameVersion version) {
goos::Object final_output_defstate_anonymous_behavior(const Function& func,
const DecompilerTypeSystem& dts) {
std::vector<goos::Object> inline_body;
std::optional<std::string> metadata_docstring;
// docstring if available - lookup the appropriate info
const auto& type_name = func.guessed_name.type_name;
@@ -116,22 +126,23 @@ goos::Object final_output_defstate_anonymous_behavior(const Function& func,
if (dts.virtual_state_metadata.count(type_name) != 0 &&
dts.virtual_state_metadata.at(type_name).count(state_name) != 0 &&
dts.virtual_state_metadata.at(type_name).at(state_name).count(handler_name) != 0) {
inline_body.insert(inline_body.begin(),
pretty_print::new_string(dts.virtual_state_metadata.at(type_name)
.at(state_name)
.at(handler_name)
.docstring.value()));
metadata_docstring = dts.virtual_state_metadata.at(type_name)
.at(state_name)
.at(handler_name)
.docstring.value();
}
} else if (func.guessed_name.kind == FunctionName::FunctionKind::NV_STATE) {
if (dts.state_metadata.count(state_name) != 0 &&
dts.state_metadata.at(state_name).count(handler_name) != 0) {
inline_body.insert(inline_body.begin(),
pretty_print::new_string(
dts.state_metadata.at(state_name).at(handler_name).docstring.value()));
metadata_docstring =
dts.state_metadata.at(state_name).at(handler_name).docstring.value();
}
}
func.ir2.top_form->inline_forms(inline_body, func.ir2.env);
if (metadata_docstring) {
set_metadata_docstring(&inline_body, *metadata_docstring);
}
auto var_dec = func.ir2.env.local_var_type_list(func.ir2.top_form, func.type.arg_count() - 1);
auto result = pretty_print::build_list("behavior", get_arg_list_for_function(func, func.ir2.env));
@@ -183,7 +194,7 @@ std::string final_defun_out(const Function& func,
if (dts.symbol_metadata_map.count(func.name()) != 0) {
auto& meta = dts.symbol_metadata_map.at(func.name());
if (meta.docstring) {
inline_body.insert(inline_body.begin(), pretty_print::new_string(meta.docstring.value()));
set_metadata_docstring(&inline_body, meta.docstring.value());
}
}
@@ -205,8 +216,7 @@ std::string final_defun_out(const Function& func,
auto top_form = pretty_print::build_list(top);
if (method_info.docstring) {
inline_body.insert(inline_body.begin(),
pretty_print::new_string(method_info.docstring.value()));
set_metadata_docstring(&inline_body, method_info.docstring.value());
}
append_body_to_function_definition(&top_form, inline_body, var_dec, method_info.type,
dts.version());
+101 -15
View File
@@ -124,7 +124,6 @@ FormElement* rewrite_as_dotimes(LetElement* in, const Env& env, FormPool& pool)
// look for setting a var to zero.
auto ra = in->entries().at(0).dest;
auto var = env.get_variable_name(ra);
if (!is_constant_int(in->entries().at(0).src, 0)) {
return nullptr;
}
@@ -143,7 +142,7 @@ FormElement* rewrite_as_dotimes(LetElement* in, const Env& env, FormPool& pool)
// check the lt operation:
auto lt_var = mr.maps.regs.at(0);
ASSERT(lt_var);
if (env.get_variable_name(*lt_var) != var) {
if (env.get_program_var_id(*lt_var) != env.get_program_var_id(ra)) {
return nullptr; // wrong variable checked
}
@@ -161,7 +160,7 @@ FormElement* rewrite_as_dotimes(LetElement* in, const Env& env, FormPool& pool)
auto inc_var = int_mr.maps.regs.at(0);
ASSERT(inc_var);
if (env.get_variable_name(*inc_var) != var) {
if (env.get_program_var_id(*inc_var) != env.get_program_var_id(ra)) {
return nullptr; // wrong variable incremented
}
@@ -630,8 +629,6 @@ FormElement* rewrite_as_countdown(LetElement* in, const Env& env, FormPool& pool
// look for setting a var to the initial value.
auto ra = in->entries().at(0).dest;
auto idx_var = env.get_variable_name(ra);
// still have to check body for the increment and have to check that the lt operates on the right
// thing.
Matcher while_matcher = Matcher::while_loop(
@@ -646,7 +643,7 @@ FormElement* rewrite_as_countdown(LetElement* in, const Env& env, FormPool& pool
// check the zero operation:
auto lt_var = mr.maps.regs.at(0);
ASSERT(lt_var);
if (env.get_variable_name(*lt_var) != idx_var) {
if (env.get_program_var_id(*lt_var) != env.get_program_var_id(ra)) {
return nullptr; // wrong variable checked
}
@@ -664,7 +661,7 @@ FormElement* rewrite_as_countdown(LetElement* in, const Env& env, FormPool& pool
auto inc_var = int_mr.maps.regs.at(0);
ASSERT(inc_var);
if (env.get_variable_name(*inc_var) != idx_var) {
if (env.get_program_var_id(*inc_var) != env.get_program_var_id(ra)) {
return nullptr; // wrong variable incremented
}
@@ -3912,6 +3909,79 @@ FormElement* rewrite_let_sequence(const std::vector<LetElement*>& in,
return nullptr;
}
FormElement* rewrite_ja_play_sequence(FormElement* setup,
FormElement* wait,
const Env& env,
FormPool& pool) {
auto setup_call = dynamic_cast<GenericElement*>(setup);
if (!setup_call || !setup_call->op().is_func() ||
!setup_call->op().func()->to_form(env).is_symbol("ja-no-eval")) {
return nullptr;
}
auto wait_loop = dynamic_cast<UntilElement*>(wait);
if (!wait_loop || wait_loop->body->size() < 2) {
return nullptr;
}
auto find_keyword_arg = [&](const GenericElement* call, const std::string& keyword) -> Form* {
const auto& args = call->elts();
for (size_t i = 0; i + 1 < args.size(); i++) {
if (args.at(i)->to_form(env).is_symbol(keyword)) {
return args.at(i + 1);
}
}
return nullptr;
};
auto setup_num = find_keyword_arg(setup_call, ":num!");
if (!setup_num) {
return nullptr;
}
auto setup_chan = find_keyword_arg(setup_call, ":chan");
const auto setup_chan_text = setup_chan ? setup_chan->to_form(env).print() : "0";
if (wait_loop->condition->to_string(env) !=
fmt::format("(ja-done? {})", setup_chan_text)) {
return nullptr;
}
const auto& wait_body = wait_loop->body->elts();
auto suspend_op = dynamic_cast<AtomicOpElement*>(wait_body.at(wait_body.size() - 2));
if (!suspend_op || !suspend_op->op() || !dynamic_cast<SpecialOp*>(suspend_op->op()) ||
dynamic_cast<SpecialOp*>(suspend_op->op())->kind() != SpecialOp::Kind::SUSPEND) {
return nullptr;
}
auto advance_call = dynamic_cast<GenericElement*>(wait_body.back());
if (!advance_call || !advance_call->op().is_func() ||
!advance_call->op().func()->to_form(env).is_symbol("ja")) {
return nullptr;
}
auto advance_num = find_keyword_arg(advance_call, ":num!");
auto advance_chan = find_keyword_arg(advance_call, ":chan");
const auto advance_chan_text = advance_chan ? advance_chan->to_form(env).print() : "0";
if (!advance_num || advance_num->to_form(env).print() != setup_num->to_form(env).print() ||
advance_chan_text != setup_chan_text) {
return nullptr;
}
size_t expected_advance_args = advance_chan ? 4 : 2;
if (advance_call->elts().size() != expected_advance_args) {
return nullptr;
}
std::vector<Form*> macro_args = setup_call->elts();
for (size_t i = 0; i + 2 < wait_body.size(); i++) {
macro_args.push_back(pool.alloc_single_form(nullptr, wait_body.at(i)));
}
return pool.alloc_element<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("ja-play")), macro_args);
}
Form* insert_cast_for_let(RegisterAccess dst,
const TypeSpec& src_type,
Form* src,
@@ -3968,7 +4038,7 @@ LetStats insert_lets(const Function& func,
// Stored per variable.
struct PerVarInfo {
std::string var_name; // name used to uniquely identify
std::string unique_name; // displayed name used to join deliberately co-named SSA variables
RegisterAccess access;
std::unordered_set<FormElement*> elts_using_var; // all FormElements using var
Form* lca_form = nullptr; // the lowest common form that contains all the above elts
@@ -4001,10 +4071,10 @@ LetStats insert_lets(const Function& func,
// and add it.
for (auto& access : reg_accesses) {
if (register_can_hold_var(access.reg())) {
auto name = env.get_variable_name(access);
var_info[name].elts_using_var.insert(elt);
var_info[name].var_name = name;
var_info[name].access = access;
auto unique_name = env.get_variable_name(access);
var_info[unique_name].elts_using_var.insert(elt);
var_info[unique_name].unique_name = unique_name;
var_info[unique_name].access = access;
}
}
});
@@ -4036,7 +4106,7 @@ LetStats insert_lets(const Function& func,
bool uses = false;
for (auto& ra : ras) {
if ((ra.reg().get_kind() == Reg::FPR || ra.reg().get_kind() == Reg::GPR) &&
env.get_variable_name(ra) == kv.second.var_name) {
env.get_variable_name(ra) == kv.second.unique_name) {
uses = true;
}
}
@@ -4082,7 +4152,8 @@ LetStats insert_lets(const Function& func,
auto first_form = info.lca_form->at(info.start_idx);
auto first_form_as_set = dynamic_cast<SetVarElement*>(first_form);
if (first_form_as_set && register_can_hold_var(first_form_as_set->dst().reg()) &&
env.get_variable_name(first_form_as_set->dst()) == env.get_variable_name(info.access) &&
env.get_variable_name(first_form_as_set->dst()) ==
env.get_variable_name(info.access) &&
!first_form_as_set->info().is_eliminated_coloring_move) {
bool allowed = true;
@@ -4105,7 +4176,7 @@ LetStats insert_lets(const Function& func,
li.start_elt = info.start_idx;
li.end_elt = info.end_idx;
li.set_form = first_form_as_set;
li.name = info.var_name;
li.name = info.unique_name;
possible_insertions[li.form].push_back(li);
stats.vars_in_lets++;
}
@@ -4291,6 +4362,21 @@ LetStats insert_lets(const Function& func,
}
});
// Part 11: recover the animation-play convenience macro after individual JA setup/eval forms
// have been recognized.
top_level_form->apply_form([&](Form* f) {
auto& form_elts = f->elts();
for (size_t i = 0; i + 1 < form_elts.size(); ++i) {
auto rewritten = rewrite_ja_play_sequence(form_elts.at(i), form_elts.at(i + 1), env, pool);
if (rewritten) {
form_elts.erase(form_elts.begin() + i + 1);
form_elts.at(i) = rewritten;
rewritten->parent_form = f;
let_rewrite_stats.ja_play++;
}
}
});
return stats;
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -151,7 +151,7 @@
"collide-probe": [
["L100", "vector"],
["L102", "vector"]
["L102", "vu-function"]
],
"collide-cache": [
@@ -342,8 +342,8 @@
[333, "(function task-control symbol :behavior process-taskable)"],
[334, "(function task-control symbol :behavior process-taskable)"],
[335, "(function task-control symbol :behavior process-taskable)"],
[336, "(function task-control task-control symbol)"],
[337, "(function task-control task-control symbol)"],
[336, "(function task-control symbol :behavior process-taskable)"],
[337, "(function task-control symbol :behavior process-taskable)"],
[338, "(function task-control symbol :behavior process-taskable)"],
[339, "(function task-control symbol :behavior process-taskable)"],
[340, "(function task-control symbol :behavior process-taskable)"],
@@ -368,10 +368,10 @@
[359, "(function task-control symbol :behavior process-taskable)"],
[360, "(function task-control symbol :behavior process-taskable)"],
[361, "(function task-control symbol :behavior process-taskable)"],
[362, "(function task-control task-control symbol)"],
[363, "(function task-control task-control symbol)"],
[364, "(function task-control task-control symbol)"],
[365, "(function task-control task-control symbol)"],
[362, "(function task-control symbol :behavior process-taskable)"],
[363, "(function task-control symbol :behavior process-taskable)"],
[364, "(function task-control symbol :behavior process-taskable)"],
[365, "(function task-control symbol :behavior process-taskable)"],
[366, "(function task-control symbol :behavior process-taskable)"],
[367, "(function task-control symbol :behavior process-taskable)"],
[368, "(function task-control symbol :behavior process-taskable)"],
@@ -420,8 +420,8 @@
[411, "(function task-control symbol :behavior process-taskable)"],
[412, "(function task-control symbol :behavior process-taskable)"],
[413, "(function task-control symbol :behavior process-taskable)"],
[414, "(function task-control task-control symbol)"],
[415, "(function task-control task-control symbol)"],
[414, "(function task-control symbol :behavior process-taskable)"],
[415, "(function task-control symbol :behavior process-taskable)"],
[416, "(function task-control symbol :behavior process-taskable)"],
[417, "(function task-control symbol :behavior process-taskable)"],
[418, "(function task-control symbol :behavior process-taskable)"],
@@ -431,40 +431,40 @@
[422, "(function task-control symbol :behavior process-taskable)"],
[423, "(function task-control symbol :behavior process-taskable)"],
[424, "(function task-control symbol :behavior process-taskable)"],
[425, "(function task-control task-control symbol)"],
[426, "(function task-control task-control symbol)"],
[425, "(function task-control symbol :behavior process-taskable)"],
[426, "(function task-control symbol :behavior process-taskable)"],
[427, "(function task-control symbol :behavior process-taskable)"],
[428, "(function task-control symbol :behavior process-taskable)"],
[429, "(function task-control symbol :behavior process-taskable)"],
[430, "(function task-control symbol :behavior process-taskable)"],
[431, "(function task-control symbol :behavior process-taskable)"],
[432, "(function task-control task-control symbol)"],
[433, "(function task-control task-control symbol)"],
[434, "(function task-control task-control symbol)"],
[432, "(function task-control symbol :behavior process-taskable)"],
[433, "(function task-control symbol :behavior process-taskable)"],
[434, "(function task-control symbol :behavior process-taskable)"],
[435, "(function task-control symbol :behavior process-taskable)"],
[436, "(function task-control task-control symbol)"],
[437, "(function task-control task-control symbol)"],
[438, "(function task-control task-control symbol)"],
[436, "(function task-control symbol :behavior process-taskable)"],
[437, "(function task-control symbol :behavior process-taskable)"],
[438, "(function task-control symbol :behavior process-taskable)"],
[439, "(function task-control symbol :behavior process-taskable)"],
[440, "(function task-control symbol :behavior process-taskable)"],
[441, "(function task-control symbol :behavior process-taskable)"],
[442, "(function task-control symbol :behavior process-taskable)"],
[443, "(function task-control task-control symbol)"],
[444, "(function task-control task-control symbol)"],
[443, "(function task-control symbol :behavior process-taskable)"],
[444, "(function task-control symbol :behavior process-taskable)"],
[445, "(function task-control symbol :behavior process-taskable)"],
[446, "(function task-control task-control symbol)"],
[447, "(function task-control task-control symbol)"],
[448, "(function task-control task-control symbol)"],
[446, "(function task-control symbol :behavior process-taskable)"],
[447, "(function task-control symbol :behavior process-taskable)"],
[448, "(function task-control symbol :behavior process-taskable)"],
[449, "(function task-control symbol :behavior process-taskable)"],
[450, "(function task-control symbol :behavior process-taskable)"],
[451, "(function task-control symbol :behavior process-taskable)"],
[452, "(function task-control symbol :behavior process-taskable)"],
[453, "(function task-control task-control symbol)"],
[454, "(function task-control task-control symbol)"],
[453, "(function task-control symbol :behavior process-taskable)"],
[454, "(function task-control symbol :behavior process-taskable)"],
[455, "(function task-control symbol :behavior process-taskable)"],
[456, "(function task-control task-control symbol)"],
[457, "(function task-control task-control symbol)"],
[458, "(function task-control task-control symbol)"],
[456, "(function task-control symbol :behavior process-taskable)"],
[457, "(function task-control symbol :behavior process-taskable)"],
[458, "(function task-control symbol :behavior process-taskable)"],
[459, "(function task-control symbol :behavior process-taskable)"],
[460, "(function task-control symbol :behavior process-taskable)"],
[461, "(function task-control symbol :behavior process-taskable)"],
@@ -480,10 +480,10 @@
[471, "(function task-control symbol :behavior process-taskable)"],
[472, "(function task-control symbol :behavior process-taskable)"],
[473, "(function task-control symbol :behavior process-taskable)"],
[474, "(function task-control task-control symbol)"],
[475, "(function task-control task-control symbol)"],
[476, "(function task-control task-control symbol)"],
[477, "(function task-control task-control symbol)"],
[474, "(function task-control symbol :behavior process-taskable)"],
[475, "(function task-control symbol :behavior process-taskable)"],
[476, "(function task-control symbol :behavior process-taskable)"],
[477, "(function task-control symbol :behavior process-taskable)"],
[478, "(function task-control symbol :behavior process-taskable)"],
[479, "(function task-control symbol :behavior process-taskable)"],
[480, "(function task-control symbol :behavior process-taskable)"],
@@ -694,7 +694,7 @@
]
],
"projectiles": [[27, "(function projectile int)"]],
"projectiles": [[27, "(function process int)"]],
"sidekick-human": [
[7, "(function sparticle-launch-control :behavior sequenceC)"],
@@ -230,16 +230,11 @@
"(method 12 collide-mesh)",
// process-drawable BUG
"cspace-inspect-tree",
//"(method 19 process-drawable)",
// ambient
"ambient-inspect",
// target2 BUG
"look-for-points-of-interest", // Failed to split nested sc - looks like dead code to me
// collide-cache
"(method 10 collide-puss-work)", // CFG
"(method 9 collide-puss-work)", // decompiler crash
@@ -1959,7 +1959,7 @@
"collide-probe": [
["L100", "vector"],
["L102", "vector"]
["L102", "vu-function"]
],
"collide-cache": [
@@ -147,7 +147,7 @@
"screen-gradient": [[16, "draw-context"]],
"(method 10 oscillating-vector)": [[16, "vector"]],
"show-mc-info": [[16, "mc-slot-info"]],
"update-mood-erase-color2": [[16, "mood-fog"]],
"update-mood-erase-color2": [[16, "vector"]],
"make-light-kit": [[16, "matrix"]],
"matrix<-parented-transformq!": [[16, "vector"]],
"(method 20 trsqv)": [[16, "vector"]],
@@ -333,7 +333,7 @@
"(method 18 tracking-spline)": [
[16, "tracking-spline-sampler"],
[32, "tracking-spline-sampler"]
[32, "vector"]
],
"draw-ocean-transition": [[16, "sphere"]],
@@ -1545,7 +1545,7 @@
],
"cam-string-line-of-sight": [
[16, "clip-travel-vector-to-mesh-return-info"],
[16, "collide-los-result"],
[176, "vector"],
[192, "vector"],
[208, "vector"],
@@ -3322,7 +3322,7 @@
"(trans launcher-active)": [[16, "event-message-block"]],
"(code touch-tracker-idle)": [[16, "touching-shapes-entry"]],
"(code touch-tracker-idle)": [[16, "overlaps-others-params"]],
"(event manipy-idle)": [[16, "matrix"]],
@@ -3702,7 +3702,9 @@
"(method 44 collide-shape)": [[16, "pull-rider-info"]],
"(method 12 collide-mesh)": [[16, "matrix"]],
"(method 12 collide-mesh)": [[16, "sopt-work"]],
"(method 11 collide-mesh)": [[16, "spat-work"]],
"target-attack-up": [
[16, "vector"],
@@ -3919,7 +3921,7 @@
[48, "vector"]
],
"(method 10 collide-mesh)": [[16, "matrix"]],
"(method 10 collide-mesh)": [[16, "oot-work"]],
"(method 22 collide-shape-prim-mesh)": [[16, "collide-tri-result"]],
+27 -12
View File
@@ -1926,7 +1926,8 @@
],
"build-continue-menu": [
[4, "v1", "symbol"],
[[5, 15], "v1", "level-load-info"]
[5, "v1", "level-load-info"],
[[7, 15], "v1", "continue-point"]
],
"(method 26 basebutton)": [[31, "v1", "art-joint-anim"]],
"debug-menu-item-var-make-float": [
@@ -2006,8 +2007,11 @@
],
"(method 11 beach-rock)": [[77, "v1", "int"]],
"(anon-function 27 projectiles)": [
[16, "s5", "process-drawable"],
[27, "s4", "collide-shape"],
[36, "s4", "collide-shape"]
[36, "s4", "collide-shape"],
[53, "s5", "process-drawable"],
[57, "s5", "process-drawable"]
],
"projectile-update-velocity-space-wars": [[60, "a0", "target"]],
"projectile-init-by-other": [
@@ -2021,6 +2025,7 @@
],
"(method 28 projectile-yellow)": [
[26, "a0", "target"],
[88, "a0", "collide-shape"],
[118, "a1", "target"]
],
"(method 27 projectile-blue)": [
@@ -4182,12 +4187,16 @@
"(method 54 collide-shape)": [[[18, 33], "v1", "collide-shape-prim-group"]],
"(method 45 collide-shape)": [
[18, "v1", "connection"],
[79, "v1", "int"],
[[19, 146], "s3", "collide-shape-moving"],
[146, "v1", "connection"],
[207, "v1", "int"],
[[147, 272], "s3", "collide-shape-moving"],
[272, "v1", "connection"],
[333, "v1", "int"],
[[273, 398], "s3", "collide-shape-moving"],
[398, "v1", "connection"],
[459, "v1", "int"],
[[399, 497], "s3", "collide-shape-moving"]
],
"(method 55 collide-shape)": [
@@ -4497,8 +4506,8 @@
[16, "gp", "process-drawable"]
],
"next-level": [
[7, "a1", "level-load-info"],
[10, "a1", "level-load-info"]
[6, "a1", "symbol"],
[[7, 14], "a1", "level-load-info"]
],
"target-generic-event-handler": [
[10, "v1", "float"],
@@ -5218,9 +5227,7 @@
],
"(method 23 joint-exploder)": [
[[12, 102], "s3", "joint-exploder-joint"],
[[144, 146], "v1", "joint-exploder-list"],
[148, "v1", "matrix"],
[152, "v1", "matrix"]
[[144, 146], "v1", "joint-exploder-list"]
],
"(method 20 joint-exploder)": [
[[8, 10], "a3", "joint-exploder-joint"],
@@ -5619,17 +5626,17 @@
[[319, 324], "v1", "dma-packet"],
[[356, 362], "a0", "dma-packet"],
[[365, 371], "a0", "gs-gif-tag"],
[376, "a0", "(pointer gs-reg64)"],
[376, "a0", "(pointer gs-alpha)"],
[378, "a0", "(pointer gs-reg64)"],
[[382, 387], "v1", "dma-packet"],
[[415, 421], "a0", "dma-packet"],
[[424, 430], "a0", "gs-gif-tag"],
[435, "a0", "(pointer gs-reg64)"],
[435, "a0", "(pointer gs-alpha)"],
[437, "a0", "(pointer gs-reg64)"],
[[441, 446], "v1", "dma-packet"],
[[474, 480], "a0", "dma-packet"],
[[483, 489], "a0", "gs-gif-tag"],
[494, "a0", "(pointer gs-reg64)"],
[494, "a0", "(pointer gs-alpha)"],
[496, "a0", "(pointer gs-reg64)"],
[[500, 505], "v1", "dma-packet"]
],
@@ -6159,11 +6166,19 @@
[124, "v1", "terrain-context"]
],
"target-collision-reaction": [
["_stack_", 96, "cshape-moving-flags"],
["_stack_", 96, "collide-status"],
["_stack_", 104, "cshape-reaction-flags"]
],
"cspace-inspect-tree": [
[[27, 105], "s2", "cspace"],
[[106, 138], "s2", "pair"]
],
"target-collision-low-coverage": [
["_stack_", 32, "cshape-reaction-flags"],
["_stack_", 40, "cshape-moving-flags"]
["_stack_", 40, "collide-status"]
],
"poly-find-nearest-edge": [
[72, "v1", "vector"],
[81, "v1", "vector"]
]
}
File diff suppressed because it is too large Load Diff