summaryrefslogtreecommitdiffstats
path: root/utils/ABITest/TypeGen.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ABITest/TypeGen.py')
-rw-r--r--utils/ABITest/TypeGen.py381
1 files changed, 381 insertions, 0 deletions
diff --git a/utils/ABITest/TypeGen.py b/utils/ABITest/TypeGen.py
new file mode 100644
index 0000000..d5678db
--- /dev/null
+++ b/utils/ABITest/TypeGen.py
@@ -0,0 +1,381 @@
+"""Flexible enumeration of C types."""
+
+from Enumeration import *
+
+# TODO:
+
+# - struct improvements (flexible arrays, packed &
+# unpacked, alignment)
+# - objective-c qualified id
+# - anonymous / transparent unions
+# - VLAs
+# - block types
+# - K&R functions
+# - pass arguments of different types (test extension, transparent union)
+# - varargs
+
+###
+# Actual type types
+
+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(Type):
+ def __init__(self, index, isUnion, fields):
+ self.index = index
+ self.isUnion = isUnion
+ self.fields = fields
+ self.name = None
+
+ 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(map(getField, self.fields)))
+
+ def getTypedefDef(self, name, printer):
+ 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(Type):
+ def __init__(self, index, isVector, elementType, size):
+ if isVector:
+ # Note that for vectors, this is the size in bytes.
+ assert size > 0
+ else:
+ assert size is None or size >= 0
+ self.index = index
+ self.isVector = isVector
+ self.elementType = elementType
+ self.size = size
+ if isVector:
+ eltSize = self.elementType.sizeof()
+ assert not (self.size % eltSize)
+ self.numElements = self.size // eltSize
+ else:
+ self.numElements = self.size
+
+ def __str__(self):
+ if self.isVector:
+ return 'vector (%s)[%d]'%(self.elementType,self.size)
+ elif self.size is not None:
+ return '(%s)[%d]'%(self.elementType,self.size)
+ else:
+ return '(%s)[]'%(self.elementType,)
+
+ def getTypedefDef(self, name, printer):
+ elementName = printer.getTypeName(self.elementType)
+ if self.isVector:
+ return 'typedef %s %s __attribute__ ((vector_size (%d)));'%(elementName,
+ name,
+ self.size)
+ else:
+ if self.size is None:
+ sizeStr = ''
+ else:
+ sizeStr = str(self.size)
+ return 'typedef %s %s[%s];'%(elementName, name, sizeStr)
+
+class ComplexType(Type):
+ def __init__(self, index, elementType):
+ self.index = index
+ self.elementType = elementType
+
+ def __str__(self):
+ return '_Complex (%s)'%(self.elementType)
+
+ def getTypedefDef(self, name, printer):
+ return 'typedef _Complex %s %s;'%(printer.getTypeName(self.elementType), name)
+
+class FunctionType(Type):
+ def __init__(self, index, returnType, argTypes):
+ self.index = index
+ self.returnType = returnType
+ self.argTypes = argTypes
+
+ def __str__(self):
+ if self.returnType is None:
+ rt = 'void'
+ else:
+ rt = str(self.returnType)
+ if not self.argTypes:
+ at = 'void'
+ else:
+ at = ', '.join(map(str, self.argTypes))
+ return '%s (*)(%s)'%(rt, at)
+
+ def getTypedefDef(self, name, printer):
+ if self.returnType is None:
+ rt = 'void'
+ else:
+ rt = str(self.returnType)
+ if not self.argTypes:
+ at = 'void'
+ else:
+ at = ', '.join(map(str, self.argTypes))
+ return 'typedef %s (*%s)(%s);'%(rt, name, at)
+
+###
+# Type enumerators
+
+class TypeGenerator(object):
+ def __init__(self):
+ self.cache = {}
+
+ def setCardinality(self):
+ abstract
+
+ def get(self, N):
+ T = self.cache.get(N)
+ if T is None:
+ assert 0 <= N < self.cardinality
+ T = self.cache[N] = self.generateType(N)
+ return T
+
+ def generateType(self, N):
+ abstract
+
+class FixedTypeGenerator(TypeGenerator):
+ def __init__(self, types):
+ TypeGenerator.__init__(self)
+ self.types = types
+ self.setCardinality()
+
+ def setCardinality(self):
+ self.cardinality = len(self.types)
+
+ def generateType(self, N):
+ return self.types[N]
+
+class ComplexTypeGenerator(TypeGenerator):
+ def __init__(self, typeGen):
+ TypeGenerator.__init__(self)
+ self.typeGen = typeGen
+ self.setCardinality()
+
+ def setCardinality(self):
+ self.cardinality = self.typeGen.cardinality
+
+ def generateType(self, N):
+ return ComplexType(N, self.typeGen.get(N))
+
+class VectorTypeGenerator(TypeGenerator):
+ def __init__(self, typeGen, sizes):
+ TypeGenerator.__init__(self)
+ self.typeGen = typeGen
+ self.sizes = tuple(map(int,sizes))
+ self.setCardinality()
+
+ def setCardinality(self):
+ self.cardinality = len(self.sizes)*self.typeGen.cardinality
+
+ def generateType(self, N):
+ S,T = getNthPairBounded(N, len(self.sizes), self.typeGen.cardinality)
+ return ArrayType(N, True, self.typeGen.get(T), self.sizes[S])
+
+class FixedArrayTypeGenerator(TypeGenerator):
+ def __init__(self, typeGen, sizes):
+ TypeGenerator.__init__(self)
+ self.typeGen = typeGen
+ self.sizes = tuple(size)
+ self.setCardinality()
+
+ def setCardinality(self):
+ self.cardinality = len(self.sizes)*self.typeGen.cardinality
+
+ def generateType(self, N):
+ S,T = getNthPairBounded(N, len(self.sizes), self.typeGen.cardinality)
+ return ArrayType(N, false, self.typeGen.get(T), self.sizes[S])
+
+class ArrayTypeGenerator(TypeGenerator):
+ def __init__(self, typeGen, maxSize, useIncomplete=False, useZero=False):
+ TypeGenerator.__init__(self)
+ self.typeGen = typeGen
+ self.useIncomplete = useIncomplete
+ self.useZero = useZero
+ self.maxSize = int(maxSize)
+ self.W = useIncomplete + useZero + self.maxSize
+ self.setCardinality()
+
+ def setCardinality(self):
+ self.cardinality = self.W * self.typeGen.cardinality
+
+ def generateType(self, N):
+ S,T = getNthPairBounded(N, self.W, self.typeGen.cardinality)
+ if self.useIncomplete:
+ if S==0:
+ size = None
+ S = None
+ else:
+ S = S - 1
+ if S is not None:
+ if self.useZero:
+ size = S
+ else:
+ size = S + 1
+ return ArrayType(N, False, self.typeGen.get(T), size)
+
+class RecordTypeGenerator(TypeGenerator):
+ def __init__(self, typeGen, useUnion, maxSize):
+ TypeGenerator.__init__(self)
+ self.typeGen = typeGen
+ self.useUnion = bool(useUnion)
+ self.maxSize = int(maxSize)
+ self.setCardinality()
+
+ def setCardinality(self):
+ M = 1 + self.useUnion
+ if self.maxSize is aleph0:
+ S = aleph0 * self.typeGen.cardinality
+ else:
+ S = 0
+ for i in range(self.maxSize+1):
+ S += M * (self.typeGen.cardinality ** i)
+ self.cardinality = S
+
+ def generateType(self, N):
+ isUnion,I = False,N
+ if self.useUnion:
+ isUnion,I = (I&1),I>>1
+ fields = map(self.typeGen.get,getNthTuple(I,self.maxSize,self.typeGen.cardinality))
+ return RecordType(N, isUnion, fields)
+
+class FunctionTypeGenerator(TypeGenerator):
+ def __init__(self, typeGen, useReturn, maxSize):
+ TypeGenerator.__init__(self)
+ self.typeGen = typeGen
+ self.useReturn = useReturn
+ self.maxSize = maxSize
+ self.setCardinality()
+
+ def setCardinality(self):
+ if self.maxSize is aleph0:
+ S = aleph0 * self.typeGen.cardinality()
+ elif self.useReturn:
+ S = 0
+ for i in range(1,self.maxSize+1+1):
+ S += self.typeGen.cardinality ** i
+ else:
+ S = 0
+ for i in range(self.maxSize+1):
+ S += self.typeGen.cardinality ** i
+ self.cardinality = S
+
+ def generateType(self, N):
+ if self.useReturn:
+ # Skip the empty tuple
+ argIndices = getNthTuple(N+1, self.maxSize+1, self.typeGen.cardinality)
+ retIndex,argIndices = argIndices[0],argIndices[1:]
+ retTy = self.typeGen.get(retIndex)
+ else:
+ retTy = None
+ argIndices = getNthTuple(N, self.maxSize, self.typeGen.cardinality)
+ args = map(self.typeGen.get, argIndices)
+ return FunctionType(N, retTy, args)
+
+class AnyTypeGenerator(TypeGenerator):
+ def __init__(self):
+ TypeGenerator.__init__(self)
+ self.generators = []
+ self.bounds = []
+ self.setCardinality()
+ self._cardinality = None
+
+ def getCardinality(self):
+ if self._cardinality is None:
+ return aleph0
+ else:
+ return self._cardinality
+ def setCardinality(self):
+ self.bounds = [g.cardinality for g in self.generators]
+ self._cardinality = sum(self.bounds)
+ cardinality = property(getCardinality, None)
+
+ def addGenerator(self, g):
+ self.generators.append(g)
+ for i in range(100):
+ prev = self._cardinality
+ self._cardinality = None
+ for g in self.generators:
+ g.setCardinality()
+ self.setCardinality()
+ if (self._cardinality is aleph0) or prev==self._cardinality:
+ break
+ else:
+ raise RuntimeError,"Infinite loop in setting cardinality"
+
+ def generateType(self, N):
+ index,M = getNthPairVariableBounds(N, self.bounds)
+ 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()
+ atg.addGenerator( btg )
+ 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__':
+ test()
OpenPOWER on IntegriCloud