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()