vatest.py 3.1 KB

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