This commit is contained in:
2026-06-11 10:59:54 -06:00
commit 8650a71f67
159 changed files with 78653 additions and 0 deletions

25
test/_alt.ssa Normal file
View 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
}

2687
test/_bf99.ssa Normal file

File diff suppressed because it is too large Load Diff

9079
test/_bfmandel.ssa Normal file

File diff suppressed because it is too large Load Diff

233
test/_chacha20.ssa Normal file
View File

@@ -0,0 +1,233 @@
export function $chacha20_rounds_qbe(l %out, l %in) {
@start
%t0 =w loadw %in
%in =l add %in, 4
%t1 =w loadw %in
%in =l add %in, 4
%t2 =w loadw %in
%in =l add %in, 4
%t3 =w loadw %in
%in =l add %in, 4
%t4 =w loadw %in
%in =l add %in, 4
%t5 =w loadw %in
%in =l add %in, 4
%t6 =w loadw %in
%in =l add %in, 4
%t7 =w loadw %in
%in =l add %in, 4
%t8 =w loadw %in
%in =l add %in, 4
%t9 =w loadw %in
%in =l add %in, 4
%t10 =w loadw %in
%in =l add %in, 4
%t11 =w loadw %in
%in =l add %in, 4
%t12 =w loadw %in
%in =l add %in, 4
%t13 =w loadw %in
%in =l add %in, 4
%t14 =w loadw %in
%in =l add %in, 4
%t15 =w loadw %in
%in =l add %in, 4
%counter =w copy 10
@loop
%t0 =w add %t0, %t4
%t12 =w xor %t12, %t0
%rotl32_a =w shl %t12, 16
%rotl32_b =w shr %t12, 16
%t12 =w xor %rotl32_a, %rotl32_b
%t8 =w add %t8, %t12
%t4 =w xor %t4, %t8
%rotl32_a =w shl %t4, 12
%rotl32_b =w shr %t4, 20
%t4 =w xor %rotl32_a, %rotl32_b
%t0 =w add %t0, %t4
%t12 =w xor %t12, %t0
%rotl32_a =w shl %t12, 8
%rotl32_b =w shr %t12, 24
%t12 =w xor %rotl32_a, %rotl32_b
%t8 =w add %t8, %t12
%t4 =w xor %t4, %t8
%rotl32_a =w shl %t4, 7
%rotl32_b =w shr %t4, 25
%t4 =w xor %rotl32_a, %rotl32_b
%t1 =w add %t1, %t5
%t13 =w xor %t13, %t1
%rotl32_a =w shl %t13, 16
%rotl32_b =w shr %t13, 16
%t13 =w xor %rotl32_a, %rotl32_b
%t9 =w add %t9, %t13
%t5 =w xor %t5, %t9
%rotl32_a =w shl %t5, 12
%rotl32_b =w shr %t5, 20
%t5 =w xor %rotl32_a, %rotl32_b
%t1 =w add %t1, %t5
%t13 =w xor %t13, %t1
%rotl32_a =w shl %t13, 8
%rotl32_b =w shr %t13, 24
%t13 =w xor %rotl32_a, %rotl32_b
%t9 =w add %t9, %t13
%t5 =w xor %t5, %t9
%rotl32_a =w shl %t5, 7
%rotl32_b =w shr %t5, 25
%t5 =w xor %rotl32_a, %rotl32_b
%t2 =w add %t2, %t6
%t14 =w xor %t14, %t2
%rotl32_a =w shl %t14, 16
%rotl32_b =w shr %t14, 16
%t14 =w xor %rotl32_a, %rotl32_b
%t10 =w add %t10, %t14
%t6 =w xor %t6, %t10
%rotl32_a =w shl %t6, 12
%rotl32_b =w shr %t6, 20
%t6 =w xor %rotl32_a, %rotl32_b
%t2 =w add %t2, %t6
%t14 =w xor %t14, %t2
%rotl32_a =w shl %t14, 8
%rotl32_b =w shr %t14, 24
%t14 =w xor %rotl32_a, %rotl32_b
%t10 =w add %t10, %t14
%t6 =w xor %t6, %t10
%rotl32_a =w shl %t6, 7
%rotl32_b =w shr %t6, 25
%t6 =w xor %rotl32_a, %rotl32_b
%t3 =w add %t3, %t7
%t15 =w xor %t15, %t3
%rotl32_a =w shl %t15, 16
%rotl32_b =w shr %t15, 16
%t15 =w xor %rotl32_a, %rotl32_b
%t11 =w add %t11, %t15
%t7 =w xor %t7, %t11
%rotl32_a =w shl %t7, 12
%rotl32_b =w shr %t7, 20
%t7 =w xor %rotl32_a, %rotl32_b
%t3 =w add %t3, %t7
%t15 =w xor %t15, %t3
%rotl32_a =w shl %t15, 8
%rotl32_b =w shr %t15, 24
%t15 =w xor %rotl32_a, %rotl32_b
%t11 =w add %t11, %t15
%t7 =w xor %t7, %t11
%rotl32_a =w shl %t7, 7
%rotl32_b =w shr %t7, 25
%t7 =w xor %rotl32_a, %rotl32_b
%t0 =w add %t0, %t5
%t15 =w xor %t15, %t0
%rotl32_a =w shl %t15, 16
%rotl32_b =w shr %t15, 16
%t15 =w xor %rotl32_a, %rotl32_b
%t10 =w add %t10, %t15
%t5 =w xor %t5, %t10
%rotl32_a =w shl %t5, 12
%rotl32_b =w shr %t5, 20
%t5 =w xor %rotl32_a, %rotl32_b
%t0 =w add %t0, %t5
%t15 =w xor %t15, %t0
%rotl32_a =w shl %t15, 8
%rotl32_b =w shr %t15, 24
%t15 =w xor %rotl32_a, %rotl32_b
%t10 =w add %t10, %t15
%t5 =w xor %t5, %t10
%rotl32_a =w shl %t5, 7
%rotl32_b =w shr %t5, 25
%t5 =w xor %rotl32_a, %rotl32_b
%t1 =w add %t1, %t6
%t12 =w xor %t12, %t1
%rotl32_a =w shl %t12, 16
%rotl32_b =w shr %t12, 16
%t12 =w xor %rotl32_a, %rotl32_b
%t11 =w add %t11, %t12
%t6 =w xor %t6, %t11
%rotl32_a =w shl %t6, 12
%rotl32_b =w shr %t6, 20
%t6 =w xor %rotl32_a, %rotl32_b
%t1 =w add %t1, %t6
%t12 =w xor %t12, %t1
%rotl32_a =w shl %t12, 8
%rotl32_b =w shr %t12, 24
%t12 =w xor %rotl32_a, %rotl32_b
%t11 =w add %t11, %t12
%t6 =w xor %t6, %t11
%rotl32_a =w shl %t6, 7
%rotl32_b =w shr %t6, 25
%t6 =w xor %rotl32_a, %rotl32_b
%t2 =w add %t2, %t7
%t13 =w xor %t13, %t2
%rotl32_a =w shl %t13, 16
%rotl32_b =w shr %t13, 16
%t13 =w xor %rotl32_a, %rotl32_b
%t8 =w add %t8, %t13
%t7 =w xor %t7, %t8
%rotl32_a =w shl %t7, 12
%rotl32_b =w shr %t7, 20
%t7 =w xor %rotl32_a, %rotl32_b
%t2 =w add %t2, %t7
%t13 =w xor %t13, %t2
%rotl32_a =w shl %t13, 8
%rotl32_b =w shr %t13, 24
%t13 =w xor %rotl32_a, %rotl32_b
%t8 =w add %t8, %t13
%t7 =w xor %t7, %t8
%rotl32_a =w shl %t7, 7
%rotl32_b =w shr %t7, 25
%t7 =w xor %rotl32_a, %rotl32_b
%t3 =w add %t3, %t4
%t14 =w xor %t14, %t3
%rotl32_a =w shl %t14, 16
%rotl32_b =w shr %t14, 16
%t14 =w xor %rotl32_a, %rotl32_b
%t9 =w add %t9, %t14
%t4 =w xor %t4, %t9
%rotl32_a =w shl %t4, 12
%rotl32_b =w shr %t4, 20
%t4 =w xor %rotl32_a, %rotl32_b
%t3 =w add %t3, %t4
%t14 =w xor %t14, %t3
%rotl32_a =w shl %t14, 8
%rotl32_b =w shr %t14, 24
%t14 =w xor %rotl32_a, %rotl32_b
%t9 =w add %t9, %t14
%t4 =w xor %t4, %t9
%rotl32_a =w shl %t4, 7
%rotl32_b =w shr %t4, 25
%t4 =w xor %rotl32_a, %rotl32_b
%counter =w sub %counter, 10
jnz %counter, @loop, @done
@done
storew %t0, %out
%out =l add %out, 4
storew %t1, %out
%out =l add %out, 4
storew %t2, %out
%out =l add %out, 4
storew %t3, %out
%out =l add %out, 4
storew %t4, %out
%out =l add %out, 4
storew %t5, %out
%out =l add %out, 4
storew %t6, %out
%out =l add %out, 4
storew %t7, %out
%out =l add %out, 4
storew %t8, %out
%out =l add %out, 4
storew %t9, %out
%out =l add %out, 4
storew %t10, %out
%out =l add %out, 4
storew %t11, %out
%out =l add %out, 4
storew %t12, %out
%out =l add %out, 4
storew %t13, %out
%out =l add %out, 4
storew %t14, %out
%out =l add %out, 4
storew %t15, %out
%out =l add %out, 4
ret
}

33
test/_dragon.ssa Normal file
View 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
View 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
View 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
View 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
View 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
}

48
test/_gcm1.ssa Normal file
View File

@@ -0,0 +1,48 @@
export
function w $ifmv(w %p1, w %p2, w %p3) {
@start
@entry
%rt =w add %p2, %p3 # gcm moves to @true
%rf =w sub %p2, %p3 # gcm moves to @false
jnz %p1, @true, @false
@true
%r =w copy %rt
jmp @exit
@false
%r =w copy %rf
jmp @exit
@exit
ret %r
}
export
function w $hoist1(w %p1, w %p2, w %p3) {
@start
@entry
%n =w copy 0
%i =w copy %p1
@loop
%base =w add %p2, %p3 # gcm moves to @exit
%i =w sub %i, 1
%n =w add %n, 1
jnz %i, @loop, @exit
@exit
%r =w add %base, %n
ret %r
}
export
function w $hoist2(w %p1, w %p2, w %p3) {
@start
@entry
%n =w copy 0
%i =w copy %p1
@loop
%base =w add %p2, %p3 # gcm moves to @entry
%i =w sub %i, 1
%n =w add %n, %base
jnz %i, @loop, @exit
@exit
%r =w add %base, %n
ret %r
}

43
test/_gcm2.ssa Normal file
View File

@@ -0,0 +1,43 @@
# Programs from "Global Code Motion Global Value Numbering" by Cliff Click
# https://courses.cs.washington.edu/courses/cse501/06wi/reading/click-pldi95.pdf
# GCM program in Figure 1
function w $gcm_test(w %a){
@start
%i.0 =w copy 0
@loop
%i.1 =w phi @start %i.0, @loop %i.2
%b =w add %a, 1 # early schedule moves to @start
%i.2 =w add %i.1, %b
%c =w mul %i.2, 2 # late schedule moves to @end
%x =w csltw %i.2, 10
jnz %x, @loop, @end
@end
ret %c
}
# GCM program in "Figure 3 x's definition does not dominate it's use"
#
# SSA contruction will insert phi instruction for "x" in @if_false
# preventing the "add" in @if_false from being moved to @if_true
function $gcm_test2 (w %a){
@start
%f =w copy 1
%x =w copy 0
%s.0 =w copy 0
@loop
%s.1 = w phi @start %s.0, @if_false %s.2
jnz %a, @if, @end
@if
jnz %f, @if_true, @if_false
@if_true
%f =w copy 0
%x =w add %x, 1
@if_false
%s.2 =w add %s.1, %x
jmp @loop
@end
ret
}

21
test/_live.ssa Normal file
View 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
}

17
test/_load-elim.ssa Normal file
View File

@@ -0,0 +1,17 @@
# GCM can eliminate unused add/load instructions
export
function w $f(l %p, w %c) {
@start
jnz %c, @true, @false
@true
%p1 =l add %p, 4
%v1 =w loaduw %p1
jmp @end
@false
%p2 =l add %p, 4
%v2 =w loaduw %p2
jmp @end
@end
ret 0
}

12
test/_rpo.ssa Normal file
View 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
}

35762
test/_slow.qbe Normal file

File diff suppressed because it is too large Load Diff

22
test/_spill1.ssa Normal file
View 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
View 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
View 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
}

60
test/abi1.ssa Normal file
View File

@@ -0,0 +1,60 @@
# 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
}
export
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
# <<<

19
test/abi2.ssa Normal file
View File

@@ -0,0 +1,19 @@
type :fps = { s, b, s }
export
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. */
# <<<

45
test/abi3.ssa Normal file
View File

@@ -0,0 +1,45 @@
type :four = {l, b, w}
data $z = { w 0 }
export
function $test() {
@start
%a =w loadw $z
%y =w add %a, %a
%yl =l extsw %y
%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, %yl
%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 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
# <<<

39
test/abi4.ssa Normal file
View File

@@ -0,0 +1,39 @@
# 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
}
export
function :mem $test() {
@ini
%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
# <<<

144
test/abi5.ssa Normal file
View File

@@ -0,0 +1,144 @@
# 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 }
type :un9 = { { b } { s } }
type :st9 = { w, :un9 }
type :sta = { b, s }
type :stb = { b, b, s }
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 }
data $fmt9 = { b "t9: %d %f\n", b 0 }
data $fmta = { b "ta: %d %f\n", b 0 }
data $fmtb = { b "tb: %d %d %f\n", b 0 }
export
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)
%r9 =:st9 call $t9()
%r94 =l add 4, %r9
%w9 =w loadw %r9
%s9 =s loads %r94
%d9 =d exts %s9
%i9 =w call $printf(l $fmt9, ..., w %w9, d %d9)
%ra =:sta call $ta()
%ra4 =l add 4, %ra
%wa =w loadsb %ra
%sa =s loads %ra4
%da =d exts %sa
%ia =w call $printf(l $fmta, ..., w %wa, d %da)
%rb =:stb call $tb()
%rb1 =l add 1, %rb
%rb4 =l add 4, %rb
%w0b =w loadsb %rb
%w1b =w loadsb %rb1
%sb =s loads %rb4
%db =d exts %sb
%ib =w call $printf(l $fmtb, ..., w %w0b, w %w1b, d %db)
ret
}
# >>> driver
# 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 long l; } st5;
# typedef struct { char t[16]; } st6;
# typedef struct { float f; double d; } st7;
# typedef struct { int i[4]; } st8;
# typedef struct { int i; union { char c; float f; } u; } st9;
# typedef struct { char c; float f; } sta;
# typedef struct { char c0, c1; float f; } stb;
# 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}; }
# st9 t9() { return (st9){9,{.f=9.9}}; }
# sta ta() { return (sta){-10,10.1}; }
# stb tb() { return (stb){-1,11,11.11}; }
# 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
# t9: 9 9.900000
# ta: -10 10.100000
# tb: -1 11 11.110000
# <<<

38
test/abi6.ssa Normal file
View File

@@ -0,0 +1,38 @@
# test arm64's hfa
data $dfmt = { b "double: %g\n", b 0 }
type :hfa3 = { s, s, s }
export
function $f(:hfa3 %h1, :hfa3 %h2, d %d1, :hfa3 %h3, d %d2) {
# the first three parameters should be in 7 registers
# the last two should be on the stack
@start
call $phfa3(:hfa3 %h1)
call $phfa3(:hfa3 %h2)
call $phfa3(:hfa3 %h3)
call $printf(l $dfmt, ..., d %d1)
call $printf(l $dfmt, ..., d %d2)
ret
}
# >>> driver
# #include <stdio.h>
# typedef struct { float f1, f2, f3; } hfa3;
# void f(hfa3, hfa3, double, hfa3, double);
# void phfa3(hfa3 h) { printf("{ %g, %g, %g }\n", h.f1, h.f2, h.f3); }
# int main() {
# hfa3 h1={1,2,3}, h2={2,3,4}, h3={3,4,5};
# f(h1, h2, 1, h3, 2);
# }
# <<<
# >>> output
# { 1, 2, 3 }
# { 2, 3, 4 }
# { 3, 4, 5 }
# double: 1
# double: 2
# <<<

21
test/abi7.ssa Normal file
View File

@@ -0,0 +1,21 @@
# test padding calculation with
# embedded struct
type :s1 = align 4 { w 3 }
type :s2 = align 4 { b 1, :s1 1 }
export function :s2 $test() {
@start
ret $s
}
# >>> driver
# struct s2 {
# char x;
# struct { int a[3]; } s1;
# } s = { .x = 123 };
# extern struct s2 test(void);
# int main(void) {
# return !(test().x == 123);
# }
# <<<

278
test/abi8.ssa Normal file
View File

@@ -0,0 +1,278 @@
# riscv64 ABI stress
# see tools/abi8.py
type :fi1 = { h, s } # in a gp & fp pair
type :fi2 = { s, w } # ditto
type :uw = { { w } }
type :fi3 = { s, :uw } # in a single gp reg
type :ss = { s, s } # in two fp regs
type :sd = { s, d } # ditto
type :ww = { w, w } # in a single gp reg
type :lb = { l, b } # in two gp regs
type :big = { b 17 } # by reference
type :ddd = { d, d, d} # big hfa on arm64
data $ctoqbestr = { b "c->qbe(%d)", b 0 }
data $emptystr = { b 0 }
export
function $qfn0(s %p0, s %p1, s %p2, s %p3, s %p4, s %p5, s %p6, s %p7, s %p8) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 0)
call $ps(s %p8)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn1(w %p0, s %p1, :fi1 %p2) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 1)
call $pw(w %p0)
call $ps(s %p1)
call $pfi1(l %p2)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn2(w %p0, :fi2 %p1, s %p2) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 2)
call $pw(w %p0)
call $pfi2(l %p1)
call $ps(s %p2)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn3(w %p0, s %p1, :fi3 %p2) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 3)
call $pw(w %p0)
call $ps(s %p1)
call $pfi3(l %p2)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn4(:ss %p0) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 4)
call $pss(l %p0)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn5(d %p0, d %p1, d %p2, d %p3, d %p4, d %p5, d %p6, :ss %p7, s %p8, l %p9) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 5)
call $pss(l %p7)
call $ps(s %p8)
call $pl(l %p9)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn6(:lb %p0) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 6)
call $plb(l %p0)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn7(w %p0, w %p1, w %p2, w %p3, w %p4, w %p5, w %p6, :lb %p7) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 7)
call $plb(l %p7)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn8(w %p0, w %p1, w %p2, w %p3, w %p4, w %p5, w %p6, w %p7, :lb %p8) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 8)
call $plb(l %p8)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn9(:big %p0) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 9)
call $pbig(l %p0)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn10(w %p0, w %p1, w %p2, w %p3, w %p4, w %p5, w %p6, w %p7, :big %p8, s %p9, l %p10) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 10)
call $pbig(l %p8)
call $ps(s %p9)
call $pl(l %p10)
%r1 =w call $puts(l $emptystr)
ret
}
export
function $qfn11(:ddd %p0) {
@start
%r0 =w call $printf(l $ctoqbestr, ..., w 11)
call $pddd(l %p0)
%r1 =w call $puts(l $emptystr)
ret
}
export
function w $main() {
@start
call $cfn0(s 0, s 0, s 0, s 0, s 0, s 0, s 0, s 0, s s_9.9)
call $cfn1(w 1, s s_2.2, :fi1 $fi1)
call $cfn2(w 1, :fi2 $fi2, s s_3.3)
call $cfn3(w 1, s s_2.2, :fi3 $fi3)
call $cfn4(:ss $ss)
call $cfn5(d 0, d 0, d 0, d 0, d 0, d 0, d 0, :ss $ss, s s_9.9, l 10)
call $cfn6(:lb $lb)
call $cfn7(w 0, w 0, w 0, w 0, w 0, w 0, w 0, :lb $lb)
call $cfn8(w 0, w 0, w 0, w 0, w 0, w 0, w 0, w 0, :lb $lb)
call $cfn9(:big $big)
call $cfn10(w 0, w 0, w 0, w 0, w 0, w 0, w 0, w 0, :big $big, s s_10.10, l 11)
call $cfn11(:ddd $ddd)
ret 0
}
# >>> driver
# #include <stdio.h>
# typedef struct { short h; float s; } Sfi1;
# typedef struct { float s; int w; } Sfi2;
# typedef struct { float s; union { int w; } u; } Sfi3;
# typedef struct { float s0, s1; } Sss;
# typedef struct { float s; double d; } Ssd;
# typedef struct { int w0, w1; } Sww;
# typedef struct { long long l; char b; } Slb;
# typedef struct { char b[17]; } Sbig;
# typedef struct { double d0, d1, d2; } Sddd;
# Sfi1 zfi1, fi1 = { -123, 4.56 };
# Sfi2 zfi2, fi2 = { 1.23, 456 };
# Sfi3 zfi3, fi3 = { 3.45, 567 };
# Sss zss, ss = { 1.23, 45.6 };
# Ssd zsd, sd = { 2.34, 5.67 };
# Sww zww, ww = { -123, -456 };
# Slb zlb, lb = { 123, 'z' };
# Sbig zbig, big = { "abcdefhijklmnopqr" };
# Sddd zddd, ddd = { 1.23, 45.6, 7.89 };
# void pfi1(Sfi1 *s) { printf(" { %d, %g }", s->h, s->s); }
# void pfi2(Sfi2 *s) { printf(" { %g, %d }", s->s, s->w); }
# void pfi3(Sfi3 *s) { printf(" { %g, %d }", s->s, s->u.w); }
# void pss(Sss *s) { printf(" { %g, %g }", s->s0, s->s1); }
# void psd(Ssd *s) { printf(" { %g, %g }", s->s, s->d); }
# void pww(Sww *s) { printf(" { %d, %d }", s->w0, s->w1); }
# void plb(Slb *s) { printf(" { %lld, '%c' }", s->l, s->b); }
# void pbig(Sbig *s) { printf(" \"%.17s\"", s->b); }
# void pddd(Sddd *s) { printf(" { %g, %g, %g }", s->d0, s->d1, s->d2); }
# void pw(int w) { printf(" %d", w); }
# void pl(long long l) { printf(" %lld", l); }
# void ps(float s) { printf(" %g", s); }
# void pd(double d) { printf(" %g", d); }
# /* --------------------------- */
# extern void qfn0(float, float, float, float, float, float, float, float, float);
# void cfn0(float p0, float p1, float p2, float p3, float p4, float p5, float p6, float p7, float p8) {
# printf("qbe->c(%d)", 0);
# ps(p8); puts("");
# qfn0(p0, p1, p2, p3, p4, p5, p6, p7, p8);
# }
# extern void qfn1(int, float, Sfi1);
# void cfn1(int p0, float p1, Sfi1 p2) {
# printf("qbe->c(%d)", 1);
# pw(p0); ps(p1); pfi1(&p2); puts("");
# qfn1(p0, p1, p2);
# }
# extern void qfn2(int, Sfi2, float);
# void cfn2(int p0, Sfi2 p1, float p2) {
# printf("qbe->c(%d)", 2);
# pw(p0); pfi2(&p1); ps(p2); puts("");
# qfn2(p0, p1, p2);
# }
# extern void qfn3(int, float, Sfi3);
# void cfn3(int p0, float p1, Sfi3 p2) {
# printf("qbe->c(%d)", 3);
# pw(p0); ps(p1); pfi3(&p2); puts("");
# qfn3(p0, p1, p2);
# }
# extern void qfn4(Sss);
# void cfn4(Sss p0) {
# printf("qbe->c(%d)", 4);
# pss(&p0); puts("");
# qfn4(p0);
# }
# extern void qfn5(double, double, double, double, double, double, double, Sss, float, long long);
# void cfn5(double p0, double p1, double p2, double p3, double p4, double p5, double p6, Sss p7, float p8, long long p9) {
# printf("qbe->c(%d)", 5);
# pss(&p7); ps(p8); pl(p9); puts("");
# qfn5(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
# }
# extern void qfn6(Slb);
# void cfn6(Slb p0) {
# printf("qbe->c(%d)", 6);
# plb(&p0); puts("");
# qfn6(p0);
# }
# extern void qfn7(int, int, int, int, int, int, int, Slb);
# void cfn7(int p0, int p1, int p2, int p3, int p4, int p5, int p6, Slb p7) {
# printf("qbe->c(%d)", 7);
# plb(&p7); puts("");
# qfn7(p0, p1, p2, p3, p4, p5, p6, p7);
# }
# extern void qfn8(int, int, int, int, int, int, int, int, Slb);
# void cfn8(int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7, Slb p8) {
# printf("qbe->c(%d)", 8);
# plb(&p8); puts("");
# qfn8(p0, p1, p2, p3, p4, p5, p6, p7, p8);
# }
# extern void qfn9(Sbig);
# void cfn9(Sbig p0) {
# printf("qbe->c(%d)", 9);
# pbig(&p0); puts("");
# qfn9(p0);
# }
# extern void qfn10(int, int, int, int, int, int, int, int, Sbig, float, long long);
# void cfn10(int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7, Sbig p8, float p9, long long p10) {
# printf("qbe->c(%d)", 10);
# pbig(&p8); ps(p9); pl(p10); puts("");
# qfn10(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
# }
# extern void qfn11(Sddd);
# void cfn11(Sddd p0) {
# printf("qbe->c(%d)", 11);
# pddd(&p0); puts("");
# qfn11(p0);
# }
# <<<
# >>> output
# qbe->c(0) 9.9
# c->qbe(0) 9.9
# qbe->c(1) 1 2.2 { -123, 4.56 }
# c->qbe(1) 1 2.2 { -123, 4.56 }
# qbe->c(2) 1 { 1.23, 456 } 3.3
# c->qbe(2) 1 { 1.23, 456 } 3.3
# qbe->c(3) 1 2.2 { 3.45, 567 }
# c->qbe(3) 1 2.2 { 3.45, 567 }
# qbe->c(4) { 1.23, 45.6 }
# c->qbe(4) { 1.23, 45.6 }
# qbe->c(5) { 1.23, 45.6 } 9.9 10
# c->qbe(5) { 1.23, 45.6 } 9.9 10
# qbe->c(6) { 123, 'z' }
# c->qbe(6) { 123, 'z' }
# qbe->c(7) { 123, 'z' }
# c->qbe(7) { 123, 'z' }
# qbe->c(8) { 123, 'z' }
# c->qbe(8) { 123, 'z' }
# qbe->c(9) "abcdefhijklmnopqr"
# c->qbe(9) "abcdefhijklmnopqr"
# qbe->c(10) "abcdefhijklmnopqr" 10.1 11
# c->qbe(10) "abcdefhijklmnopqr" 10.1 11
# qbe->c(11) { 1.23, 45.6, 7.89 }
# c->qbe(11) { 1.23, 45.6, 7.89 }
# <<<

20
test/abi9.ssa Normal file
View File

@@ -0,0 +1,20 @@
type :obj = { l, l, l, l }
export
function :obj $f(l %self) {
@_0
%_1 =l alloc8 16
storel 77, %_1
ret %_1
}
# >>> driver
# #include <stdio.h>
# typedef struct { long long a, b, c, d; } obj;
# extern obj f();
# int main() { obj ret = f(); printf("%lld\n", ret.a); return 0; }
# <<<
# >>> output
# 77
# <<<

21
test/alias1.ssa Normal file
View File

@@ -0,0 +1,21 @@
export function w $main() {
@start
%a =l alloc4 4
%b =l alloc4 4
storew 4, %a
storew 5, %b
@loop
# %mem will be %a and %b successively,
# but we do not know it when processing
# the phi because %b goes through a cpy
%mem =l phi @start %a, @loop %bcpy
%w =w load %mem
%eq5 =w ceqw %w, 5
%bcpy =l copy %b
jnz %eq5, @exit, @loop
@exit
ret 0
}

17
test/align.ssa Normal file
View File

@@ -0,0 +1,17 @@
export
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); }
# <<<

17
test/cmp1.ssa Normal file
View File

@@ -0,0 +1,17 @@
# test cmp used in jnz as well as its result value
export
function w $test(w %c) {
@start
%cmp =w cultw 1, %c
jnz %cmp, @yes, @no
@yes
%cmp =w copy 1
@no
ret %cmp
}
# >>> driver
# int test(int);
# int main(void) { return test(0); }
# <<<

62
test/collatz.ssa Normal file
View File

@@ -0,0 +1,62 @@
# a solution for N=1000 to
# https://projecteuler.net/problem=14
# we use a fast local array to
# memoize small collatz numbers
export
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 shr %n0, 1
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); }
# <<<

76
test/conaddr.ssa Normal file
View File

@@ -0,0 +1,76 @@
# skip amd64_win (no signals on win32)
# test amd64 addressing modes
export
function w $f0(l %o) {
@start
%addr =l add $a, %o
%char =w loadub %addr
ret %char
}
export
function w $f1(l %o) {
@start
%o1 =l mul %o, 1
%addr =l add 10, %o1
%char =w loadub %addr
ret %char
}
export
function w $f2(l %o1, l %o2) {
@start
%o22 =l mul %o2, 2
%o =l add %o1, %o22
%addr =l add $a, %o
%char =w loadub %addr
ret %char
}
export
function l $f3(l %o) {
@start
%addr =l add %o, $a
ret %addr
}
export
function $f4() {
@start
storel $p, $p
ret
}
export
function $writeto0() {
@start
storel 0, 0
ret
}
# >>> driver
# #include <stdlib.h>
# #include <signal.h>
# char a[] = "qbe rocks";
# void *p;
# int ok;
# extern unsigned f0(long), f1(long), f2(long, long);
# extern char *f3(long);
# extern void f4(), writeto0();
# void h(int sig, siginfo_t *si, void *unused) {
# ok += si->si_addr == 0;
# exit(!(ok == 6));
# }
# int main() {
# struct sigaction sa = {.sa_flags=SA_SIGINFO, .sa_sigaction=h};
# sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, 0);
# ok += f0(2) == 'e';
# ok += f1((long)a-5) == 'o';
# ok += f2(4, 2) == 's';
# ok += *f3(0) == 'q';
# f4();
# ok += p == &p;
# writeto0(); /* will segfault */
# }
# <<<

30
test/copy.ssa Normal file
View File

@@ -0,0 +1,30 @@
export function w $f() {
@start
%x0 =w loadsb $a
# the extension must not be eliminated
# even though the load already extended
%x1 =l extsb %x0
%c =w ceql %x1, -1
ret %c
}
export function w $g(w %arg) {
@start
%a0 =w extuh %arg # 1
%a1 =w or 65536, %a0 # 65537
@loop
%a2 =w phi @loop %a2, @start %a1 # 65537
jnz %arg, @end, @loop
@end
%a3 =w shr %a2, 1 # 32768
%a4 =w or %a2, 1 # 65537
%a5 =w or %a3, %a4 # 98305
%ret =w extuh %a5 # 32769
ret %ret
}
# >>> driver
# char a = -1;
# extern int f(), g(int);
# int main() { return !(f() == 1 && g(1) == 32769); }
# <<<

104
test/cprime.ssa Normal file
View File

@@ -0,0 +1,104 @@
# generated by Andrew Chambers'
# compiler from the C program
# following in comments
export
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;
# }

18
test/cup.ssa Normal file
View File

@@ -0,0 +1,18 @@
# counts up from -1988 to 1991
export
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; }
# <<<

32
test/dark.ssa Normal file
View File

@@ -0,0 +1,32 @@
# skip arm64 arm64_apple rv64 amd64_win
# a hack example,
# we use a dark type to get
# a pointer to the stack.
type :magic = align 1 { 0 }
data $ret = { l 0 }
export
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); }
# <<<

25
test/double.ssa Normal file
View File

@@ -0,0 +1,25 @@
export
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); }
# <<<

27
test/dynalloc.ssa Normal file
View File

@@ -0,0 +1,27 @@
# make sure dynamic allocations
# and caller-save regs interact
# soundly
function $g() {
@start
ret
}
function w $f(w %arg) {
@start
call $g()
@alloc
%r =l alloc8 16
storel 180388626474, %r
%r8 =l add 8, %r
storel 180388626474, %r8
ret %arg
}
export
function w $main() {
@start
%a =w call $f(w 0)
%b =w call $f(w 0)
ret %a
}

33
test/echo.ssa Normal file
View File

@@ -0,0 +1,33 @@
export
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
# <<<

21
test/env.ssa Normal file
View File

@@ -0,0 +1,21 @@
# sanity checks for env calls
function l $epar(env %e, l %i) {
@start
%x =l add %e, %i
ret %x
}
export function l $earg(l %a, l %b) {
@start
%r1 =l call $epar(env %a, l %b)
# okay to call a regular function
# with an env argument
%r2 =l call $labs(env 113, l %r1)
ret %r2
}
# >>> driver
# extern long earg(long, long);
# int main(void) { return !(earg(2, -44) == 42); }
# <<<

25
test/eucl.ssa Normal file
View File

@@ -0,0 +1,25 @@
# euclide's algorithm in ssa
# it is a fairly interesting
# ssa program because of the
# swap of b and a
export
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); }
# <<<

30
test/euclc.ssa Normal file
View File

@@ -0,0 +1,30 @@
export
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); }
# <<<

15
test/fixarg.ssa Normal file
View File

@@ -0,0 +1,15 @@
# regression test for 3bec2c60
export
function w $test() {
@start
%x1 =l alloc8 8
%x2 =l alloc8 8
%r =w cnel %x1, %x2 # both operands need fixing
ret %r
}
# >>> driver
# extern int test();
# int main() { return !(test() == 1); }
# <<<

47
test/fold1.ssa Normal file
View File

@@ -0,0 +1,47 @@
export
function w $f1() {
@start
%x =w sar 2147483648, 31
ret %x
}
export
function w $f2() {
@start
%x =w div 4294967040, 8 # -256 / 8
ret %x
}
export
function w $f3() {
@start
%x =w rem 4294967284, 7 # -12 % 7
ret %x
}
export
function w $f4() {
@start
%x =w shr 4294967296, 1 # 2^32 >> 1
ret %x
}
export
function w $f5() {
@start
%x =w udiv 1, 4294967297 # 1 / (2^32 + 1)
ret %x
}
export
function w $f6() {
@start
%x =w urem 4294967296, 7 # 2^32 % 7
ret %x
}
# >>> driver
# extern int f1(), f2(), f3(), f4(), f5(), f6();
# int main() { return !(f1() == -1 && f2() == -32 && f3() == -5 &&
# f4() == 0 && f5() == 1 && f6() == 0); }
# <<<

134
test/fpcnv.ssa Normal file
View File

@@ -0,0 +1,134 @@
# floating point casts and conversions
export
function s $fneg(s %f) {
@fneg
%b0 =w cast %f
%b1 =w xor 2147483648, %b0
%rs =s cast %b1
ret %rs
}
export
function d $ftrunc(d %f) {
@ftrunc
%l0 =w dtosi %f
%rt =d swtof %l0
ret %rt
}
export
function s $wtos(w %w) {
@start
%rt =s uwtof %w
ret %rt
}
export
function d $wtod(w %w) {
@start
%rt =d uwtof %w
ret %rt
}
export
function s $ltos(l %l) {
@start
%rt =s ultof %l
ret %rt
}
export
function d $ltod(l %l) {
@start
%rt =d ultof %l
ret %rt
}
export
function w $stow(s %f) {
@start
%rt =w stoui %f
ret %rt
}
export
function w $dtow(d %f) {
@start
%rt =w dtoui %f
ret %rt
}
export
function l $stol(s %f) {
@start
%rt =l stoui %f
ret %rt
}
export
function l $dtol(d %f) {
@start
%rt =l dtoui %f
ret %rt
}
# >>> driver
# #include <float.h>
# #include <limits.h>
#
# extern float fneg(float);
# extern double ftrunc(double);
#
# extern float wtos(unsigned int);
# extern double wtod(unsigned int);
# extern float ltos(long long unsigned int);
# extern double ltod(long long unsigned int);
#
# extern unsigned int stow(float);
# extern unsigned int dtow(double);
# extern unsigned long long stol(float);
# extern unsigned long long dtol(double);
#
# unsigned long long iin[] = { 0, 1, 16, 234987, 427386245, 0x7fff0000,
# 0xffff0000, 23602938196141, 72259248152500195, 9589010795705032704ull,
# 0xdcf5fbe299d0148aull, 0xffffffff00000000ull, -1 };
#
# double fin[] = { 0.17346516197824458, 442.0760005466251, 4342856.879893436,
# 4294967295.0, 98547543006.49626, 236003043787688.3, 9.499222733527032e+18,
# 1.1936266170755652e+19 };
#
# int main() {
# int i;
#
# if (fneg(1.23f) != -1.23f) return 1;
# if (ftrunc(3.1415) != 3.0) return 2;
# if (ftrunc(-1.234) != -1.0) return 3;
#
# for (i=0; i<sizeof(iin)/sizeof(iin[0]); i++) {
# if (wtos(iin[i]) != (float) (unsigned int)iin[i])
# return 4;
# if (wtod(iin[i]) != (double)(unsigned int)iin[i])
# return 5;
# if (ltos(iin[i]) != (float) iin[i])
# return 6;
# if (ltod(iin[i]) != (double)iin[i])
# return 7;
# }
# for (i=0; i<sizeof(fin)/sizeof(fin[0]); i++) {
# if (fin[i] >= 1LL << DBL_MANT_DIG)
# break;
# if (dtol(fin[i]) != (unsigned long long)fin[i])
# return 8;
# if((unsigned long long)fin[i] > UINT_MAX)
# continue;
# if (dtow(fin[i]) != (unsigned int)fin[i])
# return 9;
# if (fin[i] >= 1LL << FLT_MANT_DIG)
# continue;
# if (stol((float)fin[i]) != (unsigned long long)(float)fin[i])
# return 10;
# if (stow((float)fin[i]) != (unsigned int)(float)fin[i])
# return 11;
# }
# return 0;
# }
# <<<

19
test/gvn1.ssa Normal file
View File

@@ -0,0 +1,19 @@
export
function w $test(w %p1, w %p2) {
@start
@entry
%t1 =w copy 1
jnz %t1, @live, @dead1
@live
%t2 =w add %p1, %p2
ret %t2
@dead1
%t2 =w add %p1, %p2 # live ins in dead blk
@dead2
jnz %t1, @live, @dead1
}
# >>> driver
# extern int test(int p1, int p2);
# int main() { return test(1, 2) != 3; }
# <<<

31
test/gvn2.ssa Normal file
View File

@@ -0,0 +1,31 @@
# GVN 0/non-0 inference removes @yesyes, @yesno, @noyes, @nono
export
function w $test(w %c) {
@start
jnz %c, @yes, @no
@yes
%c0 =w cnew %c, 0
jnz %c0, @yesyes, @yesno
@yesyes
%rc =w copy 1
jmp @end
@yesno
%rc =w copy 111
jmp @end
@no
%c1 =w cnew %c, 0
jnz %c1, @noyes, @nono
@noyes
%rc =w copy 222
jmp @end
@nono
%rc =w copy 0
@end
ret %rc
}
# >>> driver
# int test(int);
# int main(void) { return test(0); }
# <<<

238
test/ifc.ssa Normal file
View File

@@ -0,0 +1,238 @@
export
function l $ifc1(l %v0, l %v1, w %c) {
@start
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifc2(l %v0, l %v1, w %p) {
@start
%c =w cnew %p, 42
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifc3(l %v0, l %v1, w %p) {
@start
%c =w cugtw %p, 42
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifclts(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w clts %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifcles(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w cles %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifcgts(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w cgts %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifcges(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w cges %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifceqs(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w ceqs %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifcnes(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w cnes %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifcos(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w cos %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
export
function l $ifcuos(s %s0, s %s1, l %v0, l %v1) {
@start
%c =w cuos %s0, %s1
jnz %c, @true, @false
@true
%v =l copy %v1
jmp @end
@false
%v =l copy %v0
jmp @end
@end
ret %v
}
# >>> driver
# extern long ifc1(long, long, int);
# extern long ifc2(long, long, int);
# extern long ifc3(long, long, int);
# extern long ifclts(float, float, long, long);
# extern long ifcles(float, float, long, long);
# extern long ifcgts(float, float, long, long);
# extern long ifcges(float, float, long, long);
# extern long ifceqs(float, float, long, long);
# extern long ifcnes(float, float, long, long);
# extern long ifcos(float, float, long, long);
# extern long ifcuos(float, float, long, long);
# int main() {
# return
# ifc1(7, 5, 0) != 7
# || ifc1(7, 5, 1) != 5
# || ifc1(7, 5, 33) != 5
# || ifc2(7, 5, 42) != 7
# || ifc2(7, 5, 41) != 5
# || ifc2(7, 5, 43) != 5
# || ifc3(7, 5, 42) != 7
# || ifc3(7, 5, 41) != 7
# || ifc3(7, 5, 43) != 5
# || ifclts(5.0f, 6.0f, 7, 5) != 5
# || ifclts(5.0f, 5.0f, 7, 5) != 7
# || ifclts(5.0f, 4.0f, 7, 5) != 7
# || ifclts(5.0f, 0.0f/0.0f, 7, 5) != 7
# || ifclts(0.0f/0.0f, 5.0f, 7, 5) != 7
# || ifclts(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcles(5.0f, 6.0f, 7, 5) != 5
# || ifcles(5.0f, 5.0f, 7, 5) != 5
# || ifcles(5.0f, 4.0f, 7, 5) != 7
# || ifcles(5.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcles(0.0f/0.0f, 5.0f, 7, 5) != 7
# || ifcles(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcgts(5.0f, 6.0f, 7, 5) != 7
# || ifcgts(5.0f, 5.0f, 7, 5) != 7
# || ifcgts(5.0f, 4.0f, 7, 5) != 5
# || ifcgts(5.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcgts(0.0f/0.0f, 5.0f, 7, 5) != 7
# || ifcgts(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcges(5.0f, 6.0f, 7, 5) != 7
# || ifcges(5.0f, 5.0f, 7, 5) != 5
# || ifcges(5.0f, 4.0f, 7, 5) != 5
# || ifcges(5.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcges(0.0f/0.0f, 5.0f, 7, 5) != 7
# || ifcges(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 7
# || ifceqs(5.0f, 6.0f, 7, 5) != 7
# || ifceqs(5.0f, 5.0f, 7, 5) != 5
# || ifceqs(5.0f, 4.0f, 7, 5) != 7
# || ifceqs(5.0f, 0.0f/0.0f, 7, 5) != 7
# || ifceqs(0.0f/0.0f, 5.0f, 7, 5) != 7
# || ifceqs(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcnes(5.0f, 6.0f, 7, 5) != 5
# || ifcnes(5.0f, 5.0f, 7, 5) != 7
# || ifcnes(5.0f, 4.0f, 7, 5) != 5
# || ifcnes(5.0f, 0.0f/0.0f, 7, 5) != 5
# || ifcnes(0.0f/0.0f, 5.0f, 7, 5) != 5
# || ifcnes(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 5
# || ifcos(5.0f, 6.0f, 7, 5) != 5
# || ifcos(5.0f, 5.0f, 7, 5) != 5
# || ifcos(5.0f, 4.0f, 7, 5) != 5
# || ifcos(5.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcos(0.0f/0.0f, 5.0f, 7, 5) != 7
# || ifcos(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 7
# || ifcuos(5.0f, 6.0f, 7, 5) != 7
# || ifcuos(5.0f, 5.0f, 7, 5) != 7
# || ifcuos(5.0f, 4.0f, 7, 5) != 7
# || ifcuos(5.0f, 0.0f/0.0f, 7, 5) != 5
# || ifcuos(0.0f/0.0f, 5.0f, 7, 5) != 5
# || ifcuos(0.0f/0.0f, 0.0f/0.0f, 7, 5) != 5
# ;
# }
# <<<

24
test/isel1.ssa Normal file
View File

@@ -0,0 +1,24 @@
# tests that the address matcher is not
# confused by the two multiplications
# note: the code handling apple asm fixes
# ruins the good work of the matcher here,
# I should revisit these fixes
export function w $f(l %i, l %j) {
@start
%off1 =l mul %i, 8
%a_i =l add $a, %off1
%off2 =l mul %j, 4
%a_ij =l add %a_i, %off2
%x =w loadsw %a_ij
ret %x
}
# >>> driver
# int a[] = {1, 2, 3, 4};
# extern int f(long long, long long);
# int main() {
# return !(f(0, 0) == 1 && f(0, 1) == 2 && f(1, 0) == 3 && f(1, 1) == 4);
# }
# <<<

122
test/isel2.ssa Normal file
View File

@@ -0,0 +1,122 @@
# tests that NaN is handled properly by
# floating point comparisons
export function w $lt(d %x, d %y) {
@start
%r =w cltd %x, %y
ret %r
}
export function w $le(d %x, d %y) {
@start
%r =w cled %x, %y
ret %r
}
export function w $gt(d %x, d %y) {
@start
%r =w cgtd %x, %y
ret %r
}
export function w $ge(d %x, d %y) {
@start
%r =w cged %x, %y
ret %r
}
export function w $eq1(d %x, d %y) {
@start
%r =w ceqd %x, %y
ret %r
}
export function w $eq2(d %x, d %y) {
@start
%r =w ceqd %x, %y
jnz %r, @true, @false
@true
ret 1
@false
ret 0
}
export function w $eq3(d %x, d %y) {
@start
%r =w ceqd %x, %y
jnz %r, @true, @false
@true
ret %r
@false
ret 0
}
export function w $ne1(d %x, d %y) {
@start
%r =w cned %x, %y
ret %r
}
export function w $ne2(d %x, d %y) {
@start
%r =w cned %x, %y
jnz %r, @true, @false
@true
ret 1
@false
ret 0
}
export function w $ne3(d %x, d %y) {
@start
%r =w cned %x, %y
jnz %r, @true, @false
@true
ret %r
@false
ret 0
}
export function w $o(d %x, d %y) {
@start
%r =w cod %x, %y
ret %r
}
export function w $uo(d %x, d %y) {
@start
%r =w cuod %x, %y
ret %r
}
# >>> driver
# #include <math.h>
# extern int lt(double, double);
# extern int le(double, double);
# extern int gt(double, double);
# extern int ge(double, double);
# extern int eq1(double, double);
# extern int eq2(double, double);
# extern int eq3(double, double);
# extern int ne1(double, double);
# extern int ne2(double, double);
# extern int ne3(double, double);
# extern int o(double, double);
# extern int uo(double, double);
# int main(void) {
# /* LessThan Equal GreaterThan Unordered */
# return !lt(0, 1) + lt(0, 0) + lt(1, 0) + lt(NAN, NAN)
# + !le(0, 1) + !le(0, 0) + le(1, 0) + le(NAN, NAN)
# + gt(0, 1) + gt(0, 0) + !gt(1, 0) + gt(NAN, NAN)
# + ge(0, 1) + !ge(0, 0) + !ge(1, 0) + ge(NAN, NAN)
# + eq1(0, 1) + !eq1(0, 0) + eq1(1, 0) + eq1(NAN, NAN)
# + eq2(0, 1) + !eq2(0, 0) + eq2(1, 0) + eq2(NAN, NAN)
# + eq3(0, 1) + !eq3(0, 0) + eq3(1, 0) + eq3(NAN, NAN)
# + !ne1(0, 1) + ne1(0, 0) + !ne1(1, 0) + !ne1(NAN, NAN)
# + !ne2(0, 1) + ne2(0, 0) + !ne2(1, 0) + !ne2(NAN, NAN)
# + !ne3(0, 1) + ne3(0, 0) + !ne3(1, 0) + !ne3(NAN, NAN)
# + !o(0, 1) + !o(0, 0) + !o(1, 0) + o(NAN, NAN)
# + uo(0, 1) + uo(0, 0) + uo(1, 0) + !uo(NAN, NAN)
# ;
# }
# <<<

87
test/isel3.ssa Normal file
View File

@@ -0,0 +1,87 @@
export function w $slt(w %x, w %y) {
@start
%r =w csltw %x, %y
ret %r
}
export function w $sle(w %x, w %y) {
@start
%r =w cslew %x, %y
ret %r
}
export function w $sgt(w %x, w %y) {
@start
%r =w csgtw %x, %y
ret %r
}
export function w $sge(w %x, w %y) {
@start
%r =w csgew %x, %y
ret %r
}
export function w $ult(w %x, w %y) {
@start
%r =w cultw %x, %y
ret %r
}
export function w $ule(w %x, w %y) {
@start
%r =w culew %x, %y
ret %r
}
export function w $ugt(w %x, w %y) {
@start
%r =w cugtw %x, %y
ret %r
}
export function w $uge(w %x, w %y) {
@start
%r =w cugew %x, %y
ret %r
}
export function w $eq(w %x, w %y) {
@start
%r =w ceqw %x, %y
ret %r
}
export function w $ne(w %x, w %y) {
@start
%r =w cnew %x, %y
ret %r
}
# >>> driver
# #include <math.h>
# extern int slt(int, int);
# extern int sle(int, int);
# extern int sgt(int, int);
# extern int sge(int, int);
# extern int ult(unsigned, unsigned);
# extern int ule(unsigned, unsigned);
# extern int ugt(unsigned, unsigned);
# extern int uge(unsigned, unsigned);
# extern int eq(unsigned, unsigned);
# extern int ne(unsigned, unsigned);
# int main(void) {
# /* LessThan Equal GreaterThan */
# return !slt(-1, 0) + slt(0, 0) + slt(0, -1)
# + !sle(-1, 0) + !sle(0, 0) + sle(0, -1)
# + sgt(-1, 0) + sgt(0, 0) + !sgt(0, -1)
# + sge(-1, 0) + !sge(0, 0) + !sge(0, -1)
# + !ult(0, -1) + ult(0, 0) + ult(-1, 0)
# + !ule(0, -1) + !ule(0, 0) + ule(-1, 0)
# + ugt(0, -1) + ugt(0, 0) + !ugt(-1, 0)
# + uge(0, -1) + !uge(0, 0) + !uge(-1, 0)
# + eq(0, 1) + !eq(0, 0) + eq(1, 0)
# + !ne(0, 1) + ne(0, 0) + !ne(1, 0)
# ;
# }
# <<<

64
test/isel4.ssa Normal file
View File

@@ -0,0 +1,64 @@
# amd64 address-folding stress
export function w $f0(l %a, l %b) {
@start
%c =l add %b, 2
%d =l mul %c, 4
%e =l add %a, %d
%q =l loadw %e
ret %q
}
export function w $f1(l %a, l %b) {
@start
%c =l add 1, %b
%f =l add %c, 1
%d =l mul %f, 4
%e =l add %d, %a
%q =l loadw %e
ret %q
}
export function w $f2(l %a, l %b) {
@start
%l =l mul %b, 4
%d =l add 8, %l
%e =l add %a, %d
%q =l loadw %e
ret %q
}
# fixme: folding is not good here
export function w $f3(l %a, l %b) {
@start
%l =l mul %b, 4
%d =l add 4, %l
%f =l add 4, %d
%e =l add %a, %f
%q =l loadw %e
ret %q
}
export function w $f4(l %a, l %b) {
@start
%c =l add 1, %b
%d =l mul %c, 4
%e =l add 4, %d
%f =l add %e, %a
%q =l loadw %f
ret %q
}
# >>> driver
# int a[] = {1, 2, 3, 4};
# typedef int loadf(int *, long long);
# extern loadf f0, f1, f2, f3, f4;
# loadf *fns[] = {&f0, &f1, &f2, &f3, &f4, 0};
# int main() {
# loadf **f;
# int n;
# for (n=1,f=fns; *f; f++,n++)
# if ((*f)(a, 1) != 4) return n;
# return 0;
# }
# <<<

16
test/isel5.ssa Normal file
View File

@@ -0,0 +1,16 @@
# make sure the local symbols used for
# fp constants do not get a _ prefix
# on apple arm hardware
export function w $main() {
@start
%r =d copy d_1.2
%x =w call $printf(l $fmt, ..., d %r)
ret 0
}
data $fmt = { b "%.06f\n", b 0 }
# >>> output
# 1.200000
# <<<

38
test/isel6.ssa Normal file
View File

@@ -0,0 +1,38 @@
# make sure large consts are lowered
# without an offset
# i.e. not movq $9223372036854775807, 64(%rax)
export function w $main() {
@_0
%_1 =w call $myfunc(l 1, l 2, l 3, l 4, l 5, l 6, l 7, l 8, l 9223372036854775807)
ret 0
}
# >>> driver
# #include <stdio.h>
# #include <stdint.h>
# #include <inttypes.h>
# void myfunc(int64_t a, int64_t b, int64_t c, int64_t d, int64_t e, int64_t f, int64_t g, int64_t h, int64_t i) {
# printf("%" PRId64 "\n", a);
# printf("%" PRId64 "\n", b);
# printf("%" PRId64 "\n", c);
# printf("%" PRId64 "\n", d);
# printf("%" PRId64 "\n", e);
# printf("%" PRId64 "\n", f);
# printf("%" PRId64 "\n", g);
# printf("%" PRId64 "\n", h);
# printf("%" PRId64 "\n", i);
# }
# <<<
# >>> output
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9223372036854775807
# <<<

40
test/ldbits.ssa Normal file
View File

@@ -0,0 +1,40 @@
# unit tests for load elimination
export
function $tests() {
@start
%p =l alloc8 16
%p3 =l add %p, 3
%p4 =l add %p, 4
%p6 =l add %p, 6
%p8 =l add %p, 8
@test1
storew 1, $a
storel 1311768467139281697, %p
storeh 255, %p8
%x1 =w load %p6
%c1 =w cnew %x1, 16716340
jnz %c1, @fail, @test2
@test2
storew 2, $a
%x2 =w loadub %p3
%c2 =w cnew %x2, 135
jnz %c2, @fail, @test3
@test3
storew 3, $a
storew 2864434397, %p8
%x3 =l load %p3
%c3 =w cnel %x3, -4914310023110821753
jnz %c3, @fail, @test4
@test4
@ok
storew 0, $a
@fail
ret
}
# >>> driver
# extern void tests(void);
# int a;
# int main() { tests(); return a; }
# <<<

21
test/ldhoist.ssa Normal file
View File

@@ -0,0 +1,21 @@
# loads must not be unsafely hoisted
export
function w $f(w %n, l %p) {
@start
%r =w copy 0
@loop
%n =w sub %n, 1
%c =w csgew %n, 0
jnz %c, @loop1, @end
@loop1
%r =w loadw %p
jmp @loop
@end
ret %r
}
# >>> driver
# extern int f(int, int *);
# int main() { return f(0, 0); }
# <<<

27
test/load1.ssa Normal file
View File

@@ -0,0 +1,27 @@
# checks that phi arguments are correctly
# handled in alias analysis
export
function w $f(w %cond) {
@start
%x =l alloc4 4
%y =l alloc4 4
storew 0, %x
jnz %cond, @true, @false
@true
jmp @end
@false
jmp @end
@end
%ptr =l phi @true %x, @false %y
storew 1, %ptr
%result =w loadsw %x
ret %result
}
# >>> driver
# extern int f(int);
# int main() {
# return !(f(0) == 0 && f(1) == 1);
# }
# <<<

75
test/load2.ssa Normal file
View File

@@ -0,0 +1,75 @@
# blit & load elimination
export
function $f() {
@start
%x =l alloc4 12
%y =l alloc4 12
%x1 =l add 1, %x
%x2 =l add 1, %x1
%x3 =l add 1, %x2
%x4 =l add 1, %x3
%x5 =l add 1, %x4
%x6 =l add 1, %x5
%x7 =l add 1, %x6
%x8 =l add 1, %x7
%x9 =l add 1, %x8
%xa =l add 1, %x9
%xb =l add 1, %xa
%y1 =l add 1, %y
%y4 =l add 4, %y
storew 287454020, %x4 # 0x11223344
storew 1432778632, %y # 0x55667788
blit %y, %x5, 1
%n =w load %x4
call $px(w %n) # 0x11228844
storew 287454020, %x4 # 0x11223344
storew 1432778632, %y # 0x55667788
blit %y, %x5, 2
%n =w load %x4
call $px(w %n) # 0x11778844
storew 287454020, %x4 # 0x11223344
storew 1432778632, %y # 0x55667788
blit %y, %x5, 4
%n =w load %x4
call $px(w %n) # 0x66778844
storew 287454020, %x4 # 0x11223344
storew 1432778632, %y # 0x55667788
blit %y, %x2, 4
%n =w load %x4
call $px(w %n) # 0x11225566
storew 287454020, %x4 # 0x11223344
storew 0, %y
storew 1432778632, %y4 # 0x55667788
blit %y1, %x2, 7
%n =w load %x4
call $px(w %n) # 0x66778800
ret
}
# >>> driver
# #include <stdio.h>
# void px(unsigned n) {
# printf("0x%08x\n", n);
# }
# int main() {
# extern void f(void);
# f();
# }
# <<<
# >>> output
# 0x11228844
# 0x11778844
# 0x66778844
# 0x11225566
# 0x66778800
# <<<

50
test/load3.ssa Normal file
View File

@@ -0,0 +1,50 @@
# regression test for load()
# see comment below
function w $rand() {
@start
ret 0
}
function w $chk(w %a, w %b) {
@start
%ok =w ceqw %a, 1
%ok1 =w ceqw %b, 0
%ok2 =w and %ok, %ok1
%ret =w xor %ok2, 1
ret %ret
}
export
function w $main() {
@start
%s0 =l alloc4 8
%s1 =l alloc4 8
storew 1, %s0
%s04 =l add 4, %s0
storew 0, %s04
%rnd =w call $rand()
jnz %rnd, @tt, @ff
@tt
jmp @blit
@ff
jmp @blit
@blit
# we make sure def() checks
# offsets correctly when
# processing inserted phis;
# if not, %w1 will bogusly
# have the same value as %w0
blit %s0, %s1, 8
%w0 =w load %s1
%s14 =l add 4, %s1
%w1 =w load %s14
%ret =w call $chk(w %w0, w %w1)
ret %ret
}

24
test/loop.ssa Normal file
View File

@@ -0,0 +1,24 @@
# simple looping program
# sums all integers from 100 to 0
export
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); }
# <<<

124
test/mandel.ssa Normal file
View File

@@ -0,0 +1,124 @@
# 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
}
export
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
# #
# #
# #
# #
# * #
# **** #
# **** #
# *** #
# ***** #
# ********* #
# ************ #
# ***************** #
# **************** #
# *************** #
# **************** #
# **************** #
# ***************** #
# **************** #
# **************** #
# ************** #
# ************* #
# ************ #
# ********* #
# ***** #
# *********** #
# ***************** #
# ********************** #
# * *********************** ** #
# *************************** #
# ***************************** #
# * ******************************* ** #
# ** *********************************** #
# *********************************** * #
# *********************************** #
# ************************************* #
# ************************************* #
# *************************************** #
# *************************************** #
# *************************************** #
# **************************************** #
# * **************************************** #
# ********************************************** **** #
# **************************************************** #
# * ***************************************************** #
# * ***************************************************** #
# ***** **************************************** **** #
# * **************************************** * #
# **************************************** #
# *************************************** #
# **************************************** #
# *************************************** #
# **************************************** #
# ************************************ #
# *********************************** #
# ********************************* #
# ************************************ #
# *** ************* ************** *** #
# *********** ************ ** #
# ******** ******** #
# ** * * #
# #
# #
# #
# <<<

34
test/max.ssa Normal file
View File

@@ -0,0 +1,34 @@
# 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 }
export
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); }
# <<<

35
test/mem1.ssa Normal file
View File

@@ -0,0 +1,35 @@
type :i3 = { w 3 }
export
function :i3 $blit() {
@start
%l0 =l alloc4 12
%l1 =l alloc4 12
storew 287454020, %l0
%l04 =l add %l0, 4
storew 1432778632, %l04
%l08 =l add %l0, 8
storew 2578103244, %l08
# we expect that %l0 and %l1
# are coalesced and the blit
# goes backwards
%l11 =l add %l1, 1
blit %l0, %l11, 11
storeb 221, %l1
ret %l1
}
# >>> driver
# struct i3 { int a, b, c; };
# extern struct i3 blit();
# int main() {
# struct i3 s = blit();
# return !(s.a == 0x223344dd
# && s.b == 0x66778811
# && s.c == 0xaabbcc55);
# }
# <<<

32
test/mem2.ssa Normal file
View File

@@ -0,0 +1,32 @@
# Ember Sawady reported this bug
# in stack-slot coalescing
type :t = { w 2 }
function :t $func() {
@start.0
%temp =l alloc4 4
%ret =l alloc4 8
storew 1, %temp
# storew can also go here
%field =l add %ret, 4
storew 2, %ret
blit %temp, %field, 4
# removing either of these storews causes it to work
storew 2, %ret
ret %ret
}
export function w $main() {
@start
%ret =:t call $func()
%fptr =l add %ret, 4
%field =w loaduw %fptr
%x =w ceqw %field, 1
jnz %x, @passed, @failed
@failed
# this fails despite 1 => temp => ret + 4 => field
call $abort()
@passed
ret 0
}

48
test/mem3.ssa Normal file
View File

@@ -0,0 +1,48 @@
# Ember Sawady reported this bug
# in stack-slot coalescing
type :type.3 = align 8 { l 1, l 1 }
type :tags.2 = { { :type.3 1 } }
type :type.1 = align 8 { w 1, :tags.2 1 }
type :tags.9 = { { w 1 } }
type :type.8 = align 4 { w 1, :tags.9 1 }
function :type.1 $func() {
@start.0
%object.5 =l alloc8 24
%object.7 =l alloc4 8
%binding.21 =l alloc8 16
%object.23 =l alloc8 24
@body.4
%.10 =l add %object.7, 4
jnz 1, @matches.13, @next.14
@matches.13
# binding.21 gets fused with object.23
storel 1, %binding.21
%value.22 =l add %binding.21, 8
storel 2, %value.22
%.24 =l add %object.23, 8
# but the blit direction is not set correctly
blit %binding.21, %.24, 16
ret %object.23
@next.14
storew 2543892678, %object.5
ret %object.5
}
export function w $main() {
@start.27
%object.43 =l alloc8 24
%object.49 =l alloc8 24
@body.28
%returns.34 =:type.1 call $func()
%value.47 =l add %returns.34, 16
%load.48 =l loadl %value.47
%.33 =w ceql %load.48, 2
jnz %.33, @passed.32, @failed.31
@failed.31
call $abort()
@passed.32
ret 0
}

34
test/philv.ssa Normal file
View File

@@ -0,0 +1,34 @@
# regression test for 1f4ff634
# warning! headaches can occur
# when trying to figure out what
# the test is doing!
export
function w $t0() {
@start
@loop
%x0 =w phi @start 256, @loop %y0
%y0 =w phi @start 128, @loop %y1
%y1 =w shr %x0, 1
jnz %y1, @loop, @end
@end
ret %x0
}
export
function w $t1() { # swapped phis
@start
@loop
%y0 =w phi @start 128, @loop %y1
%x0 =w phi @start 256, @loop %y0
%y1 =w shr %x0, 1
jnz %y1, @loop, @end
@end
ret %x0
}
# >>> driver
# extern int t0(void), t1(void);
# int main() { return !(t0() == 1 && t1() == 1);}
# <<<

33
test/prime.ssa Normal file
View File

@@ -0,0 +1,33 @@
# find the 10,001st prime
# store it in a
export
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); }
# <<<

30
test/puts10.ssa Normal file
View File

@@ -0,0 +1,30 @@
export
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
# <<<

282
test/queen.ssa Normal file
View File

@@ -0,0 +1,282 @@
# eight queens program
# generated by minic
export function w $chk(w %t0, w %t1) {
@l0
%x =l alloc4 4
storew %t0, %x
%y =l alloc4 4
storew %t1, %y
%i =l alloc4 4
%r =l alloc4 4
storew 0, %i
storew 0, %r
@l1
%t6 =w loadw %i
%t7 =w loadw $glo1
%t5 =w csltw %t6, %t7
jnz %t5, @l2, @l3
@l2
%t10 =w loadw %r
%t15 =l loadl $glo3
%t16 =w loadw %x
%t17 =l extsw %t16
%t18 =l mul 8, %t17
%t14 =l add %t15, %t18
%t13 =l loadl %t14
%t19 =w loadw %i
%t20 =l extsw %t19
%t21 =l mul 4, %t20
%t12 =l add %t13, %t21
%t11 =w loadw %t12
%t9 =w add %t10, %t11
storew %t9, %r
%t24 =w loadw %r
%t29 =l loadl $glo3
%t30 =w loadw %i
%t31 =l extsw %t30
%t32 =l mul 8, %t31
%t28 =l add %t29, %t32
%t27 =l loadl %t28
%t33 =w loadw %y
%t34 =l extsw %t33
%t35 =l mul 4, %t34
%t26 =l add %t27, %t35
%t25 =w loadw %t26
%t23 =w add %t24, %t25
storew %t23, %r
%t39 =w loadw %x
%t40 =w loadw %i
%t38 =w add %t39, %t40
%t41 =w loadw $glo1
%t37 =w csltw %t38, %t41
%t44 =w loadw %y
%t45 =w loadw %i
%t43 =w add %t44, %t45
%t46 =w loadw $glo1
%t42 =w csltw %t43, %t46
%t36 =w and %t37, %t42
jnz %t36, @l4, @l5
@l4
%t49 =w loadw %r
%t54 =l loadl $glo3
%t56 =w loadw %x
%t57 =w loadw %i
%t55 =w add %t56, %t57
%t58 =l extsw %t55
%t59 =l mul 8, %t58
%t53 =l add %t54, %t59
%t52 =l loadl %t53
%t61 =w loadw %y
%t62 =w loadw %i
%t60 =w add %t61, %t62
%t63 =l extsw %t60
%t64 =l mul 4, %t63
%t51 =l add %t52, %t64
%t50 =w loadw %t51
%t48 =w add %t49, %t50
storew %t48, %r
@l5
%t68 =w loadw %x
%t69 =w loadw %i
%t67 =w add %t68, %t69
%t70 =w loadw $glo1
%t66 =w csltw %t67, %t70
%t74 =w loadw %y
%t75 =w loadw %i
%t73 =w sub %t74, %t75
%t71 =w cslew 0, %t73
%t65 =w and %t66, %t71
jnz %t65, @l7, @l8
@l7
%t78 =w loadw %r
%t83 =l loadl $glo3
%t85 =w loadw %x
%t86 =w loadw %i
%t84 =w add %t85, %t86
%t87 =l extsw %t84
%t88 =l mul 8, %t87
%t82 =l add %t83, %t88
%t81 =l loadl %t82
%t90 =w loadw %y
%t91 =w loadw %i
%t89 =w sub %t90, %t91
%t92 =l extsw %t89
%t93 =l mul 4, %t92
%t80 =l add %t81, %t93
%t79 =w loadw %t80
%t77 =w add %t78, %t79
storew %t77, %r
@l8
%t98 =w loadw %x
%t99 =w loadw %i
%t97 =w sub %t98, %t99
%t95 =w cslew 0, %t97
%t102 =w loadw %y
%t103 =w loadw %i
%t101 =w add %t102, %t103
%t104 =w loadw $glo1
%t100 =w csltw %t101, %t104
%t94 =w and %t95, %t100
jnz %t94, @l10, @l11
@l10
%t107 =w loadw %r
%t112 =l loadl $glo3
%t114 =w loadw %x
%t115 =w loadw %i
%t113 =w sub %t114, %t115
%t116 =l extsw %t113
%t117 =l mul 8, %t116
%t111 =l add %t112, %t117
%t110 =l loadl %t111
%t119 =w loadw %y
%t120 =w loadw %i
%t118 =w add %t119, %t120
%t121 =l extsw %t118
%t122 =l mul 4, %t121
%t109 =l add %t110, %t122
%t108 =w loadw %t109
%t106 =w add %t107, %t108
storew %t106, %r
@l11
%t127 =w loadw %x
%t128 =w loadw %i
%t126 =w sub %t127, %t128
%t124 =w cslew 0, %t126
%t132 =w loadw %y
%t133 =w loadw %i
%t131 =w sub %t132, %t133
%t129 =w cslew 0, %t131
%t123 =w and %t124, %t129
jnz %t123, @l13, @l14
@l13
%t136 =w loadw %r
%t141 =l loadl $glo3
%t143 =w loadw %x
%t144 =w loadw %i
%t142 =w sub %t143, %t144
%t145 =l extsw %t142
%t146 =l mul 8, %t145
%t140 =l add %t141, %t146
%t139 =l loadl %t140
%t148 =w loadw %y
%t149 =w loadw %i
%t147 =w sub %t148, %t149
%t150 =l extsw %t147
%t151 =l mul 4, %t150
%t138 =l add %t139, %t151
%t137 =w loadw %t138
%t135 =w add %t136, %t137
storew %t135, %r
@l14
%t153 =w loadw %i
%t152 =w add %t153, 1
storew %t152, %i
jmp @l1
@l3
%t154 =w loadw %r
ret %t154
}
export function w $go(w %t0) {
@l16
%y =l alloc4 4
storew %t0, %y
%x =l alloc4 4
%t2 =w loadw %y
%t3 =w loadw $glo1
%t1 =w ceqw %t2, %t3
jnz %t1, @l17, @l18
@l17
%t5 =w loadw $glo2
%t4 =w add %t5, 1
storew %t4, $glo2
ret 0
@l18
storew 0, %x
@l20
%t10 =w loadw %x
%t11 =w loadw $glo1
%t9 =w csltw %t10, %t11
jnz %t9, @l21, @l22
@l21
%t14 =w loadw %x
%t15 =w loadw %y
%t13 =w call $chk(w %t14, w %t15)
%t12 =w ceqw %t13, 0
jnz %t12, @l23, @l24
@l23
%t21 =l loadl $glo3
%t22 =w loadw %x
%t23 =l extsw %t22
%t24 =l mul 8, %t23
%t20 =l add %t21, %t24
%t19 =l loadl %t20
%t25 =w loadw %y
%t26 =l extsw %t25
%t27 =l mul 4, %t26
%t18 =l add %t19, %t27
%t28 =w loadw %t18
%t17 =w add %t28, 1
storew %t17, %t18
%t31 =w loadw %y
%t30 =w add %t31, 1
%t29 =w call $go(w %t30)
%t37 =l loadl $glo3
%t38 =w loadw %x
%t39 =l extsw %t38
%t40 =l mul 8, %t39
%t36 =l add %t37, %t40
%t35 =l loadl %t36
%t41 =w loadw %y
%t42 =l extsw %t41
%t43 =l mul 4, %t42
%t34 =l add %t35, %t43
%t44 =w loadw %t34
%t33 =w sub %t44, 1
storew %t33, %t34
@l24
%t46 =w loadw %x
%t45 =w add %t46, 1
storew %t45, %x
jmp @l20
@l22
ret 0
}
export function w $main() {
@l26
%i =l alloc4 4
storew 8, $glo1
%t4 =w loadw $glo1
%t3 =l call $calloc(w %t4, w 8)
storel %t3, $glo3
storew 0, %i
@l27
%t9 =w loadw %i
%t10 =w loadw $glo1
%t8 =w csltw %t9, %t10
jnz %t8, @l28, @l29
@l28
%t13 =w loadw $glo1
%t12 =l call $calloc(w %t13, w 4)
%t16 =l loadl $glo3
%t17 =w loadw %i
%t18 =l extsw %t17
%t19 =l mul 8, %t18
%t15 =l add %t16, %t19
storel %t12, %t15
%t21 =w loadw %i
%t20 =w add %t21, 1
storew %t20, %i
jmp @l27
@l29
%t22 =w call $go(w 0)
%t25 =w loadw $glo2
%t24 =w cnew %t25, 92
ret %t24
}
data $glo1 = { w 0 }
data $glo2 = { w 0 }
data $glo3 = { l 0 }

24
test/rega1.ssa Normal file
View File

@@ -0,0 +1,24 @@
# tests that %b and %a0 do not end up in
# the same register at the start of @loop
export function l $f(l %a) {
@start
@loop
%b =l phi @start 42, @loop0 %a1, @loop1 %a1
%a0 =l phi @start %a, @loop0 %a1, @loop1 %a1
%a1 =l sub %a0, 1
jnz %b, @loop0, @loop1
@loop0
jnz %a1, @loop, @end
@loop1
jnz %a1, @loop, @end
@end
ret %b
}
# >>> driver
# extern long long f(long long);
# int main() {
# return !(f(1) == 42 && f(2) == 1 && f(42) == 1);
# }
# <<<

68
test/spill1.ssa Normal file
View File

@@ -0,0 +1,68 @@
export
function w $f(w %n0) {
@start
@loop
%n1 =w phi @start %n0, @loop %n2
%p0 =w phi @start 0, @loop %p01
%p1 =w phi @start 0, @loop %p11
%p2 =w phi @start 0, @loop %p21
%p3 =w phi @start 0, @loop %p31
%p4 =w phi @start 0, @loop %p41
%p5 =w phi @start 0, @loop %p51
%p6 =w phi @start 0, @loop %p61
%p7 =w phi @start 0, @loop %p71
%p8 =w phi @start 0, @loop %p81
%p9 =w phi @start 0, @loop %p91
%pa =w phi @start 0, @loop %pa1
%pb =w phi @start 0, @loop %pb1
%pc =w phi @start 0, @loop %pc1
%pd =w phi @start 0, @loop %pd1
%pe =w phi @start 0, @loop %pe1
%pf =w phi @start 0, @loop %pf1
%p01 =w add 1, %p0
%p11 =w add 2, %p1
%p21 =w add 3, %p2
%p31 =w add 4, %p3
%p41 =w add 5, %p4
%p51 =w add 6, %p5
%p61 =w add 7, %p6
%p71 =w add 8, %p7
%p81 =w add 9, %p8
%p91 =w add 10, %p9
%pa1 =w add 11, %pa
%pb1 =w add 12, %pb
%pc1 =w add 13, %pc
%pd1 =w add 14, %pd
%pe1 =w add 15, %pe
%pf1 =w add 16, %pf
%n2 =w sub %n1, 1
jnz %n2, @loop, @end
@end
%a =w sub 0, 0
%a =w add %p01, %a
%a =w add %p11, %a
%a =w add %p21, %a
%a =w add %p31, %a
%a =w add %p41, %a
%a =w add %p51, %a
%a =w add %p61, %a
%a =w add %p71, %a
%a =w add %p81, %a
%a =w add %p91, %a
%a =w add %pa1, %a
%a =w add %pb1, %a
%a =w add %pc1, %a
%a =w add %pd1, %a
%a =w add %pe1, %a
%a =w add %pf1, %a
ret %a
}
# >>> driver
# extern int f(int);
# int main() { return !(f(1) == 136); }
# <<<

63
test/strcmp.ssa Normal file
View File

@@ -0,0 +1,63 @@
# the C strcmp function generated by scc
export function w $strcmp(l %s1.3.val,l %s2.5.val)
{
@.37
%s1.3 =l alloc8 8
%s2.5 =l alloc8 8
storel %s1.3.val,%s1.3
storel %s2.5.val,%s2.5
jmp @.5
@.6
%.9 =l loadl %s1.3
%.10 =l add %.9,1
storel %.10,%s1.3
%.11 =l loadl %s2.5
%.12 =l add %.11,1
storel %.12,%s2.5
@.5
%.15 =l loadl %s1.3
%.16 =w loadsb %.15
%.17 =w extsb %.16
%.18 =w cnew %.17,0
jnz %.18,@.14,@.8
@.14
%.19 =l loadl %s2.5
%.20 =w loadsb %.19
%.21 =w extsb %.20
%.22 =w cnew %.21,0
jnz %.22,@.13,@.8
@.13
%.23 =l loadl %s1.3
%.24 =w loadsb %.23
%.25 =w extsb %.24
%.26 =l loadl %s2.5
%.27 =w loadsb %.26
%.28 =w extsb %.27
%.29 =w ceqw %.25,%.28
jnz %.29,@.6,@.8
@.8
@.7
%.30 =l loadl %s1.3
%.31 =w loadub %.30
%.32 =w extub %.31
%.33 =l loadl %s2.5
%.34 =w loadub %.33
%.35 =w extub %.34
%.36 =w sub %.32,%.35
ret %.36
}
# >>> driver
# extern int strcmp(const char *, const char *);
# int main() {
# char a[] = "Hello world";
# return !(
# strcmp(a, a) == 0 &&
# strcmp("aaa", "aab") < 0 &&
# strcmp("..cnn", "..bbc") > 0 &&
# strcmp(a, "Hellp ...") < 0 &&
# strcmp(a, "Hello vorld") > 0
# );
# }
# <<<

77
test/strspn.ssa Normal file
View File

@@ -0,0 +1,77 @@
# the C strspn function generated by scc
export function w $strspn_(l %s1.81.val,l %s2.82.val)
{
@.64
%s1.81 =l alloc8 8
%s2.82 =l alloc8 8
%n.83 =l alloc4 4
%c.84 =l alloc4 4
%p.85 =l alloc8 8
storel %s1.81.val,%s1.81
storel %s2.82.val,%s2.82
storew 0,%n.83
jmp @.27
@.28
%.39 =l loadl %s2.82
storel %.39,%p.85
jmp @.29
@.30
@.31
%.40 =l loadl %p.85
%.41 =l add %.40,1
storel %.41,%p.85
@.29
%.43 =l loadl %p.85
%.44 =w loadsb %.43
%.45 =w extsb %.44
%.46 =w cnew %.45,0
jnz %.46,@.42,@.36
@.42
%.47 =l loadl %p.85
%.48 =w loadsb %.47
%.49 =w extsb %.48
%.50 =w loadsw %c.84
%.51 =w cnew %.49,%.50
jnz %.51,@.30,@.36
@.36
@.32
%.52 =l loadl %p.85
%.53 =w loadsb %.52
%.54 =w extsb %.53
%.55 =w cnew %.54,0
jnz %.55,@.33,@.37
@.37
jmp @.34
@.33
@.35
%.56 =w loaduw %n.83
%.57 =w add %.56,1
storew %.57,%n.83
@.27
%.58 =l loadl %s1.81
%.59 =l add %.58,1
storel %.59,%s1.81
%.60 =w loadsb %.58
%.61 =w extsb %.60
storew %.61,%c.84
%.62 =w cnew %.61,0
jnz %.62,@.28,@.38
@.38
@.34
%.63 =w loaduw %n.83
ret %.63
}
# >>> driver
# extern unsigned strspn_(const char *, const char *);
# int main() {
# return !(
# strspn_("", "abc") == 0 &&
# strspn_("abc", "") == 0 &&
# strspn_("abc", "bac") == 3 &&
# strspn_("xabc", "bac") == 0 &&
# strspn_("axbc", "bca") == 1
# );
# }
# <<<

32
test/sum.ssa Normal file
View File

@@ -0,0 +1,32 @@
# Simple test for addressing modes.
export
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);
# }
# <<<

75
test/tls.ssa Normal file
View File

@@ -0,0 +1,75 @@
# skip amd64_win (pthread and tls not implemented)
thread data $i = align 4 {w 42}
data $fmti = align 1 {b "i%d==%d\n", b 0}
thread data $x = {w 1, w 2, w 3, w 4}
data $fmtx = align 1 {b "*(x+%d)==%d\n", b 0}
export
function w $main() {
@start
%pthr =l alloc8 8
%rval =l alloc8 8
call $pthread_create(l %pthr, l 0, l $thread, l 0)
%t =l load %pthr
call $pthread_join(l %t, l %rval)
%i0 =w loadw thread $i
call $printf(l $fmti, ..., w 0, w %i0)
%i1 =w load %rval
call $printf(l $fmti, ..., w 1, w %i1)
%a0 =l call $xaddr()
%x0 =w load %a0
call $printf(l $fmtx, ..., w 0, w %x0)
%a4 =l call $xaddroff4()
%x4 =w load %a4
call $printf(l $fmtx, ..., w 4, w %x4)
%a8 =l call $xaddroff(l 8)
%x8 =w load %a8
call $printf(l $fmtx, ..., w 8, w %x8)
%xc =l call $xvalcnt(l 3)
call $printf(l $fmtx, ..., w 12, w %xc)
ret 0
}
function l $thread(l %arg) {
@start
%i3 =l add thread $i, 3
storeb 24, %i3
%ret =l loadsw thread $i
ret %ret
}
function l $xaddr() {
@start
ret thread $x
}
function l $xaddroff4() {
@start
%a =l add 4, thread $x
ret %a
}
function l $xaddroff(l %off) {
@start
%a =l add thread $x, %off
ret %a
}
function w $xvalcnt(l %cnt) {
@start
%o =l mul 4, %cnt
%a =l add thread $x, %o
%x =w load %a
ret %x
}
# >>> output
# i0==42
# i1==402653226
# *(x+0)==1
# *(x+4)==2
# *(x+8)==3
# *(x+12)==4
# <<<

35
test/vararg1.ssa Normal file
View File

@@ -0,0 +1,35 @@
export
function d $f(l %x, ...) {
@start
%vp =l alloc8 32
vastart %vp
%i =l vaarg %vp
%n =d vaarg %vp
ret %n
}
export
function w $g(l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret %r
}
# >>> driver
# #include <stdarg.h>
# #include <stdio.h>
# extern double f(int, ...);
# extern int g(char *, ...);
# int print(const char *fmt, va_list *ap) {
# return vprintf(fmt, *ap);
# }
# int main() {
# g("Hell%c %s %g!\n", 'o', "world", f(42, "x", 42.0));
# }
# <<<
# >>> output
# Hello world 42!
# <<<

684
test/vararg2.ssa Normal file
View File

@@ -0,0 +1,684 @@
export function $qbeprint0(l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall0(l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
export function $qbeprint1(w %argw0, l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall1(w %argw0, l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
export function $qbeprint2(d %argd0, l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall2(d %argd0, l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
export function $qbeprint3(w %argw0, w %argw1, w %argw2, w %argw3, l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall3(w %argw0, w %argw1, w %argw2, w %argw3, l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
export function $qbeprint4(d %argd0, d %argd1, d %argd2, d %argd3, d %argd4, d %argd5, l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall4(d %argd0, d %argd1, d %argd2, d %argd3, d %argd4, d %argd5, l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
export function $qbeprint5(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, d %argd0, d %argd1, d %argd2, d %argd3, d %argd4, d %argd5, d %argd6, l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall5(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, d %argd0, d %argd1, d %argd2, d %argd3, d %argd4, d %argd5, d %argd6, l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
export function $qbeprint6(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, w %argw5, w %argw6, w %argw7, w %argw8, w %argw9, d %argd0, d %argd1, d %argd2, d %argd3, d %argd4, d %argd5, d %argd6, d %argd7, d %argd8, d %argd9, l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall6(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, w %argw5, w %argw6, w %argw7, w %argw8, w %argw9, d %argd0, d %argd1, d %argd2, d %argd3, d %argd4, d %argd5, d %argd6, d %argd7, d %argd8, d %argd9, l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
export function $qbeprint7(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, w %argw5, w %argw6, w %argw7, w %argw8, l %fmt, ...) {
@start
%fmtdbl =l alloc4 4
%fmtint =l alloc4 4
%emptys =l alloc4 4
storew 2122789, %fmtint
storew 2123557, %fmtdbl
storew 0, %emptys
%vp =l alloc8 32
%fmt1 =l add 1, %fmt
vastart %vp
@loop
%p =l phi @start %fmt1, @casef %p1, @cased %p1
%c =w loadsb %p
%p1 =l add 3, %p
jnz %c, @loop1, @end
@loop1
%isg =w ceqw %c, 103
jnz %isg, @casef, @cased
@casef
%dbl =d vaarg %vp
%r =w call $printf(l %fmtdbl, ..., d %dbl)
jmp @loop
@cased
%int =w vaarg %vp
%r =w call $printf(l %fmtint, ..., w %int)
jmp @loop
@end
%r =w call $puts(l %emptys)
ret
}
export function $qbecall7(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, w %argw5, w %argw6, w %argw7, w %argw8, l %fmt, ...) {
@start
%vp =l alloc8 32
vastart %vp
%r =w call $print(l %fmt, l %vp)
ret
}
# >>> driver
# #include <stdarg.h>
# #include <stdio.h>
# extern void qbeprint0(char *, ...);
# extern void qbecall0(char *, ...);
# extern void qbeprint1(int argw0, char *, ...);
# extern void qbecall1(int argw0, char *, ...);
# extern void qbeprint2(double argd0, char *, ...);
# extern void qbecall2(double argd0, char *, ...);
# extern void qbeprint3(int argw0, int argw1, int argw2, int argw3, char *, ...);
# extern void qbecall3(int argw0, int argw1, int argw2, int argw3, char *, ...);
# extern void qbeprint4(double argd0, double argd1, double argd2, double argd3, double argd4, double argd5, char *, ...);
# extern void qbecall4(double argd0, double argd1, double argd2, double argd3, double argd4, double argd5, char *, ...);
# extern void qbeprint5(int argw0, int argw1, int argw2, int argw3, int argw4, double argd0, double argd1, double argd2, double argd3, double argd4, double argd5, double argd6, char *, ...);
# extern void qbecall5(int argw0, int argw1, int argw2, int argw3, int argw4, double argd0, double argd1, double argd2, double argd3, double argd4, double argd5, double argd6, char *, ...);
# extern void qbeprint6(int argw0, int argw1, int argw2, int argw3, int argw4, int argw5, int argw6, int argw7, int argw8, int argw9, double argd0, double argd1, double argd2, double argd3, double argd4, double argd5, double argd6, double argd7, double argd8, double argd9, char *, ...);
# extern void qbecall6(int argw0, int argw1, int argw2, int argw3, int argw4, int argw5, int argw6, int argw7, int argw8, int argw9, double argd0, double argd1, double argd2, double argd3, double argd4, double argd5, double argd6, double argd7, double argd8, double argd9, char *, ...);
# extern void qbeprint7(int argw0, int argw1, int argw2, int argw3, int argw4, int argw5, int argw6, int argw7, int argw8, char *, ...);
# extern void qbecall7(int argw0, int argw1, int argw2, int argw3, int argw4, int argw5, int argw6, int argw7, int argw8, char *, ...);
# int print(char *fmt, va_list *ap) {
# return vprintf(fmt, *ap);
# }
# int main() {
# puts("# (0 int, 0 double)");
# qbeprint0("%d \n", 3);
# qbecall0("%d \n", 3);
# qbeprint0("%g \n", -9.5);
# qbecall0("%g \n", -9.5);
# qbeprint0("%d %g \n", -5, -5.536);
# qbecall0("%d %g \n", -5, -5.536);
# qbeprint0("%g %g \n", 4.729, 3.534);
# qbecall0("%g %g \n", 4.729, 3.534);
# qbeprint0("%d %d %d %d \n", 8, -9, -2, -10);
# qbecall0("%d %d %d %d \n", 8, -9, -2, -10);
# qbeprint0("%g %g %g %g \n", -5.627, 0.1071, -9.469, -6.023);
# qbecall0("%g %g %g %g \n", -5.627, 0.1071, -9.469, -6.023);
# qbeprint0("%d %g %d %g \n", 3, 0.8988, -6, 1.785);
# qbecall0("%d %g %d %g \n", 3, 0.8988, -6, 1.785);
# qbeprint0("%g %g %d %d \n", 6.189, -9.87, 6, 4);
# qbecall0("%g %g %d %d \n", 6.189, -9.87, 6, 4);
# qbeprint0("%d %d %g %g \n", -3, -7, 9.144, -3.268);
# qbecall0("%d %d %g %g \n", -3, -7, 9.144, -3.268);
# qbeprint0("\n");
# qbecall0("\n");
# puts("# (1 int, 0 double)");
# qbeprint1(0, "%d \n", -9);
# qbecall1(0, "%d \n", -9);
# qbeprint1(0, "%g \n", -8.066);
# qbecall1(0, "%g \n", -8.066);
# qbeprint1(0, "%d %g \n", 7, 2.075);
# qbecall1(0, "%d %g \n", 7, 2.075);
# qbeprint1(0, "%g %g \n", 6.143, 4.595);
# qbecall1(0, "%g %g \n", 6.143, 4.595);
# qbeprint1(0, "%d %d %d %d \n", 1, 10, -3, 1);
# qbecall1(0, "%d %d %d %d \n", 1, 10, -3, 1);
# qbeprint1(0, "%g %g %g %g \n", 6.588, 2.37, 7.234, 1.547);
# qbecall1(0, "%g %g %g %g \n", 6.588, 2.37, 7.234, 1.547);
# qbeprint1(0, "%d %g %d %g \n", 4, -9.084, -6, -4.212);
# qbecall1(0, "%d %g %d %g \n", 4, -9.084, -6, -4.212);
# qbeprint1(0, "%g %g %d %d \n", -8.404, -5.344, -8, -5);
# qbecall1(0, "%g %g %d %d \n", -8.404, -5.344, -8, -5);
# qbeprint1(0, "%d %d %g %g \n", 3, -3, -2.596, -5.81);
# qbecall1(0, "%d %d %g %g \n", 3, -3, -2.596, -5.81);
# qbeprint1(0, "\n");
# qbecall1(0, "\n");
# puts("# (0 int, 1 double)");
# qbeprint2(0, "%d \n", -5);
# qbecall2(0, "%d \n", -5);
# qbeprint2(0, "%g \n", 8.733);
# qbecall2(0, "%g \n", 8.733);
# qbeprint2(0, "%d %g \n", 3, 2.183);
# qbecall2(0, "%d %g \n", 3, 2.183);
# qbeprint2(0, "%g %g \n", -6.577, 4.583);
# qbecall2(0, "%g %g \n", -6.577, 4.583);
# qbeprint2(0, "%d %d %d %d \n", -7, -3, 10, 3);
# qbecall2(0, "%d %d %d %d \n", -7, -3, 10, 3);
# qbeprint2(0, "%g %g %g %g \n", 1.139, 3.692, 6.857, 5.52);
# qbecall2(0, "%g %g %g %g \n", 1.139, 3.692, 6.857, 5.52);
# qbeprint2(0, "%d %g %d %g \n", -6, -9.358, -4, -4.645);
# qbecall2(0, "%d %g %d %g \n", -6, -9.358, -4, -4.645);
# qbeprint2(0, "%g %g %d %d \n", -5.78, 8.858, 8, -4);
# qbecall2(0, "%g %g %d %d \n", -5.78, 8.858, 8, -4);
# qbeprint2(0, "%d %d %g %g \n", 3, -2, 8.291, -0.823);
# qbecall2(0, "%d %d %g %g \n", 3, -2, 8.291, -0.823);
# qbeprint2(0, "\n");
# qbecall2(0, "\n");
# puts("# (4 int, 0 double)");
# qbeprint3(0, 0, 0, 0, "%d \n", -5);
# qbecall3(0, 0, 0, 0, "%d \n", -5);
# qbeprint3(0, 0, 0, 0, "%g \n", -5.067);
# qbecall3(0, 0, 0, 0, "%g \n", -5.067);
# qbeprint3(0, 0, 0, 0, "%d %g \n", 1, -4.745);
# qbecall3(0, 0, 0, 0, "%d %g \n", 1, -4.745);
# qbeprint3(0, 0, 0, 0, "%g %g \n", 1.692, 7.956);
# qbecall3(0, 0, 0, 0, "%g %g \n", 1.692, 7.956);
# qbeprint3(0, 0, 0, 0, "%d %d %d %d \n", -2, -6, 10, 0);
# qbecall3(0, 0, 0, 0, "%d %d %d %d \n", -2, -6, 10, 0);
# qbeprint3(0, 0, 0, 0, "%g %g %g %g \n", -8.182, -9.058, -7.807, 2.549);
# qbecall3(0, 0, 0, 0, "%g %g %g %g \n", -8.182, -9.058, -7.807, 2.549);
# qbeprint3(0, 0, 0, 0, "%d %g %d %g \n", 6, -1.557, -9, -2.368);
# qbecall3(0, 0, 0, 0, "%d %g %d %g \n", 6, -1.557, -9, -2.368);
# qbeprint3(0, 0, 0, 0, "%g %g %d %d \n", 9.922, 0.5823, 10, 8);
# qbecall3(0, 0, 0, 0, "%g %g %d %d \n", 9.922, 0.5823, 10, 8);
# qbeprint3(0, 0, 0, 0, "%d %d %g %g \n", -10, 5, 3.634, 0.7394);
# qbecall3(0, 0, 0, 0, "%d %d %g %g \n", -10, 5, 3.634, 0.7394);
# qbeprint3(0, 0, 0, 0, "\n");
# qbecall3(0, 0, 0, 0, "\n");
# puts("# (0 int, 6 double)");
# qbeprint4(0, 0, 0, 0, 0, 0, "%d \n", -5);
# qbecall4(0, 0, 0, 0, 0, 0, "%d \n", -5);
# qbeprint4(0, 0, 0, 0, 0, 0, "%g \n", 2.819);
# qbecall4(0, 0, 0, 0, 0, 0, "%g \n", 2.819);
# qbeprint4(0, 0, 0, 0, 0, 0, "%d %g \n", -8, -1.305);
# qbecall4(0, 0, 0, 0, 0, 0, "%d %g \n", -8, -1.305);
# qbeprint4(0, 0, 0, 0, 0, 0, "%g %g \n", -0.9255, 9.076);
# qbecall4(0, 0, 0, 0, 0, 0, "%g %g \n", -0.9255, 9.076);
# qbeprint4(0, 0, 0, 0, 0, 0, "%d %d %d %d \n", 8, -5, 0, -7);
# qbecall4(0, 0, 0, 0, 0, 0, "%d %d %d %d \n", 8, -5, 0, -7);
# qbeprint4(0, 0, 0, 0, 0, 0, "%g %g %g %g \n", 8.253, 7.41, -4.031, 2.779);
# qbecall4(0, 0, 0, 0, 0, 0, "%g %g %g %g \n", 8.253, 7.41, -4.031, 2.779);
# qbeprint4(0, 0, 0, 0, 0, 0, "%d %g %d %g \n", 2, -6.943, 6, 0.7876);
# qbecall4(0, 0, 0, 0, 0, 0, "%d %g %d %g \n", 2, -6.943, 6, 0.7876);
# qbeprint4(0, 0, 0, 0, 0, 0, "%g %g %d %d \n", 5.573, 0.6071, -10, -4);
# qbecall4(0, 0, 0, 0, 0, 0, "%g %g %d %d \n", 5.573, 0.6071, -10, -4);
# qbeprint4(0, 0, 0, 0, 0, 0, "%d %d %g %g \n", -10, 9, 7.574, 6.633);
# qbecall4(0, 0, 0, 0, 0, 0, "%d %d %g %g \n", -10, 9, 7.574, 6.633);
# qbeprint4(0, 0, 0, 0, 0, 0, "\n");
# qbecall4(0, 0, 0, 0, 0, 0, "\n");
# puts("# (5 int, 7 double)");
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d \n", -4);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d \n", -4);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g \n", -8.841);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g \n", -8.841);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g \n", 8, 8.939);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g \n", 8, 8.939);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g \n", -8.287, -0.2802);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g \n", -8.287, -0.2802);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %d %d \n", -9, 5, 6, -8);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %d %d \n", -9, 5, 6, -8);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %g %g \n", -0.4944, 0.9961, -4.699, 7.449);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %g %g \n", -0.4944, 0.9961, -4.699, 7.449);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g %d %g \n", -2, -5.764, 1, 4.599);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g %d %g \n", -2, -5.764, 1, 4.599);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %d %d \n", -5.977, -3.766, 10, 3);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %d %d \n", -5.977, -3.766, 10, 3);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %g %g \n", -1, 0, -7.58, -5.506);
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %g %g \n", -1, 0, -7.58, -5.506);
# qbeprint5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "\n");
# qbecall5(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "\n");
# puts("# (10 int, 10 double)");
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d \n", -3);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d \n", -3);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g \n", 1.766);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g \n", 1.766);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g \n", -6, -5.596);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g \n", -6, -5.596);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g \n", -8.58, 2.622);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g \n", -8.58, 2.622);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %d %d \n", -6, 9, 8, -9);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %d %d \n", -6, 9, 8, -9);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %g %g \n", -5.24, 3.38, -5.715, -7.354);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %g %g \n", -5.24, 3.38, -5.715, -7.354);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g %d %g \n", 9, 1.421, -1, 5.692);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g %d %g \n", 9, 1.421, -1, 5.692);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %d %d \n", 6.15, -6.192, -8, -1);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %d %d \n", 6.15, -6.192, -8, -1);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %g %g \n", -2, -1, 4.582, 3.467);
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %g %g \n", -2, -1, 4.582, 3.467);
# qbeprint6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "\n");
# qbecall6(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "\n");
# puts("# (9 int, 0 double)");
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d \n", 10);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d \n", 10);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g \n", -8.032);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g \n", -8.032);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g \n", -2, -3.214);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g \n", -2, -3.214);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g \n", 7.233, -5.027);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g \n", 7.233, -5.027);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %d %d \n", -7, -1, -2, -5);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %d %d \n", -7, -1, -2, -5);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %g %g \n", -5.004, 8.465, -1.137, 7.227);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %g %g \n", -5.004, 8.465, -1.137, 7.227);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g %d %g \n", 1, -8.988, 10, 6.721);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %g %d %g \n", 1, -8.988, 10, 6.721);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %d %d \n", 9.38, 8.527, 7, -7);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%g %g %d %d \n", 9.38, 8.527, 7, -7);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %g %g \n", 0, -6, -1.979, -8.827);
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "%d %d %g %g \n", 0, -6, -1.979, -8.827);
# qbeprint7(0, 0, 0, 0, 0, 0, 0, 0, 0, "\n");
# qbecall7(0, 0, 0, 0, 0, 0, 0, 0, 0, "\n");
# }
# <<<
# >>> output
# # (0 int, 0 double)
# 3
# 3
# -9.5
# -9.5
# -5 -5.536
# -5 -5.536
# 4.729 3.534
# 4.729 3.534
# 8 -9 -2 -10
# 8 -9 -2 -10
# -5.627 0.1071 -9.469 -6.023
# -5.627 0.1071 -9.469 -6.023
# 3 0.8988 -6 1.785
# 3 0.8988 -6 1.785
# 6.189 -9.87 6 4
# 6.189 -9.87 6 4
# -3 -7 9.144 -3.268
# -3 -7 9.144 -3.268
#
#
# # (1 int, 0 double)
# -9
# -9
# -8.066
# -8.066
# 7 2.075
# 7 2.075
# 6.143 4.595
# 6.143 4.595
# 1 10 -3 1
# 1 10 -3 1
# 6.588 2.37 7.234 1.547
# 6.588 2.37 7.234 1.547
# 4 -9.084 -6 -4.212
# 4 -9.084 -6 -4.212
# -8.404 -5.344 -8 -5
# -8.404 -5.344 -8 -5
# 3 -3 -2.596 -5.81
# 3 -3 -2.596 -5.81
#
#
# # (0 int, 1 double)
# -5
# -5
# 8.733
# 8.733
# 3 2.183
# 3 2.183
# -6.577 4.583
# -6.577 4.583
# -7 -3 10 3
# -7 -3 10 3
# 1.139 3.692 6.857 5.52
# 1.139 3.692 6.857 5.52
# -6 -9.358 -4 -4.645
# -6 -9.358 -4 -4.645
# -5.78 8.858 8 -4
# -5.78 8.858 8 -4
# 3 -2 8.291 -0.823
# 3 -2 8.291 -0.823
#
#
# # (4 int, 0 double)
# -5
# -5
# -5.067
# -5.067
# 1 -4.745
# 1 -4.745
# 1.692 7.956
# 1.692 7.956
# -2 -6 10 0
# -2 -6 10 0
# -8.182 -9.058 -7.807 2.549
# -8.182 -9.058 -7.807 2.549
# 6 -1.557 -9 -2.368
# 6 -1.557 -9 -2.368
# 9.922 0.5823 10 8
# 9.922 0.5823 10 8
# -10 5 3.634 0.7394
# -10 5 3.634 0.7394
#
#
# # (0 int, 6 double)
# -5
# -5
# 2.819
# 2.819
# -8 -1.305
# -8 -1.305
# -0.9255 9.076
# -0.9255 9.076
# 8 -5 0 -7
# 8 -5 0 -7
# 8.253 7.41 -4.031 2.779
# 8.253 7.41 -4.031 2.779
# 2 -6.943 6 0.7876
# 2 -6.943 6 0.7876
# 5.573 0.6071 -10 -4
# 5.573 0.6071 -10 -4
# -10 9 7.574 6.633
# -10 9 7.574 6.633
#
#
# # (5 int, 7 double)
# -4
# -4
# -8.841
# -8.841
# 8 8.939
# 8 8.939
# -8.287 -0.2802
# -8.287 -0.2802
# -9 5 6 -8
# -9 5 6 -8
# -0.4944 0.9961 -4.699 7.449
# -0.4944 0.9961 -4.699 7.449
# -2 -5.764 1 4.599
# -2 -5.764 1 4.599
# -5.977 -3.766 10 3
# -5.977 -3.766 10 3
# -1 0 -7.58 -5.506
# -1 0 -7.58 -5.506
#
#
# # (10 int, 10 double)
# -3
# -3
# 1.766
# 1.766
# -6 -5.596
# -6 -5.596
# -8.58 2.622
# -8.58 2.622
# -6 9 8 -9
# -6 9 8 -9
# -5.24 3.38 -5.715 -7.354
# -5.24 3.38 -5.715 -7.354
# 9 1.421 -1 5.692
# 9 1.421 -1 5.692
# 6.15 -6.192 -8 -1
# 6.15 -6.192 -8 -1
# -2 -1 4.582 3.467
# -2 -1 4.582 3.467
#
#
# # (9 int, 0 double)
# 10
# 10
# -8.032
# -8.032
# -2 -3.214
# -2 -3.214
# 7.233 -5.027
# 7.233 -5.027
# -7 -1 -2 -5
# -7 -1 -2 -5
# -5.004 8.465 -1.137 7.227
# -5.004 8.465 -1.137 7.227
# 1 -8.988 10 6.721
# 1 -8.988 10 6.721
# 9.38 8.527 7 -7
# 9.38 8.527 7 -7
# 0 -6 -1.979 -8.827
# 0 -6 -1.979 -8.827
#
#
# <<<