blob: 62925e7adea07658b6ba946057639a31caf3cc46 [file] [log] [blame]
Eli Friedman77a1fe92009-07-10 20:15:12 +00001#!/usr/bin/env python
Daniel Dunbara83fb862009-01-15 04:24:17 +00002
3from pprint import pprint
4import random, atexit, time
5from random import randrange
Daniel Dunbar0f1730d2009-02-22 04:17:53 +00006import re
Daniel Dunbara83fb862009-01-15 04:24:17 +00007
8from Enumeration import *
9from TypeGen import *
10
11####
12
13class TypePrinter:
14 def __init__(self, output, outputHeader=None,
15 outputTests=None, outputDriver=None,
16 headerName=None, info=None):
17 self.output = output
18 self.outputHeader = outputHeader
19 self.outputTests = outputTests
20 self.outputDriver = outputDriver
21 self.writeBody = outputHeader or outputTests or outputDriver
22 self.types = {}
23 self.testValues = {}
24 self.testReturnValues = {}
Daniel Dunbar5ce61572009-01-28 02:01:23 +000025 self.layoutTests = []
Daniel Dunbar7b1ab132010-09-27 20:13:24 +000026 self.declarations = set()
Daniel Dunbara83fb862009-01-15 04:24:17 +000027
28 if info:
29 for f in (self.output,self.outputHeader,self.outputTests,self.outputDriver):
30 if f:
31 print >>f,info
32
33 if self.writeBody:
34 print >>self.output, '#include <stdio.h>\n'
35 if self.outputTests:
Daniel Dunbar9dd60b42009-02-17 23:13:43 +000036 print >>self.outputTests, '#include <stdio.h>'
37 print >>self.outputTests, '#include <string.h>'
38 print >>self.outputTests, '#include <assert.h>\n'
Daniel Dunbara83fb862009-01-15 04:24:17 +000039
40 if headerName:
41 for f in (self.output,self.outputTests,self.outputDriver):
42 if f is not None:
43 print >>f, '#include "%s"\n'%(headerName,)
44
45 if self.outputDriver:
Douglas Gregorc6277a02010-02-02 17:49:52 +000046 print >>self.outputDriver, '#include <stdio.h>'
47 print >>self.outputDriver, '#include <stdlib.h>\n'
Daniel Dunbara83fb862009-01-15 04:24:17 +000048 print >>self.outputDriver, 'int main(int argc, char **argv) {'
Daniel Dunbar484c7ca2009-05-08 23:40:45 +000049 print >>self.outputDriver, ' int index = -1;'
50 print >>self.outputDriver, ' if (argc > 1) index = atoi(argv[1]);'
Daniel Dunbara83fb862009-01-15 04:24:17 +000051
52 def finish(self):
Daniel Dunbar5ce61572009-01-28 02:01:23 +000053 if self.layoutTests:
54 print >>self.output, 'int main(int argc, char **argv) {'
Daniel Dunbar484c7ca2009-05-08 23:40:45 +000055 print >>self.output, ' int index = -1;'
56 print >>self.output, ' if (argc > 1) index = atoi(argv[1]);'
57 for i,f in self.layoutTests:
58 print >>self.output, ' if (index == -1 || index == %d)' % i
59 print >>self.output, ' %s();' % f
Daniel Dunbar5ce61572009-01-28 02:01:23 +000060 print >>self.output, ' return 0;'
61 print >>self.output, '}'
62
Daniel Dunbara83fb862009-01-15 04:24:17 +000063 if self.outputDriver:
Daniel Dunbar9dd60b42009-02-17 23:13:43 +000064 print >>self.outputDriver, ' printf("DONE\\n");'
Daniel Dunbara83fb862009-01-15 04:24:17 +000065 print >>self.outputDriver, ' return 0;'
Daniel Dunbar5ce61572009-01-28 02:01:23 +000066 print >>self.outputDriver, '}'
Daniel Dunbara83fb862009-01-15 04:24:17 +000067
Daniel Dunbar7b1ab132010-09-27 20:13:24 +000068 def addDeclaration(self, decl):
69 if decl in self.declarations:
70 return False
71
72 self.declarations.add(decl)
73 if self.outputHeader:
74 print >>self.outputHeader, decl
75 else:
76 print >>self.output, decl
77 if self.outputTests:
78 print >>self.outputTests, decl
79 return True
80
Daniel Dunbara83fb862009-01-15 04:24:17 +000081 def getTypeName(self, T):
Daniel Dunbara83fb862009-01-15 04:24:17 +000082 name = self.types.get(T)
83 if name is None:
Daniel Dunbara83fb862009-01-15 04:24:17 +000084 # Reserve slot
85 self.types[T] = None
Daniel Dunbar7b1ab132010-09-27 20:13:24 +000086 self.types[T] = name = T.getTypeName(self)
Daniel Dunbara83fb862009-01-15 04:24:17 +000087 return name
88
Daniel Dunbar5ce61572009-01-28 02:01:23 +000089 def writeLayoutTest(self, i, ty):
90 tyName = self.getTypeName(ty)
91 tyNameClean = tyName.replace(' ','_').replace('*','star')
92 fnName = 'test_%s' % tyNameClean
93
94 print >>self.output,'void %s(void) {' % fnName
95 self.printSizeOfType(' %s'%fnName, tyName, ty, self.output)
96 self.printAlignOfType(' %s'%fnName, tyName, ty, self.output)
97 self.printOffsetsOfType(' %s'%fnName, tyName, ty, self.output)
98 print >>self.output,'}'
99 print >>self.output
100
Daniel Dunbar484c7ca2009-05-08 23:40:45 +0000101 self.layoutTests.append((i,fnName))
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000102
Daniel Dunbara83fb862009-01-15 04:24:17 +0000103 def writeFunction(self, i, FT):
104 args = ', '.join(['%s arg%d'%(self.getTypeName(t),i) for i,t in enumerate(FT.argTypes)])
105 if not args:
106 args = 'void'
107
108 if FT.returnType is None:
109 retvalName = None
110 retvalTypeName = 'void'
111 else:
112 retvalTypeName = self.getTypeName(FT.returnType)
113 if self.writeBody or self.outputTests:
114 retvalName = self.getTestReturnValue(FT.returnType)
115
116 fnName = 'fn%d'%(FT.index,)
117 if self.outputHeader:
118 print >>self.outputHeader,'%s %s(%s);'%(retvalTypeName, fnName, args)
119 elif self.outputTests:
120 print >>self.outputTests,'%s %s(%s);'%(retvalTypeName, fnName, args)
121
122 print >>self.output,'%s %s(%s)'%(retvalTypeName, fnName, args),
123 if self.writeBody:
124 print >>self.output, '{'
125
126 for i,t in enumerate(FT.argTypes):
127 self.printValueOfType(' %s'%fnName, 'arg%d'%i, t)
128
129 if retvalName is not None:
130 print >>self.output, ' return %s;'%(retvalName,)
131 print >>self.output, '}'
132 else:
133 print >>self.output, '{}'
134 print >>self.output
135
136 if self.outputDriver:
Daniel Dunbar484c7ca2009-05-08 23:40:45 +0000137 print >>self.outputDriver, ' if (index == -1 || index == %d) {' % i
138 print >>self.outputDriver, ' extern void test_%s(void);' % fnName
139 print >>self.outputDriver, ' test_%s();' % fnName
140 print >>self.outputDriver, ' }'
Daniel Dunbara83fb862009-01-15 04:24:17 +0000141
142 if self.outputTests:
143 if self.outputHeader:
144 print >>self.outputHeader, 'void test_%s(void);'%(fnName,)
145
146 if retvalName is None:
147 retvalTests = None
148 else:
149 retvalTests = self.getTestValuesArray(FT.returnType)
150 tests = map(self.getTestValuesArray, FT.argTypes)
151 print >>self.outputTests, 'void test_%s(void) {'%(fnName,)
152
153 if retvalTests is not None:
154 print >>self.outputTests, ' printf("%s: testing return.\\n");'%(fnName,)
155 print >>self.outputTests, ' for (int i=0; i<%d; ++i) {'%(retvalTests[1],)
156 args = ', '.join(['%s[%d]'%(t,randrange(l)) for t,l in tests])
157 print >>self.outputTests, ' %s RV;'%(retvalTypeName,)
158 print >>self.outputTests, ' %s = %s[i];'%(retvalName, retvalTests[0])
159 print >>self.outputTests, ' RV = %s(%s);'%(fnName, args)
160 self.printValueOfType(' %s_RV'%fnName, 'RV', FT.returnType, output=self.outputTests, indent=4)
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000161 self.checkTypeValues('RV', '%s[i]' % retvalTests[0], FT.returnType, output=self.outputTests, indent=4)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000162 print >>self.outputTests, ' }'
163
164 if tests:
165 print >>self.outputTests, ' printf("%s: testing arguments.\\n");'%(fnName,)
166 for i,(array,length) in enumerate(tests):
167 for j in range(length):
168 args = ['%s[%d]'%(t,randrange(l)) for t,l in tests]
169 args[i] = '%s[%d]'%(array,j)
170 print >>self.outputTests, ' %s(%s);'%(fnName, ', '.join(args),)
171 print >>self.outputTests, '}'
172
173 def getTestReturnValue(self, type):
174 typeName = self.getTypeName(type)
175 info = self.testReturnValues.get(typeName)
176 if info is None:
177 name = '%s_retval'%(typeName.replace(' ','_').replace('*','star'),)
178 print >>self.output, '%s %s;'%(typeName,name)
179 if self.outputHeader:
180 print >>self.outputHeader, 'extern %s %s;'%(typeName,name)
181 elif self.outputTests:
182 print >>self.outputTests, 'extern %s %s;'%(typeName,name)
183 info = self.testReturnValues[typeName] = name
184 return info
185
186 def getTestValuesArray(self, type):
187 typeName = self.getTypeName(type)
188 info = self.testValues.get(typeName)
189 if info is None:
190 name = '%s_values'%(typeName.replace(' ','_').replace('*','star'),)
191 print >>self.outputTests, 'static %s %s[] = {'%(typeName,name)
192 length = 0
193 for item in self.getTestValues(type):
194 print >>self.outputTests, '\t%s,'%(item,)
195 length += 1
196 print >>self.outputTests,'};'
197 info = self.testValues[typeName] = (name,length)
198 return info
199
200 def getTestValues(self, t):
201 if isinstance(t, BuiltinType):
202 if t.name=='float':
203 for i in ['0.0','-1.0','1.0']:
204 yield i+'f'
205 elif t.name=='double':
206 for i in ['0.0','-1.0','1.0']:
207 yield i
208 elif t.name in ('void *'):
209 yield '(void*) 0'
210 yield '(void*) -1'
211 else:
212 yield '(%s) 0'%(t.name,)
213 yield '(%s) -1'%(t.name,)
214 yield '(%s) 1'%(t.name,)
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000215 elif isinstance(t, EnumType):
216 for i in range(0, len(t.enumerators)):
217 yield 'enum%dval%d' % (t.index, i)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000218 elif isinstance(t, RecordType):
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000219 nonPadding = [f for f in t.fields
220 if not f.isPaddingBitField()]
221
222 if not nonPadding:
Daniel Dunbara83fb862009-01-15 04:24:17 +0000223 yield '{ }'
Daniel Dunbar900ed552009-01-29 07:36:46 +0000224 return
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000225
Daniel Dunbar900ed552009-01-29 07:36:46 +0000226 # FIXME: Use designated initializers to access non-first
227 # fields of unions.
228 if t.isUnion:
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000229 for v in self.getTestValues(nonPadding[0]):
230 yield '{ %s }' % v
Daniel Dunbar900ed552009-01-29 07:36:46 +0000231 return
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000232
233 fieldValues = map(list, map(self.getTestValues, nonPadding))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000234 for i,values in enumerate(fieldValues):
235 for v in values:
236 elements = map(random.choice,fieldValues)
237 elements[i] = v
238 yield '{ %s }'%(', '.join(elements))
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000239
Daniel Dunbara83fb862009-01-15 04:24:17 +0000240 elif isinstance(t, ComplexType):
241 for t in self.getTestValues(t.elementType):
Daniel Dunbar550faa32009-01-26 19:05:20 +0000242 yield '%s + %s * 1i'%(t,t)
243 elif isinstance(t, ArrayType):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000244 values = list(self.getTestValues(t.elementType))
245 if not values:
246 yield '{ }'
Daniel Dunbar550faa32009-01-26 19:05:20 +0000247 for i in range(t.numElements):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000248 for v in values:
Daniel Dunbar550faa32009-01-26 19:05:20 +0000249 elements = [random.choice(values) for i in range(t.numElements)]
Daniel Dunbara83fb862009-01-15 04:24:17 +0000250 elements[i] = v
251 yield '{ %s }'%(', '.join(elements))
252 else:
253 raise NotImplementedError,'Cannot make tests values of type: "%s"'%(t,)
254
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000255 def printSizeOfType(self, prefix, name, t, output=None, indent=2):
Eli Friedman98a71702009-05-25 21:38:01 +0000256 print >>output, '%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'%(indent, '', prefix, name, name)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000257 def printAlignOfType(self, prefix, name, t, output=None, indent=2):
Eli Friedman98a71702009-05-25 21:38:01 +0000258 print >>output, '%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'%(indent, '', prefix, name, name)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000259 def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):
260 if isinstance(t, RecordType):
261 for i,f in enumerate(t.fields):
Eli Friedman98a71702009-05-25 21:38:01 +0000262 if f.isBitField():
Daniel Dunbar122ed242009-05-07 23:19:55 +0000263 continue
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000264 fname = 'field%d' % i
Eli Friedman98a71702009-05-25 21:38:01 +0000265 print >>output, '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000266
Daniel Dunbara83fb862009-01-15 04:24:17 +0000267 def printValueOfType(self, prefix, name, t, output=None, indent=2):
268 if output is None:
269 output = self.output
270 if isinstance(t, BuiltinType):
Daniel Dunbar3dbe0b72010-09-27 20:13:19 +0000271 value_expr = name
272 if t.name.split(' ')[-1] == '_Bool':
273 # Hack to work around PR5579.
274 value_expr = "%s ? 2 : 0" % name
275
Daniel Dunbara83fb862009-01-15 04:24:17 +0000276 if t.name.endswith('long long'):
277 code = 'lld'
278 elif t.name.endswith('long'):
279 code = 'ld'
Daniel Dunbar3d2fd8d2010-09-27 20:13:22 +0000280 elif t.name.split(' ')[-1] in ('_Bool','char','short',
281 'int','unsigned'):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000282 code = 'd'
283 elif t.name in ('float','double'):
284 code = 'f'
285 elif t.name == 'long double':
286 code = 'Lf'
287 else:
288 code = 'p'
Daniel Dunbar3dbe0b72010-09-27 20:13:19 +0000289 print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(
290 indent, '', prefix, name, code, value_expr)
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000291 elif isinstance(t, EnumType):
292 print >>output, '%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000293 elif isinstance(t, RecordType):
294 if not t.fields:
295 print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name)
296 for i,f in enumerate(t.fields):
Daniel Dunbar122ed242009-05-07 23:19:55 +0000297 if f.isPaddingBitField():
298 continue
Daniel Dunbara83fb862009-01-15 04:24:17 +0000299 fname = '%s.field%d'%(name,i)
300 self.printValueOfType(prefix, fname, f, output=output, indent=indent)
301 elif isinstance(t, ComplexType):
302 self.printValueOfType(prefix, '(__real %s)'%name, t.elementType, output=output,indent=indent)
303 self.printValueOfType(prefix, '(__imag %s)'%name, t.elementType, output=output,indent=indent)
Daniel Dunbar550faa32009-01-26 19:05:20 +0000304 elif isinstance(t, ArrayType):
305 for i in range(t.numElements):
306 # Access in this fashion as a hackish way to portably
307 # access vectors.
Daniel Dunbare61e95f2009-01-29 08:48:06 +0000308 if t.isVector:
309 self.printValueOfType(prefix, '((%s*) &%s)[%d]'%(t.elementType,name,i), t.elementType, output=output,indent=indent)
310 else:
311 self.printValueOfType(prefix, '%s[%d]'%(name,i), t.elementType, output=output,indent=indent)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000312 else:
313 raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
314
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000315 def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2):
316 prefix = 'foo'
317 if output is None:
318 output = self.output
319 if isinstance(t, BuiltinType):
320 print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000321 elif isinstance(t, EnumType):
322 print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000323 elif isinstance(t, RecordType):
324 for i,f in enumerate(t.fields):
Daniel Dunbar122ed242009-05-07 23:19:55 +0000325 if f.isPaddingBitField():
326 continue
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000327 self.checkTypeValues('%s.field%d'%(nameLHS,i), '%s.field%d'%(nameRHS,i),
328 f, output=output, indent=indent)
329 if t.isUnion:
330 break
331 elif isinstance(t, ComplexType):
332 self.checkTypeValues('(__real %s)'%nameLHS, '(__real %s)'%nameRHS, t.elementType, output=output,indent=indent)
333 self.checkTypeValues('(__imag %s)'%nameLHS, '(__imag %s)'%nameRHS, t.elementType, output=output,indent=indent)
334 elif isinstance(t, ArrayType):
335 for i in range(t.numElements):
336 # Access in this fashion as a hackish way to portably
337 # access vectors.
338 if t.isVector:
339 self.checkTypeValues('((%s*) &%s)[%d]'%(t.elementType,nameLHS,i),
340 '((%s*) &%s)[%d]'%(t.elementType,nameRHS,i),
341 t.elementType, output=output,indent=indent)
342 else:
343 self.checkTypeValues('%s[%d]'%(nameLHS,i), '%s[%d]'%(nameRHS,i),
344 t.elementType, output=output,indent=indent)
345 else:
346 raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
347
Daniel Dunbara83fb862009-01-15 04:24:17 +0000348import sys
349
350def main():
351 from optparse import OptionParser, OptionGroup
352 parser = OptionParser("%prog [options] {indices}")
353 parser.add_option("", "--mode", dest="mode",
354 help="autogeneration mode (random or linear) [default %default]",
355 type='choice', choices=('random','linear'), default='linear')
356 parser.add_option("", "--count", dest="count",
357 help="autogenerate COUNT functions according to MODE",
358 type=int, default=0)
359 parser.add_option("", "--min", dest="minIndex", metavar="N",
360 help="start autogeneration with the Nth function type [default %default]",
361 type=int, default=0)
362 parser.add_option("", "--max", dest="maxIndex", metavar="N",
363 help="maximum index for random autogeneration [default %default]",
364 type=int, default=10000000)
365 parser.add_option("", "--seed", dest="seed",
366 help="random number generator seed [default %default]",
367 type=int, default=1)
368 parser.add_option("", "--use-random-seed", dest="useRandomSeed",
369 help="use random value for initial random number generator seed",
370 action='store_true', default=False)
Daniel Dunbar1ca717b2010-09-27 20:13:17 +0000371 parser.add_option("", "--skip", dest="skipTests",
372 help="add a test index to skip",
373 type=int, action='append', default=[])
Daniel Dunbara83fb862009-01-15 04:24:17 +0000374 parser.add_option("-o", "--output", dest="output", metavar="FILE",
375 help="write output to FILE [default %default]",
376 type=str, default='-')
377 parser.add_option("-O", "--output-header", dest="outputHeader", metavar="FILE",
378 help="write header file for output to FILE [default %default]",
379 type=str, default=None)
380 parser.add_option("-T", "--output-tests", dest="outputTests", metavar="FILE",
381 help="write function tests to FILE [default %default]",
382 type=str, default=None)
383 parser.add_option("-D", "--output-driver", dest="outputDriver", metavar="FILE",
384 help="write test driver to FILE [default %default]",
385 type=str, default=None)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000386 parser.add_option("", "--test-layout", dest="testLayout", metavar="FILE",
387 help="test structure layout",
388 action='store_true', default=False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000389
390 group = OptionGroup(parser, "Type Enumeration Options")
391 # Builtins - Ints
392 group.add_option("", "--no-char", dest="useChar",
393 help="do not generate char types",
394 action="store_false", default=True)
395 group.add_option("", "--no-short", dest="useShort",
396 help="do not generate short types",
397 action="store_false", default=True)
398 group.add_option("", "--no-int", dest="useInt",
399 help="do not generate int types",
400 action="store_false", default=True)
401 group.add_option("", "--no-long", dest="useLong",
402 help="do not generate long types",
403 action="store_false", default=True)
404 group.add_option("", "--no-long-long", dest="useLongLong",
405 help="do not generate long long types",
406 action="store_false", default=True)
407 group.add_option("", "--no-unsigned", dest="useUnsigned",
408 help="do not generate unsigned integer types",
409 action="store_false", default=True)
410
411 # Other builtins
412 group.add_option("", "--no-bool", dest="useBool",
413 help="do not generate bool types",
414 action="store_false", default=True)
415 group.add_option("", "--no-float", dest="useFloat",
416 help="do not generate float types",
417 action="store_false", default=True)
418 group.add_option("", "--no-double", dest="useDouble",
419 help="do not generate double types",
420 action="store_false", default=True)
421 group.add_option("", "--no-long-double", dest="useLongDouble",
422 help="do not generate long double types",
423 action="store_false", default=True)
424 group.add_option("", "--no-void-pointer", dest="useVoidPointer",
425 help="do not generate void* types",
426 action="store_false", default=True)
427
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000428 # Enumerations
429 group.add_option("", "--no-enums", dest="useEnum",
430 help="do not generate enum types",
431 action="store_false", default=True)
432
Daniel Dunbara83fb862009-01-15 04:24:17 +0000433 # Derived types
434 group.add_option("", "--no-array", dest="useArray",
435 help="do not generate record types",
436 action="store_false", default=True)
437 group.add_option("", "--no-complex", dest="useComplex",
438 help="do not generate complex types",
439 action="store_false", default=True)
440 group.add_option("", "--no-record", dest="useRecord",
441 help="do not generate record types",
442 action="store_false", default=True)
443 group.add_option("", "--no-union", dest="recordUseUnion",
444 help="do not generate union types",
445 action="store_false", default=True)
446 group.add_option("", "--no-vector", dest="useVector",
447 help="do not generate vector types",
448 action="store_false", default=True)
Daniel Dunbar122ed242009-05-07 23:19:55 +0000449 group.add_option("", "--no-bit-field", dest="useBitField",
450 help="do not generate bit-field record members",
451 action="store_false", default=True)
452 group.add_option("", "--no-builtins", dest="useBuiltins",
453 help="do not use any types",
454 action="store_false", default=True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000455
456 # Tuning
457 group.add_option("", "--no-function-return", dest="functionUseReturn",
458 help="do not generate return types for functions",
459 action="store_false", default=True)
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000460 group.add_option("", "--vector-types", dest="vectorTypes",
461 help="comma separated list of vector types (e.g., v2i32) [default %default]",
Daniel Dunbarec1abb92009-03-02 06:14:33 +0000462 action="store", type=str, default='v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32', metavar="N")
Daniel Dunbar122ed242009-05-07 23:19:55 +0000463 group.add_option("", "--bit-fields", dest="bitFields",
464 help="comma separated list 'type:width' bit-field specifiers [default %default]",
Daniel Dunbar3d2fd8d2010-09-27 20:13:22 +0000465 action="store", type=str, default=(
466 "char:0,char:4,int:0,unsigned:1,int:1,int:4,int:13,int:24"))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000467 group.add_option("", "--max-args", dest="functionMaxArgs",
468 help="maximum number of arguments per function [default %default]",
469 action="store", type=int, default=4, metavar="N")
470 group.add_option("", "--max-array", dest="arrayMaxSize",
471 help="maximum array size [default %default]",
472 action="store", type=int, default=4, metavar="N")
473 group.add_option("", "--max-record", dest="recordMaxSize",
474 help="maximum number of fields per record [default %default]",
475 action="store", type=int, default=4, metavar="N")
476 group.add_option("", "--max-record-depth", dest="recordMaxDepth",
477 help="maximum nested structure depth [default %default]",
478 action="store", type=int, default=None, metavar="N")
479 parser.add_option_group(group)
480 (opts, args) = parser.parse_args()
481
482 if not opts.useRandomSeed:
483 random.seed(opts.seed)
484
485 # Contruct type generator
486 builtins = []
Daniel Dunbar122ed242009-05-07 23:19:55 +0000487 if opts.useBuiltins:
488 ints = []
489 if opts.useChar: ints.append(('char',1))
490 if opts.useShort: ints.append(('short',2))
491 if opts.useInt: ints.append(('int',4))
492 # FIXME: Wrong size.
493 if opts.useLong: ints.append(('long',4))
494 if opts.useLongLong: ints.append(('long long',8))
495 if opts.useUnsigned:
496 ints = ([('unsigned %s'%i,s) for i,s in ints] +
497 [('signed %s'%i,s) for i,s in ints])
498 builtins.extend(ints)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000499
Daniel Dunbar122ed242009-05-07 23:19:55 +0000500 if opts.useBool: builtins.append(('_Bool',1))
501 if opts.useFloat: builtins.append(('float',4))
502 if opts.useDouble: builtins.append(('double',8))
503 if opts.useLongDouble: builtins.append(('long double',16))
504 # FIXME: Wrong size.
505 if opts.useVoidPointer: builtins.append(('void*',4))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000506
Daniel Dunbar550faa32009-01-26 19:05:20 +0000507 btg = FixedTypeGenerator([BuiltinType(n,s) for n,s in builtins])
Daniel Dunbar122ed242009-05-07 23:19:55 +0000508
509 bitfields = []
510 for specifier in opts.bitFields.split(','):
511 if not specifier.strip():
512 continue
513 name,width = specifier.strip().split(':', 1)
514 bitfields.append(BuiltinType(name,None,int(width)))
515 bftg = FixedTypeGenerator(bitfields)
516
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000517 charType = BuiltinType('char',1)
518 shortType = BuiltinType('short',2)
519 intType = BuiltinType('int',4)
520 longlongType = BuiltinType('long long',8)
521 floatType = BuiltinType('float',4)
522 doubleType = BuiltinType('double',8)
523 sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType])
Daniel Dunbara83fb862009-01-15 04:24:17 +0000524
525 atg = AnyTypeGenerator()
526 artg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000527 def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000528 atg.addGenerator(btg)
Daniel Dunbar122ed242009-05-07 23:19:55 +0000529 if useBitField and opts.useBitField:
530 atg.addGenerator(bftg)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000531 if useRecord and opts.useRecord:
532 assert subgen
Daniel Dunbar122ed242009-05-07 23:19:55 +0000533 atg.addGenerator(RecordTypeGenerator(subfieldgen, opts.recordUseUnion,
Daniel Dunbara83fb862009-01-15 04:24:17 +0000534 opts.recordMaxSize))
535 if opts.useComplex:
536 # FIXME: Allow overriding builtins here
537 atg.addGenerator(ComplexTypeGenerator(sbtg))
538 if useArray and opts.useArray:
539 assert subgen
540 atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize))
541 if opts.useVector:
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000542 vTypes = []
543 for i,t in enumerate(opts.vectorTypes.split(',')):
544 m = re.match('v([1-9][0-9]*)([if][1-9][0-9]*)', t.strip())
545 if not m:
546 parser.error('Invalid vector type: %r' % t)
547 count,kind = m.groups()
548 count = int(count)
549 type = { 'i8' : charType,
550 'i16' : shortType,
551 'i32' : intType,
552 'i64' : longlongType,
553 'f32' : floatType,
554 'f64' : doubleType,
555 }.get(kind)
556 if not type:
557 parser.error('Invalid vector type: %r' % t)
558 vTypes.append(ArrayType(i, True, type, count * type.size))
559
560 atg.addGenerator(FixedTypeGenerator(vTypes))
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000561 if opts.useEnum:
562 atg.addGenerator(EnumTypeGenerator([None, '-1', '1', '1u'], 1, 4))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000563
564 if opts.recordMaxDepth is None:
565 # Fully recursive, just avoid top-level arrays.
Daniel Dunbar122ed242009-05-07 23:19:55 +0000566 subFTG = AnyTypeGenerator()
Daniel Dunbara83fb862009-01-15 04:24:17 +0000567 subTG = AnyTypeGenerator()
568 atg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000569 makeGenerator(subFTG, atg, atg, True, True, True)
570 makeGenerator(subTG, atg, subFTG, True, True, False)
571 makeGenerator(atg, subTG, subFTG, True, False, False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000572 else:
573 # Make a chain of type generators, each builds smaller
574 # structures.
575 base = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000576 fbase = AnyTypeGenerator()
577 makeGenerator(base, None, None, False, False, False)
578 makeGenerator(fbase, None, None, False, False, True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000579 for i in range(opts.recordMaxDepth):
580 n = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000581 fn = AnyTypeGenerator()
582 makeGenerator(n, base, fbase, True, True, False)
583 makeGenerator(fn, base, fbase, True, True, True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000584 base = n
Daniel Dunbar122ed242009-05-07 23:19:55 +0000585 fbase = fn
Daniel Dunbara83fb862009-01-15 04:24:17 +0000586 atg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000587 makeGenerator(atg, base, fbase, True, False, False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000588
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000589 if opts.testLayout:
590 ftg = atg
591 else:
592 ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000593
594 # Override max,min,count if finite
595 if opts.maxIndex is None:
596 if ftg.cardinality is aleph0:
597 opts.maxIndex = 10000000
598 else:
599 opts.maxIndex = ftg.cardinality
600 opts.maxIndex = min(opts.maxIndex, ftg.cardinality)
601 opts.minIndex = max(0,min(opts.maxIndex-1, opts.minIndex))
602 if not opts.mode=='random':
603 opts.count = min(opts.count, opts.maxIndex-opts.minIndex)
604
605 if opts.output=='-':
606 output = sys.stdout
607 else:
608 output = open(opts.output,'w')
609 atexit.register(lambda: output.close())
610
611 outputHeader = None
612 if opts.outputHeader:
613 outputHeader = open(opts.outputHeader,'w')
614 atexit.register(lambda: outputHeader.close())
615
616 outputTests = None
617 if opts.outputTests:
618 outputTests = open(opts.outputTests,'w')
619 atexit.register(lambda: outputTests.close())
620
621 outputDriver = None
622 if opts.outputDriver:
623 outputDriver = open(opts.outputDriver,'w')
624 atexit.register(lambda: outputDriver.close())
625
626 info = ''
627 info += '// %s\n'%(' '.join(sys.argv),)
628 info += '// Generated: %s\n'%(time.strftime('%Y-%m-%d %H:%M'),)
629 info += '// Cardinality of function generator: %s\n'%(ftg.cardinality,)
630 info += '// Cardinality of type generator: %s\n'%(atg.cardinality,)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000631
632 if opts.testLayout:
633 info += '\n#include <stdio.h>'
Daniel Dunbara83fb862009-01-15 04:24:17 +0000634
635 P = TypePrinter(output,
636 outputHeader=outputHeader,
637 outputTests=outputTests,
638 outputDriver=outputDriver,
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000639 headerName=opts.outputHeader,
Daniel Dunbara83fb862009-01-15 04:24:17 +0000640 info=info)
641
642 def write(N):
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000643 try:
Daniel Dunbara83fb862009-01-15 04:24:17 +0000644 FT = ftg.get(N)
645 except RuntimeError,e:
646 if e.args[0]=='maximum recursion depth exceeded':
647 print >>sys.stderr,'WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,)
648 return
649 raise
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000650 if opts.testLayout:
651 P.writeLayoutTest(N, FT)
652 else:
653 P.writeFunction(N, FT)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000654
655 if args:
656 [write(int(a)) for a in args]
657
Daniel Dunbar1ca717b2010-09-27 20:13:17 +0000658 skipTests = set(opts.skipTests)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000659 for i in range(opts.count):
660 if opts.mode=='linear':
661 index = opts.minIndex + i
662 else:
663 index = opts.minIndex + int((opts.maxIndex-opts.minIndex) * random.random())
Daniel Dunbar1ca717b2010-09-27 20:13:17 +0000664 if index in skipTests:
665 continue
Daniel Dunbara83fb862009-01-15 04:24:17 +0000666 write(index)
667
668 P.finish()
669
670if __name__=='__main__':
671 main()
672