misc small improvements (#217)

This commit is contained in:
water111 2021-01-27 15:39:50 -05:00 committed by GitHub
parent b35beab372
commit 3ea8cbea6f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 441 additions and 240 deletions

View file

@ -32,6 +32,10 @@ void FormElement::push_to_stack(const Env& env, FormPool&, FormStack&) {
throw std::runtime_error("push_to_stack not implemented for " + to_string(env));
}
goos::Object FormElement::to_form_as_condition(const Env& env) const {
return to_form(env);
}
///////////////////
// Form
//////////////////
@ -50,6 +54,26 @@ goos::Object Form::to_form(const Env& env) const {
}
}
goos::Object Form::to_form_as_condition(const Env& env) const {
assert(!m_elements.empty());
if (m_elements.size() == 1) {
return m_elements.front()->to_form_as_condition(env);
} else {
std::vector<goos::Object> forms;
forms.push_back(pretty_print::to_symbol("begin"));
for (size_t i = 0; i < m_elements.size(); i++) {
const auto& x = m_elements.at(i);
if (i == m_elements.size() - 1) {
forms.push_back(x->to_form_as_condition(env));
} else {
forms.push_back(x->to_form(env));
}
}
return pretty_print::build_list(forms);
}
}
std::string Form::to_string(const Env& env) const {
return to_form(env).print();
}
@ -310,6 +334,14 @@ goos::Object ConditionElement::to_form(const Env& env) const {
}
}
goos::Object ConditionElement::to_form_as_condition(const Env& env) const {
if (m_kind == IR2_Condition::Kind::TRUTHY) {
return m_src[0]->to_form(env.file->labels, &env);
} else {
return to_form(env);
}
}
void ConditionElement::apply(const std::function<void(FormElement*)>& f) {
f(this);
}
@ -435,7 +467,7 @@ goos::Object CondWithElseElement::to_form(const Env& env) const {
else_ir->is_single_element()) {
std::vector<goos::Object> list;
list.push_back(pretty_print::to_symbol("if"));
list.push_back(entries.front().condition->to_form(env));
list.push_back(entries.front().condition->to_form_as_condition(env));
list.push_back(entries.front().body->to_form(env));
list.push_back(else_ir->to_form(env));
return pretty_print::build_list(list);
@ -444,7 +476,7 @@ goos::Object CondWithElseElement::to_form(const Env& env) const {
list.push_back(pretty_print::to_symbol("cond"));
for (auto& e : entries) {
std::vector<goos::Object> entry;
entry.push_back(e.condition->to_form(env));
entry.push_back(e.condition->to_form_as_condition(env));
e.body->inline_forms(entry, env);
list.push_back(pretty_print::build_list(entry));
}
@ -511,7 +543,7 @@ void WhileElement::apply(const std::function<void(FormElement*)>& f) {
goos::Object WhileElement::to_form(const Env& env) const {
std::vector<goos::Object> list;
list.push_back(pretty_print::to_symbol("while"));
list.push_back(condition->to_form(env));
list.push_back(condition->to_form_as_condition(env));
body->inline_forms(list, env);
return pretty_print::build_list(list);
}
@ -540,7 +572,7 @@ void UntilElement::apply(const std::function<void(FormElement*)>& f) {
goos::Object UntilElement::to_form(const Env& env) const {
std::vector<goos::Object> list;
list.push_back(pretty_print::to_symbol("until"));
list.push_back(condition->to_form(env));
list.push_back(condition->to_form_as_condition(env));
body->inline_forms(list, env);
return pretty_print::build_list(list);
}
@ -596,7 +628,7 @@ goos::Object ShortCircuitElement::to_form(const Env& env) const {
assert(false);
}
for (auto& x : entries) {
forms.push_back(x.condition->to_form(env));
forms.push_back(x.condition->to_form_as_condition(env));
}
return pretty_print::build_list(forms);
}
@ -617,7 +649,7 @@ goos::Object CondNoElseElement::to_form(const Env& env) const {
// print as an if statement if we can put the body in a single form.
std::vector<goos::Object> list;
list.push_back(pretty_print::to_symbol("if"));
list.push_back(entries.front().condition->to_form(env));
list.push_back(entries.front().condition->to_form_as_condition(env));
list.push_back(entries.front().body->to_form(env));
return pretty_print::build_list(list);
} else if (entries.size() == 1) {
@ -626,7 +658,7 @@ goos::Object CondNoElseElement::to_form(const Env& env) const {
// unless.
std::vector<goos::Object> list;
list.push_back(pretty_print::to_symbol("when"));
list.push_back(entries.front().condition->to_form(env));
list.push_back(entries.front().condition->to_form_as_condition(env));
entries.front().body->inline_forms(list, env);
return pretty_print::build_list(list);
} else {
@ -634,7 +666,7 @@ goos::Object CondNoElseElement::to_form(const Env& env) const {
list.push_back(pretty_print::to_symbol("cond"));
for (auto& e : entries) {
std::vector<goos::Object> entry;
entry.push_back(e.condition->to_form(env));
entry.push_back(e.condition->to_form_as_condition(env));
entries.front().body->inline_forms(list, env);
list.push_back(pretty_print::build_list(entry));
}
@ -924,12 +956,18 @@ GenericElement::GenericElement(GenericOperator op, std::vector<Form*> forms)
: m_head(op), m_elts(std::move(forms)) {}
goos::Object GenericElement::to_form(const Env& env) const {
std::vector<goos::Object> result;
result.push_back(m_head.to_form(env));
for (auto x : m_elts) {
result.push_back(x->to_form(env));
if (m_head.kind() == GenericOperator::Kind::CONDITION_OPERATOR &&
m_head.condition_kind() == IR2_Condition::Kind::TRUTHY) {
assert(m_elts.size() == 1);
return m_elts.front()->to_form_as_condition(env);
} else {
std::vector<goos::Object> result;
result.push_back(m_head.to_form(env));
for (auto x : m_elts) {
result.push_back(x->to_form(env));
}
return pretty_print::build_list(result);
}
return pretty_print::build_list(result);
}
void GenericElement::apply(const std::function<void(FormElement*)>& f) {

View file

@ -22,6 +22,7 @@ class FormElement {
Form* parent_form = nullptr;
virtual goos::Object to_form(const Env& env) const = 0;
virtual goos::Object to_form_as_condition(const Env& env) const;
virtual ~FormElement() = default;
virtual void apply(const std::function<void(FormElement*)>& f) = 0;
virtual void apply_form(const std::function<void(Form*)>& f) = 0;
@ -249,6 +250,7 @@ class ConditionElement : public FormElement {
std::optional<SimpleAtom> src1,
RegSet consumed);
goos::Object to_form(const Env& env) const override;
goos::Object to_form_as_condition(const Env& env) const override;
void apply(const std::function<void(FormElement*)>& f) override;
void apply_form(const std::function<void(Form*)>& f) override;
void collect_vars(VariableSet& vars) const override;
@ -607,6 +609,11 @@ class GenericOperator {
return m_fixed_kind;
}
IR2_Condition::Kind condition_kind() const {
assert(m_kind == Kind::CONDITION_OPERATOR);
return m_condition_kind;
}
const Form* func() const {
assert(m_kind == Kind::FUNCTION_EXPR);
return m_function;
@ -785,6 +792,7 @@ class Form {
void clear() { m_elements.clear(); }
goos::Object to_form(const Env& env) const;
goos::Object to_form_as_condition(const Env& env) const;
std::string to_string(const Env& env) const;
void inline_forms(std::vector<goos::Object>& forms, const Env& env) const;
void apply(const std::function<void(FormElement*)>& f);

View file

@ -412,9 +412,10 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
if (m_src->is_single_element()) {
auto src_as_se = dynamic_cast<SimpleExpressionElement*>(m_src->back());
if (src_as_se) {
const auto& consumes = env.reg_use().op.at(m_dst.idx()).consumes;
if (src_as_se->expr().kind() == SimpleExpression::Kind::IDENTITY &&
src_as_se->expr().get_arg(0).is_var()) {
stack.push_value_to_reg(m_dst, m_src, false);
stack.push_non_seq_reg_to_reg(m_dst, src_as_se->expr().get_arg(0).var(), m_src);
return;
}
}
@ -616,6 +617,35 @@ void CondNoElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
}
void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
// first, let's try to detect if all bodies write the same value
std::optional<Variable> last_var;
bool rewrite_as_set = true;
// collect all forms which should write the output.
std::vector<Form*> write_output_forms;
for (const auto& entry : entries) {
write_output_forms.push_back(entry.body);
}
write_output_forms.push_back(else_ir);
// check all to see if they write the value.
for (auto form : write_output_forms) {
auto last_in_body = dynamic_cast<SetVarElement*>(form->elts().back());
if (last_in_body) {
if (last_var.has_value()) {
if (last_var->reg() != last_in_body->dst().reg()) {
rewrite_as_set = false;
break;
}
}
last_var = last_in_body->dst();
}
}
if (rewrite_as_set) {
assert(last_var.has_value());
}
for (auto& entry : entries) {
for (auto form : {entry.condition, entry.body}) {
FormStack temp_stack;
@ -624,8 +654,8 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
}
std::vector<FormElement*> new_entries;
if (form == entry.body) {
new_entries = temp_stack.rewrite(pool);
if (form == entry.body && rewrite_as_set) {
new_entries = temp_stack.rewrite_to_get_var(pool, *last_var, env);
} else {
new_entries = temp_stack.rewrite(pool);
}
@ -642,14 +672,23 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
elt->push_to_stack(env, pool, temp_stack);
}
auto new_entries = temp_stack.rewrite(pool);
std::vector<FormElement*> new_entries;
if (rewrite_as_set) {
new_entries = temp_stack.rewrite_to_get_var(pool, *last_var, env);
} else {
new_entries = temp_stack.rewrite(pool);
}
else_ir->clear();
for (auto e : new_entries) {
else_ir->push_back(e);
}
stack.push_form_element(this, true);
if (rewrite_as_set) {
stack.push_value_to_reg(*last_var, pool.alloc_single_form(nullptr, this), true);
} else {
stack.push_form_element(this, true);
}
}
///////////////////

View file

@ -5,11 +5,13 @@ namespace decompiler {
std::string FormStack::StackEntry::print(const Env& env) const {
if (destination.has_value()) {
assert(source && !elt);
return fmt::format("d: {} s: {} | {} <- {}", active, sequence_point,
destination.value().reg().to_charp(), source->to_string(env));
return fmt::format("d: {} s: {} | {} <- {} f: {}", active, sequence_point,
destination.value().reg().to_charp(), source->to_string(env),
non_seq_source.has_value());
} else {
assert(elt && !source);
return fmt::format("d: {} s: {} | {}", active, sequence_point, elt->to_string(env));
return fmt::format("d: {} s: {} | {} f: {}", active, sequence_point, elt->to_string(env),
non_seq_source.has_value());
}
}
@ -31,6 +33,18 @@ void FormStack::push_value_to_reg(Variable var, Form* value, bool sequence_point
m_stack.push_back(entry);
}
void FormStack::push_non_seq_reg_to_reg(const Variable& dst,
const Variable& src,
Form* src_as_form) {
StackEntry entry;
entry.active = true;
entry.sequence_point = false;
entry.destination = dst;
entry.non_seq_source = src;
entry.source = src_as_form;
m_stack.push_back(entry);
}
bool FormStack::is_single_expression() {
int count = 0;
for (auto& e : m_stack) {
@ -56,6 +70,13 @@ Form* FormStack::pop_reg(Register reg) {
if (entry.destination->reg() == reg) {
entry.active = false;
assert(entry.source);
if (entry.non_seq_source.has_value()) {
assert(entry.sequence_point == false);
auto result = pop_reg(entry.non_seq_source->reg());
if (result) {
return result;
}
}
return entry.source;
} else {
// we didn't match

View file

@ -14,6 +14,7 @@ class FormStack {
public:
FormStack() = default;
void push_value_to_reg(Variable var, Form* value, bool sequence_point);
void push_non_seq_reg_to_reg(const Variable& dst, const Variable& src, Form* src_as_form);
void push_form_element(FormElement* elt, bool sequence_point);
Form* pop_reg(const Variable& var);
Form* pop_reg(Register reg);
@ -26,7 +27,8 @@ class FormStack {
struct StackEntry {
bool active = true; // should this appear in the output?
std::optional<Variable> destination; // what register we are setting (or nullopt if no dest.)
Form* source = nullptr; // the value we are setting the register to.
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.
FormElement* elt = nullptr;
bool sequence_point = false;

View file

@ -5,52 +5,143 @@
#include "decompiler/util/DecompilerTypeSystem.h"
namespace decompiler {
void insert_extras_into_parent(Form* top_condition, Form* parent_form, FormElement* this_elt) {
auto real_condition = top_condition->back();
top_condition->pop_back();
auto& parent_vector = parent_form->elts();
// find us in the parent vector
auto me = std::find_if(parent_vector.begin(), parent_vector.end(),
[&](FormElement* x) { return x == this_elt; });
assert(me != parent_vector.end());
// now insert the fake condition
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
top_condition->elts() = {real_condition};
}
void clean_up_ifs(Form* top_level_form) {
top_level_form->apply([&](FormElement* elt) {
auto as_cne = dynamic_cast<CondNoElseElement*>(elt);
if (!as_cne) {
return;
}
bool changed = true;
while (changed) {
changed = false;
top_level_form->apply([&](FormElement* elt) {
auto as_cne = dynamic_cast<CondNoElseElement*>(elt);
if (!as_cne) {
return;
}
auto top_condition = as_cne->entries.front().condition;
if (!top_condition->is_single_element() && elt->parent_form) {
auto real_condition = top_condition->back();
top_condition->pop_back();
auto top_condition = as_cne->entries.front().condition;
if (!top_condition->is_single_element() && elt->parent_form) {
auto real_condition = top_condition->back();
top_condition->pop_back();
auto& parent_vector = elt->parent_form->elts();
// find us in the parent vector
auto me = std::find_if(parent_vector.begin(), parent_vector.end(),
[&](FormElement* x) { return x == elt; });
assert(me != parent_vector.end());
auto& parent_vector = elt->parent_form->elts();
// find us in the parent vector
auto me = std::find_if(parent_vector.begin(), parent_vector.end(),
[&](FormElement* x) { return x == elt; });
assert(me != parent_vector.end());
// now insert the fake condition
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
top_condition->elts() = {real_condition};
}
});
// now insert the fake condition
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
top_condition->elts() = {real_condition};
changed = true;
}
});
top_level_form->apply([&](FormElement* elt) {
auto as_cwe = dynamic_cast<CondWithElseElement*>(elt);
if (!as_cwe) {
return;
}
top_level_form->apply([&](FormElement* elt) {
auto as_cwe = dynamic_cast<CondWithElseElement*>(elt);
if (!as_cwe) {
return;
}
auto top_condition = as_cwe->entries.front().condition;
if (!top_condition->is_single_element() && elt->parent_form) {
auto real_condition = top_condition->back();
top_condition->pop_back();
auto top_condition = as_cwe->entries.front().condition;
if (!top_condition->is_single_element() && elt->parent_form) {
auto real_condition = top_condition->back();
top_condition->pop_back();
auto& parent_vector = elt->parent_form->elts();
// find us in the parent vector
auto me = std::find_if(parent_vector.begin(), parent_vector.end(),
[&](FormElement* x) { return x == elt; });
assert(me != parent_vector.end());
auto& parent_vector = elt->parent_form->elts();
// find us in the parent vector
auto me = std::find_if(parent_vector.begin(), parent_vector.end(),
[&](FormElement* x) { return x == elt; });
assert(me != parent_vector.end());
// now insert the fake condition
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
top_condition->elts() = {real_condition};
}
});
// now insert the fake condition
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
top_condition->elts() = {real_condition};
changed = true;
}
});
top_level_form->apply([&](FormElement* elt) {
auto as_sc = dynamic_cast<ShortCircuitElement*>(elt);
if (!as_sc) {
return;
}
auto top_condition = as_sc->entries.front().condition;
if (!top_condition->is_single_element() && elt->parent_form) {
auto real_condition = top_condition->back();
top_condition->pop_back();
auto& parent_vector = elt->parent_form->elts();
// find us in the parent vector
auto me = std::find_if(parent_vector.begin(), parent_vector.end(),
[&](FormElement* x) { return x == elt; });
assert(me != parent_vector.end());
// now insert the fake condition
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
top_condition->elts() = {real_condition};
changed = true;
}
// if (!changed) {
// auto as_condition =
// dynamic_cast<GenericElement*>(top_condition->try_as_single_element()); if
// (as_condition) {
// if (as_condition->op().kind() == GenericOperator::Kind::CONDITION_OPERATOR) {
// if (as_condition->op().condition_kind() == IR2_Condition::Kind::TRUTHY) {
// auto to_repack = as_condition->elts().front();
// if (!to_repack->try_as_single_element() && as_condition->parent_form) {
// changed = true;
// insert_extras_into_parent(to_repack, as_condition->parent_form,
// as_condition);
// }
// }
// }
// }
// }
});
top_level_form->apply([&](FormElement* elt) {
auto as_ge = dynamic_cast<GenericElement*>(elt);
if (!as_ge) {
return;
}
if (as_ge->op().kind() == GenericOperator::Kind::CONDITION_OPERATOR) {
if (as_ge->op().condition_kind() == IR2_Condition::Kind::TRUTHY) {
assert(as_ge->elts().size() == 1);
auto top_condition = as_ge->elts().front();
if (!top_condition->is_single_element() && elt->parent_form) {
auto real_condition = top_condition->back();
top_condition->pop_back();
auto& parent_vector = elt->parent_form->elts();
// find us in the parent vector
auto me = std::find_if(parent_vector.begin(), parent_vector.end(),
[&](FormElement* x) { return x == elt; });
assert(me != parent_vector.end());
// now insert the fake condition
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
top_condition->elts() = {real_condition};
changed = true;
}
}
}
});
}
}
bool convert_to_expressions(Form* top_level_form,

View file

@ -291,12 +291,12 @@ TEST_F(FormRegressionTest, Or) {
" (begin\n"
" (set! a0-0 (-> a0-0 parent))\n"
" (set! a3-0 (= a0-0 v1-0))\n"
" (truthy a3-0)\n" // this sets a2-0, the unused result of the OR. it gets a separate
// variable because it's not used.
" a3-0\n" // this sets a2-0, the unused result of the OR. it gets a separate
// variable because it's not used.
" )\n"
" (set! a2-1 (zero? a0-0))\n" // so this should be a2-1.
" )\n"
" (truthy a2-1)\n"
" a2-1\n"
" )\n"
" (if\n"
" (= a0-0 a1-0)\n"
@ -487,10 +487,10 @@ TEST_F(FormRegressionTest, And) {
" (while\n"
" (begin\n"
" (and\n"
" (begin (set! a0-1 '()) (set! a1-0 (!= v1-1 a0-1)) (truthy a1-0))\n" // check v1-1
" (begin (set! a0-3 (sll v1-1 62)) (set! a0-2 (<0.si a0-3)))\n" // check v1-1
" (begin (set! a0-1 '()) (set! a1-0 (!= v1-1 a0-1)) a1-0)\n" // check v1-1
" (begin (set! a0-3 (sll v1-1 62)) (set! a0-2 (<0.si a0-3)))\n" // check v1-1
" )\n"
" (truthy a0-2)\n" // this variable doesn't appear, but is set by the and.
" a0-2\n" // this variable doesn't appear, but is set by the and.
" )\n"
" (set! v0-0 (+ v0-0 1))\n" // merged (and the result)
" (set! v1-1 (cdr v1-1))\n" // also merged.
@ -563,7 +563,7 @@ TEST_F(FormRegressionTest, FunctionCall) {
" (while\n"
" (begin\n"
" (or\n"
" (begin (set! v1-0 '()) (set! a0-1 (= gp-0 v1-0)) (truthy a0-1))\n" // got empty list.
" (begin (set! v1-0 '()) (set! a0-1 (= gp-0 v1-0)) a0-1)\n" // got empty list.
" (begin\n"
" (set! t9-0 name=)\n"
" (set! a0-2 (car gp-0))\n"
@ -706,7 +706,7 @@ TEST_F(FormRegressionTest, NestedAndOr) {
" (set! v1-6 (cdr s3-0))\n" // s3-0 = cdr
" (set! a0-4 '())\n"
" (set! a0-5 (= v1-6 a0-4))\n"
" (truthy a0-5)\n" // cdr = empty list (sets v1-7 secretly)
" a0-5\n" // cdr = empty list (sets v1-7 secretly)
" )\n"
" (begin\n"
" (set! v1-8 (cdr s3-0))\n"
@ -734,11 +734,11 @@ TEST_F(FormRegressionTest, NestedAndOr) {
" )\n"
" (set! a0-2 (>0.si v1-1))\n" // >0
" )\n"
" (truthy a0-2)\n" // false or >0
" a0-2\n" // false or >0
" )\n"
" (begin (set! a0-3 '#t) (set! v1-2 (!= v1-2 a0-3)))\n" // not #t
" )\n"
" (truthy v1-2)\n" // (and (or false >0) (not #t))
" v1-2\n" // (and (or false >0) (not #t))
" )\n"
" (set! s4-0 (+ s4-0 1))\n" // increment, merge
" (set! (car s3-0) s1-0)\n" // set iter's car to cadr

View file

@ -513,11 +513,9 @@ TEST_F(FormRegressionTest, ExprTypeTypep) {
"(begin\n"
" (set! v1-0 object)\n"
" (until\n"
" (truthy\n"
" (or\n"
" (begin (set! a0-0 (-> a0-0 parent)) (truthy (= a0-0 v1-0)))\n" // set! as value.
" (zero? a0-0)\n"
" )\n"
" (begin\n"
" (set! a0-0 (-> a0-0 parent))\n"
" (or (= a0-0 v1-0) (zero? a0-0))\n"
" )\n"
" (if (= a0-0 a1-0) (return '#t (set! v1-0 0)))\n"
" )\n"
@ -686,9 +684,8 @@ TEST_F(FormRegressionTest, ExprPairMethod4) {
" (set! v1-1 (cdr a0-0))\n"
" (set! v0-0 1)\n"
" (while\n"
" (truthy\n"
" (and (truthy (!= v1-1 '())) "
" (<0.si (sll (the-as uint v1-1) 62)))\n"
" (and (!= v1-1 '()) "
" (<0.si (sll (the-as uint v1-1) 62))\n"
" )\n"
" (set! v0-0 (+ v0-0 1))\n"
" (set! v1-1 (cdr v1-1))\n"
@ -795,7 +792,7 @@ TEST_F(FormRegressionTest, ExprMember) {
"(begin\n"
" (set! v1-0 a1-0)\n"
" (while\n"
" (not (or (truthy (= v1-0 '())) (= (car v1-0) a0-0)))\n"
" (not (or (= v1-0 '()) (= (car v1-0) a0-0)))\n"
" (set! v1-0 (cdr v1-0))\n"
" )\n"
" (set! a0-1 '#f)\n"
@ -860,7 +857,7 @@ TEST_F(FormRegressionTest, ExprNmember) {
" (set! s5-0 a0-0)\n"
" (set! gp-0 a1-0)\n"
" (while\n"
" (not (or (truthy (= gp-0 '())) (name= (car gp-0) s5-0)))\n"
" (not (or (= gp-0 '()) (name= (car gp-0) s5-0)))\n"
" (set! gp-0 (cdr gp-0))\n"
" )\n"
" (set! v1-2 '#f)\n"
@ -912,7 +909,7 @@ TEST_F(FormRegressionTest, ExprAssoc) {
"(begin\n"
" (set! v1-0 a1-0)\n"
" (while\n"
" (not (or (truthy (= v1-0 '())) (= (car (car v1-0)) a0-0)))\n"
" (not (or (= v1-0 '()) (= (car (car v1-0)) a0-0)))\n"
" (set! v1-0 (cdr v1-0))\n"
" )\n"
" (set! a0-1 '#f)\n"
@ -977,8 +974,8 @@ TEST_F(FormRegressionTest, ExprAssoce) {
" (while\n"
" (not\n"
" (or\n"
" (truthy (= v1-0 '()))\n"
" (truthy (= (car (car v1-0)) a0-0))\n"
" (= v1-0 '())\n"
" (= (car (car v1-0)) a0-0)\n"
" (= (car (car v1-0)) 'else)\n"
" )\n"
" )\n"
@ -1058,7 +1055,6 @@ TEST_F(FormRegressionTest, ExprNassoc) {
" daddiu sp, sp, 48";
std::string type = "(function object object object)";
// will need fixing if we clean up the set! if thing
std::string expected =
"(begin\n"
" (set! s5-0 a0-0)\n"
@ -1066,22 +1062,17 @@ TEST_F(FormRegressionTest, ExprNassoc) {
" (while\n"
" (not\n"
" (or\n"
" (truthy (= gp-0 '()))\n"
" (= gp-0 (quote ()))\n"
" (begin\n"
" (set! a1-1 (car (car gp-0)))\n"
" (if\n"
" (pair? a1-1)\n"
" (set! v1-1 (nmember s5-0 a1-1))\n"
" (set! v1-1 (name= a1-1 s5-0))\n"
" )\n"
" v1-1\n"
" (if (pair? a1-1) (nmember s5-0 a1-1) (name= a1-1 s5-0))\n"
" )\n"
" )\n"
" )\n"
" (set! gp-0 (cdr gp-0))\n"
" )\n"
" (set! v1-3 '#f)\n"
" (if (!= gp-0 '()) (car gp-0))\n"
" (set! v1-3 (quote #f))\n"
" (if (!= gp-0 (quote ())) (car gp-0))\n"
" )";
test_with_expr(func, type, expected, true, "");
}
@ -1172,22 +1163,21 @@ TEST_F(FormRegressionTest, ExprNassoce) {
" (while\n"
" (not\n"
" (or\n"
" (truthy (= gp-0 '()))\n"
" (= gp-0 (quote ()))\n"
" (begin\n"
" (set! s4-0 (car (car gp-0)))\n"
" (if\n"
" (pair? s4-0)\n"
" (set! v1-1 (nmember s5-0 s4-0))\n"
" (set! v1-1 (or (truthy (name= s4-0 s5-0)) (= s4-0 'else)))\n"
" (nmember s5-0 s4-0)\n"
" (or (name= s4-0 s5-0) (= s4-0 (quote else)))\n"
" )\n"
" v1-1\n"
" )\n"
" )\n"
" )\n"
" (set! gp-0 (cdr gp-0))\n"
" )\n"
" (set! v1-4 '#f)\n"
" (if (!= gp-0 '()) (car gp-0))\n"
" (set! v1-4 (quote #f))\n"
" (if (!= gp-0 (quote ())) (car gp-0))\n"
" )";
test_with_expr(func, type, expected, true, "");
}
@ -1236,25 +1226,16 @@ TEST_F(FormRegressionTest, ExprAppend) {
" daddu sp, sp, r0";
std::string type = "(function object object object)";
// todo - will be changed by if fix.
std::string expected =
"(begin\n"
" (cond\n"
" ((= a0-0 '()) (set! v0-0 a1-0))\n"
" (else\n"
" (set! v1-1 a0-0)\n"
" (while (!= (cdr v1-1) '()) "
" (nop!) "
" (nop!) "
" (set! v1-1 (cdr v1-1)))\n"
" (set! a2-1 '#f)\n"
" (when (!= v1-1 '()) "
" (set! (cdr v1-1) a1-0) "
" (set! v1-2 a1-0))\n"
" (set! v0-0 a0-0)\n"
" )\n"
"(cond\n"
" ((= a0-0 '()) a1-0)\n"
" (else\n"
" (set! v1-1 a0-0)\n"
" (while (!= (cdr v1-1) '()) (nop!) (nop!) (set! v1-1 (cdr v1-1)))\n"
" (set! a2-1 '#f)\n"
" (when (!= v1-1 '()) (set! (cdr v1-1) a1-0) (set! v1-2 a1-0))\n"
" a0-0\n"
" )\n"
" v0-0\n"
" )";
test_with_expr(func, type, expected, true, "");
}
@ -1314,25 +1295,24 @@ TEST_F(FormRegressionTest, ExprDelete) {
" daddu sp, sp, r0";
std::string type = "(function object object pair)";
// todo - will be changed by if fix.
std::string expected =
"(begin\n"
"(the-as\n"
" pair\n"
" (cond\n"
" ((= a0-0 (car a1-0)) (set! v0-0 (cdr a1-0)))\n"
" ((= a0-0 (car a1-0)) (cdr a1-0))\n"
" (else\n"
" (set! v1-1 a1-0)\n"
" (set! a2-0 (cdr a1-0))\n"
" (while\n"
" (not (or (truthy (= a2-0 (quote ()))) (= (car a2-0) a0-0)))\n"
" (not (or (= a2-0 (quote ())) (= (car a2-0) a0-0)))\n"
" (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"
" (set! v0-0 a1-0)\n"
" a1-0\n"
" )\n"
" )\n"
" (the-as pair v0-0)\n"
" )";
test_with_expr(func, type, expected, true, "");
}
@ -1394,25 +1374,24 @@ TEST_F(FormRegressionTest, ExprDeleteCar) {
" daddu sp, sp, r0";
std::string type = "(function object object pair)";
// todo - will be changed by if fix.
std::string expected =
"(begin\n"
"(the-as\n"
" pair\n"
" (cond\n"
" ((= a0-0 (car (car a1-0))) (set! v0-0 (cdr a1-0)))\n"
" ((= a0-0 (car (car a1-0))) (cdr a1-0))\n"
" (else\n"
" (set! v1-2 a1-0)\n"
" (set! a2-0 (cdr a1-0))\n"
" (while\n"
" (not (or (truthy (= a2-0 (quote ()))) (= (car (car a2-0)) a0-0)))\n"
" (not (or (= a2-0 (quote ())) (= (car (car a2-0)) a0-0)))\n"
" (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"
" (set! v0-0 a1-0)\n"
" a1-0\n"
" )\n"
" )\n"
" (the-as pair v0-0)\n"
" )";
test_with_expr(func, type, expected, true, "");
}
@ -1455,115 +1434,138 @@ TEST_F(FormRegressionTest, ExprInsertCons) {
test_with_expr(func, type, expected, true, "");
}
// TEST_F(FormRegressionTest, ExprSort) {
// std::string func =
// " sll r0, r0, 0\n"
// " daddiu sp, sp, -112\n"
// " sd ra, 0(sp)\n"
// " sq s1, 16(sp)\n"
// " sq s2, 32(sp)\n"
// " sq s3, 48(sp)\n"
// " sq s4, 64(sp)\n"
// " sq s5, 80(sp)\n"
// " sq gp, 96(sp)\n"
//
// " or gp, a0, r0\n"
// " or s5, a1, r0\n"
// " addiu s4, r0, -1\n"
// " beq r0, r0, L208\n"
// " sll r0, r0, 0\n"
//
// "L201:\n"
// " addiu s4, r0, 0\n"
// " or s3, gp, r0\n"
// " beq r0, r0, L206\n"
// " sll r0, r0, 0\n"
//
// "L202:\n"
// " lw s2, -2(s3)\n"
// " lw v1, 2(s3)\n"
// " lw s1, -2(v1)\n"
// " or t9, s5, r0\n"
// " or a0, s2, r0\n"
// " or a1, s1, r0\n"
// " jalr ra, t9\n"
// " sll v0, ra, 0\n"
//
// " or v1, v0, r0\n"
// " beql s7, v1, L203\n"
// " daddiu a0, s7, 8\n"
//
// " slt a1, r0, v1\n"
// " daddiu a0, s7, 8\n"
// " movz a0, s7, a1\n"
//
// "L203:\n"
// " beql s7, a0, L204\n"
// " or v1, a0, r0\n"
//
// " daddiu a0, s7, #t\n"
// " dsubu a0, v1, a0\n"
// " daddiu v1, s7, 8\n"
// " movz v1, s7, a0\n"
//
// "L204:\n"
// " beq s7, v1, L205\n"
// " or v1, s7, r0\n"
//
// " daddiu s4, s4, 1\n"
// " sw s1, -2(s3)\n"
// " lw v1, 2(s3)\n"
// " sw s2, -2(v1)\n"
// " or v1, s2, r0\n"
//
// "L205:\n"
// " lw s3, 2(s3)\n"
//
// "L206:\n"
// " lw v1, 2(s3)\n"
// " daddiu a0, s7, -10\n"
// " dsubu v1, v1, a0\n"
// " daddiu a0, s7, 8\n"
// " movn a0, s7, v1\n"
// " bnel s7, a0, L207\n"
// " or v1, a0, r0\n"
//
// " lw v1, 2(s3)\n"
// " dsll32 v1, v1, 30\n"
// " slt a0, v1, r0\n"
// " daddiu v1, s7, 8\n"
// " movn v1, s7, a0\n"
//
// "L207:\n"
// " beq s7, v1, L202\n"
// " sll r0, r0, 0\n"
//
// " or v1, s7, r0\n"
// " or v1, s7, r0\n"
//
// "L208:\n"
// " bne s4, r0, L201\n"
// " sll r0, r0, 0\n"
//
// " or v1, s7, r0\n"
// " or v0, gp, r0\n"
// " ld ra, 0(sp)\n"
// " lq gp, 96(sp)\n"
// " lq s5, 80(sp)\n"
// " lq s4, 64(sp)\n"
// " lq s3, 48(sp)\n"
// " lq s2, 32(sp)\n"
// " lq s1, 16(sp)\n"
// " jr ra\n"
// " daddiu sp, sp, 112";
// std::string type = "(function object (function object object object) object)";
//
// // NOTE - this appears to _not_ be a nested call.
// std::string expected =
// "(begin\n"
// " (set! gp-0 a0-0)\n"
// " (set! a3-0 (delete-car! (car gp-0) a1-0))\n"
// " (new 'global pair gp-0 a3-0)\n"
// " )";
// test_with_expr(func, type, expected, true, "");
//}
TEST_F(FormRegressionTest, ExprSort) {
std::string func =
" sll r0, r0, 0\n"
" daddiu sp, sp, -112\n"
" sd ra, 0(sp)\n"
" sq s1, 16(sp)\n"
" sq s2, 32(sp)\n"
" sq s3, 48(sp)\n"
" sq s4, 64(sp)\n"
" sq s5, 80(sp)\n"
" sq gp, 96(sp)\n"
" or gp, a0, r0\n"
" or s5, a1, r0\n"
" addiu s4, r0, -1\n"
" beq r0, r0, L208\n"
" sll r0, r0, 0\n"
"L201:\n"
" addiu s4, r0, 0\n"
" or s3, gp, r0\n"
" beq r0, r0, L206\n"
" sll r0, r0, 0\n"
"L202:\n"
" lw s2, -2(s3)\n"
" lw v1, 2(s3)\n"
" lw s1, -2(v1)\n"
" or t9, s5, r0\n"
" or a0, s2, r0\n"
" or a1, s1, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" or v1, v0, r0\n"
" beql s7, v1, L203\n"
" daddiu a0, s7, 8\n"
" slt a1, r0, v1\n"
" daddiu a0, s7, 8\n"
" movz a0, s7, a1\n"
"L203:\n"
" beql s7, a0, L204\n"
" or v1, a0, r0\n"
" daddiu a0, s7, #t\n"
" dsubu a0, v1, a0\n"
" daddiu v1, s7, 8\n"
" movz v1, s7, a0\n"
"L204:\n"
" beq s7, v1, L205\n"
" or v1, s7, r0\n"
" daddiu s4, s4, 1\n"
" sw s1, -2(s3)\n"
" lw v1, 2(s3)\n"
" sw s2, -2(v1)\n"
" or v1, s2, r0\n"
"L205:\n"
" lw s3, 2(s3)\n"
"L206:\n"
" lw v1, 2(s3)\n"
" daddiu a0, s7, -10\n"
" dsubu v1, v1, a0\n"
" daddiu a0, s7, 8\n"
" movn a0, s7, v1\n"
" bnel s7, a0, L207\n"
" or v1, a0, r0\n"
" lw v1, 2(s3)\n"
" dsll32 v1, v1, 30\n"
" slt a0, v1, r0\n"
" daddiu v1, s7, 8\n"
" movn v1, s7, a0\n"
"L207:\n"
" beq s7, v1, L202\n"
" sll r0, r0, 0\n"
" or v1, s7, r0\n"
" or v1, s7, r0\n"
"L208:\n"
" bne s4, r0, L201\n"
" sll r0, r0, 0\n"
" or v1, s7, r0\n"
" or v0, gp, r0\n"
" ld ra, 0(sp)\n"
" lq gp, 96(sp)\n"
" lq s5, 80(sp)\n"
" lq s4, 64(sp)\n"
" lq s3, 48(sp)\n"
" lq s2, 32(sp)\n"
" lq s1, 16(sp)\n"
" jr ra\n"
" daddiu sp, sp, 112";
std::string type = "(function object (function object object object) object)";
// TODO - this should probably be tested.
std::string expected =
"(begin\n"
" (set! gp-0 a0-0)\n"
" (set! s5-0 a1-0)\n"
" (set! s4-0 -1)\n"
" (while\n"
" (nonzero? s4-0)\n"
" (set! s4-0 0)\n"
" (set! s3-0 gp-0)\n"
" (while\n"
" (not\n"
" (or (= (cdr s3-0) (quote ())) (>=0.si (sll (the-as uint (cdr s3-0)) 62)))\n"
" )\n"
" (set! v1-1 (s5-0 (car s3-0) (car (cdr s3-0))))\n"
" (when\n"
" (and (or (not v1-1) (>0.si v1-1)) (!= v1-2 (quote #t)))\n"
" (set! s4-0 (+ s4-0 1))\n"
" (set! (car s3-0) s1-0)\n"
" (set! (car (cdr s3-0)) s2-0)\n"
" (set! v1-5 s2-0)\n"
" )\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"
" gp-0\n"
" )";
test_with_expr(func, type, expected, true, "");
}