mirror of
https://github.com/open-goal/jak-project
synced 2026-07-10 07:07:04 -04:00
[Decomp] Math library: transform and quaternion (#344)
* decompile transform * types for quaternion * part of quaternion * finish quaternion * fix offline test reference * wip fix to let issue * fix
This commit is contained in:
@@ -342,6 +342,12 @@ Form* make_cast(Form* in, const TypeSpec& in_type, const TypeSpec& out_type, For
|
||||
if (in_type == out_type) {
|
||||
return in;
|
||||
}
|
||||
|
||||
auto in_as_cast = dynamic_cast<CastElement*>(in->try_as_single_element());
|
||||
if (in_as_cast && in_as_cast->type() == out_type) {
|
||||
return in;
|
||||
}
|
||||
|
||||
return pool.alloc_single_element_form<CastElement>(nullptr, out_type, in);
|
||||
}
|
||||
|
||||
@@ -378,7 +384,10 @@ void SimpleExpressionElement::update_from_stack_identity(const Env& env,
|
||||
bool allow_side_effects) {
|
||||
auto& arg = m_expr.get_arg(0);
|
||||
if (arg.is_var()) {
|
||||
pop_helper({arg.var()}, env, pool, stack, {result}, allow_side_effects);
|
||||
auto forms = pop_to_forms({arg.var()}, env, pool, stack, allow_side_effects);
|
||||
for (auto x : forms.at(0)->elts()) {
|
||||
result->push_back(x);
|
||||
}
|
||||
} else if (arg.is_static_addr()) {
|
||||
auto lab = env.file->labels.at(arg.label());
|
||||
if (env.file->is_string(lab.target_segment, lab.offset)) {
|
||||
@@ -422,7 +431,10 @@ void SimpleExpressionElement::update_from_stack_gpr_to_fpr(const Env& env,
|
||||
auto src_type = env.get_types_before_op(src.var().idx()).get(src.var().reg());
|
||||
std::vector<FormElement*> src_fes;
|
||||
if (src.is_var()) {
|
||||
pop_helper({src.var()}, env, pool, stack, {&src_fes}, allow_side_effects);
|
||||
auto forms = pop_to_forms({src.var()}, env, pool, stack, allow_side_effects);
|
||||
for (auto x : forms.at(0)->elts()) {
|
||||
src_fes.push_back(x);
|
||||
}
|
||||
} else {
|
||||
src_fes = {this};
|
||||
}
|
||||
@@ -966,6 +978,10 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
|
||||
update_from_stack_force_si_2(env, FixedOperatorKind::MOD, pool, stack, result,
|
||||
allow_side_effects, false);
|
||||
break;
|
||||
case SimpleExpression::Kind::MOD_UNSIGNED:
|
||||
update_from_stack_force_ui_2(env, FixedOperatorKind::MOD, pool, stack, result,
|
||||
allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::MIN_SIGNED:
|
||||
update_from_stack_force_si_2(env, FixedOperatorKind::MIN, pool, stack, result,
|
||||
allow_side_effects, false);
|
||||
@@ -1145,6 +1161,11 @@ void StoreInPairElement::push_to_stack(const Env& env, FormPool& pool, FormStack
|
||||
namespace {
|
||||
Form* make_optional_cast(const std::optional<TypeSpec>& cast_type, Form* in, FormPool& pool) {
|
||||
if (cast_type) {
|
||||
auto in_as_cast = dynamic_cast<CastElement*>(in->try_as_single_element());
|
||||
if (in_as_cast && in_as_cast->type() == cast_type) {
|
||||
return in;
|
||||
}
|
||||
|
||||
return pool.alloc_single_element_form<CastElement>(nullptr, *cast_type, in);
|
||||
} else {
|
||||
return in;
|
||||
@@ -1768,6 +1789,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
||||
|
||||
// check all to see if they write the value.
|
||||
std::vector<SetVarElement*> dest_sets;
|
||||
std::vector<TypeSpec> source_types; // only explicit accesses that aren't move-eliminated
|
||||
for (auto form : write_output_forms) {
|
||||
auto last_in_body = dynamic_cast<SetVarElement*>(form->elts().back());
|
||||
if (last_in_body) {
|
||||
@@ -1777,6 +1799,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
||||
rewrite_as_set = false;
|
||||
break;
|
||||
}
|
||||
source_types.push_back(last_in_body->src_type());
|
||||
}
|
||||
last_var = last_in_body->dst();
|
||||
} // For now, I am fine with letting this fail. For example, if the set is eliminated by a
|
||||
@@ -1822,7 +1845,31 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
||||
if (set_unused) {
|
||||
stack.push_form_element(this, true);
|
||||
} else {
|
||||
stack.push_value_to_reg(*last_var, pool.alloc_single_form(nullptr, this), true,
|
||||
// We may need to insert a cast here.
|
||||
|
||||
// Note:
|
||||
// I think this might skip a cast if you have something like
|
||||
// (set! x (if y z (expr))) and z requires a cast, but the move from z to x is
|
||||
// eliminated by GOAL's register allocator.
|
||||
|
||||
// fmt::print("checking:\n");
|
||||
// for (auto& t : source_types) {
|
||||
// fmt::print(" {}\n", t.print());
|
||||
// }
|
||||
|
||||
auto expected_type = env.get_variable_type(*last_var, true);
|
||||
// fmt::print("The expected type is {}\n", expected_type.print());
|
||||
auto result_type =
|
||||
source_types.empty() ? expected_type : env.dts->ts.lowest_common_ancestor(source_types);
|
||||
// fmt::print("but we actually got {}\n", result_type.print());
|
||||
|
||||
Form* result_value = pool.alloc_single_form(nullptr, this);
|
||||
if (!env.dts->ts.tc(expected_type, result_type)) {
|
||||
result_value =
|
||||
pool.alloc_single_element_form<CastElement>(nullptr, expected_type, result_value);
|
||||
}
|
||||
|
||||
stack.push_value_to_reg(*last_var, result_value, true,
|
||||
env.get_variable_type(*last_var, false));
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user