Get started on collide-func and clean up log forms in decompiler (#713)

* wip

* temp

* temp2

* first part of log macros

* more log macros

* logtest

* clean up

* dont initialize game info because we are missing stuff
This commit is contained in:
water111
2021-07-23 20:51:26 -04:00
committed by GitHub
parent 65b61d05e6
commit 95366d21df
73 changed files with 1900 additions and 1017 deletions
+111 -33
View File
@@ -1144,12 +1144,13 @@ void SimpleExpressionElement::update_from_stack_pcypld(const Env& env,
result->push_back(new_form);
}
void SimpleExpressionElement::update_from_stack_vector_plus_minus(bool is_add,
const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects) {
void SimpleExpressionElement::update_from_stack_vector_plus_minus_cross(
FixedOperatorKind op_kind,
const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects) {
std::vector<Form*> popped_args =
pop_to_forms({m_expr.get_arg(0).var(), m_expr.get_arg(1).var(), m_expr.get_arg(2).var()}, env,
pool, stack, allow_side_effects);
@@ -1162,8 +1163,7 @@ void SimpleExpressionElement::update_from_stack_vector_plus_minus(bool is_add,
}
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(is_add ? FixedOperatorKind::VECTOR_PLUS
: FixedOperatorKind::VECTOR_MINUS),
GenericOperator::make_fixed(op_kind),
std::vector<Form*>{popped_args.at(0), popped_args.at(1), popped_args.at(2)});
result->push_back(new_form);
}
@@ -1282,12 +1282,12 @@ Form* strip_int_or_uint_cast(Form* in) {
}
} // namespace
void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
FixedOperatorKind kind,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects) {
FormElement* SimpleExpressionElement::update_from_stack_logor_or_logand_helper(
const Env& env,
FixedOperatorKind kind,
FormPool& pool,
FormStack& stack,
bool allow_side_effects) {
// grab the normal variable type
auto arg0_type = env.get_variable_type(m_expr.get_arg(0).var(), true);
@@ -1341,15 +1341,17 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
BitfieldManip step(manip_kind, m_expr.get_arg(1).get_int());
auto other = read_elt->push_step(step, env.dts->ts, pool, env);
if (other) {
result->push_back(other);
return other;
} else {
result->push_back(read_elt);
return read_elt;
}
return;
} else if (!m_expr.get_arg(1).is_var()) {
// andi, something else (don't think this can happen?)
update_from_stack_copy_first_int_2(env, kind, pool, stack, result, allow_side_effects);
std::vector<FormElement*> result;
update_from_stack_copy_first_int_2(env, kind, pool, stack, &result, allow_side_effects);
assert(result.size() == 1);
return result.at(0);
} else {
// and, two forms
auto arg1_type = env.get_variable_type(m_expr.get_arg(1).var(), true);
@@ -1393,11 +1395,10 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
auto other = read_elt->push_step(step, env.dts->ts, pool, env);
// assert(!other); // shouldn't be complete.
if (other) {
result->push_back(other);
return other;
} else {
result->push_back(read_elt);
return read_elt;
}
return;
} else if (!made_new_read_elt) {
BitfieldManip::Kind manip_kind;
if (kind == FixedOperatorKind::LOGAND) {
@@ -1410,22 +1411,21 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
auto step = BitfieldManip::from_form(manip_kind, stripped_arg1);
auto other = read_elt->push_step(step, env.dts->ts, pool, env);
if (other) {
result->push_back(other);
return other;
} else {
result->push_back(read_elt);
return read_elt;
}
return;
}
}
if ((arg0_i && arg1_i) || (arg0_u && arg1_u) ||
if (((arg0_i || arg0_u) && (arg1_i || arg1_u)) ||
(arg0_n && arg1_type.base_type() == "pointer") ||
(arg1_n && arg0_type.base_type() == "pointer")) {
// types already good
// we also allow (logand intvar pointer) and (logand pointer intvar)
auto new_form = pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind),
args.at(0), args.at(1));
result->push_back(new_form);
return new_form;
// types bad, insert cast.
} else {
// this is an ugly hack to make (logand (lognot (enum-bitfield xxxx)) work.
@@ -1450,22 +1450,76 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
nullptr, GenericOperator::make_fixed(FixedOperatorKind::LOGNOT), inverted);
auto new_form = pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind),
normal, args.at(1));
result->push_back(new_form);
// assert(false);
return;
return new_form;
}
}
}
bool arg0_int_like = env.dts->ts.tc(TypeSpec("integer"), arg0_type);
bool arg1_int_like = env.dts->ts.tc(TypeSpec("integer"), arg1_type);
if ((arg0_int_like) && (arg1_int_like)) {
auto new_form = pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind),
args.at(0), args.at(1));
return new_form;
// types bad, insert cast.
}
auto cast = pool.alloc_single_element_form<CastElement>(
nullptr, TypeSpec(arg0_i ? "int" : "uint"), args.at(1));
auto new_form =
pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind), args.at(0), cast);
result->push_back(new_form);
return new_form;
}
}
}
void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
FixedOperatorKind kind,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects) {
auto element =
update_from_stack_logor_or_logand_helper(env, kind, pool, stack, allow_side_effects);
/*
(defmacro logclear (a b)
"Returns the result of setting the bits in b to zero in a"
`(logand (lognot ,b) ,a)
)
*/
constexpr int a_form = 0;
constexpr int b_form = 1;
auto lognot_submatcher =
Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::LOGNOT), {Matcher::any(b_form)});
auto lognot_submatchers =
Matcher::match_or({Matcher::cast("uint", lognot_submatcher),
Matcher::cast("int", lognot_submatcher), lognot_submatcher});
auto logclear_matcher =
Matcher::match_or({Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::LOGAND),
{lognot_submatchers, Matcher::any(a_form)}),
Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::LOGAND),
{Matcher::any(a_form), lognot_submatchers})});
Form hack_form;
hack_form.elts().push_back(element);
auto mr = match(logclear_matcher, &hack_form);
if (mr.matched) {
result->push_back(pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::LOGCLEAR),
std::vector<Form*>{mr.maps.forms.at(a_form), mr.maps.forms.at(b_form)}));
return;
}
result->push_back(element);
}
void SimpleExpressionElement::update_from_stack_left_shift(const Env& env,
FormPool& pool,
FormStack& stack,
@@ -1875,10 +1929,16 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
update_from_stack_pcypld(env, pool, stack, result, allow_side_effects);
break;
case SimpleExpression::Kind::VECTOR_PLUS:
update_from_stack_vector_plus_minus(true, env, pool, stack, result, allow_side_effects);
update_from_stack_vector_plus_minus_cross(FixedOperatorKind::VECTOR_PLUS, env, pool, stack,
result, allow_side_effects);
break;
case SimpleExpression::Kind::VECTOR_MINUS:
update_from_stack_vector_plus_minus(false, env, pool, stack, result, allow_side_effects);
update_from_stack_vector_plus_minus_cross(FixedOperatorKind::VECTOR_MINUS, env, pool, stack,
result, allow_side_effects);
break;
case SimpleExpression::Kind::VECTOR_CROSS:
update_from_stack_vector_plus_minus_cross(FixedOperatorKind::VECTOR_CROSS, env, pool, stack,
result, allow_side_effects);
break;
case SimpleExpression::Kind::VECTOR_FLOAT_PRODUCT:
update_from_stack_vector_float_product(env, pool, stack, result, allow_side_effects);
@@ -2033,7 +2093,10 @@ void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack
const std::pair<FixedOperatorKind, FixedOperatorKind> in_place_ops[] = {
{FixedOperatorKind::ADDITION, FixedOperatorKind::ADDITION_IN_PLACE},
{FixedOperatorKind::ADDITION_PTR, FixedOperatorKind::ADDITION_PTR_IN_PLACE}};
{FixedOperatorKind::ADDITION_PTR, FixedOperatorKind::ADDITION_PTR_IN_PLACE},
{FixedOperatorKind::LOGAND, FixedOperatorKind::LOGAND_IN_PLACE},
{FixedOperatorKind::LOGIOR, FixedOperatorKind::LOGIOR_IN_PLACE},
{FixedOperatorKind::LOGCLEAR, FixedOperatorKind::LOGCLEAR_IN_PLACE}};
auto src_as_generic = m_src->try_as_element<GenericElement>();
if (src_as_generic) {
@@ -3383,6 +3446,21 @@ FormElement* ConditionElement::make_nonzero_check_generic(const Env& env,
std::vector<Form*>{mr.maps.forms.at(0), value_form});
}
/*
(defmacro logtest? (a b)
"does a have any of the bits in b?"
`(nonzero? (logand ,a ,b))
)
*/
auto logand_matcher = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::LOGAND),
{Matcher::any(0), Matcher::any(1)});
auto mr_logand = match(logand_matcher, source_forms.at(0));
if (mr_logand.matched) {
return pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::LOGTEST), mr_logand.maps.forms.at(0),
mr_logand.maps.forms.at(1));
}
return pool.alloc_element<GenericElement>(GenericOperator::make_compare(m_kind), source_forms);
}