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