diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/_alt.ssa | 25 | ||||
-rw-r--r-- | test/_dragon.ssa | 33 | ||||
-rw-r--r-- | test/_fix1.ssa | 15 | ||||
-rw-r--r-- | test/_fix2.ssa | 15 | ||||
-rw-r--r-- | test/_fix3.ssa | 20 | ||||
-rw-r--r-- | test/_fix4.ssa | 27 | ||||
-rw-r--r-- | test/_live.ssa | 21 | ||||
-rw-r--r-- | test/_rpo.ssa | 12 | ||||
-rw-r--r-- | test/_spill1.ssa | 22 | ||||
-rw-r--r-- | test/_spill2.ssa | 22 | ||||
-rw-r--r-- | test/_spill3.ssa | 24 | ||||
-rw-r--r-- | test/abi1.ssa | 59 | ||||
-rw-r--r-- | test/abi2.ssa | 18 | ||||
-rw-r--r-- | test/abi3.ssa | 43 | ||||
-rw-r--r-- | test/abi4.ssa | 38 | ||||
-rw-r--r-- | test/abi5.ssa | 105 | ||||
-rw-r--r-- | test/align.ssa | 16 | ||||
-rw-r--r-- | test/collatz.ssa | 61 | ||||
-rw-r--r-- | test/cprime.ssa | 103 | ||||
-rw-r--r-- | test/cup.ssa | 17 | ||||
-rw-r--r-- | test/dark.ssa | 30 | ||||
-rw-r--r-- | test/double.ssa | 24 | ||||
-rw-r--r-- | test/echo.ssa | 32 | ||||
-rw-r--r-- | test/eucl.ssa | 24 | ||||
-rw-r--r-- | test/euclc.ssa | 29 | ||||
-rw-r--r-- | test/fpcnv.ssa | 27 | ||||
-rwxr-xr-x | test/go.sh | 118 | ||||
-rw-r--r-- | test/loop.ssa | 23 | ||||
-rw-r--r-- | test/mandel.ssa | 123 | ||||
-rw-r--r-- | test/max.ssa | 33 | ||||
-rw-r--r-- | test/prime.ssa | 32 | ||||
-rw-r--r-- | test/puts10.ssa | 29 | ||||
-rw-r--r-- | test/sum.ssa | 31 |
33 files changed, 1251 insertions, 0 deletions
diff --git a/test/_alt.ssa b/test/_alt.ssa new file mode 100644 index 0000000..3f89e5e --- /dev/null +++ b/test/_alt.ssa @@ -0,0 +1,25 @@ +# an example with reducible control +# flow graph that exposes poor +# handling of looping constructs + +function $test() { +@start + %ten =w copy 10 + %dum =w copy 0 # dummy live-through temporary +@loop + %alt =w phi @start 0, @left %alt1, @right %alt1 + %cnt =w phi @start 100, @left %cnt, @right %cnt1 + %alt1 =w sub 1, %alt + jnz %alt1, @right, @left +@left + %x =w phi @loop 10, @left %x1 + %x1 =w sub %x, 1 + %z =w copy %x + jnz %z, @left, @loop +@right + %cnt1 =w sub %cnt, %ten + jnz %cnt1, @loop, @end +@end + %ret =w add %cnt, %dum + ret +} diff --git a/test/_dragon.ssa b/test/_dragon.ssa new file mode 100644 index 0000000..b169e1b --- /dev/null +++ b/test/_dragon.ssa @@ -0,0 +1,33 @@ +# a moderately complex test for +# dominators computation from +# the dragon book +# because branching is limited to +# two, I had to split some blocks + +function $dragon() { +@start +@b1 + jnz 0, @b2, @b3 +@b2 + jmp @b3 +@b3 + jmp @b4.1 +@b4.1 + jnz 0, @b3, @b4.2 +@b4.2 + jnz 0, @b5, @b6 +@b5 + jmp @b7 +@b6 + jmp @b7 +@b7 + jnz 0, @b8.1, @b4.1 +@b8.1 + jnz 0, @b3, @b8.2 +@b8.2 + jnz 0, @b9, @b10 +@b9 + jmp @b1 +@b10 + jmp @b7 +} diff --git a/test/_fix1.ssa b/test/_fix1.ssa new file mode 100644 index 0000000..e89307f --- /dev/null +++ b/test/_fix1.ssa @@ -0,0 +1,15 @@ +function $test() { +@start + %x =w copy 1 +@loop + jnz %x, @noz, @isz +@noz + %x =w copy 0 + jmp @end +@isz + %x =w copy 1 + jmp @loop +@end + %z =w add 10, %x + ret +} diff --git a/test/_fix2.ssa b/test/_fix2.ssa new file mode 100644 index 0000000..89f236d --- /dev/null +++ b/test/_fix2.ssa @@ -0,0 +1,15 @@ +function $test() { +@start + %x =w copy 1 +@loop + jnz %x, @noz, @isz +@noz + %x =w copy 0 + jnz %x, @loop, @end +@isz + %x =w copy 1 + jmp @loop +@end + %z =w add 10, %x + ret +} diff --git a/test/_fix3.ssa b/test/_fix3.ssa new file mode 100644 index 0000000..283e5a1 --- /dev/null +++ b/test/_fix3.ssa @@ -0,0 +1,20 @@ +function w $test() { +@start + %x =w copy 100 + %s =w copy 0 +@l + %c =w cslew %x, 10 + jnz %c, @a, @b +@a + %s =w add %s, %x + %x =w sub %x, 1 + jmp @c +@b + %s =w sub %s, %x + jmp @c +@c + %x =w sub %x, 1 + jnz %x, @l, @end +@end + ret %s +} diff --git a/test/_fix4.ssa b/test/_fix4.ssa new file mode 100644 index 0000000..181768d --- /dev/null +++ b/test/_fix4.ssa @@ -0,0 +1,27 @@ +function $test() { +@start + %x =w copy 3 + %n =w copy 2 +@loop + %c =w ceqw %n, 10000 + jnz %c, @end, @next +@next + %t =w copy 3 + %x =w add %x, 2 +@tloop + %s =w mul %t, %t + %c =w csgtw %s, %x + jnz %c, @prime, @test +@test + %r =w rem %x, %t + jnz %r, @tnext, @loop +@tnext + %t =w add %t, 2 + jmp @tloop +@prime + %n =w add %n, 1 + jmp @loop +@end + storew %x, $a + ret +} diff --git a/test/_live.ssa b/test/_live.ssa new file mode 100644 index 0000000..fce4cb9 --- /dev/null +++ b/test/_live.ssa @@ -0,0 +1,21 @@ +# this control flow graph is irreducible +# yet, we expecet the liveness analysis +# to work properly and make %x live in +# the block @left +# +# nothing should ever be live at the entry + +function $test() { +@start + %b =w copy 0 + %x =w copy 10 + jnz 0, @loop, @left +@left + jmp @inloop +@loop + %x1 =w add %x, 1 +@inloop + %b1 =w add %b, 1 +@endloop + jmp @loop +} diff --git a/test/_rpo.ssa b/test/_rpo.ssa new file mode 100644 index 0000000..a10c6b1 --- /dev/null +++ b/test/_rpo.ssa @@ -0,0 +1,12 @@ +function $test() { +@start + jmp @foo +@baz + jnz 1, @end, @foo +@bar + jmp @end +@foo + jnz 0, @bar, @baz +@end + ret +} diff --git a/test/_spill1.ssa b/test/_spill1.ssa new file mode 100644 index 0000000..df5e4c2 --- /dev/null +++ b/test/_spill1.ssa @@ -0,0 +1,22 @@ +# test with NReg == 3 +# there must be a spill +# happening on %c +# +# if you replace the sub +# by an add or comment +# the two marked lines +# there should be no +# spill +# + +function $test() { +@start + %f =w copy 0 # here + %b =w copy 1 + %c =w copy 2 + %a =w sub %b, %c + %d =w copy %b + %e =w copy %f # and there + %g =w copy %a + ret +} diff --git a/test/_spill2.ssa b/test/_spill2.ssa new file mode 100644 index 0000000..d462d0b --- /dev/null +++ b/test/_spill2.ssa @@ -0,0 +1,22 @@ +# stupid spilling test + +function $test() { +@start + %x1 =w copy 10 + %x2 =w add %x1, %x1 + %x3 =w sub %x2, %x1 + %x4 =w add %x3, %x1 + %x5 =w sub %x4, %x1 + %x6 =w add %x5, %x1 + %x7 =w sub %x6, %x1 + %x8 =w add %x7, %x1 + %x9 =w sub %x8, %x8 + %x10 =w add %x9, %x7 + %x11 =w sub %x10, %x6 + %x12 =w add %x11, %x5 + %x13 =w sub %x12, %x4 + %x14 =w add %x13, %x3 + %x15 =w sub %x14, %x2 + %x16 =w add %x15, %x1 + ret +} diff --git a/test/_spill3.ssa b/test/_spill3.ssa new file mode 100644 index 0000000..cdfda2d --- /dev/null +++ b/test/_spill3.ssa @@ -0,0 +1,24 @@ +# make sure comparisons +# never get their two +# operands in memory +# run with NReg == 3, or +# adapt it! + +function $test() { +@start + %a =w loadw $a + %b =w loadw $a + +@loop + %c =w phi @start 0, @loop %f + %d =w phi @start 0, @loop %g + %e =w phi @start 0, @loop %h + %f =w add %c, %d + %g =w add %c, %e + %h =w add %e, %d + %x =w cslew %a, %b + jnz %x, @loop, @end + +@end + ret +} diff --git a/test/abi1.ssa b/test/abi1.ssa new file mode 100644 index 0000000..69cce44 --- /dev/null +++ b/test/abi1.ssa @@ -0,0 +1,59 @@ +# test calling into C with two +# large struct arguments (passed +# on the stack) + +type :mem = { b 17 } + +function $alpha(l %p, w %l, l %n) { +@ini + %pe =l add %p, %n +@lop + %p1 =l phi @ini %p, @lop %p2 + %l1 =w phi @ini %l, @lop %l2 + storeb %l1, %p1 + %p2 =l add %p1, 1 + %l2 =w add %l1, 1 + %c1 =w ceql %p1, %pe + jnz %c1, @end, @lop +@end + storeb 0, %pe + ret +} + +function $test() { +@start + %p =l alloc4 17 + %q =l alloc4 17 + %r0 =w call $alpha(l %p, w 65, l 16) + %r1 =w call $alpha(l %q, w 97, l 16) + %r2 =w call $fcb(:mem %p, w 1, w 2, w 3, w 4, w 5, w 6, w 7, w 8, w 9, :mem %q) + ret +} + + +# >>> driver +# #include <stdio.h> +# typedef struct { char t[17]; } mem; +# extern void test(); +# void fcb(mem m, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, mem n) { +# printf("fcb: m = (mem){ t = \"%s\" }\n", m.t); +# printf(" n = (mem){ t = \"%s\" }\n", n.t); +# #define T(n) printf(" i%d = %d\n", n, i##n); +# T(1) T(2) T(3) T(4) T(5) T(6) T(7) T(8) T(9) +# } +# int main() { test(); return 0; } +# <<< + +# >>> output +# fcb: m = (mem){ t = "ABCDEFGHIJKLMNOP" } +# n = (mem){ t = "abcdefghijklmnop" } +# i1 = 1 +# i2 = 2 +# i3 = 3 +# i4 = 4 +# i5 = 5 +# i6 = 6 +# i7 = 7 +# i8 = 8 +# i9 = 9 +# <<< diff --git a/test/abi2.ssa b/test/abi2.ssa new file mode 100644 index 0000000..b82c80c --- /dev/null +++ b/test/abi2.ssa @@ -0,0 +1,18 @@ +type :fps = { s, b, s } + +function s $sum(:fps %p) { +@start + %f1 =s load %p + %p8 =l add 8, %p + %f2 =s load %p8 + %s =s add %f1, %f2 + ret %s +} + +# >>> driver +# typedef struct { float f1; char b; float f2; } fps; +# extern float sum(fps); +# int main() { fps x = { 1.23, -1, 2.34 }; return !(sum(x) == 1.23f+2.34f); } +# /* Note the f suffixes above are important +# * otherwise C does double operations. */ +# <<< diff --git a/test/abi3.ssa b/test/abi3.ssa new file mode 100644 index 0000000..608d1db --- /dev/null +++ b/test/abi3.ssa @@ -0,0 +1,43 @@ +type :four = {l, b, w} + +data $z = { w 0 } + +function $test() { + @start + %a =w loadw $z + %y =w add %a, %a + + %s =l alloc8 16 # allocate a :four struct + %s1 =l add %s, 12 # get address of the w + storel 4, %s # set the l + storew 5, %s1 # set the w + + # only the last argument should be on the stack + %f =l add $F, %y + %x =w call %f(w %y, w 1, w 2, w 3, :four %s, w 6) + + # store the result in the + # global variable a + + %x1 =w add %y, %x + storew %x1, $a + ret +} + +# >>> driver +# #include <stdio.h> +# struct four { long l; char c; int i; }; +# extern void test(void); +# int F(int a0, int a1, int a2, int a3, struct four s, int a6) { +# printf("%d %d %d %d %d %d %d\n", +# a0, a1, a2, a3, (int)s.l, s.i, a6); +# return 42; +# } +# int a; +# int main() { test(); printf("%d\n", a); return 0; } +# <<< + +# >>> output +# 0 1 2 3 4 5 6 +# 42 +# <<< diff --git a/test/abi4.ssa b/test/abi4.ssa new file mode 100644 index 0000000..4c3d89b --- /dev/null +++ b/test/abi4.ssa @@ -0,0 +1,38 @@ +# return a large struct to C + +type :mem = { b 17 } + +function $alpha(l %p, w %l, l %n) { +@ini + %pe =l add %p, %n +@lop + %p1 =l phi @ini %p, @lop %p2 + %l1 =w phi @ini %l, @lop %l2 + storeb %l1, %p1 + %p2 =l add %p1, 1 + %l2 =w add %l1, 1 + %c1 =w ceql %p1, %pe + jnz %c1, @end, @lop +@end + storeb 0, %pe + ret +} + +function :mem $test() { +@start + %p =l alloc4 17 + %r0 =w call $alpha(l %p, w 65, l 16) + ret %p +} + + +# >>> driver +# #include <stdio.h> +# typedef struct { char t[17]; } mem; +# extern mem test(void); +# int main() { mem m = test(); printf("%s\n", m.t); return 0; } +# <<< + +# >>> output +# ABCDEFGHIJKLMNOP +# <<< diff --git a/test/abi5.ssa b/test/abi5.ssa new file mode 100644 index 0000000..4c5eaea --- /dev/null +++ b/test/abi5.ssa @@ -0,0 +1,105 @@ +# returning structs from C + +type :st1 = { b 17 } +type :st2 = { w } +type :st3 = { s, w } +type :st4 = { w, d } +type :st5 = { s, l } +type :st6 = { b 16 } +type :st7 = { s, d } +type :st8 = { w 4 } + +data $fmt1 = { b "t1: %s\n", b 0 } +data $fmt2 = { b "t2: %d\n", b 0 } +data $fmt3 = { b "t3: %f %d\n", b 0 } +data $fmt4 = { b "t4: %d %f\n", b 0 } +data $fmt5 = { b "t5: %f %lld\n", b 0 } +data $fmt6 = { b "t6: %s\n", b 0 } +data $fmt7 = { b "t7: %f %f\n", b 0 } +data $fmt8 = { b "t8: %d %d %d %d\n", b 0 } + +function $test() { +@start + %r1 =:st1 call $t1() + %i1 =w call $printf(l $fmt1, l %r1) + + %r2 =:st2 call $t2() + %w2 =w loadw %r2 + %i2 =w call $printf(l $fmt2, w %w2) + + %r3 =:st3 call $t3() + %s3 =s loads %r3 + %r34 =l add %r3, 4 + %w3 =w loadw %r34 + %p3 =d exts %s3 + %i3 =w call $printf(l $fmt3, d %p3, w %w3) + + %r4 =:st4 call $t4() + %w4 =w loadw %r4 + %r48 =l add 8, %r4 + %d4 =d loadd %r48 + %i4 =w call $printf(l $fmt4, w %w4, d %d4) + + %r5 =:st5 call $t5() + %s5 =s loads %r5 + %d5 =d exts %s5 + %r58 =l add %r5, 8 + %l5 =l loadl %r58 + %i5 =w call $printf(l $fmt5, d %d5, l %l5) + + %r6 =:st6 call $t6() + %i6 =w call $printf(l $fmt6, l %r6) + + %r7 =:st7 call $t7() + %s7 =s loads %r7 + %d71 =d exts %s7 + %r78 =l add %r7, 8 + %d72 =d loadd %r78 + %i7 =w call $printf(l $fmt7, d %d71, d %d72) + + %r8 =:st8 call $t8() + %r84 =l add 4, %r8 + %r88 =l add 4, %r84 + %r812 =l add 4, %r88 + %w81 =w loadw %r8 + %w82 =w loadw %r84 + %w83 =w loadw %r88 + %w84 =w loadw %r812 + %i8 =w call $printf(l $fmt8, w %w81, w %w82, w %w83, w %w84) + + ret +} + + +# >>> driver +# #include <stdio.h> +# typedef struct { char t[17]; } st1; +# typedef struct { int i; } st2; +# typedef struct { float f; int i; } st3; +# typedef struct { int i; double d; } st4; +# typedef struct { float f; long l; } st5; +# typedef struct { char t[16]; } st6; +# typedef struct { float f; double d; } st7; +# typedef struct { int i[4]; } st8; +# extern void test(void); +# st1 t1() { return (st1){"abcdefghijklmnop"}; } +# st2 t2() { return (st2){2}; } +# st3 t3() { return (st3){3.0,30}; } +# st4 t4() { return (st4){4,-40}; } +# st5 t5() { return (st5){5.5,-55}; } +# st6 t6() { return (st6){"abcdefghijklmno"}; } +# st7 t7() { return (st7){7.77,77.7}; } +# st8 t8() { return (st8){-8,88,-888,8888}; } +# int main() { test(); return 0; } +# <<< + +# >>> output +# t1: abcdefghijklmnop +# t2: 2 +# t3: 3.000000 30 +# t4: 4 -40.000000 +# t5: 5.500000 -55 +# t6: abcdefghijklmno +# t7: 7.770000 77.700000 +# t8: -8 88 -888 8888 +# <<< diff --git a/test/align.ssa b/test/align.ssa new file mode 100644 index 0000000..84d1fb9 --- /dev/null +++ b/test/align.ssa @@ -0,0 +1,16 @@ +function $test() { +@start + %x =l alloc16 16 + %y =l add %x, 8 + %m =w rem %y, 16 + storew %m, %y + %n =w loadw %y + storew %n, $a + ret +} + +# >>> driver +# extern void test(void); +# int a; +# int main() { test(); return !(a == 8 || a == -8); } +# <<< diff --git a/test/collatz.ssa b/test/collatz.ssa new file mode 100644 index 0000000..373ecac --- /dev/null +++ b/test/collatz.ssa @@ -0,0 +1,61 @@ +# a solution for N=1000 to +# https://projecteuler.net/problem=14 +# we use a fast local array to +# memoize small collatz numbers + +function $test() { +@start + %mem =l alloc4 4000 +@loop + %n =w phi @start 1, @newm %n9, @oldm %n9 + %cmax =w phi @start 0, @newm %c, @oldm %cmax + %fin =w csltw %n, 1000 + jnz %fin, @cloop, @end +@cloop + %n0 =w phi @loop %n, @odd %n2, @even %n3 + %c0 =w phi @loop 0, @odd %c1, @even %c1 + %no1 =w cnew %n0, 1 + jnz %no1, @iter0, @endcl +@iter0 + %ism =w csltw %n0, %n + jnz %ism, @getmemo, @iter1 +@iter1 + %c1 =w add %c0, 1 + %p =w and %n0, 1 + jnz %p, @odd, @even +@odd + %n1 =w mul 3, %n0 + %n2 =w add %n1, 1 + jmp @cloop +@even + %n3 =w div %n0, 2 + jmp @cloop +@getmemo # get the count for n0 in mem + %n0l =l extsw %n0 + %idx0 =l mul %n0l, 4 + %loc0 =l add %idx0, %mem + %cn0 =w loadw %loc0 + %c2 =w add %c0, %cn0 +@endcl # store the count for n in mem + %c =w phi @getmemo %c2, @cloop %c0 + %nl =l extsw %n + %idx1 =l mul %nl, 4 + %loc1 =l add %idx1, %mem + storew %c, %loc1 + %n9 =w add 1, %n + %big =w cslew %cmax, %c + jnz %big, @newm, @oldm +@newm + jmp @loop +@oldm + jmp @loop +@end + storew %cmax, $a + ret +} + +# >>> driver +# extern void test(void); +# int a; +# int main() { test(); return !(a == 178); } +# <<< diff --git a/test/cprime.ssa b/test/cprime.ssa new file mode 100644 index 0000000..1ca60e1 --- /dev/null +++ b/test/cprime.ssa @@ -0,0 +1,103 @@ +# generated by Andrew Chambers' +# compiler from the C program +# following in comments + +function w $main() { +@start + %v0 =l alloc8 4 + %v1 =l alloc8 4 + %v2 =l alloc8 4 + %v3 =l alloc8 4 + %v4 =l alloc8 4 + storew 5, %v1 + storew 11, %v2 + storew 12, %v3 +@L0 + %v5 =w loadw %v1 + %v6 =w cnew %v5, 201 + jnz %v6, @L8, @L1 +@L8 + storew 1, %v4 + %v7 =w loadw %v3 + %v8 =w rem %v7, 2 + %v9 =w ceqw %v8, 0 + jnz %v9, @L9, @L5 +@L9 + storew 0, %v4 +@L5 + storew 3, %v0 +@L2 + %v10 =w loadw %v0 + %v11 =w loadw %v3 + %v12 =w csltw %v10, %v11 + jnz %v12, @L10, @L3 +@L10 + %v13 =w loadw %v3 + %v14 =w loadw %v0 + %v15 =w rem %v13, %v14 + %v16 =w ceqw %v15, 0 + jnz %v16, @L11, @L4 +@L11 + storew 0, %v4 + jmp @L3 +@L4 + %v17 =w loadw %v0 + %v18 =w add %v17, 2 + storew %v18, %v0 + jmp @L2 +@L3 + %v19 =w loadw %v4 + jnz %v19, @L12, @L6 +@L12 + %v20 =w loadw %v3 + storew %v20, %v2 + %v21 =w loadw %v1 + %v22 =w add %v21, 1 + storew %v22, %v1 +@L6 + %v23 =w loadw %v3 + %v24 =w add %v23, 1 + storew %v24, %v3 + jmp @L0 +@L1 + %v25 =w loadw %v2 + %v26 =w cnew %v25, 1229 + jnz %v26, @L13, @L7 +@L13 + ret 1 +@L7 + ret 0 +@end + ret 0 +} + +# int +# main() +# { +# int i, n, p, next, isprime; +# +# n = 5; +# p = 11; +# next = 12; +# while(n != 201) { +# isprime = 1; +# if(next % 2 == 0) { +# isprime = 0; +# } else { +# for(i = 3; i < next; i = i + 2) { +# if(next % i == 0) { +# isprime = 0; +# break; +# } +# } +# } +# if(isprime) { +# p = next; +# n = n + 1; +# } +# next = next + 1; +# } +# if(p != 1229) +# return 1; +# return 0; +# } diff --git a/test/cup.ssa b/test/cup.ssa new file mode 100644 index 0000000..013394f --- /dev/null +++ b/test/cup.ssa @@ -0,0 +1,17 @@ +# counts up from -1988 to 1991 + +function $test() { +@start +@loop + %n0 =l phi @start -1988, @loop %n1 + %n1 =l add 1, %n0 + %cmp =w cslel 1991, %n1 + jnz %cmp, @end, @loop +@end + ret +} + +# >>> driver +# extern void test(void); +# int main() { test(); return 0; } +# <<< diff --git a/test/dark.ssa b/test/dark.ssa new file mode 100644 index 0000000..5046af3 --- /dev/null +++ b/test/dark.ssa @@ -0,0 +1,30 @@ +# a hack example, +# we use a dark type to get +# a pointer to the stack. + +type :magic = align 1 { 0 } + +data $ret = { l 0 } + +function $test(:magic %p) { +@start + %av =w loadw $a + %a1 =w add 1, %av + storew %a1, $a # increment $a + %r1 =l loadl $ret # fetch from $ret + %p1 =l add %p, -8 + %r2 =l loadl %p1 # get the return address + storel %r2, $ret # store it in $ret + %c =w ceql %r1, %r2 + jnz %c, @fin, @cal +@cal + %i =w call $test() # no argument given, intentionally! +@fin + ret +} + +# >>> driver +# extern void test(void); +# int a = 2; +# int main() { test(); return !(a == 5); } +# <<< diff --git a/test/double.ssa b/test/double.ssa new file mode 100644 index 0000000..d885d28 --- /dev/null +++ b/test/double.ssa @@ -0,0 +1,24 @@ +function $test() { +@start + %x1 =d copy d_0.1 + %x2 =d add d_0.2, %x1 + %x3 =d sub %x2, d_0.3 + +@loop + %x4 =d phi @start %x3, @loop %x5 + %i1 =w phi @start 0, @loop %i2 + %x5 =d add %x4, %x4 + %i2 =w add %i1, 1 + %c0 =w cled %x5, 4607182418800017408 # d_1.0 + jnz %c0, @loop, @end + +@end + storew %i2, $a + ret +} + +# >>> driver +# extern void test(void); +# int a; +# int main() { test(); return !(a == 55); } +# <<< diff --git a/test/echo.ssa b/test/echo.ssa new file mode 100644 index 0000000..d3c8a25 --- /dev/null +++ b/test/echo.ssa @@ -0,0 +1,32 @@ +function w $main(w %argc, l %argv) { +@start + %fmt =l alloc8 8 + storel 1663398693, %fmt # "%s%c" + %av0 =l add %argv, 8 + %ac0 =w sub %argc, 1 +@loop + %av =l phi @start %av0, @loop2 %av1 + %ac =w phi @start %ac0, @loop2 %ac1 + %c0 =w ceqw %ac, 0 + jnz %c0, @end, @loop1 +@loop1 + %c1 =w ceqw %ac, 1 + jnz %c1, @last, @nolast +@last + jmp @loop2 +@nolast + jmp @loop2 +@loop2 + %sep =w phi @last 10, @nolast 32 + %arg =l loadl %av + %r =w call $printf(l %fmt, l %arg, w %sep) + %av1 =l add %av, 8 + %ac1 =w sub %ac, 1 + jmp @loop +@end + ret 0 +} + +# >>> output +# a b c +# <<< diff --git a/test/eucl.ssa b/test/eucl.ssa new file mode 100644 index 0000000..f50fd2c --- /dev/null +++ b/test/eucl.ssa @@ -0,0 +1,24 @@ +# euclide's algorithm in ssa +# it is a fairly interesting +# ssa program because of the +# swap of b and a + +function $test() { +@start + +@loop + %a =w phi @start 380, @loop %r + %b =w phi @start 747, @loop %a + %r =w rem %b, %a + jnz %r, @loop, @end + +@end + storew %a, $a + ret +} + +# >>> driver +# extern void test(void); +# int a; +# int main() { test(); return !(a == 1); } +# <<< diff --git a/test/euclc.ssa b/test/euclc.ssa new file mode 100644 index 0000000..c76db2f --- /dev/null +++ b/test/euclc.ssa @@ -0,0 +1,29 @@ +function w $test() { +@l0 + %a =l alloc4 4 + %b =l alloc4 4 + %r =l alloc4 4 + storew 747, %a + storew 380, %b +@l1 + %t4 =w loadw %b + jnz %t4, @l2, @l3 +@l2 + %t7 =w loadw %a + %t8 =w loadw %b + %t6 =w rem %t7, %t8 + storew %t6, %r + %t10 =w loadw %b + storew %t10, %a + %t12 =w loadw %r + storew %t12, %b + jmp @l1 +@l3 + %t13 =w loadw %a + ret %t13 +} + +# >>> driver +# extern int test(void); +# int main() { return !(test() == 1); } +# <<< diff --git a/test/fpcnv.ssa b/test/fpcnv.ssa new file mode 100644 index 0000000..5fd3be9 --- /dev/null +++ b/test/fpcnv.ssa @@ -0,0 +1,27 @@ +# floating point casts and conversions + +function s $fneg(s %f) { +@fneg + %b0 =w cast %f + %b1 =w xor 2147483648, %b0 + %rs =s cast %b1 + ret %rs +} + +function d $ftrunc(d %f) { +@ftrunc + %l0 =l ftosi %f + %rt =d sitof %l0 + ret %rt +} + +# >>> driver +# extern float fneg(float); +# extern double ftrunc(double); +# int main() { +# if (fneg(1.23f) != -1.23f) return 1; +# if (ftrunc(3.1415) != 3.0) return 2; +# if (ftrunc(-1.234) != -1.0) return 3; +# return 0; +# } +# <<< diff --git a/test/go.sh b/test/go.sh new file mode 100755 index 0000000..7bc795f --- /dev/null +++ b/test/go.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +QBE=`readlink -f $0 | xargs dirname`/../src/qbe + +TMP=/tmp/qbe.zzzz + +DRV=$TMP.c +ASM=$TMP.s +BIN=$TMP.bin +OUT=$TMP.out + +cleanup() { + rm -f $DRV $ASM $BIN $OUT +} + +extract() { + WHAT="$1" + FILE="$2" + + awk " + /^# >>> $WHAT/ { + p = 1 + next + } + /^# <<</ { + if (p) + p = 0 + } + p + " $FILE \ + | sed -e 's/# //' \ + | sed -e 's/#$//' +} + +once() { + T="$1" + + if ! test -f $T + then + echo "invalid test file $T" >&2 + exit 1 + fi + + echo "$T... " + + if ! $QBE -o $ASM $T + then + echo "[qbe fail]" + return 1 + fi + + extract driver $T > $DRV + extract output $T > $OUT + + if test -s $DRV + then + LNK="$DRV $ASM" + else + LNK="$ASM" + fi + + if ! cc -g -o $BIN $LNK + then + echo "[cc fail]" + return 1 + fi + + if test -s $OUT + then + $BIN a b c | diff - $OUT + RET=$? + REASON="output" + else + $BIN a b c + RET=$? + REASON="returned $RET" + fi + + if test $RET -ne 0 + then + echo "[$REASON fail]" + return 1 + fi + + printf "\033[1A\033[45C[ok]\n" +} + + +#trap cleanup TERM QUIT + +if test -z "$1" +then + echo "usage: test/go.sh {all, SSAFILE}" 2>&1 + exit 1 +fi + +case $1 in + "all") + F=0 + for T in test/[!_]*.ssa + do + once $T + F=`expr $F + $?` + done + if test $F -ge 1 + then + echo + echo "$F test(s) failed!" + else + echo + echo "All is fine!" + fi + ;; + *) + once $1 + exit $? + ;; +esac diff --git a/test/loop.ssa b/test/loop.ssa new file mode 100644 index 0000000..c8c4ee0 --- /dev/null +++ b/test/loop.ssa @@ -0,0 +1,23 @@ +# simple looping program +# sums all integers from 100 to 0 + +function $test() { +@start + +@loop + %s =w phi @start 0, @loop %s1 + %n =w phi @start 100, @loop %n1 + %s1 =w add %s, %n + %n1 =w sub %n, 1 + jnz %n1, @loop, @end + +@end + storew %s1, $a + ret +} + +# >>> driver +# extern void test(void); +# int a; +# int main() { test(); return !(a == 5050); } +# <<< diff --git a/test/mandel.ssa b/test/mandel.ssa new file mode 100644 index 0000000..efefeb3 --- /dev/null +++ b/test/mandel.ssa @@ -0,0 +1,123 @@ +# Print the Mandelbrot set on the +# terminal line output. + +function w $mandel(d %x, d %y) { +@mandel + %cr =d sub %y, d_0.5 + %ci =d copy %x +@loop + %i =w phi @mandel 0, @loop1 %i1 + %zr =d phi @mandel d_0, @loop1 %zr1 + %zi =d phi @mandel d_0, @loop1 %zi1 + %i1 =w add 1, %i + %tmp =d mul %zr, %zi + %zr2 =d mul %zr, %zr + %zi2 =d mul %zi, %zi + %zrx =d sub %zr2, %zi2 + %zr1 =d add %zrx, %cr + %zix =d add %tmp, %tmp + %zi1 =d add %zix, %ci + %sum =d add %zi2, %zr2 + %cmp1 =w cgtd %sum, d_16 + jnz %cmp1, @reti, @loop1 +@loop1 + %cmp2 =w csgtw %i1, 1000 + jnz %cmp2, @ret0, @loop +@reti + ret %i1 +@ret0 + ret 0 +} + +function w $main() { +@main +@loopy + %y =d phi @main d_-1, @loopy1 %y1 +@loopx + %x =d phi @loopy d_-1, @loopx1 %x1 + %i =w call $mandel(d %x, d %y) + jnz %i, @out, @in +@in + %r0 =w call $putchar(w 42) # '*' + jmp @loopx1 +@out + %r1 =w call $putchar(w 32) # ' ' + jmp @loopx1 +@loopx1 + %x1 =d add %x, d_0.032 + %cmp1 =w cgtd %x1, d_1 + jnz %cmp1, @loopy1, @loopx +@loopy1 + %r2 =w call $putchar(w 10) # '\n' + %y1 =d add %y, d_0.032 + %cmp2 =w cgtd %y1, d_1 + jnz %cmp2, @ret, @loopy +@ret + ret 0 +} + +# >>> output +# # +# # +# # +# # +# * # +# **** # +# **** # +# *** # +# ***** # +# ********* # +# ************ # +# ***************** # +# **************** # +# *************** # +# **************** # +# **************** # +# ***************** # +# **************** # +# **************** # +# ************** # +# ************* # +# ************ # +# ********* # +# ***** # +# *********** # +# ***************** # +# ********************** # +# * *********************** ** # +# *************************** # +# ***************************** # +# * ******************************* ** # +# ** *********************************** # +# *********************************** * # +# *********************************** # +# ************************************* # +# ************************************* # +# *************************************** # +# *************************************** # +# *************************************** # +# **************************************** # +# * **************************************** # +# ********************************************** **** # +# **************************************************** # +# * ***************************************************** # +# * ***************************************************** # +# ***** **************************************** **** # +# * **************************************** * # +# **************************************** # +# *************************************** # +# **************************************** # +# *************************************** # +# **************************************** # +# ************************************ # +# *********************************** # +# ********************************* # +# ************************************ # +# *** ************* ************** *** # +# *********** ************ ** # +# ******** ******** # +# ** * * # +# # +# # +# # +# <<< diff --git a/test/max.ssa b/test/max.ssa new file mode 100644 index 0000000..547e9d4 --- /dev/null +++ b/test/max.ssa @@ -0,0 +1,33 @@ +# find the maximum value +# in a nul-terminated array +# of unsigned bytes +# +# the output is stored in $a + +data $arr = { b 10, b -60, b 10, b 100, b 200, b 0 } + +function $test() { +@start +@loop + %max =w phi @start -1, @new %byt, @old %max + %loc =l phi @start $arr, @new %loc1, @old %loc1 + %byt =w loadub %loc + %loc1 =l add 1, %loc + jnz %byt, @iter, @end +@iter + %cmp =w cslew %max, %byt + jnz %cmp, @new, @old +@new + jmp @loop +@old + jmp @loop +@end + storew %max, $a + ret +} + +# >>> driver +# extern void test(void); +# int a; +# int main() { test(); return !(a == 200); } +# <<< diff --git a/test/prime.ssa b/test/prime.ssa new file mode 100644 index 0000000..12d0273 --- /dev/null +++ b/test/prime.ssa @@ -0,0 +1,32 @@ +# find the 10,001st prime +# store it in a + +function $test() { +@start +@loop + %n =w phi @start 5, @tloop %n, @yes %n1 + %p =w phi @start 13, @tloop %p1, @yes %p1 + %p1 =w add %p, 2 +@tloop + %t =w phi @loop 3, @next %t1 + %r =w rem %p, %t + jnz %r, @next, @loop +@next + %t1 =w add 2, %t + %tsq =w mul %t1, %t1 + %c0 =w csgtw %tsq, %p + jnz %c0, @yes, @tloop +@yes + %n1 =w add 1, %n + %c1 =w ceqw 10001, %n1 + jnz %c1, @end, @loop +@end + storew %p, $a + ret +} + +# >>> driver +# extern void test(void); +# int a; +# int main() { test(); return !(a == 104743); } +# <<< diff --git a/test/puts10.ssa b/test/puts10.ssa new file mode 100644 index 0000000..1dcf227 --- /dev/null +++ b/test/puts10.ssa @@ -0,0 +1,29 @@ +function $main() { +@start + %y =l alloc4 4 + %y1 =l add %y, 1 + storeb 0, %y1 +@loop + %n =w phi @start 0, @loop %n1 + %c =w add %n, 48 + storeb %c, %y + %r =w call $puts(l %y) + %n1 =w add %n, 1 + %cmp =w cslew %n1, 9 + jnz %cmp, @loop, @end +@end + ret +} + +# >>> output +# 0 +# 1 +# 2 +# 3 +# 4 +# 5 +# 6 +# 7 +# 8 +# 9 +# <<< diff --git a/test/sum.ssa b/test/sum.ssa new file mode 100644 index 0000000..266054e --- /dev/null +++ b/test/sum.ssa @@ -0,0 +1,31 @@ +# Simple test for addressing modes. + +function w $sum(l %arr, w %num) { +@start +@loop + %n1 =w phi @start %num, @loop1 %n2 + %s0 =w phi @start 0, @loop1 %s1 + %n2 =w sub %n1, 1 + %c =w cslew %n1, 0 + jnz %c, @end, @loop1 +@loop1 + %idx0 =l extsw %n2 + %idx1 =l mul 4, %idx0 + %idx2 =l add %idx1, %arr + %w =w loadw %idx2 + %s1 =w add %w, %s0 + jmp @loop +@end + ret %s0 +} + +# >>> driver +# extern int sum(int *, int); +# int arr[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21 }; +# #define N sizeof arr / sizeof arr[0] +# int main() { +# int i, s; +# for (s=i=0; i<N; i++) s+=arr[i]; +# return !(sum(arr, N) == s); +# } +# <<< |