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