This commit is contained in:
water 2021-02-11 16:13:03 -05:00
parent d9a8f28e52
commit e8231c2708
13 changed files with 286 additions and 117 deletions

View file

@ -12,7 +12,7 @@ namespace versions {
constexpr s32 GOAL_VERSION_MAJOR = 0;
constexpr s32 GOAL_VERSION_MINOR = 6;
constexpr int DECOMPILER_VERSION = 1;
constexpr int DECOMPILER_VERSION = 2;
// these versions are from the game
constexpr u32 ART_FILE_VERSION = 6;

View file

@ -153,6 +153,38 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
}
}
if (input_type.kind == TP_Type::Kind::OBJECT_PLUS_PRODUCT_WITH_CONSTANT) {
FieldReverseLookupInput rd_in;
DerefKind dk;
dk.is_store = true;
dk.reg_kind = get_reg_kind(ro.reg);
dk.size = m_size;
rd_in.deref = dk;
rd_in.base_type = input_type.get_obj_plus_const_mult_typespec();
rd_in.stride = input_type.get_multiplier();
rd_in.offset = ro.offset;
auto rd = env.dts->ts.reverse_field_lookup(rd_in);
if (rd.success) {
std::vector<DerefToken> tokens;
assert(!rd.tokens.empty());
for (auto& token : rd.tokens) {
tokens.push_back(to_token(token));
}
// we pass along the register offset because code generation seems to be a bit
// different in different cases.
auto source = pool.alloc_single_element_form<ArrayFieldAccess>(
nullptr, ro.var, tokens, input_type.get_multiplier(), ro.offset);
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(
nullptr, m_value.as_expr(), m_my_idx);
assert(!rd.addr_of);
return pool.alloc_element<SetFormFormElement>(source, val);
}
}
FieldReverseLookupInput rd_in;
DerefKind dk;
dk.is_store = true;

View file

@ -274,12 +274,16 @@ void SimpleAtomElement::get_modified_regs(RegSet& regs) const {
// SetVarElement
/////////////////////////////
SetVarElement::SetVarElement(const Variable& var, Form* value, bool is_sequence_point)
: m_dst(var), m_src(value), m_is_sequence_point(is_sequence_point) {
SetVarElement::SetVarElement(const Variable& var,
Form* value,
bool is_sequence_point,
const SetVarInfo& info)
: m_dst(var), m_src(value), m_is_sequence_point(is_sequence_point), m_var_info(info) {
value->parent_element = this;
}
goos::Object SetVarElement::to_form_internal(const Env& env) const {
assert(active());
return pretty_print::build_list("set!", m_dst.to_form(env), m_src->to_form(env));
}

View file

@ -223,7 +223,10 @@ class SimpleAtomElement : public FormElement {
*/
class SetVarElement : public FormElement {
public:
SetVarElement(const Variable& var, Form* value, bool is_sequence_point);
SetVarElement(const Variable& var,
Form* value,
bool is_sequence_point,
const SetVarInfo& info = {});
goos::Object to_form_internal(const Env& env) const override;
void apply(const std::function<void(FormElement*)>& f) override;
void apply_form(const std::function<void(Form*)>& f) override;
@ -241,28 +244,23 @@ class SetVarElement : public FormElement {
const Variable& dst() const { return m_dst; }
const Form* src() const { return m_src; }
Form* src() { return m_src; }
bool is_eliminated_coloring_move() const { return m_is_eliminated_coloring_move; }
void eliminate_as_coloring_move() { m_is_eliminated_coloring_move = true; }
bool is_eliminated_coloring_move() const { return m_var_info.is_eliminated_coloring_move; }
void eliminate_as_coloring_move() { m_var_info.is_eliminated_coloring_move = true; }
bool is_dead_set() const { return m_is_dead_set; }
void mark_as_dead_set() { m_is_dead_set = true; }
bool is_dead_set() const { return m_var_info.is_dead_set; }
void mark_as_dead_set() { m_var_info.is_dead_set = true; }
bool is_dead_false_set() const { return m_is_dead_false; }
void mark_as_dead_false() { m_is_dead_false = true; }
bool is_dead_false_set() const { return m_var_info.is_dead_false; }
void mark_as_dead_false() { m_var_info.is_dead_false = true; }
const SetVarInfo& info() const { return m_var_info; }
private:
Variable m_dst;
Form* m_src = nullptr;
bool m_is_sequence_point = true;
// is this a compiler-inserted move at the beginning of a function
// that should be eliminated?
bool m_is_eliminated_coloring_move = false;
// is this a (set! var expr) which consumes the reg for expr,
// and var is written and unused?
bool m_is_dead_set = false;
// is this a (set! var #f) where the value of #f isn't used?
bool m_is_dead_false = false;
SetVarInfo m_var_info;
};
/*!

View file

@ -746,14 +746,14 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
auto& info = env.reg_use().op.at(var.idx());
if (info.consumes.find(var.reg()) != info.consumes.end()) {
stack.push_non_seq_reg_to_reg(m_dst, src_as_se->expr().get_arg(0).var(), m_src,
m_is_eliminated_coloring_move);
m_var_info);
return;
}
}
}
}
stack.push_value_to_reg(m_dst, m_src, true, m_is_eliminated_coloring_move);
stack.push_value_to_reg(m_dst, m_src, true, m_var_info);
for (auto x : m_src->elts()) {
assert(x->parent_form == m_src);
}
@ -773,8 +773,8 @@ void SetVarElement::update_from_stack(const Env& env,
void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
// todo - is the order here right?
m_src->update_children_from_stack(env, pool, stack, false);
m_dst->update_children_from_stack(env, pool, stack, false);
m_src->update_children_from_stack(env, pool, stack, false);
stack.push_form_element(this, true);
}
@ -1141,7 +1141,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
}
std::vector<FormElement*> new_entries;
if (form == entry.body && rewrite_as_set) {
if (form == entry.body && rewrite_as_set && !set_unused) {
new_entries = temp_stack.rewrite_to_get_var(pool, *last_var, env);
} else {
new_entries = temp_stack.rewrite(pool);
@ -1161,7 +1161,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
}
std::vector<FormElement*> new_entries;
if (rewrite_as_set) {
if (rewrite_as_set && !set_unused) {
new_entries = temp_stack.rewrite_to_get_var(pool, *last_var, env);
} else {
new_entries = temp_stack.rewrite(pool);
@ -1405,24 +1405,41 @@ FormElement* ConditionElement::make_generic(const Env&,
}
void ConditionElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
std::vector<Form*> source_forms;
std::vector<Form*> source_forms, popped_forms;
std::vector<TypeSpec> source_types;
std::vector<Variable> vars;
for (int i = 0; i < get_condition_num_args(m_kind); i++) {
auto& var = m_src[i]->var();
vars.push_back(var);
source_types.push_back(env.get_types_before_op(var.idx()).get(var.reg()).typespec());
if (m_src[i]->is_var()) {
auto& var = m_src[i]->var();
vars.push_back(var);
source_types.push_back(env.get_types_before_op(var.idx()).get(var.reg()).typespec());
} else if (m_src[i]->is_int()) {
source_types.push_back(TypeSpec("int"));
} else {
throw std::runtime_error("Unsupported atom in ConditionElement::push_to_stack");
}
}
if (m_flipped) {
std::reverse(vars.begin(), vars.end());
}
source_forms = pop_to_forms(vars, env, pool, stack, true, m_consumed);
popped_forms = pop_to_forms(vars, env, pool, stack, true, m_consumed);
if (m_flipped) {
std::reverse(source_forms.begin(), source_forms.end());
std::reverse(popped_forms.begin(), popped_forms.end());
}
int popped_counter = 0;
for (int i = 0; i < get_condition_num_args(m_kind); i++) {
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]));
}
}
assert(popped_counter == int(popped_forms.size()));
assert(source_forms.size() == source_types.size());
stack.push_form_element(make_generic(env, pool, source_forms, source_types), true);
}

View file

@ -25,21 +25,24 @@ std::string FormStack::print(const Env& env) {
return result;
}
void FormStack::push_value_to_reg(Variable var, Form* value, bool sequence_point, bool is_elim) {
void FormStack::push_value_to_reg(Variable var,
Form* value,
bool sequence_point,
const SetVarInfo& info) {
assert(value);
StackEntry entry;
entry.active = true; // by default, we should display everything!
entry.sequence_point = sequence_point;
entry.destination = var;
entry.source = value;
entry.eliminated_as_coloring_move = is_elim;
entry.set_info = info;
m_stack.push_back(entry);
}
void FormStack::push_non_seq_reg_to_reg(const Variable& dst,
const Variable& src,
Form* src_as_form,
bool is_elim) {
const SetVarInfo& info) {
assert(src_as_form);
StackEntry entry;
entry.active = true;
@ -47,7 +50,7 @@ void FormStack::push_non_seq_reg_to_reg(const Variable& dst,
entry.destination = dst;
entry.non_seq_source = src;
entry.source = src_as_form;
entry.eliminated_as_coloring_move = is_elim;
entry.set_info = info;
m_stack.push_back(entry);
}
@ -152,10 +155,8 @@ std::vector<FormElement*> FormStack::rewrite(FormPool& pool) {
}
if (e.destination.has_value()) {
auto elt = pool.alloc_element<SetVarElement>(*e.destination, e.source, e.sequence_point);
if (e.eliminated_as_coloring_move) {
elt->eliminate_as_coloring_move();
}
auto elt =
pool.alloc_element<SetVarElement>(*e.destination, e.source, e.sequence_point, e.set_info);
e.source->parent_element = elt;
result.push_back(elt);
} else {

View file

@ -16,11 +16,11 @@ class FormStack {
void push_value_to_reg(Variable var,
Form* value,
bool sequence_point,
bool is_eliminated = false);
const SetVarInfo& info = {});
void push_non_seq_reg_to_reg(const Variable& dst,
const Variable& src,
Form* src_as_form,
bool is_elim);
const SetVarInfo& info = {});
void push_form_element(FormElement* elt, bool sequence_point);
Form* pop_reg(const Variable& var,
const RegSet& barrier,
@ -38,11 +38,13 @@ class FormStack {
std::optional<Variable> destination; // what register we are setting (or nullopt if no dest.)
std::optional<Variable> non_seq_source; // source variable, if we are setting var to var.
Form* source = nullptr; // the value we are setting the register to.
bool eliminated_as_coloring_move = false;
FormElement* elt = nullptr;
bool sequence_point = false;
TP_Type type;
SetVarInfo set_info;
std::string print(const Env& env) const;
};
std::vector<StackEntry> m_stack;

View file

@ -149,4 +149,16 @@ struct VariableNames {
}
}
};
struct SetVarInfo {
// is this a compiler-inserted move at the beginning of a function
// that should be eliminated?
bool is_eliminated_coloring_move = false;
// is this a (set! var expr) which consumes the reg for expr,
// and var is written and unused?
bool is_dead_set = false;
// is this a (set! var #f) where the value of #f isn't used?
bool is_dead_false = false;
};
} // namespace decompiler

View file

@ -2031,7 +2031,7 @@
(state int32 :offset-assert 84)
(align uint8 6 :offset-assert 88)
(direct uint8 6 :offset-assert 94)
(buzz-val uint16 2 :offset-assert 100)
(buzz-val uint8 2 :offset-assert 100)
(buzz-time uint64 2 :offset-assert 104)
(buzz basic :offset-assert 120)
(buzz-act int32 :offset-assert 124)

View file

@ -6,4 +6,10 @@
- Remove useless `(set! <a> <b>)` and eliminate useless temporaries created by these.
- Remove useless `set!`s sometimes appearing around functions `(set! <a> (some-function ...))` when the result is unused, but moved into a different register.
- Recognize `(break!)` (GOAL breakpoint)
- Support `(new 'process ...)`
- Support `(new 'process ...)`
## Version 2
- Expressions like `(set! (-> a b) (-> c d))` are much less likely to have fake temporaries.
- Many more useless `set!`s will be removed
- Stores into arrays are supported
- Fixed bug where unused/eliminated temporaries would sometimes be used as the result of a block

View file

@ -623,7 +623,6 @@ TEST_F(FormRegressionTest, ExprFindParentMethod) {
" (set! v0-0 (-> arg0 method-table arg1))\n"
" (if (zero? v0-0) (return nothing))\n"
" )\n"
" (set! v1-5 '#f)\n"
" v0-0\n"
" )";
test_with_expr(func, type, expected, false, "");
@ -665,8 +664,6 @@ TEST_F(FormRegressionTest, ExprRef) {
" (set! arg0 (cdr arg0))\n"
" (set! v1-0 (+ v1-0 1))\n"
" )\n"
" (set! v1-1 '#f)\n"
" (set! v1-2 '#f)\n"
" (car arg0)\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -732,7 +729,6 @@ TEST_F(FormRegressionTest, ExprPairMethod4) {
" (set! v0-0 (+ v0-0 1))\n"
" (set! v1-1 (cdr v1-1))\n"
" )\n"
" (set! v1-2 '#f)\n"
" )\n"
" )\n"
" v0-0\n"
@ -784,7 +780,6 @@ TEST_F(FormRegressionTest, ExprLast) {
" (nop!)\n"
" (nop!)\n"
" (set! v0-0 (cdr v0-0)))\n"
" (set! v1-1 '#f)\n"
" v0-0\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -837,7 +832,6 @@ TEST_F(FormRegressionTest, ExprMember) {
" (not (or (= v1-0 '()) (= (car v1-0) arg0)))\n"
" (set! v1-0 (cdr v1-0))\n"
" )\n"
" (set! a0-1 '#f)\n"
" (if (!= v1-0 '()) v1-0)\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -900,7 +894,6 @@ TEST_F(FormRegressionTest, ExprNmember) {
" (not (or (= arg1 '()) (name= (the-as basic (car arg1)) arg0)))\n"
" (set! arg1 (cdr arg1))\n"
" )\n"
" (set! v1-2 '#f)\n"
" (if (!= arg1 '()) arg1)\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -952,7 +945,6 @@ TEST_F(FormRegressionTest, ExprAssoc) {
" (not (or (= v1-0 '()) (= (car (car v1-0)) arg0)))\n"
" (set! v1-0 (cdr v1-0))\n"
" )\n"
" (set! a0-1 '#f)\n"
" (if (!= v1-0 '()) (car v1-0))\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -1021,7 +1013,6 @@ TEST_F(FormRegressionTest, ExprAssoce) {
" )\n"
" (set! v1-0 (cdr v1-0))\n"
" )\n"
" (set! a0-1 '#f)\n"
" (if (!= v1-0 '()) (car v1-0))\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -1113,7 +1104,6 @@ TEST_F(FormRegressionTest, ExprNassoc) {
" )\n"
" (set! arg1 (cdr arg1))\n"
" )\n"
" (set! v1-3 (quote #f))\n"
" (if (!= arg1 (quote ())) (car arg1))\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -1219,7 +1209,6 @@ TEST_F(FormRegressionTest, ExprNassoce) {
" )\n"
" (set! arg1 (cdr arg1))\n"
" )\n"
" (set! v1-4 (quote #f))\n"
" (if (!= arg1 (quote ())) (car arg1))\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -1275,7 +1264,6 @@ TEST_F(FormRegressionTest, ExprAppend) {
" (else\n"
" (set! v1-1 arg0)\n"
" (while (!= (cdr v1-1) '()) (nop!) (nop!) (set! v1-1 (cdr v1-1)))\n"
" (set! a2-1 '#f)\n"
" (if (!= v1-1 '()) (set! (cdr v1-1) arg1))\n"
" arg0\n"
" )\n"
@ -1351,7 +1339,6 @@ TEST_F(FormRegressionTest, ExprDelete) {
" (set! v1-1 a2-0)\n"
" (set! a2-0 (cdr a2-0))\n"
" )\n"
" (set! a0-1 (quote #f))\n"
" (if (!= a2-0 (quote ())) (set! (cdr v1-1) (cdr a2-0)))\n"
" arg1\n"
" )\n"
@ -1430,7 +1417,6 @@ TEST_F(FormRegressionTest, ExprDeleteCar) {
" (set! v1-2 a2-0)\n"
" (set! a2-0 (cdr a2-0))\n"
" )\n"
" (set! a0-1 (quote #f))\n"
" (if (!= a2-0 (quote ())) (set! (cdr v1-2) (cdr a2-0)))\n"
" arg1\n"
" )\n"
@ -1602,10 +1588,7 @@ TEST_F(FormRegressionTest, ExprSort) {
" )\n"
" (set! s3-0 (cdr s3-0))\n"
" )\n"
" (set! v1-10 (quote #f))\n"
" (set! v1-11 (quote #f))\n"
" )\n"
" (set! v1-12 (quote #f))\n"
" arg0\n"
" )";
test_with_expr(func, type, expected, true, "");
@ -1894,8 +1877,6 @@ TEST_F(FormRegressionTest, ExprMemCopy) {
" (set! arg1 (+ arg1 (the-as uint 1)))\n"
" (set! v1-0 (+ v1-0 1))\n"
" )\n"
" (set! v1-1 (quote #f))\n"
" (set! v1-2 (quote #f))\n"
" v0-0\n"
" )";
test_with_expr(func, type, expected);
@ -1937,8 +1918,6 @@ TEST_F(FormRegressionTest, ExprMemSet32) {
" (nop!)\n"
" (set! v1-0 (+ v1-0 1))\n"
" )\n"
" (set! v1-1 (quote #f))\n"
" (set! v1-2 (quote #f))\n"
" v0-0\n"
" )";
test_with_expr(func, type, expected);
@ -1989,8 +1968,6 @@ TEST_F(FormRegressionTest, ExprMemOr) {
" (set! arg1 (+ arg1 (the-as uint 1)))\n"
" (set! v1-0 (+ v1-0 1))\n"
" )\n"
" (set! v1-1 (quote #f))\n"
" (set! v1-2 (quote #f))\n"
" v0-0\n"
" )";
test_with_expr(func, type, expected);
@ -2209,7 +2186,6 @@ TEST_F(FormRegressionTest, ExprPrintTreeBitmask) {
" (set! arg0 (shr arg0 1))\n"
" (set! s4-0 (+ s4-0 1))\n"
" )\n"
" (set! v1-3 (quote #f))\n"
" (quote #f)\n"
" )";
test_with_expr(func, type, expected, false, "", {{"L323", " "}, {"L322", "| "}});

View file

@ -554,8 +554,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-0 (+ s5-0 1))\n"
" )\n"
" (set! v1-5 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint32))\n"
" (set! s5-1 0)\n"
@ -568,8 +566,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-1 (+ s5-1 1))\n"
" )\n"
" (set! v1-10 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote int64))\n"
" (set! s5-2 0)\n"
@ -582,8 +578,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-2 (+ s5-2 1))\n"
" )\n"
" (set! v1-15 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint64))\n"
" (set! s5-3 0)\n"
@ -596,8 +590,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-3 (+ s5-3 1))\n"
" )\n"
" (set! v1-20 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote int8))\n"
" (set! s5-4 0)\n"
@ -610,8 +602,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-4 (+ s5-4 1))\n"
" )\n"
" (set! v1-24 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint8))\n"
" (set! s5-5 0)\n"
@ -624,8 +614,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-5 (+ s5-5 1))\n"
" )\n"
" (set! v1-28 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote int16))\n"
" (set! s5-6 0)\n"
@ -638,8 +626,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-6 (+ s5-6 1))\n"
" )\n"
" (set! v1-33 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint16))\n"
" (set! s5-7 0)\n"
@ -652,10 +638,9 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-7 (+ s5-7 1))\n"
" )\n"
" (set! v1-38 (quote #f))\n"
" (quote #f)\n"
" )\n"
" (else\n"
// todo - why doesn't this merge?
" (set! v1-40 (or (= v1-1 (quote uint128)) (= v1-1 (quote int128))))\n"
" (cond\n"
" (v1-40\n"
@ -673,8 +658,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" (t9-10 a0-21 a1-11 a2-8)\n"
" (set! s5-8 (+ s5-8 1))\n"
" )\n"
" (set! v1-44 (quote #f))\n"
" (quote #f)\n"
" )\n"
" (else\n"
" (set! s5-9 0)\n"
@ -687,11 +670,8 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-9 (+ s5-9 1))\n"
" )\n"
" (set! v1-49 (quote #f))\n"
" (quote #f)\n"
" )\n"
" )\n"
" v1-39\n"
" )\n"
" )\n"
" )\n"
@ -708,8 +688,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-10 (+ s5-10 1))\n"
" )\n"
" (set! v1-59 (quote #f))\n"
" (quote #f)\n"
" )\n"
" (else\n"
" (set! s5-11 0)\n"
@ -722,8 +700,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
" )\n"
" (set! s5-11 (+ s5-11 1))\n"
" )\n"
" (set! v1-68 (quote #f))\n"
" (quote #f)\n"
" )\n"
" )\n"
" )\n"
@ -1240,8 +1216,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-0 (+ s5-0 1))\n"
" )\n"
" (set! v1-5 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint32))\n"
" (set! s5-1 0)\n"
@ -1255,8 +1229,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-1 (+ s5-1 1))\n"
" )\n"
" (set! v1-10 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote int64))\n"
" (set! s5-2 0)\n"
@ -1270,8 +1242,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-2 (+ s5-2 1))\n"
" )\n"
" (set! v1-15 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint64))\n"
" (set! s5-3 0)\n"
@ -1285,8 +1255,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-3 (+ s5-3 1))\n"
" )\n"
" (set! v1-20 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote int8))\n"
" (set! s5-4 0)\n"
@ -1300,8 +1268,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-4 (+ s5-4 1))\n"
" )\n"
" (set! v1-24 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint8))\n"
" (set! s5-5 0)\n"
@ -1315,8 +1281,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-5 (+ s5-5 1))\n"
" )\n"
" (set! v1-28 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote int16))\n"
" (set! s5-6 0)\n"
@ -1330,8 +1294,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-6 (+ s5-6 1))\n"
" )\n"
" (set! v1-33 (quote #f))\n"
" (quote #f)\n"
" )\n"
" ((= v1-1 (quote uint16))\n"
" (set! s5-7 0)\n"
@ -1345,8 +1307,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-7 (+ s5-7 1))\n"
" )\n"
" (set! v1-38 (quote #f))\n"
" (quote #f)\n"
" )\n"
" (else\n"
" (set! v1-40 (or (= v1-1 (quote int128)) (= v1-1 (quote uint128))))\n"
@ -1367,8 +1327,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" (t9-14 a0-25 a1-15 a2-13 a3-10)\n"
" (set! s5-8 (+ s5-8 1))\n"
" )\n"
" (set! v1-44 (quote #f))\n"
" (quote #f)\n"
" )\n"
" (else\n"
" (set! s5-9 0)\n"
@ -1377,11 +1335,8 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" (format (quote #t) \"~T [~D] ~D~%\" s5-9 (-> arg0 s5-9))\n"
" (set! s5-9 (+ s5-9 1))\n"
" )\n"
" (set! v1-49 (quote #f))\n"
" (quote #f)\n"
" )\n"
" )\n"
" v1-39\n"
" )\n"
" )\n"
" )\n"
@ -1399,8 +1354,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-10 (+ s5-10 1))\n"
" )\n"
" (set! v1-55 (quote #f))\n"
" (quote #f)\n"
" )\n"
" (else\n"
" (set! s5-11 0)\n"
@ -1414,8 +1367,6 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
" )\n"
" (set! s5-11 (+ s5-11 1))\n"
" )\n"
" (set! v1-60 (quote #f))\n"
" (quote #f)\n"
" )\n"
" )\n"
" )\n"

View file

@ -105,4 +105,174 @@ TEST_F(FormRegressionTest, ExprUnloadPackage) {
" *kernel-packages*\n"
" )";
test_with_expr(func, type, expected, true);
}
}
TEST_F(FormRegressionTest, ExprMethod1Thread) {
std::string func =
" sll r0, r0, 0\n"
"L274:\n"
" lwu v1, 4(a0)\n"
" lwu v1, 40(v1)\n"
" bne a0, v1, L275\n"
" or v1, s7, r0\n"
" lw r0, 2(r0)\n"
" addiu v1, r0, 0\n"
"L275:\n"
" lwu v0, 8(a0)\n"
" lwu v1, 4(a0)\n"
" sw v0, 44(v1)\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function thread none)";
std::string expected =
"(begin\n"
" (when (= arg0 (-> arg0 process main-thread)) (break!) (set! v1-3 0))\n"
" (set! (-> arg0 process top-thread) (-> arg0 previous))\n"
" )";
test_with_expr(func, type, expected, false);
}
TEST_F(FormRegressionTest, ExprMethod2Thread) {
std::string func =
" sll r0, r0, 0\n"
"L273:\n"
" daddiu sp, sp, -32\n"
" sd ra, 0(sp)\n"
" sd fp, 8(sp)\n"
" or fp, t9, r0\n"
" sq gp, 16(sp)\n"
" or gp, a0, r0\n"
" lw t9, format(s7)\n"
" daddiu a0, s7, #t\n"
" daddiu a1, fp, L343\n"
" lwu a2, -4(gp)\n"
" lwu a3, 0(gp)\n"
" lwu v1, 4(gp)\n"
" lwu t0, 0(v1)\n"
" lwu t1, 20(gp)\n"
" or t2, gp, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" or v0, gp, r0\n"
" ld ra, 0(sp)\n"
" ld fp, 8(sp)\n"
" lq gp, 16(sp)\n"
" jr ra\n"
" daddiu sp, sp, 32";
std::string type = "(function thread thread)";
std::string expected =
"(begin\n"
" (format\n"
" (quote #t)\n"
" \"#<~A ~S of ~S pc: #x~X @ #x~X>\"\n"
" (-> arg0 type)\n"
" (-> arg0 name)\n"
" (-> arg0 process name)\n"
" (-> arg0 pc)\n"
" arg0\n"
" )\n"
" arg0\n"
" )";
test_with_expr(func, type, expected, false, "", {{"L343", "#<~A ~S of ~S pc: #x~X @ #x~X>"}});
}
TEST_F(FormRegressionTest, ExprMethod9Thread) {
std::string func =
" sll r0, r0, 0\n"
"L268:\n"
" daddiu sp, sp, -16\n"
" sd ra, 0(sp)\n"
" sd fp, 8(sp)\n"
" or fp, t9, r0\n"
" lwu a2, 4(a0)\n"
" lwu v1, 40(a2)\n"
" beq a0, v1, L269\n"
" sll r0, r0, 0\n"
" lw t9, format(s7)\n"
" addiu a0, r0, 0\n"
" daddiu a1, fp, L342\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" or v1, v0, r0\n"
" beq r0, r0, L272\n"
" sll r0, r0, 0\n"
"L269:\n"
" lw v1, 32(a0)\n"
" bne v1, a1, L270\n"
" sll r0, r0, 0\n"
" or v1, s7, r0\n"
" beq r0, r0, L272\n"
" sll r0, r0, 0\n"
"L270:\n"
" lw v1, 32(a0)\n"
" daddiu v1, v1, -4\n"
" lwu a3, -4(a0)\n"
" lhu a3, 8(a3)\n"
" daddu v1, v1, a3\n"
" daddu v1, v1, a0\n"
" lwu a3, 84(a2)\n"
" bne a3, v1, L271\n"
" sll r0, r0, 0\n"
" daddiu v1, a1, -4\n"
" lwu a3, -4(a0)\n"
" lhu a3, 8(a3)\n"
" daddu v1, v1, a3\n"
" daddu v1, v1, a0\n"
" sw v1, 84(a2)\n"
" sw a1, 32(a0)\n"
" or v1, a1, r0\n"
" beq r0, r0, L272\n"
" sll r0, r0, 0\n"
"L271:\n"
" lw t9, format(s7)\n"
" addiu a0, r0, 0\n"
" daddiu a1, fp, L341\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" or v1, v0, r0\n"
"L272:\n"
" or v0, r0, r0\n"
" ld ra, 0(sp)\n"
" ld fp, 8(sp)\n"
" jr ra\n"
" daddiu sp, sp, 16";
std::string type = "(function thread int none)";
std::string expected =
"(begin\n"
" (set! a2-0 (-> arg0 process))\n"
" (cond\n"
" ((!= arg0 (-> a2-0 main-thread)) (format 0 \"1 ~A ~%\" a2-0))\n"
" ((= (-> arg0 stack-size) arg1))\n"
" ((=\n"
" (-> a2-0 heap-cur)\n"
" (+\n"
" (+ (+ (-> arg0 stack-size) -4) (the-as int (-> arg0 type size)))\n"
" (the-as int arg0)\n"
" )\n"
" )\n"
" (set!\n"
" (-> a2-0 heap-cur)\n"
" (+ (+ (+ arg1 -4) (the-as int (-> arg0 type size))) (the-as int arg0))\n"
" )\n"
" (set! (-> arg0 stack-size) arg1)\n"
" )\n"
" (else (format 0 \"2 ~A ~%\" a2-0))\n"
" )\n"
" (set! v0-2 0)\n"
" )";
test_with_expr(func, type, expected, false, "", {{"L342", "1 ~A ~%"}, {"L341", "2 ~A ~%"}});
}