extract tests out of src
This commit is contained in:
parent
aad52241c8
commit
36635660b4
35 changed files with 10 additions and 3 deletions
25
test/_alt.ssa
Normal file
25
test/_alt.ssa
Normal file
|
@ -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
|
||||
}
|
33
test/_dragon.ssa
Normal file
33
test/_dragon.ssa
Normal file
|
@ -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
|
||||
}
|
15
test/_fix1.ssa
Normal file
15
test/_fix1.ssa
Normal file
|
@ -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
|
||||
}
|
15
test/_fix2.ssa
Normal file
15
test/_fix2.ssa
Normal file
|
@ -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
|
||||
}
|
20
test/_fix3.ssa
Normal file
20
test/_fix3.ssa
Normal file
|
@ -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
|
||||
}
|
27
test/_fix4.ssa
Normal file
27
test/_fix4.ssa
Normal file
|
@ -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
|
||||
}
|
21
test/_live.ssa
Normal file
21
test/_live.ssa
Normal file
|
@ -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
|
||||
}
|
12
test/_rpo.ssa
Normal file
12
test/_rpo.ssa
Normal file
|
@ -0,0 +1,12 @@
|
|||
function $test() {
|
||||
@start
|
||||
jmp @foo
|
||||
@baz
|
||||
jnz 1, @end, @foo
|
||||
@bar
|
||||
jmp @end
|
||||
@foo
|
||||
jnz 0, @bar, @baz
|
||||
@end
|
||||
ret
|
||||
}
|
22
test/_spill1.ssa
Normal file
22
test/_spill1.ssa
Normal file
|
@ -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
|
||||
}
|
22
test/_spill2.ssa
Normal file
22
test/_spill2.ssa
Normal file
|
@ -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
|
||||
}
|
24
test/_spill3.ssa
Normal file
24
test/_spill3.ssa
Normal file
|
@ -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
|
||||
}
|
59
test/abi1.ssa
Normal file
59
test/abi1.ssa
Normal file
|
@ -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
|
||||
# <<<
|
18
test/abi2.ssa
Normal file
18
test/abi2.ssa
Normal file
|
@ -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. */
|
||||
# <<<
|
43
test/abi3.ssa
Normal file
43
test/abi3.ssa
Normal file
|
@ -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
|
||||
# <<<
|
38
test/abi4.ssa
Normal file
38
test/abi4.ssa
Normal file
|
@ -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
|
||||
# <<<
|
105
test/abi5.ssa
Normal file
105
test/abi5.ssa
Normal file
|
@ -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
|
||||
# <<<
|
16
test/align.ssa
Normal file
16
test/align.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
61
test/collatz.ssa
Normal file
61
test/collatz.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
103
test/cprime.ssa
Normal file
103
test/cprime.ssa
Normal file
|
@ -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;
|
||||
# }
|
17
test/cup.ssa
Normal file
17
test/cup.ssa
Normal file
|
@ -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; }
|
||||
# <<<
|
30
test/dark.ssa
Normal file
30
test/dark.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
24
test/double.ssa
Normal file
24
test/double.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
32
test/echo.ssa
Normal file
32
test/echo.ssa
Normal file
|
@ -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
|
||||
# <<<
|
24
test/eucl.ssa
Normal file
24
test/eucl.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
29
test/euclc.ssa
Normal file
29
test/euclc.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
27
test/fpcnv.ssa
Normal file
27
test/fpcnv.ssa
Normal file
|
@ -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;
|
||||
# }
|
||||
# <<<
|
118
test/go.sh
Executable file
118
test/go.sh
Executable file
|
@ -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
|
23
test/loop.ssa
Normal file
23
test/loop.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
123
test/mandel.ssa
Normal file
123
test/mandel.ssa
Normal file
|
@ -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
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# * #
|
||||
# **** #
|
||||
# **** #
|
||||
# *** #
|
||||
# ***** #
|
||||
# ********* #
|
||||
# ************ #
|
||||
# ***************** #
|
||||
# **************** #
|
||||
# *************** #
|
||||
# **************** #
|
||||
# **************** #
|
||||
# ***************** #
|
||||
# **************** #
|
||||
# **************** #
|
||||
# ************** #
|
||||
# ************* #
|
||||
# ************ #
|
||||
# ********* #
|
||||
# ***** #
|
||||
# *********** #
|
||||
# ***************** #
|
||||
# ********************** #
|
||||
# * *********************** ** #
|
||||
# *************************** #
|
||||
# ***************************** #
|
||||
# * ******************************* ** #
|
||||
# ** *********************************** #
|
||||
# *********************************** * #
|
||||
# *********************************** #
|
||||
# ************************************* #
|
||||
# ************************************* #
|
||||
# *************************************** #
|
||||
# *************************************** #
|
||||
# *************************************** #
|
||||
# **************************************** #
|
||||
# * **************************************** #
|
||||
# ********************************************** **** #
|
||||
# **************************************************** #
|
||||
# * ***************************************************** #
|
||||
# * ***************************************************** #
|
||||
# ***** **************************************** **** #
|
||||
# * **************************************** * #
|
||||
# **************************************** #
|
||||
# *************************************** #
|
||||
# **************************************** #
|
||||
# *************************************** #
|
||||
# **************************************** #
|
||||
# ************************************ #
|
||||
# *********************************** #
|
||||
# ********************************* #
|
||||
# ************************************ #
|
||||
# *** ************* ************** *** #
|
||||
# *********** ************ ** #
|
||||
# ******** ******** #
|
||||
# ** * * #
|
||||
# #
|
||||
# #
|
||||
# #
|
||||
# <<<
|
33
test/max.ssa
Normal file
33
test/max.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
32
test/prime.ssa
Normal file
32
test/prime.ssa
Normal file
|
@ -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); }
|
||||
# <<<
|
29
test/puts10.ssa
Normal file
29
test/puts10.ssa
Normal file
|
@ -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
|
||||
# <<<
|
31
test/sum.ssa
Normal file
31
test/sum.ssa
Normal file
|
@ -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);
|
||||
# }
|
||||
# <<<
|
Loading…
Add table
Add a link
Reference in a new issue