mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Add pragmas to funC for precise control of computation order (#589)
* FunC pragmas: allow-post-modification and compute-asm-ltr * Warn if #pragma is enabled only in included files * Add tests for new pragmas * Add special ops for "allow-post-modification" only when needed * Update FunC version to 0.4.1 * Allow empty inlines (#10) Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
6b49d6a382
commit
653c88aa9d
8 changed files with 344 additions and 61 deletions
78
crypto/func/auto-tests/tests/allow_post_modification.fc
Normal file
78
crypto/func/auto-tests/tests/allow_post_modification.fc
Normal file
|
@ -0,0 +1,78 @@
|
|||
#pragma allow-post-modification;
|
||||
|
||||
forall X -> tuple unsafe_tuple(X x) asm "NOP";
|
||||
|
||||
(int, int) inc(int x, int y) {
|
||||
return (x + y, y * 10);
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) test_return(int x) method_id(11) {
|
||||
return (x, x~inc(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) test_assign(int x) method_id(12) {
|
||||
(int x1, int x2, int x3, int x4, int x5, int x6, int x7) = (x, x~inc(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
return (x1, x2, x3, x4, x5, x6, x7);
|
||||
}
|
||||
|
||||
tuple test_tuple(int x) method_id(13) {
|
||||
tuple t = unsafe_tuple([x, x~inc(x / 20), x, x = x * 2, x, x += 1, x]);
|
||||
return t;
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) test_tuple_assign(int x) method_id(14) {
|
||||
[int x1, int x2, int x3, int x4, int x5, int x6, int x7] = [x, x~inc(x / 20), x, x = x * 2, x, x += 1, x];
|
||||
return (x1, x2, x3, x4, x5, x6, x7);
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) foo1(int x1, int x2, int x3, int x4, int x5, int x6, int x7) {
|
||||
return (x1, x2, x3, x4, x5, x6, x7);
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) test_call_1(int x) method_id(15) {
|
||||
return foo1(x, x~inc(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) foo2(int x1, int x2, (int, int, int, int) x3456, int x7) {
|
||||
(int x3, int x4, int x5, int x6) = x3456;
|
||||
return (x1, x2, x3, x4, x5, x6, x7);
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) test_call_2(int x) method_id(16) {
|
||||
return foo2(x, x~inc(x / 20), (x, x = x * 2, x, x += 1), x);
|
||||
}
|
||||
|
||||
(int, int, int, int, int, int, int) asm_func(int x1, int x2, int x3, int x4, int x5, int x6, int x7) asm
|
||||
(x4 x5 x6 x7 x1 x2 x3 -> 0 1 2 3 4 5 6) "NOP";
|
||||
|
||||
(int, int, int, int, int, int, int) test_call_asm_old(int x) method_id(17) {
|
||||
return asm_func(x, x += 1, x, x, x~inc(x / 20), x, x = x * 2);
|
||||
}
|
||||
|
||||
#pragma compute-asm-ltr;
|
||||
|
||||
(int, int, int, int, int, int, int) test_call_asm_new(int x) method_id(18) {
|
||||
return asm_func(x, x~inc(x / 20), x, x = x * 2, x, x += 1, x);
|
||||
}
|
||||
|
||||
global int xx;
|
||||
(int, int, int, int, int, int, int) test_global(int x) method_id(19) {
|
||||
xx = x;
|
||||
return (xx, xx~inc(xx / 20), xx, xx = xx * 2, xx, xx += 1, xx);
|
||||
}
|
||||
|
||||
() main() {
|
||||
}
|
||||
|
||||
{-
|
||||
method_id | in | out
|
||||
TESTCASE | 11 | 100 | 100 50 105 210 210 211 211
|
||||
TESTCASE | 12 | 100 | 100 50 105 210 210 211 211
|
||||
TESTCASE | 13 | 100 | [ 100 50 105 210 210 211 211 ]
|
||||
TESTCASE | 14 | 100 | 100 50 105 210 210 211 211
|
||||
TESTCASE | 15 | 100 | 100 50 105 210 210 211 211
|
||||
TESTCASE | 16 | 100 | 100 50 105 210 210 211 211
|
||||
TESTCASE | 17 | 100 | 100 50 105 210 210 211 211
|
||||
TESTCASE | 18 | 100 | 210 210 211 211 100 50 105
|
||||
TESTCASE | 19 | 100 | 100 50 105 210 210 211 211
|
||||
-}
|
113
crypto/func/auto-tests/tests/asm_arg_order.fc
Normal file
113
crypto/func/auto-tests/tests/asm_arg_order.fc
Normal file
|
@ -0,0 +1,113 @@
|
|||
tuple empty_tuple() asm "NIL";
|
||||
forall X -> (tuple, ()) tpush(tuple t, X x) asm "TPUSH";
|
||||
|
||||
tuple asm_func_1(int x, int y, int z) asm "3 TUPLE";
|
||||
tuple asm_func_2(int x, int y, int z) asm (z y x -> 0) "3 TUPLE";
|
||||
tuple asm_func_3(int x, int y, int z) asm (y z x -> 0) "3 TUPLE";
|
||||
tuple asm_func_4(int a, (int, (int, int)) b, int c) asm (b a c -> 0) "5 TUPLE";
|
||||
|
||||
(tuple, ()) asm_func_modify(tuple a, int b, int c) asm (c b a -> 0) "SWAP TPUSH SWAP TPUSH";
|
||||
|
||||
global tuple t;
|
||||
|
||||
int foo(int x) {
|
||||
t~tpush(x);
|
||||
return x * 10;
|
||||
}
|
||||
|
||||
(tuple, tuple) test_old_1() method_id(11) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = asm_func_1(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_old_2() method_id(12) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = asm_func_2(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_old_3() method_id(13) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = asm_func_3(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_old_4() method_id(14) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = empty_tuple();
|
||||
;; This actually computes left-to-right even without compute-asm-ltr
|
||||
tuple t2 = asm_func_4(foo(11), (foo(22), (foo(33), foo(44))), foo(55));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_old_modify() method_id(15) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = empty_tuple();
|
||||
t2~asm_func_modify(foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_old_dot() method_id(16) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = foo(11).asm_func_3(foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
#pragma compute-asm-ltr;
|
||||
|
||||
(tuple, tuple) test_new_1() method_id(21) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = asm_func_1(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_new_2() method_id(22) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = asm_func_2(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_new_3() method_id(23) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = asm_func_3(foo(11), foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_new_4() method_id(24) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = asm_func_4(foo(11), (foo(22), (foo(33), foo(44))), foo(55));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_new_modify() method_id(25) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = empty_tuple();
|
||||
t2~asm_func_modify(foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
(tuple, tuple) test_new_dot() method_id(26) {
|
||||
t = empty_tuple();
|
||||
tuple t2 = foo(11).asm_func_3(foo(22), foo(33));
|
||||
return (t, t2);
|
||||
}
|
||||
|
||||
() main() {
|
||||
}
|
||||
|
||||
{-
|
||||
method_id | in | out
|
||||
TESTCASE | 11 | | [ 11 22 33 ] [ 110 220 330 ]
|
||||
TESTCASE | 12 | | [ 33 22 11 ] [ 330 220 110 ]
|
||||
TESTCASE | 13 | | [ 22 33 11 ] [ 220 330 110 ]
|
||||
TESTCASE | 14 | | [ 11 22 33 44 55 ] [ 220 330 440 110 550 ]
|
||||
TESTCASE | 15 | | [ 33 22 ] [ 220 330 ]
|
||||
TESTCASE | 16 | | [ 22 33 11 ] [ 220 330 110 ]
|
||||
TESTCASE | 21 | | [ 11 22 33 ] [ 110 220 330 ]
|
||||
TESTCASE | 22 | | [ 11 22 33 ] [ 330 220 110 ]
|
||||
TESTCASE | 23 | | [ 11 22 33 ] [ 220 330 110 ]
|
||||
TESTCASE | 24 | | [ 11 22 33 44 55 ] [ 220 330 440 110 550 ]
|
||||
TESTCASE | 25 | | [ 22 33 ] [ 220 330 ]
|
||||
TESTCASE | 26 | | [ 11 22 33 ] [ 220 330 110 ]
|
||||
-}
|
Loading…
Add table
Add a link
Reference in a new issue