blob: afe58e58d0ff341e423f2c2fd46674d86a7423cf [file] [log] [blame]
Daniel Dunbara83fb862009-01-15 04:24:17 +00001#!/usr/bin/python
2
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 Dunbara83fb862009-01-15 04:24:17 +000026
27 if info:
28 for f in (self.output,self.outputHeader,self.outputTests,self.outputDriver):
29 if f:
30 print >>f,info
31
32 if self.writeBody:
33 print >>self.output, '#include <stdio.h>\n'
34 if self.outputTests:
Daniel Dunbar9dd60b42009-02-17 23:13:43 +000035 print >>self.outputTests, '#include <stdio.h>'
36 print >>self.outputTests, '#include <string.h>'
37 print >>self.outputTests, '#include <assert.h>\n'
Daniel Dunbara83fb862009-01-15 04:24:17 +000038
39 if headerName:
40 for f in (self.output,self.outputTests,self.outputDriver):
41 if f is not None:
42 print >>f, '#include "%s"\n'%(headerName,)
43
44 if self.outputDriver:
Daniel Dunbar9dd60b42009-02-17 23:13:43 +000045 print >>self.outputDriver, '#include <stdio.h>\n'
Daniel Dunbara83fb862009-01-15 04:24:17 +000046 print >>self.outputDriver, 'int main(int argc, char **argv) {'
47
48 def finish(self):
Daniel Dunbar5ce61572009-01-28 02:01:23 +000049 if self.layoutTests:
50 print >>self.output, 'int main(int argc, char **argv) {'
51 for f in self.layoutTests:
52 print >>self.output, ' %s();' % f
53 print >>self.output, ' return 0;'
54 print >>self.output, '}'
55
Daniel Dunbara83fb862009-01-15 04:24:17 +000056 if self.outputDriver:
Daniel Dunbar9dd60b42009-02-17 23:13:43 +000057 print >>self.outputDriver, ' printf("DONE\\n");'
Daniel Dunbara83fb862009-01-15 04:24:17 +000058 print >>self.outputDriver, ' return 0;'
Daniel Dunbar5ce61572009-01-28 02:01:23 +000059 print >>self.outputDriver, '}'
Daniel Dunbara83fb862009-01-15 04:24:17 +000060
61 def getTypeName(self, T):
62 if isinstance(T,BuiltinType):
63 return T.name
64 name = self.types.get(T)
65 if name is None:
66 name = 'T%d'%(len(self.types),)
67 # Reserve slot
68 self.types[T] = None
69 if self.outputHeader:
70 print >>self.outputHeader,T.getTypedefDef(name, self)
71 else:
72 print >>self.output,T.getTypedefDef(name, self)
73 if self.outputTests:
74 print >>self.outputTests,T.getTypedefDef(name, self)
75 self.types[T] = name
76 return name
77
Daniel Dunbar5ce61572009-01-28 02:01:23 +000078 def writeLayoutTest(self, i, ty):
79 tyName = self.getTypeName(ty)
80 tyNameClean = tyName.replace(' ','_').replace('*','star')
81 fnName = 'test_%s' % tyNameClean
82
83 print >>self.output,'void %s(void) {' % fnName
84 self.printSizeOfType(' %s'%fnName, tyName, ty, self.output)
85 self.printAlignOfType(' %s'%fnName, tyName, ty, self.output)
86 self.printOffsetsOfType(' %s'%fnName, tyName, ty, self.output)
87 print >>self.output,'}'
88 print >>self.output
89
90 self.layoutTests.append(fnName)
91
Daniel Dunbara83fb862009-01-15 04:24:17 +000092 def writeFunction(self, i, FT):
93 args = ', '.join(['%s arg%d'%(self.getTypeName(t),i) for i,t in enumerate(FT.argTypes)])
94 if not args:
95 args = 'void'
96
97 if FT.returnType is None:
98 retvalName = None
99 retvalTypeName = 'void'
100 else:
101 retvalTypeName = self.getTypeName(FT.returnType)
102 if self.writeBody or self.outputTests:
103 retvalName = self.getTestReturnValue(FT.returnType)
104
105 fnName = 'fn%d'%(FT.index,)
106 if self.outputHeader:
107 print >>self.outputHeader,'%s %s(%s);'%(retvalTypeName, fnName, args)
108 elif self.outputTests:
109 print >>self.outputTests,'%s %s(%s);'%(retvalTypeName, fnName, args)
110
111 print >>self.output,'%s %s(%s)'%(retvalTypeName, fnName, args),
112 if self.writeBody:
113 print >>self.output, '{'
114
115 for i,t in enumerate(FT.argTypes):
116 self.printValueOfType(' %s'%fnName, 'arg%d'%i, t)
117
118 if retvalName is not None:
119 print >>self.output, ' return %s;'%(retvalName,)
120 print >>self.output, '}'
121 else:
122 print >>self.output, '{}'
123 print >>self.output
124
125 if self.outputDriver:
126 print >>self.outputDriver, ' { extern void test_%s(void); test_%s(); }\n'%(fnName,fnName,)
127
128 if self.outputTests:
129 if self.outputHeader:
130 print >>self.outputHeader, 'void test_%s(void);'%(fnName,)
131
132 if retvalName is None:
133 retvalTests = None
134 else:
135 retvalTests = self.getTestValuesArray(FT.returnType)
136 tests = map(self.getTestValuesArray, FT.argTypes)
137 print >>self.outputTests, 'void test_%s(void) {'%(fnName,)
138
139 if retvalTests is not None:
140 print >>self.outputTests, ' printf("%s: testing return.\\n");'%(fnName,)
141 print >>self.outputTests, ' for (int i=0; i<%d; ++i) {'%(retvalTests[1],)
142 args = ', '.join(['%s[%d]'%(t,randrange(l)) for t,l in tests])
143 print >>self.outputTests, ' %s RV;'%(retvalTypeName,)
144 print >>self.outputTests, ' %s = %s[i];'%(retvalName, retvalTests[0])
145 print >>self.outputTests, ' RV = %s(%s);'%(fnName, args)
146 self.printValueOfType(' %s_RV'%fnName, 'RV', FT.returnType, output=self.outputTests, indent=4)
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000147 self.checkTypeValues('RV', '%s[i]' % retvalTests[0], FT.returnType, output=self.outputTests, indent=4)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000148 print >>self.outputTests, ' }'
149
150 if tests:
151 print >>self.outputTests, ' printf("%s: testing arguments.\\n");'%(fnName,)
152 for i,(array,length) in enumerate(tests):
153 for j in range(length):
154 args = ['%s[%d]'%(t,randrange(l)) for t,l in tests]
155 args[i] = '%s[%d]'%(array,j)
156 print >>self.outputTests, ' %s(%s);'%(fnName, ', '.join(args),)
157 print >>self.outputTests, '}'
158
159 def getTestReturnValue(self, type):
160 typeName = self.getTypeName(type)
161 info = self.testReturnValues.get(typeName)
162 if info is None:
163 name = '%s_retval'%(typeName.replace(' ','_').replace('*','star'),)
164 print >>self.output, '%s %s;'%(typeName,name)
165 if self.outputHeader:
166 print >>self.outputHeader, 'extern %s %s;'%(typeName,name)
167 elif self.outputTests:
168 print >>self.outputTests, 'extern %s %s;'%(typeName,name)
169 info = self.testReturnValues[typeName] = name
170 return info
171
172 def getTestValuesArray(self, type):
173 typeName = self.getTypeName(type)
174 info = self.testValues.get(typeName)
175 if info is None:
176 name = '%s_values'%(typeName.replace(' ','_').replace('*','star'),)
177 print >>self.outputTests, 'static %s %s[] = {'%(typeName,name)
178 length = 0
179 for item in self.getTestValues(type):
180 print >>self.outputTests, '\t%s,'%(item,)
181 length += 1
182 print >>self.outputTests,'};'
183 info = self.testValues[typeName] = (name,length)
184 return info
185
186 def getTestValues(self, t):
187 if isinstance(t, BuiltinType):
188 if t.name=='float':
189 for i in ['0.0','-1.0','1.0']:
190 yield i+'f'
191 elif t.name=='double':
192 for i in ['0.0','-1.0','1.0']:
193 yield i
194 elif t.name in ('void *'):
195 yield '(void*) 0'
196 yield '(void*) -1'
197 else:
198 yield '(%s) 0'%(t.name,)
199 yield '(%s) -1'%(t.name,)
200 yield '(%s) 1'%(t.name,)
201 elif isinstance(t, RecordType):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000202 if not t.fields:
203 yield '{ }'
Daniel Dunbar900ed552009-01-29 07:36:46 +0000204 return
205 # FIXME: Use designated initializers to access non-first
206 # fields of unions.
207 if t.isUnion:
Daniel Dunbar122ed242009-05-07 23:19:55 +0000208 firstNonPadding = None
209 for t in t.fields:
210 if not t.isPaddingBitField():
211 firstNonPadding = t
212 break
213 if firstNonPadding:
214 for v in self.getTestValues(firstNonPadding):
215 yield '{ %s }' % v
216 else:
217 yield '{ }'
Daniel Dunbar900ed552009-01-29 07:36:46 +0000218 return
Daniel Dunbar122ed242009-05-07 23:19:55 +0000219 fieldValues = [list(self.getTestValues(f))
220 for f in t.fields
221 if not f.isPaddingBitField()]
Daniel Dunbara83fb862009-01-15 04:24:17 +0000222 for i,values in enumerate(fieldValues):
223 for v in values:
224 elements = map(random.choice,fieldValues)
225 elements[i] = v
226 yield '{ %s }'%(', '.join(elements))
227 elif isinstance(t, ComplexType):
228 for t in self.getTestValues(t.elementType):
Daniel Dunbar550faa32009-01-26 19:05:20 +0000229 yield '%s + %s * 1i'%(t,t)
230 elif isinstance(t, ArrayType):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000231 values = list(self.getTestValues(t.elementType))
232 if not values:
233 yield '{ }'
Daniel Dunbar550faa32009-01-26 19:05:20 +0000234 for i in range(t.numElements):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000235 for v in values:
Daniel Dunbar550faa32009-01-26 19:05:20 +0000236 elements = [random.choice(values) for i in range(t.numElements)]
Daniel Dunbara83fb862009-01-15 04:24:17 +0000237 elements[i] = v
238 yield '{ %s }'%(', '.join(elements))
239 else:
240 raise NotImplementedError,'Cannot make tests values of type: "%s"'%(t,)
241
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000242 def printSizeOfType(self, prefix, name, t, output=None, indent=2):
243 print >>output, '%*sprintf("%s: sizeof(%s) = %%ld\\n", sizeof(%s));'%(indent, '', prefix, name, name)
244 def printAlignOfType(self, prefix, name, t, output=None, indent=2):
245 print >>output, '%*sprintf("%s: __alignof__(%s) = %%ld\\n", __alignof__(%s));'%(indent, '', prefix, name, name)
246 def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):
247 if isinstance(t, RecordType):
248 for i,f in enumerate(t.fields):
Daniel Dunbar122ed242009-05-07 23:19:55 +0000249 if f.isPaddingBitField():
250 continue
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000251 fname = 'field%d' % i
252 print >>output, '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", __builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname)
253
Daniel Dunbara83fb862009-01-15 04:24:17 +0000254 def printValueOfType(self, prefix, name, t, output=None, indent=2):
255 if output is None:
256 output = self.output
257 if isinstance(t, BuiltinType):
258 if t.name.endswith('long long'):
259 code = 'lld'
260 elif t.name.endswith('long'):
261 code = 'ld'
262 elif t.name.split(' ')[-1] in ('_Bool','char','short','int'):
263 code = 'd'
264 elif t.name in ('float','double'):
265 code = 'f'
266 elif t.name == 'long double':
267 code = 'Lf'
268 else:
269 code = 'p'
270 print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(indent, '', prefix, name, code, name)
271 elif isinstance(t, RecordType):
272 if not t.fields:
273 print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name)
274 for i,f in enumerate(t.fields):
Daniel Dunbar122ed242009-05-07 23:19:55 +0000275 if f.isPaddingBitField():
276 continue
Daniel Dunbara83fb862009-01-15 04:24:17 +0000277 fname = '%s.field%d'%(name,i)
278 self.printValueOfType(prefix, fname, f, output=output, indent=indent)
279 elif isinstance(t, ComplexType):
280 self.printValueOfType(prefix, '(__real %s)'%name, t.elementType, output=output,indent=indent)
281 self.printValueOfType(prefix, '(__imag %s)'%name, t.elementType, output=output,indent=indent)
Daniel Dunbar550faa32009-01-26 19:05:20 +0000282 elif isinstance(t, ArrayType):
283 for i in range(t.numElements):
284 # Access in this fashion as a hackish way to portably
285 # access vectors.
Daniel Dunbare61e95f2009-01-29 08:48:06 +0000286 if t.isVector:
287 self.printValueOfType(prefix, '((%s*) &%s)[%d]'%(t.elementType,name,i), t.elementType, output=output,indent=indent)
288 else:
289 self.printValueOfType(prefix, '%s[%d]'%(name,i), t.elementType, output=output,indent=indent)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000290 else:
291 raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
292
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000293 def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2):
294 prefix = 'foo'
295 if output is None:
296 output = self.output
297 if isinstance(t, BuiltinType):
298 print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
299 elif isinstance(t, RecordType):
300 for i,f in enumerate(t.fields):
Daniel Dunbar122ed242009-05-07 23:19:55 +0000301 if f.isPaddingBitField():
302 continue
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000303 self.checkTypeValues('%s.field%d'%(nameLHS,i), '%s.field%d'%(nameRHS,i),
304 f, output=output, indent=indent)
305 if t.isUnion:
306 break
307 elif isinstance(t, ComplexType):
308 self.checkTypeValues('(__real %s)'%nameLHS, '(__real %s)'%nameRHS, t.elementType, output=output,indent=indent)
309 self.checkTypeValues('(__imag %s)'%nameLHS, '(__imag %s)'%nameRHS, t.elementType, output=output,indent=indent)
310 elif isinstance(t, ArrayType):
311 for i in range(t.numElements):
312 # Access in this fashion as a hackish way to portably
313 # access vectors.
314 if t.isVector:
315 self.checkTypeValues('((%s*) &%s)[%d]'%(t.elementType,nameLHS,i),
316 '((%s*) &%s)[%d]'%(t.elementType,nameRHS,i),
317 t.elementType, output=output,indent=indent)
318 else:
319 self.checkTypeValues('%s[%d]'%(nameLHS,i), '%s[%d]'%(nameRHS,i),
320 t.elementType, output=output,indent=indent)
321 else:
322 raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
323
Daniel Dunbara83fb862009-01-15 04:24:17 +0000324import sys
325
326def main():
327 from optparse import OptionParser, OptionGroup
328 parser = OptionParser("%prog [options] {indices}")
329 parser.add_option("", "--mode", dest="mode",
330 help="autogeneration mode (random or linear) [default %default]",
331 type='choice', choices=('random','linear'), default='linear')
332 parser.add_option("", "--count", dest="count",
333 help="autogenerate COUNT functions according to MODE",
334 type=int, default=0)
335 parser.add_option("", "--min", dest="minIndex", metavar="N",
336 help="start autogeneration with the Nth function type [default %default]",
337 type=int, default=0)
338 parser.add_option("", "--max", dest="maxIndex", metavar="N",
339 help="maximum index for random autogeneration [default %default]",
340 type=int, default=10000000)
341 parser.add_option("", "--seed", dest="seed",
342 help="random number generator seed [default %default]",
343 type=int, default=1)
344 parser.add_option("", "--use-random-seed", dest="useRandomSeed",
345 help="use random value for initial random number generator seed",
346 action='store_true', default=False)
347 parser.add_option("-o", "--output", dest="output", metavar="FILE",
348 help="write output to FILE [default %default]",
349 type=str, default='-')
350 parser.add_option("-O", "--output-header", dest="outputHeader", metavar="FILE",
351 help="write header file for output to FILE [default %default]",
352 type=str, default=None)
353 parser.add_option("-T", "--output-tests", dest="outputTests", metavar="FILE",
354 help="write function tests to FILE [default %default]",
355 type=str, default=None)
356 parser.add_option("-D", "--output-driver", dest="outputDriver", metavar="FILE",
357 help="write test driver to FILE [default %default]",
358 type=str, default=None)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000359 parser.add_option("", "--test-layout", dest="testLayout", metavar="FILE",
360 help="test structure layout",
361 action='store_true', default=False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000362
363 group = OptionGroup(parser, "Type Enumeration Options")
364 # Builtins - Ints
365 group.add_option("", "--no-char", dest="useChar",
366 help="do not generate char types",
367 action="store_false", default=True)
368 group.add_option("", "--no-short", dest="useShort",
369 help="do not generate short types",
370 action="store_false", default=True)
371 group.add_option("", "--no-int", dest="useInt",
372 help="do not generate int types",
373 action="store_false", default=True)
374 group.add_option("", "--no-long", dest="useLong",
375 help="do not generate long types",
376 action="store_false", default=True)
377 group.add_option("", "--no-long-long", dest="useLongLong",
378 help="do not generate long long types",
379 action="store_false", default=True)
380 group.add_option("", "--no-unsigned", dest="useUnsigned",
381 help="do not generate unsigned integer types",
382 action="store_false", default=True)
383
384 # Other builtins
385 group.add_option("", "--no-bool", dest="useBool",
386 help="do not generate bool types",
387 action="store_false", default=True)
388 group.add_option("", "--no-float", dest="useFloat",
389 help="do not generate float types",
390 action="store_false", default=True)
391 group.add_option("", "--no-double", dest="useDouble",
392 help="do not generate double types",
393 action="store_false", default=True)
394 group.add_option("", "--no-long-double", dest="useLongDouble",
395 help="do not generate long double types",
396 action="store_false", default=True)
397 group.add_option("", "--no-void-pointer", dest="useVoidPointer",
398 help="do not generate void* types",
399 action="store_false", default=True)
400
401 # Derived types
402 group.add_option("", "--no-array", dest="useArray",
403 help="do not generate record types",
404 action="store_false", default=True)
405 group.add_option("", "--no-complex", dest="useComplex",
406 help="do not generate complex types",
407 action="store_false", default=True)
408 group.add_option("", "--no-record", dest="useRecord",
409 help="do not generate record types",
410 action="store_false", default=True)
411 group.add_option("", "--no-union", dest="recordUseUnion",
412 help="do not generate union types",
413 action="store_false", default=True)
414 group.add_option("", "--no-vector", dest="useVector",
415 help="do not generate vector types",
416 action="store_false", default=True)
Daniel Dunbar122ed242009-05-07 23:19:55 +0000417 group.add_option("", "--no-bit-field", dest="useBitField",
418 help="do not generate bit-field record members",
419 action="store_false", default=True)
420 group.add_option("", "--no-builtins", dest="useBuiltins",
421 help="do not use any types",
422 action="store_false", default=True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000423
424 # Tuning
425 group.add_option("", "--no-function-return", dest="functionUseReturn",
426 help="do not generate return types for functions",
427 action="store_false", default=True)
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000428 group.add_option("", "--vector-types", dest="vectorTypes",
429 help="comma separated list of vector types (e.g., v2i32) [default %default]",
Daniel Dunbarec1abb92009-03-02 06:14:33 +0000430 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 +0000431 group.add_option("", "--bit-fields", dest="bitFields",
432 help="comma separated list 'type:width' bit-field specifiers [default %default]",
Daniel Dunbar238a3182009-05-08 20:10:52 +0000433 action="store", type=str, default="char:0,char:4,unsigned:0,unsigned:4,unsigned:13,unsigned:24")
Daniel Dunbara83fb862009-01-15 04:24:17 +0000434 group.add_option("", "--max-args", dest="functionMaxArgs",
435 help="maximum number of arguments per function [default %default]",
436 action="store", type=int, default=4, metavar="N")
437 group.add_option("", "--max-array", dest="arrayMaxSize",
438 help="maximum array size [default %default]",
439 action="store", type=int, default=4, metavar="N")
440 group.add_option("", "--max-record", dest="recordMaxSize",
441 help="maximum number of fields per record [default %default]",
442 action="store", type=int, default=4, metavar="N")
443 group.add_option("", "--max-record-depth", dest="recordMaxDepth",
444 help="maximum nested structure depth [default %default]",
445 action="store", type=int, default=None, metavar="N")
446 parser.add_option_group(group)
447 (opts, args) = parser.parse_args()
448
449 if not opts.useRandomSeed:
450 random.seed(opts.seed)
451
452 # Contruct type generator
453 builtins = []
Daniel Dunbar122ed242009-05-07 23:19:55 +0000454 if opts.useBuiltins:
455 ints = []
456 if opts.useChar: ints.append(('char',1))
457 if opts.useShort: ints.append(('short',2))
458 if opts.useInt: ints.append(('int',4))
459 # FIXME: Wrong size.
460 if opts.useLong: ints.append(('long',4))
461 if opts.useLongLong: ints.append(('long long',8))
462 if opts.useUnsigned:
463 ints = ([('unsigned %s'%i,s) for i,s in ints] +
464 [('signed %s'%i,s) for i,s in ints])
465 builtins.extend(ints)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000466
Daniel Dunbar122ed242009-05-07 23:19:55 +0000467 if opts.useBool: builtins.append(('_Bool',1))
468 if opts.useFloat: builtins.append(('float',4))
469 if opts.useDouble: builtins.append(('double',8))
470 if opts.useLongDouble: builtins.append(('long double',16))
471 # FIXME: Wrong size.
472 if opts.useVoidPointer: builtins.append(('void*',4))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000473
Daniel Dunbar550faa32009-01-26 19:05:20 +0000474 btg = FixedTypeGenerator([BuiltinType(n,s) for n,s in builtins])
Daniel Dunbar122ed242009-05-07 23:19:55 +0000475
476 bitfields = []
477 for specifier in opts.bitFields.split(','):
478 if not specifier.strip():
479 continue
480 name,width = specifier.strip().split(':', 1)
481 bitfields.append(BuiltinType(name,None,int(width)))
482 bftg = FixedTypeGenerator(bitfields)
483
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000484 charType = BuiltinType('char',1)
485 shortType = BuiltinType('short',2)
486 intType = BuiltinType('int',4)
487 longlongType = BuiltinType('long long',8)
488 floatType = BuiltinType('float',4)
489 doubleType = BuiltinType('double',8)
490 sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType])
Daniel Dunbara83fb862009-01-15 04:24:17 +0000491
492 atg = AnyTypeGenerator()
493 artg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000494 def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000495 atg.addGenerator(btg)
Daniel Dunbar122ed242009-05-07 23:19:55 +0000496 if useBitField and opts.useBitField:
497 atg.addGenerator(bftg)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000498 if useRecord and opts.useRecord:
499 assert subgen
Daniel Dunbar122ed242009-05-07 23:19:55 +0000500 atg.addGenerator(RecordTypeGenerator(subfieldgen, opts.recordUseUnion,
Daniel Dunbara83fb862009-01-15 04:24:17 +0000501 opts.recordMaxSize))
502 if opts.useComplex:
503 # FIXME: Allow overriding builtins here
504 atg.addGenerator(ComplexTypeGenerator(sbtg))
505 if useArray and opts.useArray:
506 assert subgen
507 atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize))
508 if opts.useVector:
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000509 vTypes = []
510 for i,t in enumerate(opts.vectorTypes.split(',')):
511 m = re.match('v([1-9][0-9]*)([if][1-9][0-9]*)', t.strip())
512 if not m:
513 parser.error('Invalid vector type: %r' % t)
514 count,kind = m.groups()
515 count = int(count)
516 type = { 'i8' : charType,
517 'i16' : shortType,
518 'i32' : intType,
519 'i64' : longlongType,
520 'f32' : floatType,
521 'f64' : doubleType,
522 }.get(kind)
523 if not type:
524 parser.error('Invalid vector type: %r' % t)
525 vTypes.append(ArrayType(i, True, type, count * type.size))
526
527 atg.addGenerator(FixedTypeGenerator(vTypes))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000528
529 if opts.recordMaxDepth is None:
530 # Fully recursive, just avoid top-level arrays.
Daniel Dunbar122ed242009-05-07 23:19:55 +0000531 subFTG = AnyTypeGenerator()
Daniel Dunbara83fb862009-01-15 04:24:17 +0000532 subTG = AnyTypeGenerator()
533 atg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000534 makeGenerator(subFTG, atg, atg, True, True, True)
535 makeGenerator(subTG, atg, subFTG, True, True, False)
536 makeGenerator(atg, subTG, subFTG, True, False, False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000537 else:
538 # Make a chain of type generators, each builds smaller
539 # structures.
540 base = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000541 fbase = AnyTypeGenerator()
542 makeGenerator(base, None, None, False, False, False)
543 makeGenerator(fbase, None, None, False, False, True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000544 for i in range(opts.recordMaxDepth):
545 n = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000546 fn = AnyTypeGenerator()
547 makeGenerator(n, base, fbase, True, True, False)
548 makeGenerator(fn, base, fbase, True, True, True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000549 base = n
Daniel Dunbar122ed242009-05-07 23:19:55 +0000550 fbase = fn
Daniel Dunbara83fb862009-01-15 04:24:17 +0000551 atg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000552 makeGenerator(atg, base, fbase, True, False, False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000553
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000554 if opts.testLayout:
555 ftg = atg
556 else:
557 ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000558
559 # Override max,min,count if finite
560 if opts.maxIndex is None:
561 if ftg.cardinality is aleph0:
562 opts.maxIndex = 10000000
563 else:
564 opts.maxIndex = ftg.cardinality
565 opts.maxIndex = min(opts.maxIndex, ftg.cardinality)
566 opts.minIndex = max(0,min(opts.maxIndex-1, opts.minIndex))
567 if not opts.mode=='random':
568 opts.count = min(opts.count, opts.maxIndex-opts.minIndex)
569
570 if opts.output=='-':
571 output = sys.stdout
572 else:
573 output = open(opts.output,'w')
574 atexit.register(lambda: output.close())
575
576 outputHeader = None
577 if opts.outputHeader:
578 outputHeader = open(opts.outputHeader,'w')
579 atexit.register(lambda: outputHeader.close())
580
581 outputTests = None
582 if opts.outputTests:
583 outputTests = open(opts.outputTests,'w')
584 atexit.register(lambda: outputTests.close())
585
586 outputDriver = None
587 if opts.outputDriver:
588 outputDriver = open(opts.outputDriver,'w')
589 atexit.register(lambda: outputDriver.close())
590
591 info = ''
592 info += '// %s\n'%(' '.join(sys.argv),)
593 info += '// Generated: %s\n'%(time.strftime('%Y-%m-%d %H:%M'),)
594 info += '// Cardinality of function generator: %s\n'%(ftg.cardinality,)
595 info += '// Cardinality of type generator: %s\n'%(atg.cardinality,)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000596
597 if opts.testLayout:
598 info += '\n#include <stdio.h>'
Daniel Dunbara83fb862009-01-15 04:24:17 +0000599
600 P = TypePrinter(output,
601 outputHeader=outputHeader,
602 outputTests=outputTests,
603 outputDriver=outputDriver,
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000604 headerName=opts.outputHeader,
Daniel Dunbara83fb862009-01-15 04:24:17 +0000605 info=info)
606
607 def write(N):
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000608 try:
Daniel Dunbara83fb862009-01-15 04:24:17 +0000609 FT = ftg.get(N)
610 except RuntimeError,e:
611 if e.args[0]=='maximum recursion depth exceeded':
612 print >>sys.stderr,'WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,)
613 return
614 raise
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000615 if opts.testLayout:
616 P.writeLayoutTest(N, FT)
617 else:
618 P.writeFunction(N, FT)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000619
620 if args:
621 [write(int(a)) for a in args]
622
623 for i in range(opts.count):
624 if opts.mode=='linear':
625 index = opts.minIndex + i
626 else:
627 index = opts.minIndex + int((opts.maxIndex-opts.minIndex) * random.random())
628 write(index)
629
630 P.finish()
631
632if __name__=='__main__':
633 main()
634