jak-project/test/decompiler/test_FormBeforeExpressions.cpp
Tyler Wilding 8651179aa3
tests: Cleanup decompiler test fixtures and try to improve the test output / add a readable report (#1724)
* tests: add a Jak2 `FormRegressionTest` fixture

* tests/ci: minimize test log output and produce a readable report

* improve naming of report due to underlying GitHub issue

* hopefully fix windows handling of this argument

* test...

* final test

* test linux coverage
2022-08-05 12:12:33 -04:00

856 lines
23 KiB
C++

#include "FormRegressionTest.h"
#include "gtest/gtest.h"
using namespace decompiler;
TEST_F(FormRegressionTestJak1, StringTest) {
std::string func =
" sll r0, r0, 0\n"
" or v0, a0, r0\n"
" jr ra\n"
" daddu sp, sp, r0";
TestSettings settings;
settings.strings = {{"L100", "testing-string"}, {"L101", "testing-string-2"}};
auto test = make_function(func, TypeSpec("function", {TypeSpec("none")}), settings);
EXPECT_EQ(test->file.get_goal_string_by_label(test->file.get_label_by_name("L100")),
"testing-string");
EXPECT_EQ(test->file.get_goal_string_by_label(test->file.get_label_by_name("L101")),
"testing-string-2");
}
TEST_F(FormRegressionTestJak1, SimplestTest) {
std::string func =
" sll r0, r0, 0\n"
" or v0, a0, r0\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function object object)";
std::string expected = "(begin (set! v0-0 a0-0) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, Op3) {
std::string func =
" sll r0, r0, 0\n"
"L308:\n"
" mult3 v0, a0, a1\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected = "(begin (set! v0-0 (*.si a0-0 a1-0)) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, Division) {
std::string func =
" sll r0, r0, 0\n"
"L307:\n"
" div a0, a1\n"
" mflo v0\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected = "(begin (set! v0-0 (/.si a0-0 a1-0)) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, Ash) {
std::string func =
" sll r0, r0, 0\n"
"L305:\n"
" or v1, a0, r0\n"
" bgezl a1, L306\n"
" dsllv v0, v1, a1\n"
" dsubu a0, r0, a1\n"
" dsrav v0, v1, a0\n"
"L306:\n"
" jr ra\n"
" daddu sp, sp, r0\n"
" sll r0, r0, 0\n"
" sll r0, r0, 0";
std::string type = "(function int int int)";
std::string expected = "(begin (set! v1-0 a0-0) (set! v0-0 (ash.si v1-0 a1-0)) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, Abs) {
std::string func =
" sll r0, r0, 0\n"
"L301:\n"
" or v0, a0, r0\n"
" bltzl v0, L302\n"
" dsubu v0, r0, v0\n"
"L302:\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int)";
std::string expected = "(begin (set! v0-0 a0-0) (set! v0-0 (abs v0-0)) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, Min) {
std::string func =
" sll r0, r0, 0\n"
" or v0, a0, r0\n"
" or v1, a1, r0\n"
" slt a0, v0, v1\n"
" movz v0, v1, a0\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected =
"(begin\n"
" (set! v0-0 a0-0)\n"
" (set! v1-0 a1-0)\n"
" (set! v0-1 (min.si v0-0 v1-0))\n"
" (ret-value v0-1)\n"
" )";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, Max) {
std::string func =
" sll r0, r0, 0\n"
"L299:\n"
" or v0, a0, r0\n"
" or v1, a1, r0\n"
" slt a0, v0, v1\n"
" movn v0, v1, a0\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected =
"(begin\n"
" (set! v0-0 a0-0)\n"
" (set! v1-0 a1-0)\n"
" (set! v0-1 (max.si v0-0 v1-0))\n"
" (ret-value v0-1)\n"
" )";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, FormatString) {
std::string func =
" sll r0, r0, 0\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"
" lwc1 f0, 0(gp)\n"
" mfc1 a2, f0\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 bfloat bfloat)";
std::string expected =
"(begin\n"
" (set! t9-0 format)\n"
" (set! a0-1 #t)\n"
" (set! a1-0 L343)\n"
" (set! f0-0 (-> a0-0 data))\n"
" (set! a2-0 (fpr->gpr f0-0))\n"
" (call! a0-1 a1-0 a2-0)\n" // #t, "~f", the float
" (set! v0-1 a0-0)\n"
" (ret-value v0-1)\n"
" )";
test_no_expr(func, type, expected, false, "", {{"L343", "~f"}});
}
TEST_F(FormRegressionTestJak1, WhileLoop) {
std::string func =
" sll r0, r0, 0\n"
"L285:\n"
" lwu v1, -4(a0)\n"
" lw a0, object(s7)\n"
"L286:\n"
" bne v1, a1, L287\n"
" or a2, s7, r0\n"
" daddiu v1, s7, #t\n"
" or v0, v1, r0\n"
" beq r0, r0, L288\n"
" sll r0, r0, 0\n"
" or v1, r0, r0\n"
"L287:\n"
" lwu v1, 4(v1)\n"
" bne v1, a0, L286\n"
" sll r0, r0, 0\n"
" or v0, s7, r0\n"
"L288:\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function basic type symbol)";
std::string expected =
"(begin\n"
" (set! v1-0 (-> a0-0 type))\n"
" (set! a0-1 object)\n"
" (until\n"
" (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n"
" (if\n"
" (= v1-0 a1-0)\n"
" (return (begin (set! v1-1 #t) (set! v0-0 v1-1)))\n"
" )\n"
" )\n"
" (set! v0-0 #f)\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected);
}
// Note - this test looks weird because or's aren't fully processed at this point.
TEST_F(FormRegressionTestJak1, Or) {
std::string func =
" sll r0, r0, 0\n"
"L280:\n"
" lw v1, object(s7)\n"
"L281:\n"
" bne a0, a1, L282\n"
" or a2, s7, r0\n"
" daddiu v1, s7, #t\n"
" or v0, v1, r0\n"
" beq r0, r0, L284\n"
" sll r0, r0, 0\n"
" or v1, r0, r0\n"
"L282:\n"
" lwu a0, 4(a0)\n"
" dsubu a2, a0, v1\n"
" daddiu a3, s7, 8\n"
" movn a3, s7, a2\n"
" bnel s7, a3, L283\n"
" or a2, a3, r0\n"
" daddiu a2, s7, 8\n"
" movn a2, s7, a0\n"
"L283:\n"
" beq s7, a2, L281\n"
" sll r0, r0, 0\n"
" or v0, s7, r0\n"
"L284:\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function type type symbol)";
std::string expected =
"(begin\n"
" (set! v1-0 object)\n"
" (until\n"
" (begin\n"
" (or\n"
" (begin\n"
" (set! a0-0 (-> a0-0 parent))\n"
" (set! a3-0 (= a0-0 v1-0))\n"
" 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"
" a2-1\n"
" )\n"
" (if\n"
" (= a0-0 a1-0)\n"
" (return (begin (set! v1-1 #t) (set! v0-0 v1-1)))\n"
" )\n"
" )\n"
" (set! v0-0 #f)\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, DynamicMethodAccess) {
std::string func =
" sll r0, r0, 0\n"
"L275:\n"
" dsll v1, a1, 2\n"
" daddu v1, v1, a0\n"
" lwu v1, 16(v1)\n"
"L276:\n"
" lw a2, object(s7)\n"
" bne a0, a2, L277\n"
" or a2, s7, r0\n"
" lw v1, nothing(s7)\n"
" or v0, v1, r0\n"
" beq r0, r0, L279\n"
" sll r0, r0, 0\n"
" or v1, r0, r0\n"
"L277:\n"
" lwu a0, 4(a0)\n"
" dsll a2, a1, 2\n"
" daddu a2, a2, a0\n"
" lwu v0, 16(a2)\n"
" bne v0, r0, L278\n"
" or a2, s7, r0\n"
" lw v1, nothing(s7)\n"
" or v0, v1, r0\n"
" beq r0, r0, L279\n"
" sll r0, r0, 0\n"
" or v1, r0, r0\n"
"L278:\n"
" beq v0, v1, L276\n"
" sll r0, r0, 0\n"
" or v1, s7, r0\n"
"L279:\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function type int function)";
std::string expected =
"(begin\n"
" (set! v1-0 (sll a1-0 2))\n"
" (set! v1-1 (+ v1-0 a0-0))\n"
" (set! v1-2 (dyn-method-access v1-1))\n" // get the method of the given type.
" (until\n"
" (!= v0-0 v1-2)\n" // actually goes after the body, so it's fine to refer to v1-2
" (if\n"
" (begin\n"
" (if\n"
" (begin (set! a2-0 object) (= a0-0 a2-0))\n" // if we reached the top
" (return (begin (set! v1-3 nothing) (set! v0-0 v1-3)))\n" // return
// nothing.
" )\n"
" (set! a0-0 (-> a0-0 parent))\n" // get next parent type
" (set! a2-2 (sll a1-0 2))\n" // fancy access
" (set! a2-3 (+ a2-2 a0-0))\n"
" (set! v0-0 (dyn-method-access a2-3))\n" // get method (in v0-1, the same var as loop
// condition)
" (zero? v0-0)\n" // is it defined?
" )\n"
" (return (begin (set! v1-4 nothing) (set! v0-0 v1-4)))\n" // also
// return
// nothing.
" )\n"
" )\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected);
}
TEST_F(FormRegressionTestJak1, SimpleLoopMergeCheck) {
std::string func =
" sll r0, r0, 0\n"
"L272:\n"
" addiu v1, r0, 0\n"
" beq r0, r0, L274\n"
" sll r0, r0, 0\n"
"L273:\n"
" sll r0, r0, 0\n"
" sll r0, r0, 0\n"
" lw a0, 2(a0)\n"
" daddiu v1, v1, 1\n"
"L274:\n"
" slt a2, v1, a1\n"
" bne a2, r0, L273\n"
" sll r0, r0, 0\n"
" or v1, s7, r0\n"
" or v1, s7, r0\n"
" lw v0, -2(a0)\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function object int)";
std::string expected =
"(begin\n"
" (set! v1-0 0)\n"
" (while\n"
" (<.si v1-0 a1-0)\n"
" (nop!)\n"
" (nop!)\n"
" (set! a0-0 (cdr a0-0))\n" // should have merged
" (set! v1-0 (+ v1-0 1))\n" // also should have merged
" )\n"
" (set! v0-0 (car a0-0))\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected, true);
}
TEST_F(FormRegressionTestJak1, And) {
std::string func =
" sll r0, r0, 0\n"
"L266:\n"
" daddiu v1, s7, -10\n"
" bne a0, v1, L267\n"
" sll r0, r0, 0\n"
" addiu v0, r0, 0\n"
" beq r0, r0, L271\n"
" sll r0, r0, 0\n"
"L267:\n"
" lw v1, 2(a0)\n"
" addiu v0, r0, 1\n"
" beq r0, r0, L269\n"
" sll r0, r0, 0\n"
"L268:\n"
" daddiu v0, v0, 1\n"
" lw v1, 2(v1)\n"
"L269:\n"
" daddiu a0, s7, -10\n"
" dsubu a0, v1, a0\n"
" daddiu a1, s7, 8\n"
" movz a1, s7, a0\n"
" beql s7, a1, L270\n"
" or a0, a1, r0\n"
" dsll32 a0, v1, 30\n"
" slt a1, a0, r0\n"
" daddiu a0, s7, 8\n"
" movz a0, s7, a1\n"
"L270:\n"
" bne s7, a0, L268\n"
" sll r0, r0, 0\n"
" or v1, s7, r0\n"
"L271:\n"
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function pair int)";
std::string expected =
"(begin\n"
"(cond\n"
" ((begin (set! v1-0 '()) (= a0-0 v1-0)) (set! v0-0 0))\n" // should be a case, not a return
" (else\n"
" (set! v1-1 (cdr a0-0))\n" // v1-1 iteration.
" (set! v0-0 1)\n" // v0-1 count
" (while\n"
" (begin\n"
" (and\n"
" (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"
" 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.
" )\n"
" )\n"
" )"
"(ret-value v0-0))\n";
test_no_expr(func, type, expected, true);
}
TEST_F(FormRegressionTestJak1, FunctionCall) {
// nmember
std::string func =
" sll r0, r0, 0\n"
"L252:\n"
" daddiu sp, sp, -48\n"
" sd ra, 0(sp)\n"
" sq s5, 16(sp)\n"
" sq gp, 32(sp)\n"
" or s5, a0, r0\n"
" or gp, a1, r0\n"
" beq r0, r0, L254\n"
" sll r0, r0, 0\n"
"L253:\n"
" lw gp, 2(gp)\n"
"L254:\n"
" daddiu v1, s7, -10\n"
" dsubu v1, gp, v1\n"
" daddiu a0, s7, 8\n"
" movn a0, s7, v1\n"
" bnel s7, a0, L255\n"
" or v1, a0, r0\n"
" lw t9, name=(s7)\n"
" lw a0, -2(gp)\n"
" or a1, s5, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" or v1, v0, r0\n"
"L255:\n"
" beq s7, v1, L253\n"
" sll r0, r0, 0\n"
" or v1, s7, r0\n"
" daddiu v1, s7, -10\n"
" beq gp, v1, L256\n"
" or v0, s7, r0\n"
" or v0, gp, r0\n"
"L256:\n"
" ld ra, 0(sp)\n"
" lq gp, 32(sp)\n"
" lq s5, 16(sp)\n"
" jr ra\n"
" daddiu sp, sp, 48";
std::string type = "(function basic object object)";
std::string expected =
"(begin (if\n" // this if needs regrouping.
" (begin\n"
" (while\n"
" (begin\n"
" (or\n"
" (begin (set! v1-0 '()) (set! a0-1 (= a1-0 v1-0)) a0-1)\n" // got empty list.
" (begin\n"
" (set! t9-0 name=)\n"
" (set! a0-2 (car a1-0))\n"
" (set! a1-1 a0-0)\n"
" (set! v0-0 (call! a0-2 a1-1))\n"
" (set! v1-1 v0-0)\n" // name match
" )\n"
" )\n"
" (not v1-1)\n" // no name match AND no empty list.
" )\n"
" (set! a1-0 (cdr a1-0))\n" // get next (merged)
" )\n"
" (set! v1-3 '())\n" //
" (!= a1-0 v1-3)\n" // IF CONDITION
" )\n"
" (set! v0-1 a1-0)\n" // not empty, so return the result
" )" // the (set! v0 #f) from the if is added later.
" (ret-value v0-1))\n";
test_no_expr(func, type, expected, true);
}
TEST_F(FormRegressionTestJak1, NestedAndOr) {
std::string func =
" sll r0, r0, 0\n"
"L200:\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)";
std::string expected =
"(begin\n"
" (set! s4-0 -1)\n" // s4-0 = flag
" (while\n"
" (nonzero? s4-0)\n" // there is stuff to do...
" (set! s4-0 0)\n" // flag = 0
" (set! s3-0 a0-0)\n" // s3 = list-iter
" (while\n"
" (begin\n"
" (or\n"
" (begin\n"
" (set! v1-6 (cdr s3-0))\n" // s3-0 = cdr
" (set! a0-4 '())\n"
" (set! a0-5 (= v1-6 a0-4))\n"
" a0-5\n" // cdr = empty list (sets v1-7 secretly)
" )\n"
" (begin\n"
" (set! v1-8 (cdr s3-0))\n"
" (set! v1-9 (sll v1-8 62))\n"
" (set! v1-7 (>=0.si v1-9))\n" // car is not a list.
" )\n"
" )\n"
" (not v1-7)\n" // while we still have an iterable list...
" )\n"
" (when\n"
" (begin\n"
" (and\n"
" (begin\n"
" (or\n"
" (begin\n"
" (set! s2-0 (car s3-0))\n" // s2 = car
" (set! v1-0 (cdr s3-0))\n"
" (set! s1-0 (car v1-0))\n" // s1 = cadr
" (set! t9-0 a1-0)\n" // func
" (set! a0-1 s2-0)\n" // car
" (set! a1-1 s1-0)\n" // cadr
" (set! v0-0 (call! a0-1 a1-1))\n" // compare!
" (set! v1-1 v0-0)\n"
" (not v1-1)\n" // result is false (secretly sets a0-2)
" )\n"
" (set! a0-2 (>0.si v1-1))\n" // >0
" )\n"
" a0-2\n" // false or >0
" )\n"
" (begin (set! a0-3 #t) (set! v1-2 (!= v1-1 a0-3)))\n" // not #t
" )\n"
" 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
" (set! v1-4 (cdr s3-0))\n" // current cdr
" (set! (car v1-4) s2-0)\n" // set cadr
" (set! v1-5 s2-0)\n"
" )\n"
" (set! s3-0 (cdr s3-0))\n" // increment!
" )\n"
" )\n"
" (set! v0-1 a0-0)\n"
" (ret-value v0-1)\n"
" )";
test_no_expr(func, type, expected, true);
}
TEST_F(FormRegressionTestJak1, NewMethod) {
// inline-array-class new
std::string func =
" sll r0, r0, 0\n"
"L198:\n"
" daddiu sp, sp, -32\n"
" sd ra, 0(sp)\n"
" sq gp, 16(sp)\n"
" or gp, a2, r0\n"
" lw v1, object(s7)\n"
" lwu t9, 16(v1)\n"
" or v1, a1, r0\n"
" lhu a2, 8(a1)\n"
" lhu a1, 12(a1)\n"
" multu3 a1, gp, a1\n"
" daddu a2, a2, a1\n"
" or a1, v1, r0\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" beq v0, r0, L199\n"
" or v1, s7, r0\n"
" sw gp, 0(v0)\n"
" sw gp, 4(v0)\n"
"L199:\n"
" ld ra, 0(sp)\n"
" lq gp, 16(sp)\n"
" jr ra\n"
" daddiu sp, sp, 32";
std::string type = "(function symbol type int inline-array-class)";
std::string expected =
"(begin (when\n"
" (begin\n"
" (set! v1-0 object)\n"
" (set! t9-0 (method-of-type v1-0 new))\n" // object new
" (set! v1-1 a1-0)\n" // ?
" (set! a2-1 (-> a1-0 size))\n" // math
" (set! a1-1 (-> a1-0 heap-base))\n"
" (set! a1-2 (*.ui a2-0 a1-1))\n"
" (set! a2-2 (+ a2-1 a1-2))\n"
" (set! a1-3 v1-1)\n" // size!
" (set! v0-0 (call! a0-0 a1-3 a2-2))\n"
" (nonzero? v0-0)\n" // only if we got memory...
" )\n"
" (set! (-> v0-0 length) a2-0)\n" // store size
" (set! (-> v0-0 allocated-length) a2-0)\n"
" )"
" (ret-value v0-0))\n";
test_no_expr(func, type, expected, false, "inline-array-class");
}
TEST_F(FormRegressionTestJak1, Recursive) {
std::string func =
" sll r0, r0, 0\n"
"L65:\n"
" daddiu sp, sp, -32\n"
" sd ra, 0(sp)\n"
" sq gp, 16(sp)\n"
" or gp, a0, r0\n"
" addiu v1, r0, 1\n"
" bne gp, v1, L66\n"
" sll r0, r0, 0\n"
" addiu v0, r0, 1\n"
" beq r0, r0, L67\n"
" sll r0, r0, 0\n"
"L66:\n"
" lw t9, fact(s7)\n"
" daddiu a0, gp, -1\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" mult3 v0, gp, v0\n"
"L67:\n"
" ld ra, 0(sp)\n"
" lq gp, 16(sp)\n"
" jr ra\n"
" daddiu sp, sp, 32";
std::string type = "(function int int)";
std::string expected =
"(begin (cond\n"
" ((begin (set! v1-0 1) (= a0-0 v1-0)) (set! v0-0 1))\n" // base
" (else\n"
" (set! t9-0 fact)\n" // recurse!
" (set! a0-1 (+ a0-0 -1))\n"
" (set! v0-1 (call! a0-1))\n"
" (set! v0-0 (*.si a0-0 v0-1))\n" // not quite a tail call...
" )\n"
" )"
" (ret-value v0-0))\n";
test_no_expr(func, type, expected, false);
}
TEST_F(FormRegressionTestJak1, TypeOf) {
std::string func =
" sll r0, r0, 0\n"
"L63:\n"
" daddiu sp, sp, -16\n"
" sd ra, 0(sp)\n"
" dsll32 v1, a0, 29\n"
" beql v1, r0, L64\n"
" lw v1, binteger(s7)\n"
" bgtzl v1, L64\n"
" lw v1, pair(s7)\n"
" lwu v1, -4(a0)\n"
"L64:\n"
" lwu t9, 24(v1)\n"
" jalr ra, t9\n"
" sll v0, ra, 0\n"
" ld ra, 0(sp)\n"
" jr ra\n"
" daddiu sp, sp, 16";
std::string type = "(function object object)";
std::string expected =
"(begin\n"
" (set! v1-1 (rtype-of a0-0))\n"
" (set! t9-0 (method-of-type v1-1 print))\n" // print method.
" (set! v0-0 (call! a0-0))\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected, false);
}