[Decompiler] Expressions (Part 3) (#213)

* before inserting bonus instruction

* first part of refactor for return values

* find parent method working
This commit is contained in:
water111
2021-01-25 22:08:58 -05:00
committed by GitHub
parent 2f722e6379
commit b59e33c005
22 changed files with 782 additions and 81 deletions
+1
View File
@@ -98,6 +98,7 @@ std::unique_ptr<FormRegressionTest::TestData> FormRegressionTest::make_function(
auto ops = convert_function_to_atomic_ops(test->func, program.labels);
test->func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
test->func.ir2.atomic_ops_succeeded = true;
test->func.ir2.env.set_end_var(test->func.ir2.atomic_ops->end_op().return_var());
EXPECT_TRUE(test->func.run_type_analysis_ir2(function_type, *dts, test->file, {}));
+50 -25
View File
@@ -27,7 +27,7 @@ TEST_F(FormRegressionTest, SimplestTest) {
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function object object)";
std::string expected = "(set! v0-0 a0-0)";
std::string expected = "(begin (set! v0-0 a0-0) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
@@ -52,6 +52,7 @@ TEST_F(FormRegressionTest, FloatingPointBasic) {
" (set! f1-0 (gpr->fpr a0-0))\n"
" (set! f0-1 (/.s f0-0 f1-0))\n"
" (set! v0-0 (fpr->gpr f0-1))\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected);
}
@@ -64,7 +65,7 @@ TEST_F(FormRegressionTest, Op3) {
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected = "(set! v0-0 (*.si a0-0 a1-0))";
std::string expected = "(begin (set! v0-0 (*.si a0-0 a1-0)) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
@@ -77,7 +78,7 @@ TEST_F(FormRegressionTest, Division) {
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected = "(set! v0-0 (/.si a0-0 a1-0))";
std::string expected = "(begin (set! v0-0 (/.si a0-0 a1-0)) (ret-value v0-0))";
test_no_expr(func, type, expected);
}
@@ -97,7 +98,7 @@ TEST_F(FormRegressionTest, Ash) {
" 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)))";
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);
}
@@ -113,7 +114,7 @@ TEST_F(FormRegressionTest, Abs) {
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int)";
std::string expected = "(begin (set! v0-0 a0-0) (set! v0-1 (abs v0-0)))";
std::string expected = "(begin (set! v0-0 a0-0) (set! v0-1 (abs v0-0)) (ret-value v0-1))";
test_no_expr(func, type, expected);
}
@@ -127,7 +128,13 @@ TEST_F(FormRegressionTest, Min) {
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected = "(begin (set! v0-0 a0-0) (set! v1-0 a1-0) (set! v0-1 (min.si v0-0 v1-0)))";
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);
}
@@ -142,7 +149,13 @@ TEST_F(FormRegressionTest, Max) {
" jr ra\n"
" daddu sp, sp, r0";
std::string type = "(function int int int)";
std::string expected = "(begin (set! v0-0 a0-0) (set! v1-0 a1-0) (set! v0-1 (max.si v0-0 v1-0)))";
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);
}
@@ -182,6 +195,7 @@ TEST_F(FormRegressionTest, FormatString) {
" (set! a2-0 (fpr->gpr f0-0))\n"
" (call! a0-1 a1-0 a2-0)\n" // #t, "~f", the float
" (set! v0-1 gp-0)\n"
" (ret-value v0-1)\n"
" )";
test_no_expr(func, type, expected, false, "", {{"L343", "~f"}});
}
@@ -220,10 +234,11 @@ TEST_F(FormRegressionTest, WhileLoop) {
" (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))) ((set! v1-0 0)))\n"
" (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)) (set! v1-0 0))\n"
" )\n"
" )\n"
" (set! v0-0 '#f)\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected);
}
@@ -285,10 +300,11 @@ TEST_F(FormRegressionTest, Or) {
" )\n"
" (if\n"
" (= a0-0 a1-0)\n"
" (return ((begin (set! v1-1 '#t) (set! v0-0 v1-1))) ((set! v1-0 0)))\n"
" (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)) (set! v1-0 0))\n"
" )\n"
" )\n"
" (set! v0-0 '#f)\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected);
}
@@ -343,29 +359,30 @@ TEST_F(FormRegressionTest, DynamicMethodAccess) {
"(begin\n"
" (set! v1-0 (sll a1-0 2))\n"
" (set! v1-1 (+ v1-0 a0-0))\n"
" (set! v1-2 (l.wu (+ v1-1 16)))\n" // get the method of the given type.
" (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))) ((set! v1-2 0)))\n" // return
// nothing.
" (return (begin (set! v1-3 nothing) (set! v0-0 v1-3)) (set! v1-2 0))\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 (l.wu (+ a2-3 16)))\n" // get method (in v0-1, the same var as loop
// condition)
" (zero? v0-0)\n" // is it defined?
" (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))) ((set! v1-2 0)))\n" // also
// return
// nothing.
" (return (begin (set! v1-4 nothing) (set! v0-0 v1-4)) (set! v1-2 0))\n" // also
// return
// nothing.
" )\n"
" )\n"
" (set! v1-5 '#f)\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected);
}
@@ -409,6 +426,7 @@ TEST_F(FormRegressionTest, SimpleLoopMergeCheck) {
" (set! v1-1 '#f)\n"
" (set! v1-2 '#f)\n"
" (set! v0-0 (l.w (+ a0-0 -2)))\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected, true);
}
@@ -460,6 +478,7 @@ TEST_F(FormRegressionTest, And) {
" 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"
@@ -478,7 +497,8 @@ TEST_F(FormRegressionTest, And) {
" )\n"
" (set! v1-2 '#f)\n" // while's false, I think.
" )\n"
" )";
" )"
"(ret-value v0-0))\n";
test_no_expr(func, type, expected, true);
}
@@ -536,7 +556,7 @@ TEST_F(FormRegressionTest, FunctionCall) {
" daddiu sp, sp, 48";
std::string type = "(function basic object object)";
std::string expected =
"(if\n" // this if needs regrouping.
"(begin (if\n" // this if needs regrouping.
" (begin\n"
" (set! s5-0 a0-0)\n" // s5-0 is the thing to check
" (set! gp-0 a1-0)\n" // gp-0 is the list
@@ -561,7 +581,8 @@ TEST_F(FormRegressionTest, FunctionCall) {
" (!= gp-0 v1-3)\n" // IF CONDITION
" )\n"
" (set! v0-1 gp-0)\n" // not empty, so return the result
" )"; // the (set! v0 #f) from the if is added later.
" )" // the (set! v0 #f) from the if is added later.
" (ret-value v0-1))\n";
test_no_expr(func, type, expected, true);
}
@@ -732,6 +753,7 @@ TEST_F(FormRegressionTest, NestedAndOr) {
" )\n"
" (set! v1-12 '#f)\n"
" (set! v0-1 gp-0)\n"
" (ret-value v0-1)\n"
" )";
test_no_expr(func, type, expected, true);
}
@@ -771,7 +793,7 @@ TEST_F(FormRegressionTest, NewMethod) {
" daddiu sp, sp, 32";
std::string type = "(function symbol type int inline-array-class)";
std::string expected =
"(when\n"
"(begin (when\n"
" (begin\n"
" (set! gp-0 a2-0)\n" // gp-0 is size
" (set! v1-0 object)\n"
@@ -787,7 +809,8 @@ TEST_F(FormRegressionTest, NewMethod) {
" )\n"
" (s.w! v0-0 gp-0)\n" // store size
" (s.w! (+ v0-0 4) gp-0)\n"
" )";
" )"
" (ret-value v0-0))\n";
test_no_expr(func, type, expected, false, "inline-array-class");
}
@@ -823,7 +846,7 @@ TEST_F(FormRegressionTest, Recursive) {
" daddiu sp, sp, 32";
std::string type = "(function int int)";
std::string expected =
"(cond\n"
"(begin (cond\n"
" ((begin (set! gp-0 a0-0) (set! v1-0 1) (= gp-0 v1-0)) (set! v0-0 1))\n" // base
" (else\n"
" (set! t9-0 fact)\n" // recurse!
@@ -831,7 +854,8 @@ TEST_F(FormRegressionTest, Recursive) {
" (set! v0-1 (call! a0-1))\n"
" (set! v0-0 (*.si gp-0 v0-1))\n" // not quite a tail call...
" )\n"
" )";
" )"
" (ret-value v0-0))\n";
test_no_expr(func, type, expected, false);
}
@@ -866,6 +890,7 @@ TEST_F(FormRegressionTest, TypeOf) {
" (set! v1-1 (type-of a0-0))\n"
" (set! t9-0 (-> v1-1 method-table 2))\n" // print method.
" (set! v0-0 (call! a0-0))\n"
" (ret-value v0-0)\n"
" )";
test_no_expr(func, type, expected, false);
}
+120 -1
View File
@@ -462,10 +462,129 @@ TEST_F(FormRegressionTest, ExprBasicTypeP) {
// don't plan on supporting this.
" (if\n"
" (= v1-0 a1-0)\n"
" (return ((begin (set! v1-1 '#t) (set! v0-0 v1-1))) ((set! v1-0 0)))\n"
" (return '#t (set! v1-0 0))\n"
" )\n"
" )\n"
" '#f\n"
" )";
test_with_expr(func, type, expected);
}
TEST_F(FormRegressionTest, ExprTypeTypep) {
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"
" (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"
" )\n"
" (if (= a0-0 a1-0) (return '#t (set! v1-0 0)))\n"
" )\n"
" '#f\n"
" )";
test_with_expr(func, type, expected, false, "");
}
TEST_F(FormRegressionTest, ExprFindParentMethod) {
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-2 (-> a0-0 methods a1-0))\n"
" (until\n"
" (!= v0-0 v1-2)\n"
" (if (= a0-0 object) (return nothing (set! v1-2 0)))\n"
" (set! a0-0 (-> a0-0 parent))\n"
" (set! v0-0 (-> a0-0 methods a1-0))\n"
" (if (zero? v0-0) (return nothing (set! v1-2 0)))\n"
" )\n"
" (set! v1-5 '#f)\n"
" v0-0\n"
" )";
test_with_expr(func, type, expected, false, "");
}