qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

vatest.py (3145B)


      1 # generate variadic calls to test the
      2 # abi implementation
      3 
      4 from random import seed, randint, uniform
      5 from struct import unpack
      6 
      7 I, D = 'd', 'g'
      8 
      9 formats = [
     10 	# list of formats to test
     11 	[I],
     12 	[D],
     13 	[I,D],
     14 	[D,D],
     15 	[I,I,I,I],
     16 	[D,D,D,D],
     17 	[I,D,I,D],
     18 	[D,D,I,I],
     19 	[I,I,D,D],
     20 	[],
     21 ]
     22 
     23 generate = [
     24 	# numbers of fixed integer and
     25 	# floating point arguments to
     26 	# test
     27 	(0, 0), (1, 0), (0, 1), (4, 0),
     28 	(0, 6), (5, 7), (10, 10), (9, 0),
     29 ]
     30 
     31 def mkargs(nargs, type, name):
     32 	args = map(
     33 		lambda n: ''.join([type, name, str(n), ', ']),
     34 		range(nargs)
     35 	)
     36 	return ''.join(args)
     37 
     38 def mkfstr(fmt):
     39 	fstr = map(
     40 		lambda x: {I: '%d ', D: '%g '}[x],
     41 		fmt
     42 	)
     43 	return '"' + ''.join(fstr) + '\\n"'
     44 
     45 def randargs(fmt):
     46 	ra = {
     47 		I: lambda: '{}'.format(randint(-10, 10)),
     48 		D: lambda: '{0:.4g}'.format(uniform(-10, 10))
     49 	}
     50 	return list(map(lambda x: ra[x](), fmt))
     51 
     52 def genssa(qbeprint, qbecall):
     53 	funcs = [('qbeprint', qbeprint), ('qbecall', qbecall)]
     54 	for fnum, (nia, nfa) in enumerate(generate):
     55 		params = "{}{}l %fmt, ...".format(
     56 			mkargs(nia, 'w ', '%argw'),
     57 			mkargs(nfa, 'd ', '%argd')
     58 		)
     59 		for name, code in funcs:
     60 			print('export function ${}{}({}) {}'
     61 				.format(name, fnum, params, code)
     62 			)
     63 
     64 def gendriver():
     65 	print('# >>> driver')
     66 	print('# #include <stdarg.h>')
     67 	print('# #include <stdio.h>')
     68 
     69 	for fnum, (nia, nfa) in enumerate(generate):
     70 		params = "{}{}char *, ...".format(
     71 			mkargs(nia, 'int ', 'argw'),
     72 			mkargs(nfa, 'double ', 'argd')
     73 		)
     74 		for name in ['qbeprint', 'qbecall']:
     75 			print('# extern void {}{}({});'
     76 				.format(name, fnum, params)
     77 			)
     78 
     79 	output = ''
     80 	print('# int print(char *fmt, va_list *ap) {')
     81 	print('#    return vprintf(fmt, *ap);');
     82 	print('# }')
     83 	print('# int main() {')
     84 
     85 	for fnum, (nia, nfa) in enumerate(generate):
     86 		info = '# ({} int, {} double)'.format(nia, nfa)
     87 		print('# 	puts("{}");'.format(info))
     88 		output += '# {}\n'.format(info)
     89 		for fmt in formats:
     90 			ra = randargs(fmt)
     91 			vaargs = ', '.join(ra)
     92 			expect = ' '.join(ra)
     93 			if fmt:
     94 				vaargs = ', ' + vaargs
     95 				expect = expect + ' '
     96 			args = ''.join(
     97 				['0, '] * (nia+nfa) +
     98 				[mkfstr(fmt), vaargs]
     99 			)
    100 			for name in ['qbeprint', 'qbecall']:
    101 				print('# 	{}{}({});'
    102 					.format(name, fnum, args)
    103 				)
    104 				output += '# {}\n'.format(expect)
    105 
    106 	print('# }')
    107 	print('# <<<')
    108 
    109 	print('\n# >>> output\n' + output + '# <<<')
    110 
    111 
    112 qbeprint="""{{
    113 @start
    114 	%fmtdbl =l alloc4 4
    115 	%fmtint =l alloc4 4
    116 	%emptys =l alloc4 4
    117 	storew {}, %fmtint
    118 	storew {}, %fmtdbl
    119 	storew 0, %emptys
    120 	%vp =l alloc8 32
    121 	%fmt1 =l add 1, %fmt
    122 	vastart %vp
    123 @loop
    124 	%p =l phi @start %fmt1, @casef %p1, @cased %p1
    125 	%c =w loadsb %p
    126 	%p1 =l add 3, %p
    127 	jnz %c, @loop1, @end
    128 @loop1
    129 	%isg =w ceqw %c, 103
    130 	jnz %isg, @casef, @cased
    131 @casef
    132 	%dbl =d vaarg %vp
    133 	%r =w call $printf(l %fmtdbl, ..., d %dbl)
    134 	jmp @loop
    135 @cased
    136 	%int =w vaarg %vp
    137 	%r =w call $printf(l %fmtint, ..., w %int)
    138 	jmp @loop
    139 @end
    140 	%r =w call $puts(l %emptys)
    141 	ret
    142 }}
    143 """.format(
    144 	unpack("i", b'%d \x00')[0],
    145 	unpack("i", b'%g \x00')[0]
    146 )
    147 
    148 qbecall="""{
    149 @start
    150 	%vp =l alloc8 32
    151 	vastart %vp
    152 	%r =w call $print(l %fmt, l %vp)
    153 	ret
    154 }
    155 """
    156 
    157 
    158 if __name__ == "__main__":
    159 	seed(42)
    160 	genssa(qbeprint, qbecall)
    161 	gendriver()