mirror of
https://github.com/open-goal/jak-project
synced 2026-06-10 12:55:45 -04:00
Merge remote-tracking branch 'origin/master' into j2/progress
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "GenericElementMatcher.h"
|
||||
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
#include "common/log/log.h"
|
||||
#include "common/type_system/state.h"
|
||||
#include "common/util/Assert.h"
|
||||
#include "common/util/BitUtils.h"
|
||||
@@ -402,7 +403,7 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
|
||||
submit_regs.push_back(var.reg());
|
||||
} else {
|
||||
// auto var_id = env.get_program_var_id(var);
|
||||
// fmt::print(
|
||||
// lg::print(
|
||||
// "Unsafe to pop {}: used {} times, def {} times, expected use {} ({} {} rd:
|
||||
// {}) ({} "
|
||||
// "{})\n",
|
||||
@@ -413,7 +414,7 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
|
||||
// if (var.to_string(env) == "a3-0") {
|
||||
// for (auto& use : use_def.uses) {
|
||||
// if (!use.disabled) {
|
||||
// fmt::print(" at instruction {}\n", use.op_id);
|
||||
// lg::print(" at instruction {}\n", use.op_id);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -1051,7 +1052,7 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
|
||||
// try to find symbol to string stuff
|
||||
auto arg0_int = get_goal_integer_constant(args.at(0), env);
|
||||
|
||||
if (arg0_int && (*arg0_int == SYMBOL_TO_STRING_MEM_OFFSET_DECOMP[env.version]) &&
|
||||
if (arg0_int && ((s64)*arg0_int == SYMBOL_TO_STRING_MEM_OFFSET_DECOMP[env.version]) &&
|
||||
allowable_base_type_for_symbol_to_string(arg1_type.typespec())) {
|
||||
result->push_back(pool.alloc_element<GetSymbolStringPointer>(args.at(1)));
|
||||
return;
|
||||
@@ -1231,7 +1232,7 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
|
||||
}
|
||||
}
|
||||
}
|
||||
// fmt::print("here {} {} {}\n", rd_in.base_type.print(), rd.success,
|
||||
// lg::print("here {} {} {}\n", rd_in.base_type.print(), rd.success,
|
||||
// rd.has_variable_token());
|
||||
|
||||
if (idx_of_success >= 0) {
|
||||
@@ -1261,7 +1262,7 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
|
||||
return;
|
||||
} else {
|
||||
// TODO - output error to IR
|
||||
lg::error("Bad {} at OP: {}\n", args.at(0)->to_string(env), m_my_idx);
|
||||
lg::error("Bad {} at OP: {}", args.at(0)->to_string(env), m_my_idx);
|
||||
throw std::runtime_error("Failed to match product_with_constant inline array access 2.");
|
||||
}
|
||||
}
|
||||
@@ -1543,7 +1544,7 @@ void SimpleExpressionElement::update_from_stack_pcypld(const Env& env,
|
||||
result->push_back(as_mod);
|
||||
return;
|
||||
} else {
|
||||
fmt::print("pcpyud rewrite form fail: {} {}\n", base_form.print(), a1_form.print());
|
||||
lg::warn("pcpyud rewrite form fail: {} {}", base_form.print(), a1_form.print());
|
||||
}
|
||||
}
|
||||
auto new_form = pool.alloc_element<GenericElement>(
|
||||
@@ -2013,7 +2014,7 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
|
||||
auto repopped = stack.pop_reg(var_b, {}, env, true, stack.size() - 1);
|
||||
|
||||
if (!repopped) {
|
||||
fmt::print("repop failed.\n{}\n", stack.print(env));
|
||||
lg::warn("repop failed.\n{}", stack.print(env));
|
||||
repopped = var_to_form(var_b, pool);
|
||||
}
|
||||
|
||||
@@ -2610,7 +2611,7 @@ void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack
|
||||
m_src = value;
|
||||
}
|
||||
} else if (src_as_bf_set) {
|
||||
fmt::print("invalid bf set: {}\n", src_as_bf_set->to_string(env));
|
||||
lg::warn("invalid bf set: {}", src_as_bf_set->to_string(env));
|
||||
}
|
||||
|
||||
// setting a bitfield to zero is wonky.
|
||||
@@ -3032,12 +3033,12 @@ Form* get_set_next_state(FormElement* set_elt, const Env& env) {
|
||||
Matcher::deref(Matcher::any_reg(0), false, {DerefTokenMatcher::string("next-state")});
|
||||
auto mr = match(dst_matcher, dst);
|
||||
if (!mr.matched) {
|
||||
fmt::print("failed to match dst {}\n", dst->to_string(env));
|
||||
lg::error("failed to match dst {}", dst->to_string(env));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mr.maps.regs.at(0)->reg() != Register(Reg::GPR, Reg::S6)) {
|
||||
fmt::print("failed to match pp reg, got {}\n", mr.maps.regs.at(0)->reg().to_string());
|
||||
lg::error("failed to match pp reg, got {}", mr.maps.regs.at(0)->reg().to_string());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -3243,22 +3244,23 @@ void FunctionCallElement::update_from_stack(const Env& env,
|
||||
"type.");
|
||||
}
|
||||
|
||||
bool is_res_lump = tp_type.method_from_type().base_type() == "res-lump";
|
||||
bool is_res_lump = tp_type.method_from_type().base_type() == "res-lump" ||
|
||||
tp_type.method_from_type().base_type() == "entity-actor";
|
||||
bool should_use_virtual =
|
||||
env.dts->ts.should_use_virtual_methods(tp_type.method_from_type(), tp_type.method_id());
|
||||
|
||||
if (!should_use_virtual && !is_res_lump) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("Method call on {} id {} used a virtual call unexpectedly.",
|
||||
tp_type.method_from_type().print(), tp_type.method_id()));
|
||||
fmt::format("Method call on {} id {} at {} used a virtual call unexpectedly.",
|
||||
tp_type.method_from_type().print(), tp_type.method_id(), "ya"));
|
||||
}
|
||||
|
||||
if (should_use_virtual) {
|
||||
// fmt::print("STACK\n{}\n\n", stack.print(env));
|
||||
// lg::print("STACK\n{}\n\n", stack.print(env));
|
||||
auto pop = pop_to_forms({*arg0_mr.maps.regs.at(0)}, env, pool, stack, allow_side_effects,
|
||||
{}, {2})
|
||||
.at(0);
|
||||
// fmt::print("GOT: {}\n", pop->to_string(env));
|
||||
// lg::print("GOT: {}\n", pop->to_string(env));
|
||||
arg_forms.at(0) = pop;
|
||||
auto head = mr.maps.forms.at(1);
|
||||
|
||||
@@ -3873,7 +3875,7 @@ Form* try_rewrite_as_process_to_ppointer(CondNoElseElement* value,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// fmt::print("Matched condition {} in {}\n", condition_var.to_string(env),
|
||||
// lg::print("Matched condition {} in {}\n", condition_var.to_string(env),
|
||||
// value->to_string(env));
|
||||
|
||||
auto* menv = const_cast<Env*>(&env);
|
||||
@@ -3927,7 +3929,7 @@ Form* try_rewrite_as_pppointer_to_process(CondNoElseElement* value,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// fmt::print("Matched condition {} in {}\n", condition_var.to_string(env),
|
||||
// lg::print("Matched condition {} in {}\n", condition_var.to_string(env),
|
||||
// value->to_string(env));
|
||||
|
||||
auto* menv = const_cast<Env*>(&env);
|
||||
@@ -4063,7 +4065,7 @@ void CondNoElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
|
||||
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(),
|
||||
// lg::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,
|
||||
@@ -4231,24 +4233,24 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
||||
// (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("func: {}\n", env.func->name());
|
||||
// lg::print("func: {}\n", env.func->name());
|
||||
//
|
||||
// fmt::print("checking:\n");
|
||||
// lg::print("checking:\n");
|
||||
// for (auto& t : source_types) {
|
||||
// fmt::print(" {}\n", t.print());
|
||||
// lg::print(" {}\n", t.print());
|
||||
// }
|
||||
|
||||
auto expected_type = env.get_variable_type(*last_var, true);
|
||||
// fmt::print("The expected type is {}\n", expected_type.print());
|
||||
// lg::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());
|
||||
// lg::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.form<CastElement>(expected_type, result_value);
|
||||
}
|
||||
// fmt::print("{}\n", result_value->to_string(env));
|
||||
// lg::print("{}\n", result_value->to_string(env));
|
||||
|
||||
stack.push_value_to_reg(*last_var, result_value, true,
|
||||
env.get_variable_type(*last_var, false));
|
||||
@@ -4449,66 +4451,6 @@ FormElement* try_make_nonzero_logtest(Form* in, FormPool& pool) {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FormElement* ConditionElement::make_zero_check_generic(const Env& env,
|
||||
FormPool& pool,
|
||||
const std::vector<Form*>& source_forms,
|
||||
const std::vector<TypeSpec>& source_types) {
|
||||
// (zero? (+ thing small-integer)) -> (= thing (- small-integer))
|
||||
ASSERT(source_forms.size() == 1);
|
||||
|
||||
auto enum_type_info = env.dts->ts.try_enum_lookup(source_types.at(0));
|
||||
if (enum_type_info && !enum_type_info->is_bitfield()) {
|
||||
// (zero? (+ (the-as uint arg0) (the-as uint -2))) check enum value
|
||||
auto mr = match(
|
||||
Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION),
|
||||
{make_int_uint_cast_matcher(Matcher::any(0)),
|
||||
Matcher::match_or({Matcher::any_integer(1),
|
||||
make_int_uint_cast_matcher(Matcher::any_integer(1))})}),
|
||||
source_forms.at(0));
|
||||
if (mr.matched) {
|
||||
s64 value = mr.maps.ints.at(1);
|
||||
value = -value;
|
||||
auto enum_constant = cast_to_int_enum(enum_type_info, pool, env, value);
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::EQ),
|
||||
std::vector<Form*>{mr.maps.forms.at(0), enum_constant});
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto mr = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION),
|
||||
{Matcher::any(0), Matcher::any_integer(1)}),
|
||||
source_forms.at(0));
|
||||
if (mr.matched) {
|
||||
s64 value = -mr.maps.ints.at(1);
|
||||
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});
|
||||
}
|
||||
}
|
||||
|
||||
auto nice_constant = try_make_constant_from_int_for_compare(0, source_types.at(0), pool, env);
|
||||
if (nice_constant) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::EQ),
|
||||
std::vector<Form*>{source_forms.at(0), nice_constant});
|
||||
}
|
||||
|
||||
/*
|
||||
auto as_logtest = try_make_nonzero_logtest(source_forms.at(0), pool);
|
||||
if (as_logtest) {
|
||||
auto logtest_form = pool.alloc_single_form(nullptr, as_logtest);
|
||||
auto not_form = pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_compare(IR2_Condition::Kind::FALSE), logtest_form);
|
||||
return not_form;
|
||||
}
|
||||
*/
|
||||
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_compare(m_kind), source_forms);
|
||||
}
|
||||
|
||||
FormElement* try_make_logtest_cpad_macro(Form* in, FormPool& pool) {
|
||||
/*
|
||||
@@ -4564,6 +4506,68 @@ FormElement* try_make_logtest_cpad_macro(Form* in, FormPool& pool) {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FormElement* ConditionElement::make_zero_check_generic(const Env& env,
|
||||
FormPool& pool,
|
||||
const std::vector<Form*>& source_forms,
|
||||
const std::vector<TypeSpec>& source_types) {
|
||||
// (zero? (+ thing small-integer)) -> (= thing (- small-integer))
|
||||
ASSERT(source_forms.size() == 1);
|
||||
|
||||
auto enum_type_info = env.dts->ts.try_enum_lookup(source_types.at(0));
|
||||
if (enum_type_info && !enum_type_info->is_bitfield()) {
|
||||
// (zero? (+ (the-as uint arg0) (the-as uint -2))) check enum value
|
||||
auto mr = match(
|
||||
Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION),
|
||||
{make_int_uint_cast_matcher(Matcher::any(0)),
|
||||
Matcher::match_or({Matcher::any_integer(1),
|
||||
make_int_uint_cast_matcher(Matcher::any_integer(1))})}),
|
||||
source_forms.at(0));
|
||||
if (mr.matched) {
|
||||
s64 value = mr.maps.ints.at(1);
|
||||
value = -value;
|
||||
auto enum_constant = cast_to_int_enum(enum_type_info, pool, env, value);
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::EQ),
|
||||
std::vector<Form*>{mr.maps.forms.at(0), enum_constant});
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto mr = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION),
|
||||
{Matcher::any(0), Matcher::any_integer(1)}),
|
||||
source_forms.at(0));
|
||||
if (mr.matched) {
|
||||
s64 value = -mr.maps.ints.at(1);
|
||||
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});
|
||||
}
|
||||
}
|
||||
|
||||
auto nice_constant = try_make_constant_from_int_for_compare(0, source_types.at(0), pool, env);
|
||||
if (nice_constant) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::EQ),
|
||||
std::vector<Form*>{source_forms.at(0), nice_constant});
|
||||
}
|
||||
|
||||
auto as_logtest = try_make_nonzero_logtest(source_forms.at(0), pool);
|
||||
if (as_logtest) {
|
||||
auto logtest_form = pool.alloc_single_form(nullptr, as_logtest);
|
||||
auto as_cpad_macro = try_make_logtest_cpad_macro(logtest_form, pool);
|
||||
if (as_cpad_macro) {
|
||||
logtest_form = pool.alloc_single_form(nullptr, as_cpad_macro);
|
||||
}
|
||||
auto not_form = pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_compare(IR2_Condition::Kind::FALSE), logtest_form);
|
||||
return not_form;
|
||||
}
|
||||
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_compare(m_kind), source_forms);
|
||||
}
|
||||
|
||||
FormElement* ConditionElement::make_nonzero_check_generic(const Env& env,
|
||||
FormPool& pool,
|
||||
@@ -5339,7 +5343,7 @@ void AsmBranchElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
|
||||
|
||||
auto op = pool.alloc_element<TranslatedAsmBranch>(
|
||||
branch_condition, m_branch_delay, m_branch_op->label_id(), m_branch_op->is_likely());
|
||||
// fmt::print("rewrote as {}\n", op->to_string(env));
|
||||
// lg::print("rewrote as {}\n", op->to_string(env));
|
||||
stack.push_form_element(op, true);
|
||||
}
|
||||
|
||||
@@ -5397,7 +5401,7 @@ void BranchElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
|
||||
ASSERT(!m_op->likely());
|
||||
auto op = pool.alloc_element<TranslatedAsmBranch>(branch_condition, branch_delay,
|
||||
m_op->label_id(), m_op->likely());
|
||||
// fmt::print("rewrote (non-asm) as {}\n", op->to_string(env));
|
||||
// lg::print("rewrote (non-asm) as {}\n", op->to_string(env));
|
||||
stack.push_form_element(op, true);
|
||||
}
|
||||
|
||||
@@ -5518,7 +5522,7 @@ void ArrayFieldAccess::update_with_val(Form* new_val,
|
||||
if (!match_result.matched) {
|
||||
result->push_back(this);
|
||||
return;
|
||||
fmt::print("power {}\n", power_of_two);
|
||||
lg::error("power {}", power_of_two);
|
||||
throw std::runtime_error(
|
||||
"Couldn't match ArrayFieldAccess (stride power of 2, 0 offset) values: " +
|
||||
new_val->to_string(env));
|
||||
@@ -5762,7 +5766,7 @@ void ConditionalMoveFalseElement::push_to_stack(const Env& env, FormPool& pool,
|
||||
|
||||
Form* val = nullptr;
|
||||
|
||||
if (!val && on_zero) {
|
||||
if (on_zero) {
|
||||
auto as_logtest = try_make_nonzero_logtest(popped.at(1), pool);
|
||||
if (as_logtest) {
|
||||
auto logtest_form = pool.alloc_single_form(nullptr, as_logtest);
|
||||
|
||||
Reference in New Issue
Block a user