[decomp] better handling of animation code and art files (#1352)

* update refs

* [decompiler] read and process art groups

* finish decompiler art group selection & detect in `ja-group?`

* make art stuff work on offline tests!

* [decompiler] detect `ja-group!` (primitive)

* corrections.

* more

* use new feature on skel groups!

* find `loop!` as well

* fully fledged `ja` macro & decomp + `loop` detect

* fancy fixed point printing!

* update source

* `:num! max` (i knew i should've done this)

* Update jak1_ntsc_black_label.jsonc

* hi imports

* make compiling the game work

* fix `defskelgroup`

* clang

* update refs

* fix chan

* fix seek and finalboss

* fix tests

* delete unused function

* track let rewrite stats

* reorder `rewrite_let`

* Update .gitattributes

* fix bug with `:num! max`

* Update robotboss-part.gc

* Update goal-lib.gc

* document `ja`

* get rid of pc fixes thing

* use std::abs
This commit is contained in:
ManDude
2022-05-20 02:30:14 +01:00
committed by GitHub
parent 971a69e15c
commit 0212aa10c9
786 changed files with 21658 additions and 49501 deletions
+232 -195
View File
@@ -100,11 +100,9 @@ Form* try_cast_simplify(Form* in,
if (fc) {
double div = (double)*fc / METER_LENGTH; // GOOS will use doubles here
if (div * METER_LENGTH == *fc) {
return pool.alloc_single_element_form<GenericElement>(
nullptr,
GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "meters")),
pool.alloc_single_element_form<ConstantFloatElement>(nullptr, div));
return pool.form<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("meters")),
pool.form<ConstantFloatElement>(div));
} else {
lg::error("Floating point value {} could not be converted to meters.", *fc);
}
@@ -114,11 +112,9 @@ Form* try_cast_simplify(Form* in,
if (fc) {
double div = (double)*fc / DEGREES_LENGTH; // GOOS will use doubles here
if (div * DEGREES_LENGTH == *fc) {
return pool.alloc_single_element_form<GenericElement>(
nullptr,
GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "degrees")),
pool.alloc_single_element_form<ConstantFloatElement>(nullptr, div));
return pool.form<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("degrees")),
pool.form<ConstantFloatElement>(div));
} else {
lg::error("Floating point value {} could not be converted to degrees.", *fc);
}
@@ -142,21 +138,11 @@ Form* try_cast_simplify(Form* in,
// if they used a 1 as a time-frame, they likely just want to literally remove 1
// instead of (seconds 0.0034) or whatever the result would be.
// also 0 is decompiled as just 0.
return pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(value));
return pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(value));
}
// only rewrite if exact.
s64 seconds_int = value / (s64)TICKS_PER_SECOND;
if (seconds_int * (s64)TICKS_PER_SECOND == value) {
return pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, fmt::format("(seconds {})", seconds_int));
}
double seconds = (double)value / TICKS_PER_SECOND;
if (seconds * TICKS_PER_SECOND == value) {
return pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, fmt::format("(seconds {})", float_to_string(seconds, false)));
}
return pool.form<ConstantTokenElement>(
fmt::format("(seconds {})", fixed_point_to_string(value, TICKS_PER_SECOND)));
} else {
// not a constant like (seconds 2), probably an expression or function call. we pretend that a
// cast to int happened instead.
@@ -217,7 +203,7 @@ Form* try_cast_simplify(Form* in,
if (as_atom && as_atom->is_var()) {
if (env.get_variable_type(as_atom->var(), true) == new_type) {
// we are a variable with the right type.
return pool.alloc_single_element_form<SimpleAtomElement>(nullptr, *as_atom, true);
return pool.form<SimpleAtomElement>(*as_atom, true);
}
}
@@ -299,7 +285,7 @@ Form* repop_passthrough_arg(Form* in,
* Create a form which represents a variable.
*/
Form* var_to_form(const RegisterAccess& var, FormPool& pool) {
return pool.alloc_single_element_form<SimpleAtomElement>(nullptr, SimpleAtom::make_var(var));
return pool.form<SimpleAtomElement>(SimpleAtom::make_var(var));
}
/*!
@@ -429,7 +415,7 @@ Form* cast_form(Form* in,
return result;
}
return pool.alloc_single_element_form<CastElement>(nullptr, new_type, in);
return pool.form<CastElement>(new_type, in);
}
/*!
@@ -471,7 +457,7 @@ std::vector<Form*> pop_to_forms(const std::vector<RegisterAccess>& vars,
// there is a separate system for casting variables that will do a better job.
if (cast && !is_var) {
forms[i] = cast_form(forms[i], *cast, pool, env);
// pool.alloc_single_element_form<CastElement>(nullptr, *cast, forms[i]);
// pool.form<CastElement>(*cast, forms[i]);
}
}
@@ -941,7 +927,7 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
allow_side_effects);
} else {
args = pop_to_forms({m_expr.get_arg(0).var()}, env, pool, stack, allow_side_effects);
args.push_back(pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
args.push_back(pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
}
bool arg0_ptr = is_ptr_or_child(env, m_my_idx, m_expr.get_arg(0).var(), true);
@@ -1251,11 +1237,11 @@ void SimpleExpressionElement::update_from_stack_mult_si(const Env& env,
allow_side_effects);
if (!arg0_i) {
args.at(0) = pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("int"), args.at(0));
args.at(0) = pool.form<CastElement>(TypeSpec("int"), args.at(0));
}
if (!arg1_i) {
args.at(1) = pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("int"), args.at(1));
args.at(1) = pool.form<CastElement>(TypeSpec("int"), args.at(1));
}
auto new_form = pool.alloc_element<GenericElement>(
@@ -1299,7 +1285,7 @@ void SimpleExpressionElement::update_from_stack_force_si_2(const Env& env,
} else {
args = pop_to_forms({m_expr.get_arg(0).var()}, env, pool, stack, allow_side_effects);
args.push_back(pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
args.push_back(pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
}
switch (kind) {
@@ -1350,15 +1336,15 @@ void SimpleExpressionElement::update_from_stack_force_ui_2(const Env& env,
allow_side_effects);
} else {
args = pop_to_forms({m_expr.get_arg(0).var()}, env, pool, stack, allow_side_effects);
args.push_back(pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
args.push_back(pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
}
if (!arg0_u) {
args.at(0) = pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("uint"), args.at(0));
args.at(0) = pool.form<CastElement>(TypeSpec("uint"), args.at(0));
}
if (!arg1_u) {
args.at(1) = pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("uint"), args.at(1));
args.at(1) = pool.form<CastElement>(TypeSpec("uint"), args.at(1));
}
auto new_form =
@@ -1386,8 +1372,7 @@ void SimpleExpressionElement::update_from_stack_pcypld(const Env& env,
args.push_back(popped_args.at(ras_idx));
ras_idx++;
} else {
args.push_back(
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(arg_idx)));
args.push_back(pool.form<SimpleAtomElement>(m_expr.get_arg(arg_idx)));
}
}
@@ -1505,20 +1490,18 @@ void SimpleExpressionElement::update_from_stack_copy_first_int_2(const Env& env,
if (bti) {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(kind), args.at(0),
cast_form(pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)),
arg0_type, pool, env));
cast_form(pool.form<SimpleAtomElement>(m_expr.get_arg(1)), arg0_type, pool, env));
result->push_back(new_form);
} else {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(kind),
pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("int"), args.at(0)),
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
GenericOperator::make_fixed(kind), pool.form<CastElement>(TypeSpec("int"), args.at(0)),
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
}
} else {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(kind), args.at(0),
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
auto new_form =
pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind), args.at(0),
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
}
@@ -1543,8 +1526,7 @@ void SimpleExpressionElement::update_from_stack_copy_first_int_2(const Env& env,
args.at(0), args.at(1));
result->push_back(new_form);
} else {
auto cast = pool.alloc_single_element_form<CastElement>(
nullptr, TypeSpec(arg0_i ? "int" : "uint"), args.at(1));
auto cast = pool.form<CastElement>(TypeSpec(arg0_i ? "int" : "uint"), args.at(1));
if (kind == FixedOperatorKind::SUBTRACTION &&
is_pointer_type(env, m_my_idx, m_expr.get_arg(0).var())) {
kind = FixedOperatorKind::SUBTRACTION_PTR;
@@ -1720,17 +1702,15 @@ FormElement* SimpleExpressionElement::update_from_stack_logor_or_logand_helper(
if (integer && ((s64)*integer) < 0) {
// clearing a bitfield.
auto elts = decompile_bitfield_enum_from_int(arg1_type, env.dts->ts, ~*integer);
auto oper =
GenericOperator::make_function(pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, arg1_type.base_type()));
auto oper = GenericOperator::make_function(
pool.form<ConstantTokenElement>(arg1_type.base_type()));
std::vector<Form*> form_elts;
for (auto& x : elts) {
form_elts.push_back(pool.alloc_single_element_form<ConstantTokenElement>(nullptr, x));
form_elts.push_back(pool.form<ConstantTokenElement>(x));
}
auto inverted =
pool.alloc_single_element_form<GenericElement>(nullptr, oper, form_elts);
auto normal = pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::LOGNOT), inverted);
auto inverted = pool.form<GenericElement>(oper, form_elts);
auto normal = pool.form<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::LOGNOT), inverted);
auto new_form = pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind),
normal, args.at(1));
return new_form;
@@ -1757,8 +1737,7 @@ FormElement* SimpleExpressionElement::update_from_stack_logor_or_logand_helper(
}
}
// types bad, insert cast.
auto cast = pool.alloc_single_element_form<CastElement>(
nullptr, TypeSpec(arg0_i ? "int" : "uint"), args.at(1));
auto cast = pool.form<CastElement>(TypeSpec(arg0_i ? "int" : "uint"), args.at(1));
auto new_form =
pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind), args.at(0), cast);
return new_form;
@@ -1889,8 +1868,7 @@ void SimpleExpressionElement::update_from_stack_left_shift(const Env& env,
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::MULTIPLICATION), args.at(0),
pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(multiplier)));
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(multiplier)));
result->push_back(new_form);
return;
}
@@ -1898,15 +1876,15 @@ void SimpleExpressionElement::update_from_stack_left_shift(const Env& env,
auto arg0_i = is_int_type(env, m_my_idx, m_expr.get_arg(0).var());
auto arg0_u = is_uint_type(env, m_my_idx, m_expr.get_arg(0).var());
if (!arg0_i && !arg0_u) {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SHL),
pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("int"), args.at(0)),
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
auto new_form =
pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::SHL),
pool.form<CastElement>(TypeSpec("int"), args.at(0)),
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
} else {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SHL), args.at(0),
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
}
@@ -1970,13 +1948,13 @@ void SimpleExpressionElement::update_from_stack_right_shift_logic(const Env& env
if (!arg0_i && !arg0_u) {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SHR),
pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("int"), arg),
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
pool.form<CastElement>(TypeSpec("int"), arg),
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
} else {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SHR), arg,
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
}
}
@@ -2017,8 +1995,7 @@ void SimpleExpressionElement::update_from_stack_right_shift_arith(const Env& env
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::DIVISION), arg,
pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(multiplier)));
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(multiplier)));
result->push_back(new_form);
return;
}
@@ -2037,15 +2014,15 @@ void SimpleExpressionElement::update_from_stack_right_shift_arith(const Env& env
}
if (!arg0_i && !arg0_u) {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SAR),
pool.alloc_single_element_form<CastElement>(nullptr, TypeSpec("int"), args.at(0)),
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
auto new_form =
pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::SAR),
pool.form<CastElement>(TypeSpec("int"), args.at(0)),
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
} else {
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SAR), args.at(0),
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(1)));
pool.form<SimpleAtomElement>(m_expr.get_arg(1)));
result->push_back(new_form);
}
@@ -2350,9 +2327,8 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
m_dst.reg().get_kind() == Reg::FPR && src_as_se->expr().get_arg(0).is_int() &&
src_as_se->expr().get_arg(0).get_int() == 0) {
// not sure this is the best place for this.
stack.push_value_to_reg(m_dst,
pool.alloc_single_element_form<ConstantFloatElement>(nullptr, 0.0),
true, m_src_type, m_var_info);
stack.push_value_to_reg(m_dst, pool.form<ConstantFloatElement>(0.0), true, m_src_type,
m_var_info);
return;
}
@@ -2414,7 +2390,7 @@ void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack
loc->parent_element = this;
m_dst = loc;
auto zero = SimpleAtom::make_int_constant(0);
auto zero_form = pool.alloc_single_element_form<SimpleAtomElement>(nullptr, zero);
auto zero_form = pool.form<SimpleAtomElement>(zero);
m_src = zero_form;
}
}
@@ -2453,16 +2429,13 @@ void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack
if (dst_form == src_form_in_func) {
auto new_func_op = GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr,
call_info.inplace_name));
pool.form<ConstantTokenElement>(call_info.inplace_name));
GenericElement* inplace_call = nullptr;
if (funcname == "seek" || funcname == "seekl") {
inplace_call = pool.alloc_single_element_form<GenericElement>(
nullptr, new_func_op,
std::vector<Form*>{m_dst, src_as_generic->elts().at(1),
src_as_generic->elts().at(2)})
->try_as_element<GenericElement>();
inplace_call = pool.alloc_element<GenericElement>(
new_func_op, std::vector<Form*>{m_dst, src_as_generic->elts().at(1),
src_as_generic->elts().at(2)});
}
ASSERT_MSG(
inplace_call,
@@ -2495,9 +2468,9 @@ void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack
}
void StoreInSymbolElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
auto sym = pool.alloc_single_element_form<SimpleExpressionElement>(
nullptr, SimpleAtom::make_sym_val(m_sym_name).as_expr(), m_my_idx);
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_value, m_my_idx);
auto sym =
pool.form<SimpleExpressionElement>(SimpleAtom::make_sym_val(m_sym_name).as_expr(), m_my_idx);
auto val = pool.form<SimpleExpressionElement>(m_value, m_my_idx);
val->update_children_from_stack(env, pool, stack, true);
if (m_cast_for_set) {
@@ -2523,18 +2496,16 @@ void StoreInPairElement::push_to_stack(const Env& env, FormPool& pool, FormStack
if (m_value.is_var()) {
auto vars = std::vector<RegisterAccess>({m_value.var(), m_pair});
auto popped = pop_to_forms(vars, env, pool, stack, true);
auto addr = pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(op), popped.at(1));
auto addr = pool.form<GenericElement>(GenericOperator::make_fixed(op), popped.at(1));
addr->mark_popped();
auto fr = pool.alloc_element<SetFormFormElement>(addr, popped.at(0));
fr->mark_popped();
stack.push_form_element(fr, true);
} else {
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_value, m_my_idx);
auto val = pool.form<SimpleExpressionElement>(m_value, m_my_idx);
val->mark_popped();
auto addr = pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(op),
pop_to_forms({m_pair}, env, pool, stack, true).at(0));
auto addr = pool.form<GenericElement>(GenericOperator::make_fixed(op),
pop_to_forms({m_pair}, env, pool, stack, true).at(0));
addr->mark_popped();
auto fr = pool.alloc_element<SetFormFormElement>(addr, val);
fr->mark_popped();
@@ -2612,10 +2583,8 @@ bool try_to_rewrite_vector_inline_ctor(const Env& env,
stack.push_value_to_reg(
*matrix_entries->at(0).destination,
pool.alloc_single_element_form<GenericElement>(
nullptr,
GenericOperator::make_function(pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, fmt::format("new-stack-{}0", type_name)))),
pool.form<GenericElement>(GenericOperator::make_function(
pool.form<ConstantTokenElement>(fmt::format("new-stack-{}0", type_name)))),
true, TypeSpec(type_name));
return true;
}
@@ -2673,10 +2642,8 @@ bool try_to_rewrite_matrix_inline_ctor(const Env& env, FormPool& pool, FormStack
stack.pop(5);
stack.push_value_to_reg(*matrix_entries->at(0).destination,
pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, "new-stack-matrix0"))),
pool.form<GenericElement>(GenericOperator::make_function(
pool.form<ConstantTokenElement>("new-stack-matrix0"))),
true, TypeSpec("matrix"));
return true;
}
@@ -2715,7 +2682,7 @@ void StorePlainDeref::push_to_stack(const Env& env, FormPool& pool, FormStack& s
make_optional_cast(m_dst_cast_type, popped.at(0), pool, env));
m_dst->mark_popped();
m_dst->try_as_element<DerefElement>()->inline_nested();
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_expr, m_my_idx);
auto val = pool.form<SimpleExpressionElement>(m_expr, m_my_idx);
val->mark_popped();
auto fr = pool.alloc_element<SetFormFormElement>(
m_dst, make_optional_cast(m_src_cast_type, val, pool, env));
@@ -2744,7 +2711,7 @@ void StoreArrayAccess::push_to_stack(const Env& env, FormPool& pool, FormStack&
auto vars = std::vector<RegisterAccess>({m_base_var});
auto popped = pop_to_forms(vars, env, pool, stack, true);
m_dst->mark_popped();
expr_form = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_expr, m_my_idx);
expr_form = pool.form<SimpleExpressionElement>(m_expr, m_my_idx);
array_form = popped.at(0);
}
@@ -2961,21 +2928,17 @@ void FunctionCallElement::update_from_stack(const Env& env,
{Matcher::any(0), Matcher::any_constant_token(1)});
auto virtual_go_mr = match(virtual_go_state_matcher, go_next_state);
if (virtual_go_mr.matched && virtual_go_mr.maps.forms.at(0)->to_string(env) == "self") {
arg_forms.insert(arg_forms.begin(), pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, virtual_go_mr.maps.strings.at(1)));
arg_forms.insert(arg_forms.begin(),
pool.form<ConstantTokenElement>(virtual_go_mr.maps.strings.at(1)));
auto go_form = pool.alloc_element<GenericElement>(
GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "go-virtual")),
arg_forms);
GenericOperator::make_function(pool.form<ConstantTokenElement>("go-virtual")), arg_forms);
result->push_back(go_form);
return;
}
arg_forms.insert(arg_forms.begin(), go_next_state);
auto go_form = pool.alloc_element<GenericElement>(
GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "go")),
arg_forms);
GenericOperator::make_function(pool.form<ConstantTokenElement>("go")), arg_forms);
result->push_back(go_form);
return;
}
@@ -3059,8 +3022,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
auto& var = all_pop_vars.at(i + 1); // 0 is the function itself.
auto arg_type = env.get_types_before_op(var.idx()).get(var.reg()).typespec();
if (!env.dts->ts.tc(expected_arg_types.at(i), arg_type)) {
new_args.at(i) = pool.alloc_single_element_form<CastElement>(
nullptr, expected_arg_types.at(i), new_args.at(i));
new_args.at(i) = pool.form<CastElement>(expected_arg_types.at(i), new_args.at(i));
}
}
@@ -3101,8 +3063,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
type_2 = "boxed-array";
}
auto quoted_type = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_sym_ptr(type_2));
auto quoted_type = pool.form<SimpleAtomElement>(SimpleAtom::make_sym_ptr(type_2));
if (alloc == "global" && type_1 == "pair") {
// cons!
@@ -3194,7 +3155,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
":final in the deftype to disable virtual method calls",
tp_type.method_from_type().print(), tp_type.method_id()));
}
auto method_op = pool.alloc_single_element_form<ConstantTokenElement>(nullptr, name);
auto method_op = pool.form<ConstantTokenElement>(name);
auto gop = GenericOperator::make_function(method_op);
result->push_back(pool.alloc_element<GenericElement>(gop, arg_forms));
@@ -3227,10 +3188,9 @@ void FunctionCallElement::update_from_stack(const Env& env,
if (got_stack_new) {
std::vector<Form*> stack_new_args;
stack_new_args.push_back(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "'stack"));
stack_new_args.push_back(pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, fmt::format("'{}", type_source_form->to_string(env))));
stack_new_args.push_back(pool.form<ConstantTokenElement>("'stack"));
stack_new_args.push_back(pool.form<ConstantTokenElement>(
fmt::format("'{}", type_source_form->to_string(env))));
for (size_t i = 2; i < arg_forms.size(); i++) {
stack_new_args.push_back(arg_forms.at(i));
}
@@ -3241,8 +3201,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
}
}
auto method_op =
pool.alloc_single_element_form<GetMethodElement>(nullptr, type_source_form, name, false);
auto method_op = pool.form<GetMethodElement>(type_source_form, name, false);
auto gop = GenericOperator::make_function(method_op);
result->push_back(pool.alloc_element<GenericElement>(gop, arg_forms));
@@ -3265,6 +3224,26 @@ void FunctionCallElement::push_to_stack(const Env& env, FormPool& pool, FormStac
///////////////////
// DerefElement
///////////////////
ConstantTokenElement* DerefElement::try_as_art_const(const Env& env, FormPool& pool) {
auto mr = match(
Matcher::deref(Matcher::s6(), false,
{DerefTokenMatcher::string("draw"), DerefTokenMatcher::string("art-group"),
DerefTokenMatcher::string("data"), DerefTokenMatcher::any_integer(0)}),
this);
if (mr.matched) {
auto elt_name = env.get_art_elt_name(mr.maps.ints.at(0));
if (elt_name) {
return pool.alloc_element<ConstantTokenElement>(*elt_name);
} else {
lg::error("function {}: did not find art element {} in {}", env.func->name(),
mr.maps.ints.at(0), env.art_group());
}
}
return nullptr;
}
void DerefElement::update_from_stack(const Env& env,
FormPool& pool,
FormStack& stack,
@@ -3285,6 +3264,12 @@ void DerefElement::update_from_stack(const Env& env,
// merge nested ->'s
inline_nested();
auto as_art = try_as_art_const(env, pool);
if (as_art) {
result->push_back(as_art);
return;
}
result->push_back(this);
}
@@ -3422,8 +3407,8 @@ Form* try_rewrite_as_process_to_ppointer(CondNoElseElement* value,
}
}
return pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::PROCESS_TO_PPOINTER), repopped);
return pool.form<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::PROCESS_TO_PPOINTER), repopped);
}
// (if x (-> x 0 self)) -> (ppointer->process x)
@@ -3472,8 +3457,59 @@ Form* try_rewrite_as_pppointer_to_process(CondNoElseElement* value,
repopped = var_to_form(condition_var, pool);
}
return pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::PPOINTER_TO_PROCESS), repopped);
return pool.form<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::PPOINTER_TO_PROCESS), repopped);
}
// (if (> (-> self skel active-channels) 0)
// (-> self skel root-channel 0 frame-group)
// )
// (ja-group :chan 0)
Form* try_rewrite_as_ja_group(CondNoElseElement* value,
FormStack& stack,
FormPool& pool,
const Env& env) {
if (value->entries.size() != 1) {
return nullptr;
}
auto condition = value->entries.at(0).condition;
auto body = value->entries[0].body;
// safe to look for a reg directly here.
auto condition_matcher = Matcher::fixed_op(
FixedOperatorKind::GT, {Matcher::deref(Matcher::s6(), false,
{DerefTokenMatcher::string("skel"),
DerefTokenMatcher::string("active-channels")}),
Matcher::any(0)});
auto condition_mr = match(condition_matcher, condition);
if (!condition_mr.matched) {
return nullptr;
}
auto body_matcher = Matcher::deref(
Matcher::s6(), false,
{DerefTokenMatcher::string("skel"), DerefTokenMatcher::string("root-channel"),
DerefTokenMatcher::any_expr_or_int(0), DerefTokenMatcher::string("frame-group")});
auto body_mr = match(body_matcher, body);
if (!body_mr.matched) {
return nullptr;
}
auto chan = body_mr.int_or_form_to_form(pool, 0);
auto obj_chan = chan->to_form(env);
if (condition_mr.maps.forms.at(0)->to_form(env) == obj_chan) {
auto func = GenericOperator::make_function(pool.form<ConstantTokenElement>("ja-group"));
if (obj_chan.is_int(0)) {
return pool.form<GenericElement>(func);
} else {
return pool.form<GenericElement>(func, pool.form<ConstantTokenElement>(":chan"),
condition_mr.maps.forms.at(0));
}
}
return nullptr;
}
} // namespace
@@ -3542,11 +3578,17 @@ void CondNoElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
stack.push_value_to_reg(write_as_value, as_ppointer_to_process, true,
env.get_variable_type(final_destination, false));
} else {
// fmt::print("func {} final destination {} type {}\n", env.func->name(),
// final_destination.to_string(env),
// env.get_variable_type(final_destination, false).print());
stack.push_value_to_reg(write_as_value, pool.alloc_single_form(nullptr, this), true,
env.get_variable_type(final_destination, false));
auto as_ja_group = try_rewrite_as_ja_group(this, stack, pool, env);
if (as_ja_group) {
stack.push_value_to_reg(write_as_value, as_ja_group, true,
env.get_variable_type(final_destination, false));
} else {
// fmt::print("func {} final destination {} type {}\n", env.func->name(),
// final_destination.to_string(env),
// env.get_variable_type(final_destination, false).print());
stack.push_value_to_reg(write_as_value, pool.alloc_single_form(nullptr, this), true,
env.get_variable_type(final_destination, false));
}
}
}
@@ -3724,8 +3766,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
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);
result_value = pool.form<CastElement>(expected_type, result_value);
}
// fmt::print("{}\n", result_value->to_string(env));
@@ -3944,8 +3985,7 @@ FormElement* ConditionElement::make_zero_check_generic(const Env& env,
source_forms.at(0));
if (mr.matched) {
s64 value = -mr.maps.ints.at(1);
auto value_form = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(value));
auto value_form = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(value));
return pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::EQ),
std::vector<Form*>{mr.maps.forms.at(0), value_form});
@@ -4018,12 +4058,7 @@ FormElement* try_make_logtest_cpad_macro(Form* in, FormPool& pool) {
if (logtest_elt != nullptr) {
auto buttons_form = logtest_elt->elts().at(1);
std::vector<Form*> v;
if (mr.maps.forms.find(0) != mr.maps.forms.end()) {
v.push_back(mr.maps.forms.at(0));
} else {
v.push_back(
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(mr.maps.ints.at(0))));
}
v.push_back(mr.int_or_form_to_form(pool, 0));
GenericElement* butts =
dynamic_cast<GenericElement*>(buttons_form->at(0)); // the form with the buttons itself
if (butts) {
@@ -4063,8 +4098,7 @@ FormElement* ConditionElement::make_nonzero_check_generic(const Env& env,
source_forms.at(0));
if (mr.matched) {
s64 value = -mr.maps.ints.at(1);
auto value_form = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(value));
auto value_form = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(value));
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::NEQ),
std::vector<Form*>{mr.maps.forms.at(0), value_form});
}
@@ -4103,6 +4137,29 @@ FormElement* ConditionElement::make_equal_check_generic(const Env& env,
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::EQ),
forms_with_cast);
} else {
{
// (= (ja-group)
// (-> self draw art-group data 7)
// )
// actually (ja-group? (-> self draw art-group data 7) :channel channel)
auto mr =
match(Matcher::op(GenericOpMatcher::func(Matcher::constant_token("ja-group")), {}),
source_forms.at(0));
// check if both things matched
if (mr.matched) {
// grab args from the ja-group and pass them on
std::vector<Form*> macro_args;
macro_args.push_back(source_forms.at(1));
auto jagroup = source_forms.at(0)->try_as_element<GenericElement>();
for (int i = 1; i < jagroup->elts().size(); ++i) {
macro_args.push_back(jagroup->elts().at(i));
}
return pool.alloc_element<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("ja-group?")),
macro_args);
}
}
return pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::EQ),
cast_to_64_bit(source_forms, source_types, pool, env));
@@ -4123,8 +4180,8 @@ FormElement* ConditionElement::make_not_equal_check_generic(
// null?
return pool.alloc_element<GenericElement>(
GenericOperator::make_compare(IR2_Condition::Kind::FALSE),
pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::NULLP), source_forms.at(0)));
pool.form<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::NULLP),
source_forms.at(0)));
} else {
auto nice_constant =
try_make_constant_for_compare(source_forms.at(1), source_types.at(0), pool, env);
@@ -4164,8 +4221,7 @@ FormElement* ConditionElement::make_less_than_zero_signed_check_generic(
shift_match.maps.forms.at(0));
} else {
auto casted = make_casts_if_needed(source_forms, types, TypeSpec("int"), pool, env);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>(nullptr,
SimpleAtom::make_int_constant(0));
auto zero = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::LT),
casted);
@@ -4193,13 +4249,11 @@ FormElement* ConditionElement::make_geq_zero_signed_check_generic(
if (shift_match.matched) {
return pool.alloc_element<GenericElement>(
GenericOperator::make_compare(IR2_Condition::Kind::FALSE),
pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::PAIRP),
shift_match.maps.forms.at(0)));
pool.form<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::PAIRP),
shift_match.maps.forms.at(0)));
} else {
auto casted = make_casts_if_needed(source_forms, types, TypeSpec("int"), pool, env);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>(nullptr,
SimpleAtom::make_int_constant(0));
auto zero = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::GEQ),
casted);
@@ -4225,8 +4279,7 @@ FormElement* ConditionElement::make_geq_zero_unsigned_check_generic(
source_forms.at(0));
auto casted = make_casts_if_needed(source_forms, types, TypeSpec("uint"), pool, env);
auto zero =
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, SimpleAtom::make_int_constant(0));
auto zero = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::GEQ),
casted);
@@ -4280,8 +4333,7 @@ FormElement* ConditionElement::make_generic(const Env& env,
case IR2_Condition::Kind::LESS_THAN_ZERO_UNSIGNED: {
auto casted = make_casts_if_needed(source_forms, types, TypeSpec("uint"), pool, env);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(0));
auto zero = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::LT),
casted);
@@ -4289,8 +4341,7 @@ FormElement* ConditionElement::make_generic(const Env& env,
case IR2_Condition::Kind::LEQ_ZERO_SIGNED: {
auto casted = make_casts_if_needed(source_forms, types, TypeSpec("int"), pool, env);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(0));
auto zero = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::LEQ),
casted);
@@ -4306,8 +4357,7 @@ FormElement* ConditionElement::make_generic(const Env& env,
case IR2_Condition::Kind::GREATER_THAN_ZERO_UNSIGNED: {
auto casted = make_casts_if_needed(source_forms, types, TypeSpec("uint"), pool, env);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(0));
auto zero = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::GT),
casted);
@@ -4315,8 +4365,7 @@ FormElement* ConditionElement::make_generic(const Env& env,
case IR2_Condition::Kind::GREATER_THAN_ZERO_SIGNED: {
auto casted = make_casts_if_needed(source_forms, types, TypeSpec("int"), pool, env);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(0));
auto zero = pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::GT),
casted);
@@ -4405,7 +4454,7 @@ void ConditionElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
if (m_src[i]->is_var()) {
source_forms.push_back(popped_forms.at(popped_counter++));
} else {
source_forms.push_back(pool.alloc_single_element_form<SimpleAtomElement>(nullptr, *m_src[i]));
source_forms.push_back(pool.form<SimpleAtomElement>(*m_src[i]));
}
}
ASSERT(popped_counter == int(popped_forms.size()));
@@ -4458,7 +4507,7 @@ void ConditionElement::update_from_stack(const Env& env,
if (m_src[i]->is_var()) {
source_forms.push_back(popped_forms.at(popped_counter++));
} else {
source_forms.push_back(pool.alloc_single_element_form<SimpleAtomElement>(nullptr, *m_src[i]));
source_forms.push_back(pool.form<SimpleAtomElement>(*m_src[i]));
}
}
ASSERT(popped_counter == int(popped_forms.size()));
@@ -4591,8 +4640,8 @@ void push_asm_sllv_to_stack(const AsmOp* op,
// these are lazily converted at the destination.
stack.push_value_to_reg(
*dst,
pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::ASM_SLLV_R0), src_var),
pool.form<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::ASM_SLLV_R0),
src_var),
true, env.get_variable_type(*dst, true));
}
}
@@ -4750,7 +4799,7 @@ void AtomicOpElement::push_to_stack(const Env& env, FormPool& pool, FormStack& s
auto delay = as_branch->branch_delay();
ASSERT(delay);
// this might not be enough - we may need to back up to the cfg builder and do something there.
auto del = pool.alloc_single_element_form<AtomicOpElement>(nullptr, delay);
auto del = pool.form<AtomicOpElement>(delay);
auto be = pool.alloc_element<AsmBranchElement>(as_branch, del, false);
be->push_to_stack(env, pool, stack);
return;
@@ -4832,27 +4881,22 @@ void BranchElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
auto src = m_op->branch_delay().var(1);
auto dst = m_op->branch_delay().var(0);
auto src_form =
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, SimpleAtom::make_var(src));
auto src_form = pool.form<SimpleAtomElement>(SimpleAtom::make_var(src));
branch_delay = pool.alloc_single_element_form<SetVarElement>(
nullptr, dst, src_form, true, env.get_variable_type(src, true));
branch_delay =
pool.form<SetVarElement>(dst, src_form, true, env.get_variable_type(src, true));
} break;
case IR2_BranchDelay::Kind::SET_REG_FALSE: {
auto dst = m_op->branch_delay().var(0);
auto src_form = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_sym_val("#f"));
auto src_form = pool.form<SimpleAtomElement>(SimpleAtom::make_sym_val("#f"));
branch_delay = pool.alloc_single_element_form<SetVarElement>(nullptr, dst, src_form, true,
TypeSpec("symbol"));
branch_delay = pool.form<SetVarElement>(dst, src_form, true, TypeSpec("symbol"));
} break;
case IR2_BranchDelay::Kind::SET_REG_TRUE: {
auto dst = m_op->branch_delay().var(0);
auto src_form = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_sym_val("#t"));
auto src_form = pool.form<SimpleAtomElement>(SimpleAtom::make_sym_val("#t"));
branch_delay = pool.alloc_single_element_form<SetVarElement>(nullptr, dst, src_form, true,
TypeSpec("symbol"));
branch_delay = pool.form<SetVarElement>(dst, src_form, true, TypeSpec("symbol"));
} break;
default:
throw std::runtime_error("Unhandled branch delay in BranchElement::push_to_stack: " +
@@ -5241,8 +5285,7 @@ void ConditionalMoveFalseElement::push_to_stack(const Env& env, FormPool& pool,
}
if (!val) {
val = pool.alloc_single_element_form<GenericElement>(
nullptr,
val = pool.form<GenericElement>(
GenericOperator::make_compare(on_zero ? IR2_Condition::Kind::NONZERO
: IR2_Condition::Kind::ZERO),
std::vector<Form*>{popped.at(1)});
@@ -5260,11 +5303,10 @@ void StackSpillStoreElement::push_to_stack(const Env& env, FormPool& pool, FormS
if (m_value.is_var()) {
src = pop_to_forms({m_value.var()}, env, pool, stack, true).at(0);
} else {
src = pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_value);
src = pool.form<SimpleAtomElement>(m_value);
}
auto dst = pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, env.get_spill_slot_var_name(m_stack_offset));
auto dst = pool.form<ConstantTokenElement>(env.get_spill_slot_var_name(m_stack_offset));
if (m_cast_type) {
src = cast_form(src, *m_cast_type, pool, env);
}
@@ -5365,10 +5407,8 @@ bool try_vector_reset_inline(const Env& env,
store = repop_passthrough_arg(store, stack, env, &orig, &got_orig);
// create the actual form
Form* new_thing = pool.alloc_single_element_form<GenericElement>(
nullptr,
GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "vector-reset!")),
Form* new_thing = pool.form<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("vector-reset!")),
std::vector<Form*>{store});
if (got_orig) {
@@ -5440,24 +5480,21 @@ void MethodOfTypeElement::update_from_stack(const Env& env,
type_as_deref->tokens().pop_back();
result->push_back(pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::METHOD_OF_OBJECT),
std::vector<Form*>{type, pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, m_method_info.name)}));
std::vector<Form*>{type, pool.form<ConstantTokenElement>(m_method_info.name)}));
return;
} else if (type_as_deref->tokens().size() == 1 &&
type_as_deref->tokens().back().is_field_name("type")) {
result->push_back(pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::METHOD_OF_OBJECT),
std::vector<Form*>{
type_as_deref->base(),
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, m_method_info.name)}));
std::vector<Form*>{type_as_deref->base(),
pool.form<ConstantTokenElement>(m_method_info.name)}));
return;
}
}
result->push_back(pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::METHOD_OF_TYPE),
std::vector<Form*>{type, pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, m_method_info.name)}));
std::vector<Form*>{type, pool.form<ConstantTokenElement>(m_method_info.name)}));
}
void SimpleAtomElement::update_from_stack(const Env&,