mirror of
https://github.com/open-goal/jak-project.git
synced 2025-02-06 13:49:15 +00:00
handle zero case in enum comparison (#484)
This commit is contained in:
parent
d9f9d36f37
commit
c95e501cec
@ -2371,6 +2371,40 @@ Matcher make_int_uint_cast_matcher(const Matcher& thing) {
|
||||
// ConditionElement
|
||||
///////////////////
|
||||
|
||||
namespace {
|
||||
/*!
|
||||
* Try to make a pretty looking constant out of value for comparing to something of type.
|
||||
* If we can't do anything nice, return nullptr.
|
||||
*/
|
||||
Form* try_make_constant_for_compare(Form* value,
|
||||
const TypeSpec& type,
|
||||
FormPool& pool,
|
||||
const Env& env) {
|
||||
if (get_goal_integer_constant(value, env) && env.dts->ts.try_enum_lookup(type)) {
|
||||
return cast_form(value, type, pool, env);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Form* try_make_constant_from_int_for_compare(s64 value,
|
||||
const TypeSpec& type,
|
||||
FormPool& pool,
|
||||
const Env& env) {
|
||||
auto enum_type_info = env.dts->ts.try_enum_lookup(type);
|
||||
if (enum_type_info) {
|
||||
if (enum_type_info->is_bitfield()) {
|
||||
if (value != 0) {
|
||||
// prefer (zero? x) for bitfield enums.
|
||||
return cast_to_bitfield_enum(enum_type_info, pool, env, value);
|
||||
}
|
||||
} else {
|
||||
return cast_to_int_enum(enum_type_info, pool, env, value);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FormElement* ConditionElement::make_zero_check_generic(const Env& env,
|
||||
FormPool& pool,
|
||||
const std::vector<Form*>& source_forms,
|
||||
@ -2405,6 +2439,13 @@ FormElement* ConditionElement::make_zero_check_generic(const Env& env,
|
||||
}
|
||||
}
|
||||
|
||||
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});
|
||||
}
|
||||
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_compare(m_kind), source_forms);
|
||||
}
|
||||
|
||||
@ -2442,12 +2483,11 @@ FormElement* ConditionElement::make_equal_check_generic(const Env& env,
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::NULLP),
|
||||
source_forms.at(0));
|
||||
} else {
|
||||
auto int_val = get_goal_integer_constant(source_forms.at(1), env);
|
||||
auto src0_as_enum = env.dts->ts.try_enum_lookup(source_types.at(0));
|
||||
if (src0_as_enum && int_val) {
|
||||
// if comparing an enum against a constant integer, rewrite the enum.
|
||||
auto nice_constant =
|
||||
try_make_constant_for_compare(source_forms.at(1), source_types.at(0), pool, env);
|
||||
if (nice_constant) {
|
||||
auto forms_with_cast = source_forms;
|
||||
forms_with_cast.at(1) = cast_form(source_forms.at(1), source_types.at(0), pool, env);
|
||||
forms_with_cast.at(1) = nice_constant;
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::EQ),
|
||||
forms_with_cast);
|
||||
} else {
|
||||
|
@ -563,15 +563,7 @@ Form* cast_to_bitfield_enum(const EnumType* type_info,
|
||||
assert(type_info->is_bitfield());
|
||||
auto integer = get_goal_integer_constant(strip_int_or_uint_cast(in), env);
|
||||
if (integer) {
|
||||
auto elts =
|
||||
decompile_bitfield_enum_from_int(TypeSpec(type_info->get_name()), env.dts->ts, *integer);
|
||||
auto oper = GenericOperator::make_function(
|
||||
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, type_info->get_name()));
|
||||
std::vector<Form*> form_elts;
|
||||
for (auto& x : elts) {
|
||||
form_elts.push_back(pool.alloc_single_element_form<ConstantTokenElement>(nullptr, x));
|
||||
}
|
||||
return pool.alloc_single_element_form<GenericElement>(nullptr, oper, form_elts);
|
||||
return cast_to_bitfield_enum(type_info, pool, env, *integer);
|
||||
} else {
|
||||
// all failed, just return whatever.
|
||||
return pool.alloc_single_element_form<CastElement>(nullptr, typespec, in);
|
||||
@ -594,6 +586,7 @@ Form* cast_to_int_enum(const EnumType* type_info,
|
||||
}
|
||||
|
||||
Form* cast_to_int_enum(const EnumType* type_info, FormPool& pool, const Env& env, s64 in) {
|
||||
assert(!type_info->is_bitfield());
|
||||
auto entry = decompile_int_enum_from_int(TypeSpec(type_info->get_name()), env.dts->ts, in);
|
||||
auto oper = GenericOperator::make_function(
|
||||
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, type_info->get_name()));
|
||||
@ -601,4 +594,16 @@ Form* cast_to_int_enum(const EnumType* type_info, FormPool& pool, const Env& env
|
||||
nullptr, oper, pool.alloc_single_element_form<ConstantTokenElement>(nullptr, entry));
|
||||
}
|
||||
|
||||
Form* cast_to_bitfield_enum(const EnumType* type_info, FormPool& pool, const Env& env, s64 in) {
|
||||
assert(type_info->is_bitfield());
|
||||
auto elts = decompile_bitfield_enum_from_int(TypeSpec(type_info->get_name()), env.dts->ts, in);
|
||||
auto oper = GenericOperator::make_function(
|
||||
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, type_info->get_name()));
|
||||
std::vector<Form*> form_elts;
|
||||
for (auto& x : elts) {
|
||||
form_elts.push_back(pool.alloc_single_element_form<ConstantTokenElement>(nullptr, x));
|
||||
}
|
||||
return pool.alloc_single_element_form<GenericElement>(nullptr, oper, form_elts);
|
||||
}
|
||||
|
||||
} // namespace decompiler
|
@ -178,6 +178,7 @@ Form* cast_to_int_enum(const EnumType* type_info,
|
||||
Form* in);
|
||||
|
||||
Form* cast_to_int_enum(const EnumType* type_info, FormPool& pool, const Env& env, s64 in);
|
||||
Form* cast_to_bitfield_enum(const EnumType* type_info, FormPool& pool, const Env& env, s64 in);
|
||||
|
||||
std::optional<u64> get_goal_integer_constant(Form* in, const Env&);
|
||||
|
||||
|
@ -613,7 +613,7 @@
|
||||
((= v1-1 (dma-tag-id cnt))
|
||||
"cnt"
|
||||
)
|
||||
((zero? v1-1)
|
||||
((= v1-1 (dma-tag-id refe))
|
||||
"refe"
|
||||
)
|
||||
(else
|
||||
@ -754,7 +754,7 @@
|
||||
data-2
|
||||
(the-as dma-packet (&-> (the-as (pointer uint64) data-2) 2))
|
||||
)
|
||||
(if (zero? (-> current-tag id))
|
||||
(if (= (-> current-tag id) (dma-tag-id refe))
|
||||
(set! end-condition #t)
|
||||
)
|
||||
)
|
||||
|
@ -115,7 +115,7 @@
|
||||
((= v1-0 (gs-psm ct24))
|
||||
"ct24"
|
||||
)
|
||||
((zero? v1-0)
|
||||
((= v1-0 (gs-psm ct32))
|
||||
"ct32"
|
||||
)
|
||||
(else
|
||||
|
@ -105,7 +105,7 @@
|
||||
((= kind (file-kind tpage))
|
||||
(format *file-temp-string* "texture-page~D/tpage-~S" 7 name)
|
||||
)
|
||||
((zero? kind)
|
||||
((= kind (file-kind level-bt))
|
||||
(format *file-temp-string* "level~D/~S-bt" 30 name)
|
||||
)
|
||||
((= kind (file-kind tx))
|
||||
@ -138,7 +138,7 @@
|
||||
(defun make-vfile-name ((kind file-kind) (name string))
|
||||
(clear *file-temp-string*)
|
||||
(cond
|
||||
((zero? kind)
|
||||
((= kind (file-kind level-bt))
|
||||
(format *file-temp-string* "$LEVEL/~S" name)
|
||||
)
|
||||
((= kind (file-kind art-group))
|
||||
@ -163,7 +163,7 @@
|
||||
)
|
||||
7
|
||||
)
|
||||
((zero? v1-0)
|
||||
((= v1-0 (file-kind level-bt))
|
||||
30
|
||||
)
|
||||
((= v1-0 (file-kind art-group))
|
||||
@ -182,7 +182,7 @@
|
||||
((= v1-1 (file-kind tpage))
|
||||
"texture-page"
|
||||
)
|
||||
((zero? v1-1)
|
||||
((= v1-1 (file-kind level-bt))
|
||||
"bsp-header"
|
||||
)
|
||||
((= v1-1 (file-kind art-group))
|
||||
|
Loading…
x
Reference in New Issue
Block a user