1*e5dd7070Spatrick#!/usr/bin/env python 2*e5dd7070Spatrick 3*e5dd7070Spatrickfrom __future__ import absolute_import, division, print_function 4*e5dd7070Spatrickfrom pprint import pprint 5*e5dd7070Spatrickimport random, atexit, time 6*e5dd7070Spatrickfrom random import randrange 7*e5dd7070Spatrickimport re 8*e5dd7070Spatrick 9*e5dd7070Spatrickfrom Enumeration import * 10*e5dd7070Spatrickfrom TypeGen import * 11*e5dd7070Spatrick 12*e5dd7070Spatrick#### 13*e5dd7070Spatrick 14*e5dd7070Spatrickclass TypePrinter(object): 15*e5dd7070Spatrick def __init__(self, output, outputHeader=None, 16*e5dd7070Spatrick outputTests=None, outputDriver=None, 17*e5dd7070Spatrick headerName=None, info=None): 18*e5dd7070Spatrick self.output = output 19*e5dd7070Spatrick self.outputHeader = outputHeader 20*e5dd7070Spatrick self.outputTests = outputTests 21*e5dd7070Spatrick self.outputDriver = outputDriver 22*e5dd7070Spatrick self.writeBody = outputHeader or outputTests or outputDriver 23*e5dd7070Spatrick self.types = {} 24*e5dd7070Spatrick self.testValues = {} 25*e5dd7070Spatrick self.testReturnValues = {} 26*e5dd7070Spatrick self.layoutTests = [] 27*e5dd7070Spatrick self.declarations = set() 28*e5dd7070Spatrick 29*e5dd7070Spatrick if info: 30*e5dd7070Spatrick for f in (self.output,self.outputHeader,self.outputTests,self.outputDriver): 31*e5dd7070Spatrick if f: 32*e5dd7070Spatrick print(info, file=f) 33*e5dd7070Spatrick 34*e5dd7070Spatrick if self.writeBody: 35*e5dd7070Spatrick print('#include <stdio.h>\n', file=self.output) 36*e5dd7070Spatrick if self.outputTests: 37*e5dd7070Spatrick print('#include <stdio.h>', file=self.outputTests) 38*e5dd7070Spatrick print('#include <string.h>', file=self.outputTests) 39*e5dd7070Spatrick print('#include <assert.h>\n', file=self.outputTests) 40*e5dd7070Spatrick 41*e5dd7070Spatrick if headerName: 42*e5dd7070Spatrick for f in (self.output,self.outputTests,self.outputDriver): 43*e5dd7070Spatrick if f is not None: 44*e5dd7070Spatrick print('#include "%s"\n'%(headerName,), file=f) 45*e5dd7070Spatrick 46*e5dd7070Spatrick if self.outputDriver: 47*e5dd7070Spatrick print('#include <stdio.h>', file=self.outputDriver) 48*e5dd7070Spatrick print('#include <stdlib.h>\n', file=self.outputDriver) 49*e5dd7070Spatrick print('int main(int argc, char **argv) {', file=self.outputDriver) 50*e5dd7070Spatrick print(' int index = -1;', file=self.outputDriver) 51*e5dd7070Spatrick print(' if (argc > 1) index = atoi(argv[1]);', file=self.outputDriver) 52*e5dd7070Spatrick 53*e5dd7070Spatrick def finish(self): 54*e5dd7070Spatrick if self.layoutTests: 55*e5dd7070Spatrick print('int main(int argc, char **argv) {', file=self.output) 56*e5dd7070Spatrick print(' int index = -1;', file=self.output) 57*e5dd7070Spatrick print(' if (argc > 1) index = atoi(argv[1]);', file=self.output) 58*e5dd7070Spatrick for i,f in self.layoutTests: 59*e5dd7070Spatrick print(' if (index == -1 || index == %d)' % i, file=self.output) 60*e5dd7070Spatrick print(' %s();' % f, file=self.output) 61*e5dd7070Spatrick print(' return 0;', file=self.output) 62*e5dd7070Spatrick print('}', file=self.output) 63*e5dd7070Spatrick 64*e5dd7070Spatrick if self.outputDriver: 65*e5dd7070Spatrick print(' printf("DONE\\n");', file=self.outputDriver) 66*e5dd7070Spatrick print(' return 0;', file=self.outputDriver) 67*e5dd7070Spatrick print('}', file=self.outputDriver) 68*e5dd7070Spatrick 69*e5dd7070Spatrick def addDeclaration(self, decl): 70*e5dd7070Spatrick if decl in self.declarations: 71*e5dd7070Spatrick return False 72*e5dd7070Spatrick 73*e5dd7070Spatrick self.declarations.add(decl) 74*e5dd7070Spatrick if self.outputHeader: 75*e5dd7070Spatrick print(decl, file=self.outputHeader) 76*e5dd7070Spatrick else: 77*e5dd7070Spatrick print(decl, file=self.output) 78*e5dd7070Spatrick if self.outputTests: 79*e5dd7070Spatrick print(decl, file=self.outputTests) 80*e5dd7070Spatrick return True 81*e5dd7070Spatrick 82*e5dd7070Spatrick def getTypeName(self, T): 83*e5dd7070Spatrick name = self.types.get(T) 84*e5dd7070Spatrick if name is None: 85*e5dd7070Spatrick # Reserve slot 86*e5dd7070Spatrick self.types[T] = None 87*e5dd7070Spatrick self.types[T] = name = T.getTypeName(self) 88*e5dd7070Spatrick return name 89*e5dd7070Spatrick 90*e5dd7070Spatrick def writeLayoutTest(self, i, ty): 91*e5dd7070Spatrick tyName = self.getTypeName(ty) 92*e5dd7070Spatrick tyNameClean = tyName.replace(' ','_').replace('*','star') 93*e5dd7070Spatrick fnName = 'test_%s' % tyNameClean 94*e5dd7070Spatrick 95*e5dd7070Spatrick print('void %s(void) {' % fnName, file=self.output) 96*e5dd7070Spatrick self.printSizeOfType(' %s'%fnName, tyName, ty, self.output) 97*e5dd7070Spatrick self.printAlignOfType(' %s'%fnName, tyName, ty, self.output) 98*e5dd7070Spatrick self.printOffsetsOfType(' %s'%fnName, tyName, ty, self.output) 99*e5dd7070Spatrick print('}', file=self.output) 100*e5dd7070Spatrick print(file=self.output) 101*e5dd7070Spatrick 102*e5dd7070Spatrick self.layoutTests.append((i,fnName)) 103*e5dd7070Spatrick 104*e5dd7070Spatrick def writeFunction(self, i, FT): 105*e5dd7070Spatrick args = ', '.join(['%s arg%d'%(self.getTypeName(t),i) for i,t in enumerate(FT.argTypes)]) 106*e5dd7070Spatrick if not args: 107*e5dd7070Spatrick args = 'void' 108*e5dd7070Spatrick 109*e5dd7070Spatrick if FT.returnType is None: 110*e5dd7070Spatrick retvalName = None 111*e5dd7070Spatrick retvalTypeName = 'void' 112*e5dd7070Spatrick else: 113*e5dd7070Spatrick retvalTypeName = self.getTypeName(FT.returnType) 114*e5dd7070Spatrick if self.writeBody or self.outputTests: 115*e5dd7070Spatrick retvalName = self.getTestReturnValue(FT.returnType) 116*e5dd7070Spatrick 117*e5dd7070Spatrick fnName = 'fn%d'%(FT.index,) 118*e5dd7070Spatrick if self.outputHeader: 119*e5dd7070Spatrick print('%s %s(%s);'%(retvalTypeName, fnName, args), file=self.outputHeader) 120*e5dd7070Spatrick elif self.outputTests: 121*e5dd7070Spatrick print('%s %s(%s);'%(retvalTypeName, fnName, args), file=self.outputTests) 122*e5dd7070Spatrick 123*e5dd7070Spatrick print('%s %s(%s)'%(retvalTypeName, fnName, args), end=' ', file=self.output) 124*e5dd7070Spatrick if self.writeBody: 125*e5dd7070Spatrick print('{', file=self.output) 126*e5dd7070Spatrick 127*e5dd7070Spatrick for i,t in enumerate(FT.argTypes): 128*e5dd7070Spatrick self.printValueOfType(' %s'%fnName, 'arg%d'%i, t) 129*e5dd7070Spatrick 130*e5dd7070Spatrick if retvalName is not None: 131*e5dd7070Spatrick print(' return %s;'%(retvalName,), file=self.output) 132*e5dd7070Spatrick print('}', file=self.output) 133*e5dd7070Spatrick else: 134*e5dd7070Spatrick print('{}', file=self.output) 135*e5dd7070Spatrick print(file=self.output) 136*e5dd7070Spatrick 137*e5dd7070Spatrick if self.outputDriver: 138*e5dd7070Spatrick print(' if (index == -1 || index == %d) {' % i, file=self.outputDriver) 139*e5dd7070Spatrick print(' extern void test_%s(void);' % fnName, file=self.outputDriver) 140*e5dd7070Spatrick print(' test_%s();' % fnName, file=self.outputDriver) 141*e5dd7070Spatrick print(' }', file=self.outputDriver) 142*e5dd7070Spatrick 143*e5dd7070Spatrick if self.outputTests: 144*e5dd7070Spatrick if self.outputHeader: 145*e5dd7070Spatrick print('void test_%s(void);'%(fnName,), file=self.outputHeader) 146*e5dd7070Spatrick 147*e5dd7070Spatrick if retvalName is None: 148*e5dd7070Spatrick retvalTests = None 149*e5dd7070Spatrick else: 150*e5dd7070Spatrick retvalTests = self.getTestValuesArray(FT.returnType) 151*e5dd7070Spatrick tests = [self.getTestValuesArray(ty) for ty in FT.argTypes] 152*e5dd7070Spatrick print('void test_%s(void) {'%(fnName,), file=self.outputTests) 153*e5dd7070Spatrick 154*e5dd7070Spatrick if retvalTests is not None: 155*e5dd7070Spatrick print(' printf("%s: testing return.\\n");'%(fnName,), file=self.outputTests) 156*e5dd7070Spatrick print(' for (int i=0; i<%d; ++i) {'%(retvalTests[1],), file=self.outputTests) 157*e5dd7070Spatrick args = ', '.join(['%s[%d]'%(t,randrange(l)) for t,l in tests]) 158*e5dd7070Spatrick print(' %s RV;'%(retvalTypeName,), file=self.outputTests) 159*e5dd7070Spatrick print(' %s = %s[i];'%(retvalName, retvalTests[0]), file=self.outputTests) 160*e5dd7070Spatrick print(' RV = %s(%s);'%(fnName, args), file=self.outputTests) 161*e5dd7070Spatrick self.printValueOfType(' %s_RV'%fnName, 'RV', FT.returnType, output=self.outputTests, indent=4) 162*e5dd7070Spatrick self.checkTypeValues('RV', '%s[i]' % retvalTests[0], FT.returnType, output=self.outputTests, indent=4) 163*e5dd7070Spatrick print(' }', file=self.outputTests) 164*e5dd7070Spatrick 165*e5dd7070Spatrick if tests: 166*e5dd7070Spatrick print(' printf("%s: testing arguments.\\n");'%(fnName,), file=self.outputTests) 167*e5dd7070Spatrick for i,(array,length) in enumerate(tests): 168*e5dd7070Spatrick for j in range(length): 169*e5dd7070Spatrick args = ['%s[%d]'%(t,randrange(l)) for t,l in tests] 170*e5dd7070Spatrick args[i] = '%s[%d]'%(array,j) 171*e5dd7070Spatrick print(' %s(%s);'%(fnName, ', '.join(args),), file=self.outputTests) 172*e5dd7070Spatrick print('}', file=self.outputTests) 173*e5dd7070Spatrick 174*e5dd7070Spatrick def getTestReturnValue(self, type): 175*e5dd7070Spatrick typeName = self.getTypeName(type) 176*e5dd7070Spatrick info = self.testReturnValues.get(typeName) 177*e5dd7070Spatrick if info is None: 178*e5dd7070Spatrick name = '%s_retval'%(typeName.replace(' ','_').replace('*','star'),) 179*e5dd7070Spatrick print('%s %s;'%(typeName,name), file=self.output) 180*e5dd7070Spatrick if self.outputHeader: 181*e5dd7070Spatrick print('extern %s %s;'%(typeName,name), file=self.outputHeader) 182*e5dd7070Spatrick elif self.outputTests: 183*e5dd7070Spatrick print('extern %s %s;'%(typeName,name), file=self.outputTests) 184*e5dd7070Spatrick info = self.testReturnValues[typeName] = name 185*e5dd7070Spatrick return info 186*e5dd7070Spatrick 187*e5dd7070Spatrick def getTestValuesArray(self, type): 188*e5dd7070Spatrick typeName = self.getTypeName(type) 189*e5dd7070Spatrick info = self.testValues.get(typeName) 190*e5dd7070Spatrick if info is None: 191*e5dd7070Spatrick name = '%s_values'%(typeName.replace(' ','_').replace('*','star'),) 192*e5dd7070Spatrick print('static %s %s[] = {'%(typeName,name), file=self.outputTests) 193*e5dd7070Spatrick length = 0 194*e5dd7070Spatrick for item in self.getTestValues(type): 195*e5dd7070Spatrick print('\t%s,'%(item,), file=self.outputTests) 196*e5dd7070Spatrick length += 1 197*e5dd7070Spatrick print('};', file=self.outputTests) 198*e5dd7070Spatrick info = self.testValues[typeName] = (name,length) 199*e5dd7070Spatrick return info 200*e5dd7070Spatrick 201*e5dd7070Spatrick def getTestValues(self, t): 202*e5dd7070Spatrick if isinstance(t, BuiltinType): 203*e5dd7070Spatrick if t.name=='float': 204*e5dd7070Spatrick for i in ['0.0','-1.0','1.0']: 205*e5dd7070Spatrick yield i+'f' 206*e5dd7070Spatrick elif t.name=='double': 207*e5dd7070Spatrick for i in ['0.0','-1.0','1.0']: 208*e5dd7070Spatrick yield i 209*e5dd7070Spatrick elif t.name in ('void *'): 210*e5dd7070Spatrick yield '(void*) 0' 211*e5dd7070Spatrick yield '(void*) -1' 212*e5dd7070Spatrick else: 213*e5dd7070Spatrick yield '(%s) 0'%(t.name,) 214*e5dd7070Spatrick yield '(%s) -1'%(t.name,) 215*e5dd7070Spatrick yield '(%s) 1'%(t.name,) 216*e5dd7070Spatrick elif isinstance(t, EnumType): 217*e5dd7070Spatrick for i in range(0, len(t.enumerators)): 218*e5dd7070Spatrick yield 'enum%dval%d_%d' % (t.index, i, t.unique_id) 219*e5dd7070Spatrick elif isinstance(t, RecordType): 220*e5dd7070Spatrick nonPadding = [f for f in t.fields 221*e5dd7070Spatrick if not f.isPaddingBitField()] 222*e5dd7070Spatrick 223*e5dd7070Spatrick if not nonPadding: 224*e5dd7070Spatrick yield '{ }' 225*e5dd7070Spatrick return 226*e5dd7070Spatrick 227*e5dd7070Spatrick # FIXME: Use designated initializers to access non-first 228*e5dd7070Spatrick # fields of unions. 229*e5dd7070Spatrick if t.isUnion: 230*e5dd7070Spatrick for v in self.getTestValues(nonPadding[0]): 231*e5dd7070Spatrick yield '{ %s }' % v 232*e5dd7070Spatrick return 233*e5dd7070Spatrick 234*e5dd7070Spatrick fieldValues = [list(v) for v in map(self.getTestValues, nonPadding)] 235*e5dd7070Spatrick for i,values in enumerate(fieldValues): 236*e5dd7070Spatrick for v in values: 237*e5dd7070Spatrick elements = [random.choice(fv) for fv in fieldValues] 238*e5dd7070Spatrick elements[i] = v 239*e5dd7070Spatrick yield '{ %s }'%(', '.join(elements)) 240*e5dd7070Spatrick 241*e5dd7070Spatrick elif isinstance(t, ComplexType): 242*e5dd7070Spatrick for t in self.getTestValues(t.elementType): 243*e5dd7070Spatrick yield '%s + %s * 1i'%(t,t) 244*e5dd7070Spatrick elif isinstance(t, ArrayType): 245*e5dd7070Spatrick values = list(self.getTestValues(t.elementType)) 246*e5dd7070Spatrick if not values: 247*e5dd7070Spatrick yield '{ }' 248*e5dd7070Spatrick for i in range(t.numElements): 249*e5dd7070Spatrick for v in values: 250*e5dd7070Spatrick elements = [random.choice(values) for i in range(t.numElements)] 251*e5dd7070Spatrick elements[i] = v 252*e5dd7070Spatrick yield '{ %s }'%(', '.join(elements)) 253*e5dd7070Spatrick else: 254*e5dd7070Spatrick raise NotImplementedError('Cannot make tests values of type: "%s"'%(t,)) 255*e5dd7070Spatrick 256*e5dd7070Spatrick def printSizeOfType(self, prefix, name, t, output=None, indent=2): 257*e5dd7070Spatrick print('%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'%(indent, '', prefix, name, name), file=output) 258*e5dd7070Spatrick def printAlignOfType(self, prefix, name, t, output=None, indent=2): 259*e5dd7070Spatrick print('%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'%(indent, '', prefix, name, name), file=output) 260*e5dd7070Spatrick def printOffsetsOfType(self, prefix, name, t, output=None, indent=2): 261*e5dd7070Spatrick if isinstance(t, RecordType): 262*e5dd7070Spatrick for i,f in enumerate(t.fields): 263*e5dd7070Spatrick if f.isBitField(): 264*e5dd7070Spatrick continue 265*e5dd7070Spatrick fname = 'field%d' % i 266*e5dd7070Spatrick print('%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname), file=output) 267*e5dd7070Spatrick 268*e5dd7070Spatrick def printValueOfType(self, prefix, name, t, output=None, indent=2): 269*e5dd7070Spatrick if output is None: 270*e5dd7070Spatrick output = self.output 271*e5dd7070Spatrick if isinstance(t, BuiltinType): 272*e5dd7070Spatrick value_expr = name 273*e5dd7070Spatrick if t.name.split(' ')[-1] == '_Bool': 274*e5dd7070Spatrick # Hack to work around PR5579. 275*e5dd7070Spatrick value_expr = "%s ? 2 : 0" % name 276*e5dd7070Spatrick 277*e5dd7070Spatrick if t.name.endswith('long long'): 278*e5dd7070Spatrick code = 'lld' 279*e5dd7070Spatrick elif t.name.endswith('long'): 280*e5dd7070Spatrick code = 'ld' 281*e5dd7070Spatrick elif t.name.split(' ')[-1] in ('_Bool','char','short', 282*e5dd7070Spatrick 'int','unsigned'): 283*e5dd7070Spatrick code = 'd' 284*e5dd7070Spatrick elif t.name in ('float','double'): 285*e5dd7070Spatrick code = 'f' 286*e5dd7070Spatrick elif t.name == 'long double': 287*e5dd7070Spatrick code = 'Lf' 288*e5dd7070Spatrick else: 289*e5dd7070Spatrick code = 'p' 290*e5dd7070Spatrick print('%*sprintf("%s: %s = %%%s\\n", %s);'%( 291*e5dd7070Spatrick indent, '', prefix, name, code, value_expr), file=output) 292*e5dd7070Spatrick elif isinstance(t, EnumType): 293*e5dd7070Spatrick print('%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name), file=output) 294*e5dd7070Spatrick elif isinstance(t, RecordType): 295*e5dd7070Spatrick if not t.fields: 296*e5dd7070Spatrick print('%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name), file=output) 297*e5dd7070Spatrick for i,f in enumerate(t.fields): 298*e5dd7070Spatrick if f.isPaddingBitField(): 299*e5dd7070Spatrick continue 300*e5dd7070Spatrick fname = '%s.field%d'%(name,i) 301*e5dd7070Spatrick self.printValueOfType(prefix, fname, f, output=output, indent=indent) 302*e5dd7070Spatrick elif isinstance(t, ComplexType): 303*e5dd7070Spatrick self.printValueOfType(prefix, '(__real %s)'%name, t.elementType, output=output,indent=indent) 304*e5dd7070Spatrick self.printValueOfType(prefix, '(__imag %s)'%name, t.elementType, output=output,indent=indent) 305*e5dd7070Spatrick elif isinstance(t, ArrayType): 306*e5dd7070Spatrick for i in range(t.numElements): 307*e5dd7070Spatrick # Access in this fashion as a hackish way to portably 308*e5dd7070Spatrick # access vectors. 309*e5dd7070Spatrick if t.isVector: 310*e5dd7070Spatrick self.printValueOfType(prefix, '((%s*) &%s)[%d]'%(t.elementType,name,i), t.elementType, output=output,indent=indent) 311*e5dd7070Spatrick else: 312*e5dd7070Spatrick self.printValueOfType(prefix, '%s[%d]'%(name,i), t.elementType, output=output,indent=indent) 313*e5dd7070Spatrick else: 314*e5dd7070Spatrick raise NotImplementedError('Cannot print value of type: "%s"'%(t,)) 315*e5dd7070Spatrick 316*e5dd7070Spatrick def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2): 317*e5dd7070Spatrick prefix = 'foo' 318*e5dd7070Spatrick if output is None: 319*e5dd7070Spatrick output = self.output 320*e5dd7070Spatrick if isinstance(t, BuiltinType): 321*e5dd7070Spatrick print('%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS), file=output) 322*e5dd7070Spatrick elif isinstance(t, EnumType): 323*e5dd7070Spatrick print('%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS), file=output) 324*e5dd7070Spatrick elif isinstance(t, RecordType): 325*e5dd7070Spatrick for i,f in enumerate(t.fields): 326*e5dd7070Spatrick if f.isPaddingBitField(): 327*e5dd7070Spatrick continue 328*e5dd7070Spatrick self.checkTypeValues('%s.field%d'%(nameLHS,i), '%s.field%d'%(nameRHS,i), 329*e5dd7070Spatrick f, output=output, indent=indent) 330*e5dd7070Spatrick if t.isUnion: 331*e5dd7070Spatrick break 332*e5dd7070Spatrick elif isinstance(t, ComplexType): 333*e5dd7070Spatrick self.checkTypeValues('(__real %s)'%nameLHS, '(__real %s)'%nameRHS, t.elementType, output=output,indent=indent) 334*e5dd7070Spatrick self.checkTypeValues('(__imag %s)'%nameLHS, '(__imag %s)'%nameRHS, t.elementType, output=output,indent=indent) 335*e5dd7070Spatrick elif isinstance(t, ArrayType): 336*e5dd7070Spatrick for i in range(t.numElements): 337*e5dd7070Spatrick # Access in this fashion as a hackish way to portably 338*e5dd7070Spatrick # access vectors. 339*e5dd7070Spatrick if t.isVector: 340*e5dd7070Spatrick self.checkTypeValues('((%s*) &%s)[%d]'%(t.elementType,nameLHS,i), 341*e5dd7070Spatrick '((%s*) &%s)[%d]'%(t.elementType,nameRHS,i), 342*e5dd7070Spatrick t.elementType, output=output,indent=indent) 343*e5dd7070Spatrick else: 344*e5dd7070Spatrick self.checkTypeValues('%s[%d]'%(nameLHS,i), '%s[%d]'%(nameRHS,i), 345*e5dd7070Spatrick t.elementType, output=output,indent=indent) 346*e5dd7070Spatrick else: 347*e5dd7070Spatrick raise NotImplementedError('Cannot print value of type: "%s"'%(t,)) 348*e5dd7070Spatrick 349*e5dd7070Spatrickimport sys 350*e5dd7070Spatrick 351*e5dd7070Spatrickdef main(): 352*e5dd7070Spatrick from optparse import OptionParser, OptionGroup 353*e5dd7070Spatrick parser = OptionParser("%prog [options] {indices}") 354*e5dd7070Spatrick parser.add_option("", "--mode", dest="mode", 355*e5dd7070Spatrick help="autogeneration mode (random or linear) [default %default]", 356*e5dd7070Spatrick type='choice', choices=('random','linear'), default='linear') 357*e5dd7070Spatrick parser.add_option("", "--count", dest="count", 358*e5dd7070Spatrick help="autogenerate COUNT functions according to MODE", 359*e5dd7070Spatrick type=int, default=0) 360*e5dd7070Spatrick parser.add_option("", "--min", dest="minIndex", metavar="N", 361*e5dd7070Spatrick help="start autogeneration with the Nth function type [default %default]", 362*e5dd7070Spatrick type=int, default=0) 363*e5dd7070Spatrick parser.add_option("", "--max", dest="maxIndex", metavar="N", 364*e5dd7070Spatrick help="maximum index for random autogeneration [default %default]", 365*e5dd7070Spatrick type=int, default=10000000) 366*e5dd7070Spatrick parser.add_option("", "--seed", dest="seed", 367*e5dd7070Spatrick help="random number generator seed [default %default]", 368*e5dd7070Spatrick type=int, default=1) 369*e5dd7070Spatrick parser.add_option("", "--use-random-seed", dest="useRandomSeed", 370*e5dd7070Spatrick help="use random value for initial random number generator seed", 371*e5dd7070Spatrick action='store_true', default=False) 372*e5dd7070Spatrick parser.add_option("", "--skip", dest="skipTests", 373*e5dd7070Spatrick help="add a test index to skip", 374*e5dd7070Spatrick type=int, action='append', default=[]) 375*e5dd7070Spatrick parser.add_option("-o", "--output", dest="output", metavar="FILE", 376*e5dd7070Spatrick help="write output to FILE [default %default]", 377*e5dd7070Spatrick type=str, default='-') 378*e5dd7070Spatrick parser.add_option("-O", "--output-header", dest="outputHeader", metavar="FILE", 379*e5dd7070Spatrick help="write header file for output to FILE [default %default]", 380*e5dd7070Spatrick type=str, default=None) 381*e5dd7070Spatrick parser.add_option("-T", "--output-tests", dest="outputTests", metavar="FILE", 382*e5dd7070Spatrick help="write function tests to FILE [default %default]", 383*e5dd7070Spatrick type=str, default=None) 384*e5dd7070Spatrick parser.add_option("-D", "--output-driver", dest="outputDriver", metavar="FILE", 385*e5dd7070Spatrick help="write test driver to FILE [default %default]", 386*e5dd7070Spatrick type=str, default=None) 387*e5dd7070Spatrick parser.add_option("", "--test-layout", dest="testLayout", metavar="FILE", 388*e5dd7070Spatrick help="test structure layout", 389*e5dd7070Spatrick action='store_true', default=False) 390*e5dd7070Spatrick 391*e5dd7070Spatrick group = OptionGroup(parser, "Type Enumeration Options") 392*e5dd7070Spatrick # Builtins - Ints 393*e5dd7070Spatrick group.add_option("", "--no-char", dest="useChar", 394*e5dd7070Spatrick help="do not generate char types", 395*e5dd7070Spatrick action="store_false", default=True) 396*e5dd7070Spatrick group.add_option("", "--no-short", dest="useShort", 397*e5dd7070Spatrick help="do not generate short types", 398*e5dd7070Spatrick action="store_false", default=True) 399*e5dd7070Spatrick group.add_option("", "--no-int", dest="useInt", 400*e5dd7070Spatrick help="do not generate int types", 401*e5dd7070Spatrick action="store_false", default=True) 402*e5dd7070Spatrick group.add_option("", "--no-long", dest="useLong", 403*e5dd7070Spatrick help="do not generate long types", 404*e5dd7070Spatrick action="store_false", default=True) 405*e5dd7070Spatrick group.add_option("", "--no-long-long", dest="useLongLong", 406*e5dd7070Spatrick help="do not generate long long types", 407*e5dd7070Spatrick action="store_false", default=True) 408*e5dd7070Spatrick group.add_option("", "--no-unsigned", dest="useUnsigned", 409*e5dd7070Spatrick help="do not generate unsigned integer types", 410*e5dd7070Spatrick action="store_false", default=True) 411*e5dd7070Spatrick 412*e5dd7070Spatrick # Other builtins 413*e5dd7070Spatrick group.add_option("", "--no-bool", dest="useBool", 414*e5dd7070Spatrick help="do not generate bool types", 415*e5dd7070Spatrick action="store_false", default=True) 416*e5dd7070Spatrick group.add_option("", "--no-float", dest="useFloat", 417*e5dd7070Spatrick help="do not generate float types", 418*e5dd7070Spatrick action="store_false", default=True) 419*e5dd7070Spatrick group.add_option("", "--no-double", dest="useDouble", 420*e5dd7070Spatrick help="do not generate double types", 421*e5dd7070Spatrick action="store_false", default=True) 422*e5dd7070Spatrick group.add_option("", "--no-long-double", dest="useLongDouble", 423*e5dd7070Spatrick help="do not generate long double types", 424*e5dd7070Spatrick action="store_false", default=True) 425*e5dd7070Spatrick group.add_option("", "--no-void-pointer", dest="useVoidPointer", 426*e5dd7070Spatrick help="do not generate void* types", 427*e5dd7070Spatrick action="store_false", default=True) 428*e5dd7070Spatrick 429*e5dd7070Spatrick # Enumerations 430*e5dd7070Spatrick group.add_option("", "--no-enums", dest="useEnum", 431*e5dd7070Spatrick help="do not generate enum types", 432*e5dd7070Spatrick action="store_false", default=True) 433*e5dd7070Spatrick 434*e5dd7070Spatrick # Derived types 435*e5dd7070Spatrick group.add_option("", "--no-array", dest="useArray", 436*e5dd7070Spatrick help="do not generate record types", 437*e5dd7070Spatrick action="store_false", default=True) 438*e5dd7070Spatrick group.add_option("", "--no-complex", dest="useComplex", 439*e5dd7070Spatrick help="do not generate complex types", 440*e5dd7070Spatrick action="store_false", default=True) 441*e5dd7070Spatrick group.add_option("", "--no-record", dest="useRecord", 442*e5dd7070Spatrick help="do not generate record types", 443*e5dd7070Spatrick action="store_false", default=True) 444*e5dd7070Spatrick group.add_option("", "--no-union", dest="recordUseUnion", 445*e5dd7070Spatrick help="do not generate union types", 446*e5dd7070Spatrick action="store_false", default=True) 447*e5dd7070Spatrick group.add_option("", "--no-vector", dest="useVector", 448*e5dd7070Spatrick help="do not generate vector types", 449*e5dd7070Spatrick action="store_false", default=True) 450*e5dd7070Spatrick group.add_option("", "--no-bit-field", dest="useBitField", 451*e5dd7070Spatrick help="do not generate bit-field record members", 452*e5dd7070Spatrick action="store_false", default=True) 453*e5dd7070Spatrick group.add_option("", "--no-builtins", dest="useBuiltins", 454*e5dd7070Spatrick help="do not use any types", 455*e5dd7070Spatrick action="store_false", default=True) 456*e5dd7070Spatrick 457*e5dd7070Spatrick # Tuning 458*e5dd7070Spatrick group.add_option("", "--no-function-return", dest="functionUseReturn", 459*e5dd7070Spatrick help="do not generate return types for functions", 460*e5dd7070Spatrick action="store_false", default=True) 461*e5dd7070Spatrick group.add_option("", "--vector-types", dest="vectorTypes", 462*e5dd7070Spatrick help="comma separated list of vector types (e.g., v2i32) [default %default]", 463*e5dd7070Spatrick action="store", type=str, default='v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32', metavar="N") 464*e5dd7070Spatrick group.add_option("", "--bit-fields", dest="bitFields", 465*e5dd7070Spatrick help="comma separated list 'type:width' bit-field specifiers [default %default]", 466*e5dd7070Spatrick action="store", type=str, default=( 467*e5dd7070Spatrick "char:0,char:4,int:0,unsigned:1,int:1,int:4,int:13,int:24")) 468*e5dd7070Spatrick group.add_option("", "--max-args", dest="functionMaxArgs", 469*e5dd7070Spatrick help="maximum number of arguments per function [default %default]", 470*e5dd7070Spatrick action="store", type=int, default=4, metavar="N") 471*e5dd7070Spatrick group.add_option("", "--max-array", dest="arrayMaxSize", 472*e5dd7070Spatrick help="maximum array size [default %default]", 473*e5dd7070Spatrick action="store", type=int, default=4, metavar="N") 474*e5dd7070Spatrick group.add_option("", "--max-record", dest="recordMaxSize", 475*e5dd7070Spatrick help="maximum number of fields per record [default %default]", 476*e5dd7070Spatrick action="store", type=int, default=4, metavar="N") 477*e5dd7070Spatrick group.add_option("", "--max-record-depth", dest="recordMaxDepth", 478*e5dd7070Spatrick help="maximum nested structure depth [default %default]", 479*e5dd7070Spatrick action="store", type=int, default=None, metavar="N") 480*e5dd7070Spatrick parser.add_option_group(group) 481*e5dd7070Spatrick (opts, args) = parser.parse_args() 482*e5dd7070Spatrick 483*e5dd7070Spatrick if not opts.useRandomSeed: 484*e5dd7070Spatrick random.seed(opts.seed) 485*e5dd7070Spatrick 486*e5dd7070Spatrick # Construct type generator 487*e5dd7070Spatrick builtins = [] 488*e5dd7070Spatrick if opts.useBuiltins: 489*e5dd7070Spatrick ints = [] 490*e5dd7070Spatrick if opts.useChar: ints.append(('char',1)) 491*e5dd7070Spatrick if opts.useShort: ints.append(('short',2)) 492*e5dd7070Spatrick if opts.useInt: ints.append(('int',4)) 493*e5dd7070Spatrick # FIXME: Wrong size. 494*e5dd7070Spatrick if opts.useLong: ints.append(('long',4)) 495*e5dd7070Spatrick if opts.useLongLong: ints.append(('long long',8)) 496*e5dd7070Spatrick if opts.useUnsigned: 497*e5dd7070Spatrick ints = ([('unsigned %s'%i,s) for i,s in ints] + 498*e5dd7070Spatrick [('signed %s'%i,s) for i,s in ints]) 499*e5dd7070Spatrick builtins.extend(ints) 500*e5dd7070Spatrick 501*e5dd7070Spatrick if opts.useBool: builtins.append(('_Bool',1)) 502*e5dd7070Spatrick if opts.useFloat: builtins.append(('float',4)) 503*e5dd7070Spatrick if opts.useDouble: builtins.append(('double',8)) 504*e5dd7070Spatrick if opts.useLongDouble: builtins.append(('long double',16)) 505*e5dd7070Spatrick # FIXME: Wrong size. 506*e5dd7070Spatrick if opts.useVoidPointer: builtins.append(('void*',4)) 507*e5dd7070Spatrick 508*e5dd7070Spatrick btg = FixedTypeGenerator([BuiltinType(n,s) for n,s in builtins]) 509*e5dd7070Spatrick 510*e5dd7070Spatrick bitfields = [] 511*e5dd7070Spatrick for specifier in opts.bitFields.split(','): 512*e5dd7070Spatrick if not specifier.strip(): 513*e5dd7070Spatrick continue 514*e5dd7070Spatrick name,width = specifier.strip().split(':', 1) 515*e5dd7070Spatrick bitfields.append(BuiltinType(name,None,int(width))) 516*e5dd7070Spatrick bftg = FixedTypeGenerator(bitfields) 517*e5dd7070Spatrick 518*e5dd7070Spatrick charType = BuiltinType('char',1) 519*e5dd7070Spatrick shortType = BuiltinType('short',2) 520*e5dd7070Spatrick intType = BuiltinType('int',4) 521*e5dd7070Spatrick longlongType = BuiltinType('long long',8) 522*e5dd7070Spatrick floatType = BuiltinType('float',4) 523*e5dd7070Spatrick doubleType = BuiltinType('double',8) 524*e5dd7070Spatrick sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType]) 525*e5dd7070Spatrick 526*e5dd7070Spatrick atg = AnyTypeGenerator() 527*e5dd7070Spatrick artg = AnyTypeGenerator() 528*e5dd7070Spatrick def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField): 529*e5dd7070Spatrick atg.addGenerator(btg) 530*e5dd7070Spatrick if useBitField and opts.useBitField: 531*e5dd7070Spatrick atg.addGenerator(bftg) 532*e5dd7070Spatrick if useRecord and opts.useRecord: 533*e5dd7070Spatrick assert subgen 534*e5dd7070Spatrick atg.addGenerator(RecordTypeGenerator(subfieldgen, opts.recordUseUnion, 535*e5dd7070Spatrick opts.recordMaxSize)) 536*e5dd7070Spatrick if opts.useComplex: 537*e5dd7070Spatrick # FIXME: Allow overriding builtins here 538*e5dd7070Spatrick atg.addGenerator(ComplexTypeGenerator(sbtg)) 539*e5dd7070Spatrick if useArray and opts.useArray: 540*e5dd7070Spatrick assert subgen 541*e5dd7070Spatrick atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize)) 542*e5dd7070Spatrick if opts.useVector: 543*e5dd7070Spatrick vTypes = [] 544*e5dd7070Spatrick for i,t in enumerate(opts.vectorTypes.split(',')): 545*e5dd7070Spatrick m = re.match('v([1-9][0-9]*)([if][1-9][0-9]*)', t.strip()) 546*e5dd7070Spatrick if not m: 547*e5dd7070Spatrick parser.error('Invalid vector type: %r' % t) 548*e5dd7070Spatrick count,kind = m.groups() 549*e5dd7070Spatrick count = int(count) 550*e5dd7070Spatrick type = { 'i8' : charType, 551*e5dd7070Spatrick 'i16' : shortType, 552*e5dd7070Spatrick 'i32' : intType, 553*e5dd7070Spatrick 'i64' : longlongType, 554*e5dd7070Spatrick 'f32' : floatType, 555*e5dd7070Spatrick 'f64' : doubleType, 556*e5dd7070Spatrick }.get(kind) 557*e5dd7070Spatrick if not type: 558*e5dd7070Spatrick parser.error('Invalid vector type: %r' % t) 559*e5dd7070Spatrick vTypes.append(ArrayType(i, True, type, count * type.size)) 560*e5dd7070Spatrick 561*e5dd7070Spatrick atg.addGenerator(FixedTypeGenerator(vTypes)) 562*e5dd7070Spatrick if opts.useEnum: 563*e5dd7070Spatrick atg.addGenerator(EnumTypeGenerator([None, '-1', '1', '1u'], 1, 4)) 564*e5dd7070Spatrick 565*e5dd7070Spatrick if opts.recordMaxDepth is None: 566*e5dd7070Spatrick # Fully recursive, just avoid top-level arrays. 567*e5dd7070Spatrick subFTG = AnyTypeGenerator() 568*e5dd7070Spatrick subTG = AnyTypeGenerator() 569*e5dd7070Spatrick atg = AnyTypeGenerator() 570*e5dd7070Spatrick makeGenerator(subFTG, atg, atg, True, True, True) 571*e5dd7070Spatrick makeGenerator(subTG, atg, subFTG, True, True, False) 572*e5dd7070Spatrick makeGenerator(atg, subTG, subFTG, True, False, False) 573*e5dd7070Spatrick else: 574*e5dd7070Spatrick # Make a chain of type generators, each builds smaller 575*e5dd7070Spatrick # structures. 576*e5dd7070Spatrick base = AnyTypeGenerator() 577*e5dd7070Spatrick fbase = AnyTypeGenerator() 578*e5dd7070Spatrick makeGenerator(base, None, None, False, False, False) 579*e5dd7070Spatrick makeGenerator(fbase, None, None, False, False, True) 580*e5dd7070Spatrick for i in range(opts.recordMaxDepth): 581*e5dd7070Spatrick n = AnyTypeGenerator() 582*e5dd7070Spatrick fn = AnyTypeGenerator() 583*e5dd7070Spatrick makeGenerator(n, base, fbase, True, True, False) 584*e5dd7070Spatrick makeGenerator(fn, base, fbase, True, True, True) 585*e5dd7070Spatrick base = n 586*e5dd7070Spatrick fbase = fn 587*e5dd7070Spatrick atg = AnyTypeGenerator() 588*e5dd7070Spatrick makeGenerator(atg, base, fbase, True, False, False) 589*e5dd7070Spatrick 590*e5dd7070Spatrick if opts.testLayout: 591*e5dd7070Spatrick ftg = atg 592*e5dd7070Spatrick else: 593*e5dd7070Spatrick ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs) 594*e5dd7070Spatrick 595*e5dd7070Spatrick # Override max,min,count if finite 596*e5dd7070Spatrick if opts.maxIndex is None: 597*e5dd7070Spatrick if ftg.cardinality is aleph0: 598*e5dd7070Spatrick opts.maxIndex = 10000000 599*e5dd7070Spatrick else: 600*e5dd7070Spatrick opts.maxIndex = ftg.cardinality 601*e5dd7070Spatrick opts.maxIndex = min(opts.maxIndex, ftg.cardinality) 602*e5dd7070Spatrick opts.minIndex = max(0,min(opts.maxIndex-1, opts.minIndex)) 603*e5dd7070Spatrick if not opts.mode=='random': 604*e5dd7070Spatrick opts.count = min(opts.count, opts.maxIndex-opts.minIndex) 605*e5dd7070Spatrick 606*e5dd7070Spatrick if opts.output=='-': 607*e5dd7070Spatrick output = sys.stdout 608*e5dd7070Spatrick else: 609*e5dd7070Spatrick output = open(opts.output,'w') 610*e5dd7070Spatrick atexit.register(lambda: output.close()) 611*e5dd7070Spatrick 612*e5dd7070Spatrick outputHeader = None 613*e5dd7070Spatrick if opts.outputHeader: 614*e5dd7070Spatrick outputHeader = open(opts.outputHeader,'w') 615*e5dd7070Spatrick atexit.register(lambda: outputHeader.close()) 616*e5dd7070Spatrick 617*e5dd7070Spatrick outputTests = None 618*e5dd7070Spatrick if opts.outputTests: 619*e5dd7070Spatrick outputTests = open(opts.outputTests,'w') 620*e5dd7070Spatrick atexit.register(lambda: outputTests.close()) 621*e5dd7070Spatrick 622*e5dd7070Spatrick outputDriver = None 623*e5dd7070Spatrick if opts.outputDriver: 624*e5dd7070Spatrick outputDriver = open(opts.outputDriver,'w') 625*e5dd7070Spatrick atexit.register(lambda: outputDriver.close()) 626*e5dd7070Spatrick 627*e5dd7070Spatrick info = '' 628*e5dd7070Spatrick info += '// %s\n'%(' '.join(sys.argv),) 629*e5dd7070Spatrick info += '// Generated: %s\n'%(time.strftime('%Y-%m-%d %H:%M'),) 630*e5dd7070Spatrick info += '// Cardinality of function generator: %s\n'%(ftg.cardinality,) 631*e5dd7070Spatrick info += '// Cardinality of type generator: %s\n'%(atg.cardinality,) 632*e5dd7070Spatrick 633*e5dd7070Spatrick if opts.testLayout: 634*e5dd7070Spatrick info += '\n#include <stdio.h>' 635*e5dd7070Spatrick 636*e5dd7070Spatrick P = TypePrinter(output, 637*e5dd7070Spatrick outputHeader=outputHeader, 638*e5dd7070Spatrick outputTests=outputTests, 639*e5dd7070Spatrick outputDriver=outputDriver, 640*e5dd7070Spatrick headerName=opts.outputHeader, 641*e5dd7070Spatrick info=info) 642*e5dd7070Spatrick 643*e5dd7070Spatrick def write(N): 644*e5dd7070Spatrick try: 645*e5dd7070Spatrick FT = ftg.get(N) 646*e5dd7070Spatrick except RuntimeError as e: 647*e5dd7070Spatrick if e.args[0]=='maximum recursion depth exceeded': 648*e5dd7070Spatrick print('WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,), file=sys.stderr) 649*e5dd7070Spatrick return 650*e5dd7070Spatrick raise 651*e5dd7070Spatrick if opts.testLayout: 652*e5dd7070Spatrick P.writeLayoutTest(N, FT) 653*e5dd7070Spatrick else: 654*e5dd7070Spatrick P.writeFunction(N, FT) 655*e5dd7070Spatrick 656*e5dd7070Spatrick if args: 657*e5dd7070Spatrick [write(int(a)) for a in args] 658*e5dd7070Spatrick 659*e5dd7070Spatrick skipTests = set(opts.skipTests) 660*e5dd7070Spatrick for i in range(opts.count): 661*e5dd7070Spatrick if opts.mode=='linear': 662*e5dd7070Spatrick index = opts.minIndex + i 663*e5dd7070Spatrick else: 664*e5dd7070Spatrick index = opts.minIndex + int((opts.maxIndex-opts.minIndex) * random.random()) 665*e5dd7070Spatrick if index in skipTests: 666*e5dd7070Spatrick continue 667*e5dd7070Spatrick write(index) 668*e5dd7070Spatrick 669*e5dd7070Spatrick P.finish() 670*e5dd7070Spatrick 671*e5dd7070Spatrickif __name__=='__main__': 672*e5dd7070Spatrick main() 673*e5dd7070Spatrick 674