# FIXME: Use designated initializers to access non-first
# fields of unions.
if t.isUnion:
- for v in self.getTestValues(t.fields[0]):
- yield '{ %s }' % v
+ firstNonPadding = None
+ for t in t.fields:
+ if not t.isPaddingBitField():
+ firstNonPadding = t
+ break
+ if firstNonPadding:
+ for v in self.getTestValues(firstNonPadding):
+ yield '{ %s }' % v
+ else:
+ yield '{ }'
return
- fieldValues = [list(self.getTestValues(f)) for f in t.fields]
+ fieldValues = [list(self.getTestValues(f))
+ for f in t.fields
+ if not f.isPaddingBitField()]
for i,values in enumerate(fieldValues):
for v in values:
elements = map(random.choice,fieldValues)
def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):
if isinstance(t, RecordType):
for i,f in enumerate(t.fields):
+ if f.isPaddingBitField():
+ continue
fname = 'field%d' % i
print >>output, '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", __builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname)
if not t.fields:
print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name)
for i,f in enumerate(t.fields):
+ if f.isPaddingBitField():
+ continue
fname = '%s.field%d'%(name,i)
self.printValueOfType(prefix, fname, f, output=output, indent=indent)
elif isinstance(t, ComplexType):
print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
elif isinstance(t, RecordType):
for i,f in enumerate(t.fields):
+ if f.isPaddingBitField():
+ continue
self.checkTypeValues('%s.field%d'%(nameLHS,i), '%s.field%d'%(nameRHS,i),
f, output=output, indent=indent)
if t.isUnion:
group.add_option("", "--no-vector", dest="useVector",
help="do not generate vector types",
action="store_false", default=True)
+ group.add_option("", "--no-bit-field", dest="useBitField",
+ help="do not generate bit-field record members",
+ action="store_false", default=True)
+ group.add_option("", "--no-builtins", dest="useBuiltins",
+ help="do not use any types",
+ action="store_false", default=True)
# Tuning
group.add_option("", "--no-function-return", dest="functionUseReturn",
group.add_option("", "--vector-types", dest="vectorTypes",
help="comma separated list of vector types (e.g., v2i32) [default %default]",
action="store", type=str, default='v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32', metavar="N")
-
+ group.add_option("", "--bit-fields", dest="bitFields",
+ help="comma separated list 'type:width' bit-field specifiers [default %default]",
+ action="store", type=str, default="1,3,-2,-1")
group.add_option("", "--max-args", dest="functionMaxArgs",
help="maximum number of arguments per function [default %default]",
action="store", type=int, default=4, metavar="N")
# Contruct type generator
builtins = []
- ints = []
- if opts.useChar: ints.append(('char',1))
- if opts.useShort: ints.append(('short',2))
- if opts.useInt: ints.append(('int',4))
- # FIXME: Wrong size.
- if opts.useLong: ints.append(('long',4))
- if opts.useLongLong: ints.append(('long long',8))
- if opts.useUnsigned:
- ints = ([('unsigned %s'%i,s) for i,s in ints] +
- [('signed %s'%i,s) for i,s in ints])
- builtins.extend(ints)
-
- if opts.useBool: builtins.append(('_Bool',1))
- if opts.useFloat: builtins.append(('float',4))
- if opts.useDouble: builtins.append(('double',8))
- if opts.useLongDouble: builtins.append(('long double',16))
- # FIXME: Wrong size.
- if opts.useVoidPointer: builtins.append(('void*',4))
+ if opts.useBuiltins:
+ ints = []
+ if opts.useChar: ints.append(('char',1))
+ if opts.useShort: ints.append(('short',2))
+ if opts.useInt: ints.append(('int',4))
+ # FIXME: Wrong size.
+ if opts.useLong: ints.append(('long',4))
+ if opts.useLongLong: ints.append(('long long',8))
+ if opts.useUnsigned:
+ ints = ([('unsigned %s'%i,s) for i,s in ints] +
+ [('signed %s'%i,s) for i,s in ints])
+ builtins.extend(ints)
+
+ if opts.useBool: builtins.append(('_Bool',1))
+ if opts.useFloat: builtins.append(('float',4))
+ if opts.useDouble: builtins.append(('double',8))
+ if opts.useLongDouble: builtins.append(('long double',16))
+ # FIXME: Wrong size.
+ if opts.useVoidPointer: builtins.append(('void*',4))
btg = FixedTypeGenerator([BuiltinType(n,s) for n,s in builtins])
+
+ bitfields = []
+ for specifier in opts.bitFields.split(','):
+ if not specifier.strip():
+ continue
+ name,width = specifier.strip().split(':', 1)
+ bitfields.append(BuiltinType(name,None,int(width)))
+ bftg = FixedTypeGenerator(bitfields)
+
charType = BuiltinType('char',1)
shortType = BuiltinType('short',2)
intType = BuiltinType('int',4)
atg = AnyTypeGenerator()
artg = AnyTypeGenerator()
- def makeGenerator(atg, subgen, useRecord, useArray):
+ def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField):
atg.addGenerator(btg)
+ if useBitField and opts.useBitField:
+ atg.addGenerator(bftg)
if useRecord and opts.useRecord:
assert subgen
- atg.addGenerator(RecordTypeGenerator(subgen, opts.recordUseUnion,
+ atg.addGenerator(RecordTypeGenerator(subfieldgen, opts.recordUseUnion,
opts.recordMaxSize))
if opts.useComplex:
# FIXME: Allow overriding builtins here
if opts.recordMaxDepth is None:
# Fully recursive, just avoid top-level arrays.
+ subFTG = AnyTypeGenerator()
subTG = AnyTypeGenerator()
atg = AnyTypeGenerator()
- makeGenerator(subTG, atg, True, True)
- makeGenerator(atg, subTG, True, False)
+ makeGenerator(subFTG, atg, atg, True, True, True)
+ makeGenerator(subTG, atg, subFTG, True, True, False)
+ makeGenerator(atg, subTG, subFTG, True, False, False)
else:
# Make a chain of type generators, each builds smaller
# structures.
base = AnyTypeGenerator()
- makeGenerator(base, None, False, False)
+ fbase = AnyTypeGenerator()
+ makeGenerator(base, None, None, False, False, False)
+ makeGenerator(fbase, None, None, False, False, True)
for i in range(opts.recordMaxDepth):
n = AnyTypeGenerator()
- makeGenerator(n, base, True, True)
+ fn = AnyTypeGenerator()
+ makeGenerator(n, base, fbase, True, True, False)
+ makeGenerator(fn, base, fbase, True, True, True)
base = n
+ fbase = fn
atg = AnyTypeGenerator()
- makeGenerator(atg, base, True, False)
+ makeGenerator(atg, base, fbase, True, False, False)
if opts.testLayout:
ftg = atg
# TODO:
-# - struct improvements (bitfields, flexible arrays, packed &
+# - struct improvements (flexible arrays, packed &
# unpacked, alignment)
# - objective-c qualified id
# - anonymous / transparent unions
###
# Actual type types
-class BuiltinType:
- def __init__(self, name, size):
+class Type:
+ def isBitField(self):
+ return False
+
+ def isPaddingBitField(self):
+ return False
+
+class BuiltinType(Type):
+ def __init__(self, name, size, bitFieldSize=None):
self.name = name
self.size = size
+ self.bitFieldSize = bitFieldSize
+
+ def isBitField(self):
+ return self.bitFieldSize is not None
+
+ def isPaddingBitField(self):
+ return self.bitFieldSize is 0
+
+ def getBitFieldSize(self):
+ assert self.isBitField()
+ return self.bitFieldSize
def sizeof(self):
return self.size
def __str__(self):
return self.name
-class RecordType:
+class RecordType(Type):
def __init__(self, index, isUnion, fields):
self.index = index
self.isUnion = isUnion
self.fields = fields
self.name = None
- def __str__(self):
+ def __str__(self):
+ def getField(t):
+ if t.isBitField():
+ return "%s : %d;" % (t, t.getBitFieldSize())
+ else:
+ return "%s;" % t
+
return '%s { %s }'%(('struct','union')[self.isUnion],
- ' '.join(['%s;'%f for f in self.fields]))
+ ' '.join(map(getField, self.fields)))
def getTypedefDef(self, name, printer):
- fields = ['%s field%d;'%(printer.getTypeName(t),i) for i,t in enumerate(self.fields)]
+ def getField((i, t)):
+ if t.isBitField():
+ if t.isPaddingBitField():
+ return '%s : 0;'%(printer.getTypeName(t),)
+ else:
+ return '%s field%d : %d;'%(printer.getTypeName(t),i,
+ t.getBitFieldSize())
+ else:
+ return '%s field%d;'%(printer.getTypeName(t),i)
+ fields = map(getField, enumerate(self.fields))
# Name the struct for more readable LLVM IR.
return 'typedef %s %s { %s } %s;'%(('struct','union')[self.isUnion],
name, ' '.join(fields), name)
-class ArrayType:
+class ArrayType(Type):
def __init__(self, index, isVector, elementType, size):
if isVector:
# Note that for vectors, this is the size in bytes.
sizeStr = str(self.size)
return 'typedef %s %s[%s];'%(elementName, name, sizeStr)
-class ComplexType:
+class ComplexType(Type):
def __init__(self, index, elementType):
self.index = index
self.elementType = elementType
def getTypedefDef(self, name, printer):
return 'typedef _Complex %s %s;'%(printer.getTypeName(self.elementType), name)
-class FunctionType:
+class FunctionType(Type):
def __init__(self, index, returnType, argTypes):
self.index = index
self.returnType = returnType
return self.generators[index].get(M)
def test():
+ fbtg = FixedTypeGenerator([BuiltinType('char', 4),
+ BuiltinType('char', 4, 0),
+ BuiltinType('int', 4, 5)])
+
+ fields1 = AnyTypeGenerator()
+ fields1.addGenerator( fbtg )
+
+ fields0 = AnyTypeGenerator()
+ fields0.addGenerator( fbtg )
+# fields0.addGenerator( RecordTypeGenerator(fields1, False, 4) )
+
+ btg = FixedTypeGenerator([BuiltinType('char', 4),
+ BuiltinType('int', 4)])
+
atg = AnyTypeGenerator()
- btg = FixedTypeGenerator([BuiltinType('int',4),
- BuiltinType('float',4)])
atg.addGenerator( btg )
- atg.addGenerator( ComplexTypeGenerator(btg) )
- atg.addGenerator( RecordTypeGenerator(atg, True, 2) )
- atg.addGenerator( VectorTypeGenerator(btg, (4,8)) )
- atg.addGenerator( ArrayTypeGenerator(btg, 4) )
- atg.addGenerator( FunctionTypeGenerator(btg, False, 2) )
+ atg.addGenerator( RecordTypeGenerator(fields0, False, 4) )
print 'Cardinality:',atg.cardinality
for i in range(100):
+ if i == atg.cardinality:
+ try:
+ atg.get(i)
+ raise RuntimeError,"Cardinality was wrong"
+ except AssertionError:
+ break
print '%4d: %s'%(i, atg.get(i))
if __name__ == '__main__':