recognize vector, matrix, quaternion constructors in a better way (#630)

* recognize vector, matrix, quaternion constructors in a better way

* fix bad bug
This commit is contained in:
water111 2021-06-26 18:30:35 -04:00 committed by GitHub
parent ae2666a7c5
commit 69e24ae577
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 415 additions and 202 deletions

View file

@ -1721,10 +1721,140 @@ Form* make_optional_cast(const std::optional<TypeSpec>& cast_type,
return in;
}
}
bool try_to_rewrite_vector_inline_ctor(const Env& env,
FormPool& pool,
FormStack& stack,
const std::string& type_name) {
// now, let's check for a matrix initialization.
auto matrix_entries = stack.try_getting_active_stack_entries({true, false});
if (matrix_entries) {
// the (set! var (new 'stack-no-clear 'matrix))
if (matrix_entries->at(0).destination->reg() == Register(Reg::GPR, Reg::R0)) {
return false;
}
auto var_name = env.get_variable_name(*matrix_entries->at(0).destination);
auto src = matrix_entries->at(0).source->try_as_element<StackStructureDefElement>();
if (!src) {
return false;
}
if (src->type() != TypeSpec(type_name)) {
return false;
}
// zeroing the rows:
std::vector<RegisterAccess> write_vars;
auto elt = matrix_entries->at(1).elt;
std::vector<DerefTokenMatcher> token_matchers = {DerefTokenMatcher::string("vec"),
DerefTokenMatcher::string("quad")};
if (type_name == "vector") {
token_matchers = {DerefTokenMatcher::string("quad")};
}
auto matcher = Matcher::set(Matcher::deref(Matcher::any_reg(0), false, token_matchers),
Matcher::cast("uint128", Matcher::integer(0)));
Form hack;
hack.elts().push_back(elt);
auto mr = match(matcher, &hack);
if (mr.matched) {
if (var_name != env.get_variable_name(*mr.maps.regs.at(0))) {
return false;
}
write_vars.push_back(*mr.maps.regs.at(0));
} else {
return false;
}
// success!
for (auto& wv : write_vars) {
env.get_use_def_info(wv);
Env* menv = const_cast<Env*>(&env);
menv->disable_use(wv);
}
stack.pop(2);
stack.push_value_to_reg(
*matrix_entries->at(0).destination,
pool.alloc_single_element_form<GenericElement>(
nullptr,
GenericOperator::make_function(pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, fmt::format("new-stack-{}0", type_name)))),
true, TypeSpec(type_name));
return true;
}
return false;
}
bool try_to_rewrite_matrix_inline_ctor(const Env& env, FormPool& pool, FormStack& stack) {
// now, let's check for a matrix initialization.
auto matrix_entries = stack.try_getting_active_stack_entries({true, false, false, false, false});
if (matrix_entries) {
// the (set! var (new 'stack-no-clear 'matrix))
if (matrix_entries->at(0).destination->reg() == Register(Reg::GPR, Reg::R0)) {
return false;
}
auto var_name = env.get_variable_name(*matrix_entries->at(0).destination);
auto src = matrix_entries->at(0).source->try_as_element<StackStructureDefElement>();
if (!src) {
return false;
}
if (src->type() != TypeSpec("matrix")) {
return false;
}
// zeroing the rows:
std::vector<RegisterAccess> write_vars;
for (int i = 0; i < 4; i++) {
auto elt = matrix_entries->at(i + 1).elt;
auto matcher = Matcher::set(
Matcher::deref(Matcher::any_reg(0), false,
{DerefTokenMatcher::string("vector"), DerefTokenMatcher::integer(i),
DerefTokenMatcher::string("quad")}),
Matcher::cast("uint128", Matcher::integer(0)));
Form hack;
hack.elts().push_back(elt);
auto mr = match(matcher, &hack);
if (mr.matched) {
if (var_name != env.get_variable_name(*mr.maps.regs.at(0))) {
return false;
}
write_vars.push_back(*mr.maps.regs.at(0));
} else {
return false;
}
}
// success!
for (auto& wv : write_vars) {
env.get_use_def_info(wv);
Env* menv = const_cast<Env*>(&env);
menv->disable_use(wv);
}
stack.pop(5);
stack.push_value_to_reg(*matrix_entries->at(0).destination,
pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(
nullptr, "new-stack-matrix0"))),
true, TypeSpec("matrix"));
return true;
}
return false;
}
} // namespace
void StorePlainDeref::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
mark_popped();
if (m_expr.is_var()) {
// this matches the order in Compiler::compile_set
auto vars = std::vector<RegisterAccess>({m_expr.var(), m_base_var});
@ -1759,6 +1889,12 @@ void StorePlainDeref::push_to_stack(const Env& env, FormPool& pool, FormStack& s
fr->mark_popped();
stack.push_form_element(fr, true);
}
if (!try_to_rewrite_matrix_inline_ctor(env, pool, stack)) {
if (!try_to_rewrite_vector_inline_ctor(env, pool, stack, "vector")) {
try_to_rewrite_vector_inline_ctor(env, pool, stack, "quaternion");
}
}
}
void StoreArrayAccess::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {

View file

@ -46,7 +46,6 @@ class FormStack {
std::string print(const Env& env);
bool is_root() const { return m_is_root_stack; }
private:
struct StackEntry {
bool active = true; // should this appear in the output?
std::optional<RegisterAccess>
@ -64,6 +63,45 @@ class FormStack {
std::string print(const Env& env) const;
};
std::optional<std::vector<StackEntry>> try_getting_active_stack_entries(
const std::vector<bool>& is_set) const {
if (is_set.size() > m_stack.size()) {
return {};
}
std::vector<StackEntry> entries;
size_t offset = m_stack.size() - is_set.size();
for (size_t i = 0; i < is_set.size(); i++) {
auto& my_entry = m_stack.at(i + offset);
if (my_entry.active) {
if (is_set.at(i)) {
if (!my_entry.destination) {
return {};
}
assert(my_entry.source && !my_entry.elt);
} else {
if (my_entry.destination) {
return {};
}
assert(my_entry.elt && !my_entry.source);
}
entries.push_back(my_entry);
} else {
return {};
}
}
return entries;
}
void pop(int count) {
for (int i = 0; i < count; i++) {
assert(!m_stack.empty());
m_stack.pop_back();
}
}
private:
std::vector<StackEntry> m_stack;
bool m_is_root_stack = false;
};

View file

@ -336,100 +336,6 @@ FormElement* fix_up_abs_2(LetElement* in, const Env& env, FormPool& pool) {
return in;
}
FormElement* fix_up_vector_inline_zero(LetElement* in, const Env& env, FormPool& pool) {
/*
* (let ((local-trans (new 'stack-no-clear 'vector)))
* (set! (-> local-trans quad) (the-as uint128 0))
*/
if (in->entries().size() != 1) {
return nullptr;
}
if (in->body()->elts().empty()) {
return nullptr;
}
Form* src = in->entries().at(0).src;
auto src_as_stackvar = src->try_as_element<StackStructureDefElement>();
if (!src_as_stackvar) {
return nullptr;
}
bool is_vector = src_as_stackvar->type() == TypeSpec("vector");
bool is_matrix = src_as_stackvar->type() == TypeSpec("matrix");
if (is_vector) {
auto first_elt = in->body()->elts().at(0);
auto matcher = Matcher::set(
Matcher::deref(Matcher::any_reg(0), false, {DerefTokenMatcher::string("quad")}),
Matcher::cast("uint128", Matcher::integer(0)));
Form hack;
hack.elts().push_back(first_elt);
auto mr = match(matcher, &hack);
if (mr.matched) {
auto var = in->entries().at(0).dest;
auto var_name = env.get_variable_name(var);
if (var_name != env.get_variable_name(*mr.maps.regs.at(0))) {
return nullptr;
}
auto new_op = pool.alloc_single_element_form<GenericElement>(
nullptr,
GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "new-stack-vector0")));
src->parent_element = in;
in->entries().at(0).src = new_op;
in->body()->elts().erase(in->body()->elts().begin());
return in;
}
} else if (is_matrix) {
if (in->body()->elts().size() < 4) {
return nullptr;
}
auto var = in->entries().at(0).dest;
auto var_name = env.get_variable_name(var);
for (int i = 0; i < 4; i++) {
auto elt = in->body()->elts().at(i);
auto matcher = Matcher::set(
Matcher::deref(Matcher::any_reg(0), false,
{DerefTokenMatcher::string("vector"), DerefTokenMatcher::integer(i),
DerefTokenMatcher::string("quad")}),
Matcher::cast("uint128", Matcher::integer(0)));
Form hack;
hack.elts().push_back(elt);
auto mr = match(matcher, &hack);
if (mr.matched) {
if (var_name != env.get_variable_name(*mr.maps.regs.at(0))) {
return nullptr;
}
} else {
return nullptr;
}
}
auto new_op = pool.alloc_single_element_form<GenericElement>(
nullptr,
GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, "new-stack-matrix0")));
src->parent_element = in;
in->entries().at(0).src = new_op;
in->body()->elts().erase(in->body()->elts().begin(), in->body()->elts().begin() + 4);
return in;
}
return nullptr;
}
/*!
* Attempt to rewrite a let as another form. If it cannot be rewritten, this will return nullptr.
*/
@ -454,11 +360,6 @@ FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool) {
return as_abs_2;
}
auto as_vector = fix_up_vector_inline_zero(in, env, pool);
if (as_vector) {
return as_vector;
}
// nothing matched.
return nullptr;
}

View file

@ -23,3 +23,13 @@
(define-extern matrix->quaternion (function quaternion matrix quaternion))
(define-extern vector-y-angle (function vector float))
(defmacro new-stack-quaternion0 ()
"Get a stack quaternion that's set to 0.
This is more efficient than (new 'stack 'quaternion) because
this doesn't call the constructor."
`(let ((q (new 'stack-no-clear 'quaternion)))
(set! (-> q quad) (the-as uint128 0))
q
)
)

View file

@ -892,84 +892,80 @@
(defun quaternion-rotate-local-x! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
"Rotate existing quaternion along x axis."
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
(let ((a2-1 (quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :x 1.0 :w 1.0)
arg2
)
)
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a2-1 (t9-0 a0-1 (new 'static 'vector :x 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
)
(defun quaternion-rotate-local-y! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
"Rotate existing quaternion along y axis"
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
(let ((a2-1 (quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :y 1.0 :w 1.0)
arg2
)
)
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a2-1 (t9-0 a0-1 (new 'static 'vector :y 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
)
(defun quaternion-rotate-local-z! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
"Rotate existing quaternion along z axis."
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
(let ((a2-1 (quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :z 1.0 :w 1.0)
arg2
)
)
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a2-1 (t9-0 a0-1 (new 'static 'vector :z 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
)
(defun quaternion-rotate-y! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
"Rotate existing quaternion along y axis (right multiply)"
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
(let ((a1-2 (quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :y 1.0 :w 1.0)
arg2
)
)
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a1-2 (t9-0 a0-1 (new 'static 'vector :y 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 a1-2 arg1))
)
(quaternion-normalize! (quaternion*! arg0 a1-2 arg1))
)
)
(defun quaternion-rotate-x! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
"Rotate existing quaternion along x axis. This has a different implementation
from the others for some reason."
(let ((s4-0 quaternion-vector-angle!)
(s3-0 (new 'stack-no-clear 'quaternion))
)
(set! (-> s3-0 vec quad) (the-as uint128 0))
(let ((t9-0 vector-x-quaternion!)
(a0-1 (new 'stack-no-clear 'vector))
(let ((a1-3 (quaternion-vector-angle!
(new-stack-quaternion0)
(vector-x-quaternion! (new-stack-vector0) arg1)
arg2
)
)
(set! (-> a0-1 quad) (the-as uint128 0))
(let ((a1-3 (s4-0 s3-0 (t9-0 a0-1 arg1) arg2)))
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
)
)
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
)
)
(defun quaternion-rotate-z! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
"Rotate existing quaternion along z axis. Has the weird implementation too."
(let ((s4-0 quaternion-vector-angle!)
(s3-0 (new 'stack-no-clear 'quaternion))
)
(set! (-> s3-0 vec quad) (the-as uint128 0))
(let ((t9-0 vector-z-quaternion!)
(a0-1 (new 'stack-no-clear 'vector))
(let ((a1-3 (quaternion-vector-angle!
(new-stack-quaternion0)
(vector-z-quaternion! (new-stack-vector0) arg1)
arg2
)
)
(set! (-> a0-1 quad) (the-as uint128 0))
(let ((a1-3 (s4-0 s3-0 (t9-0 a0-1 arg1) arg2)))
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
)
)
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
)
)

View file

@ -66,6 +66,17 @@
)
)
(defmacro new-stack-quaternion0 ()
"Get a stack quaternion that's set to 0.
This is more efficient than (new 'stack 'quaternion) because
this doesn't call the constructor."
`(let ((q (new 'stack-no-clear 'quaternion)))
(set! (-> q quad) (the-as uint128 0))
q
)
)
(defmacro with-pp (&rest body)
`(rlet ((pp :reg r13 :reset-here #t :type process))
,@body)

View file

@ -772,10 +772,7 @@
;; Used lq/sq
(defun matrix-rotate-yx! ((dst matrix) (rot-y-deg float) (rot-x-deg float))
(matrix-rotate-y! dst rot-y-deg)
(let* ((t9-1 matrix-rotate-x!)
(a0-2 (new-stack-matrix0))
(a1-2 (t9-1 a0-2 rot-x-deg))
)
(let ((a1-2 (matrix-rotate-x! (new-stack-matrix0) rot-x-deg)))
(matrix*! dst a1-2 dst)
)
dst

View file

@ -924,13 +924,16 @@
(defun
quaternion-rotate-local-x!
((arg0 quaternion) (arg1 quaternion) (arg2 float))
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a2-1 (t9-0 a0-1 (new 'static 'vector :x 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
(let
((a2-1
(quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :x 1.0 :w 1.0)
arg2
)
)
)
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
)
@ -939,13 +942,16 @@
(defun
quaternion-rotate-local-y!
((arg0 quaternion) (arg1 quaternion) (arg2 float))
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a2-1 (t9-0 a0-1 (new 'static 'vector :y 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
(let
((a2-1
(quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :y 1.0 :w 1.0)
arg2
)
)
)
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
)
@ -954,58 +960,64 @@
(defun
quaternion-rotate-local-z!
((arg0 quaternion) (arg1 quaternion) (arg2 float))
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a2-1 (t9-0 a0-1 (new 'static 'vector :z 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
(let
((a2-1
(quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :z 1.0 :w 1.0)
arg2
)
)
)
(quaternion-normalize! (quaternion*! arg0 arg1 a2-1))
)
)
;; definition for function quaternion-rotate-y!
;; Used lq/sq
(defun quaternion-rotate-y! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
(let ((t9-0 quaternion-vector-angle!)
(a0-1 (new 'stack-no-clear 'quaternion))
)
(set! (-> a0-1 vec quad) (the-as uint128 0))
(let ((a1-2 (t9-0 a0-1 (new 'static 'vector :y 1.0 :w 1.0) arg2)))
(quaternion-normalize! (quaternion*! arg0 a1-2 arg1))
(let
((a1-2
(quaternion-vector-angle!
(new-stack-quaternion0)
(new 'static 'vector :y 1.0 :w 1.0)
arg2
)
)
)
(quaternion-normalize! (quaternion*! arg0 a1-2 arg1))
)
)
;; definition for function quaternion-rotate-x!
;; Used lq/sq
(defun quaternion-rotate-x! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
(let ((s4-0 quaternion-vector-angle!)
(s3-0 (new 'stack-no-clear 'quaternion))
)
(set! (-> s3-0 vec quad) (the-as uint128 0))
(let* ((t9-0 vector-x-quaternion!)
(a0-1 (new-stack-vector0))
(a1-3 (s4-0 s3-0 (t9-0 a0-1 arg1) arg2))
)
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
(let
((a1-3
(quaternion-vector-angle!
(new-stack-quaternion0)
(vector-x-quaternion! (new-stack-vector0) arg1)
arg2
)
)
)
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
)
)
;; definition for function quaternion-rotate-z!
;; Used lq/sq
(defun quaternion-rotate-z! ((arg0 quaternion) (arg1 quaternion) (arg2 float))
(let ((s4-0 quaternion-vector-angle!)
(s3-0 (new 'stack-no-clear 'quaternion))
)
(set! (-> s3-0 vec quad) (the-as uint128 0))
(let* ((t9-0 vector-z-quaternion!)
(a0-1 (new-stack-vector0))
(a1-3 (s4-0 s3-0 (t9-0 a0-1 arg1) arg2))
)
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
(let
((a1-3
(quaternion-vector-angle!
(new-stack-quaternion0)
(vector-z-quaternion! (new-stack-vector0) arg1)
arg2
)
)
)
(quaternion-normalize! (quaternion*! arg0 a1-3 arg1))
)
)

View file

@ -415,9 +415,7 @@
(set! sv-56 (t9-3 a0-5 1.0))
)
(let* ((f30-0 (vector-y-angle sv-52))
(t9-5 vector-flatten!)
(a0-7 (new-stack-vector0))
(a0-8 (t9-5 a0-7 sv-56 sv-48))
(a0-8 (vector-flatten! (new-stack-vector0) sv-56 sv-48))
(f0-0 (vector-y-angle a0-8))
(f0-1 (deg-diff f30-0 f0-0))
)
@ -482,9 +480,7 @@
)
)
(f30-2 (vector-x-angle sv-52))
(t9-16 vector-flatten!)
(a0-19 (new-stack-vector0))
(s3-2 (t9-16 a0-19 sv-56 s3-1))
(s3-2 (vector-flatten! (new-stack-vector0) sv-56 s3-1))
(f0-15 (vector-x-angle s3-2))
(f0-21
(fmax
@ -595,9 +591,7 @@
(set! sv-56 (t9-3 a0-3 1.0))
)
(let* ((f30-0 (vector-y-angle sv-52))
(t9-5 vector-flatten!)
(a0-5 (new-stack-vector0))
(a0-6 (t9-5 a0-5 sv-56 sv-48))
(a0-6 (vector-flatten! (new-stack-vector0) sv-56 sv-48))
(f0-0 (vector-y-angle a0-6))
(f0-1 (deg-diff f30-0 f0-0))
)
@ -645,9 +639,7 @@
)
)
(f30-2 (vector-x-angle sv-52))
(t9-14 vector-flatten!)
(a0-14 (new-stack-vector0))
(s4-4 (t9-14 a0-14 sv-56 s4-3))
(s4-4 (vector-flatten! (new-stack-vector0) sv-56 s4-3))
(f0-14 (vector-x-angle s4-4))
(f0-20
(fmax

View file

@ -1382,4 +1382,124 @@ TEST_F(FormRegressionTest, DebugMenuFuncDecode) {
" )\n"
" )";
test_with_expr(func, type, expected, false, "", {}, "[[13, \"a0\", \"symbol\"]]");
}
TEST_F(FormRegressionTest, MatrixNewInlineProp) {
std::string func =
"sll r0, r0, 0\n"
" daddiu sp, sp, -112\n"
" sd ra, 0(sp)\n"
" sq s5, 80(sp)\n"
" sq gp, 96(sp)\n"
" or gp, a0, r0\n"
" or s5, a2, r0\n"
" lw t9, matrix-rotate-y!(s7)\n"
" or a0, gp, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" lw t9, matrix-rotate-x!(s7)\n"
" daddiu a0, sp, 16\n"
" sq r0, 0(a0)\n"
" sq r0, 16(a0)\n"
" sq r0, 32(a0)\n"
" sq r0, 48(a0)\n"
" or a1, s5, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" or a1, v0, r0\n"
" lw t9, matrix*!(s7)\n"
" or a0, gp, r0\n"
" or a2, gp, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" or v1, v0, r0\n"
" or v0, gp, r0\n"
" ld ra, 0(sp)\n"
" lq gp, 96(sp)\n"
" lq s5, 80(sp)\n"
" jr ra\n"
" daddiu sp, sp, 112\n"
" sll r0, r0, 0\n"
" sll r0, r0, 0\n"
" sll r0, r0, 0\n";
std::string type = "(function matrix float float matrix)";
std::string expected =
"(begin\n"
" (matrix-rotate-y! arg0 arg1)\n"
" (let ((a1-2 (matrix-rotate-x! (new-stack-matrix0) arg2)))\n"
" (matrix*! arg0 a1-2 arg0)\n"
" )\n"
" arg0\n"
" )";
test_with_stack_structures(func, type, expected, R"([[16, "matrix"]])");
}
TEST_F(FormRegressionTest, VectorNewInlineProp) {
std::string func =
"sll r0, r0, 0\n"
" daddiu sp, sp, -64\n"
" sd ra, 0(sp)\n"
" sd fp, 8(sp)\n"
" or fp, t9, r0\n"
" sq s5, 32(sp)\n"
" sq gp, 48(sp)\n"
" or gp, a0, r0\n"
" daddiu s5, sp, 16\n"
" sq r0, 0(s5)\n"
" or v1, s5, r0\n"
" lwc1 f0, 0(a1)\n"
" swc1 f0, 0(v1)\n"
" lwc1 f0, 4(a1)\n"
" swc1 f0, 4(v1)\n"
" lwc1 f0, 8(a1)\n"
" swc1 f0, 8(v1)\n"
" mtc1 f0, r0\n"
" swc1 f0, 12(v1)\n"
" lw t9, vector-matrix*!(s7)\n"
" or a0, s5, r0\n"
" or a1, s5, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" lwc1 f0, 0(s5)\n"
" swc1 f0, 0(gp)\n"
" lwc1 f0, 4(s5)\n"
" swc1 f0, 4(gp)\n"
" lwc1 f0, 8(s5)\n"
" swc1 f0, 8(gp)\n"
" or v1, gp, r0\n"
" or v0, gp, r0\n"
" ld ra, 0(sp)\n"
" ld fp, 8(sp)\n"
" lq gp, 48(sp)\n"
" lq s5, 32(sp)\n"
" jr ra\n"
" daddiu sp, sp, 64\n"
" sll r0, r0, 0\n"
" sll r0, r0, 0\n"
" sll r0, r0, 0\n";
std::string type = "(function vector3s vector3s matrix vector3s)";
std::string expected =
"(begin\n"
" (let ((s5-0 (new-stack-vector0)))\n"
" (let ((v1-0 s5-0))\n"
" (set! (-> v1-0 x) (-> arg1 x))\n"
" (set! (-> v1-0 y) (-> arg1 y))\n"
" (set! (-> v1-0 z) (-> arg1 z))\n"
" (set! (-> v1-0 w) 0.0)\n"
" )\n"
" (vector-matrix*! s5-0 s5-0 arg2)\n"
" (set! (-> arg0 x) (-> s5-0 x))\n"
" (set! (-> arg0 y) (-> s5-0 y))\n"
" (set! (-> arg0 z) (-> s5-0 z))\n"
" )\n"
" arg0\n"
" )";
test_with_stack_structures(func, type, expected, R"([[16, "vector"]])");
}