These classes are not very entangled with the rest of __init__, and we'll be expanding them a bit.
99 lines
3.3 KiB
Python
99 lines
3.3 KiB
Python
"""
|
|
Type variables for Parametric polymorphism.
|
|
|
|
Cretonne instructions and instruction transformations can be specified to be
|
|
polymorphic by using type variables.
|
|
"""
|
|
from __future__ import absolute_import
|
|
from collections import namedtuple
|
|
from . import value
|
|
|
|
#: A `TypeSet` represents a set of types. We don't allow arbitrary subsets of
|
|
#: types, but use a parametrized approach instead.
|
|
#: This is represented as a named tuple so it can be used as a dictionary key.
|
|
TypeSet = namedtuple(
|
|
'TypeSet', [
|
|
'allow_scalars',
|
|
'allow_simd',
|
|
'base',
|
|
'all_ints',
|
|
'all_floats',
|
|
'all_bools'])
|
|
|
|
|
|
class TypeVar(object):
|
|
"""
|
|
Type variables can be used in place of concrete types when defining
|
|
instructions. This makes the instructions *polymorphic*.
|
|
|
|
A type variable is restricted to vary over a subset of the value types.
|
|
This subset is specified by a set of flags that control the permitted base
|
|
types and whether the type variable can assume scalar or vector types, or
|
|
both.
|
|
|
|
:param name: Short name of type variable used in instruction descriptions.
|
|
:param doc: Documentation string.
|
|
:param base: Single base type or list of base types. Use this to specify an
|
|
exact set of base types if the general categories below are not good
|
|
enough.
|
|
:param ints: Allow all integer base types.
|
|
:param floats: Allow all floating point base types.
|
|
:param bools: Allow all boolean base types.
|
|
:param scalars: Allow type variable to assume scalar types.
|
|
:param simd: Allow type variable to assume vector types.
|
|
"""
|
|
|
|
def __init__(
|
|
self, name, doc, base=None,
|
|
ints=False, floats=False, bools=False,
|
|
scalars=True, simd=False,
|
|
derived_func=None):
|
|
self.name = name
|
|
self.__doc__ = doc
|
|
self.base = base
|
|
self.is_derived = isinstance(base, TypeVar)
|
|
if self.is_derived:
|
|
assert derived_func
|
|
self.derived_func = derived_func
|
|
self.name = '{}({})'.format(derived_func, base.name)
|
|
else:
|
|
self.type_set = TypeSet(
|
|
allow_scalars=scalars,
|
|
allow_simd=simd,
|
|
base=base,
|
|
all_ints=ints,
|
|
all_floats=floats,
|
|
all_bools=bools)
|
|
|
|
def __str__(self):
|
|
return "`{}`".format(self.name)
|
|
|
|
def lane_of(self):
|
|
"""
|
|
Return a derived type variable that is the scalar lane type of this
|
|
type variable.
|
|
|
|
When this type variable assumes a scalar type, the derived type will be
|
|
the same scalar type.
|
|
"""
|
|
return TypeVar(None, None, base=self, derived_func='LaneOf')
|
|
|
|
def as_bool(self):
|
|
"""
|
|
Return a derived type variable that has the same vector geometry as
|
|
this type variable, but with boolean lanes. Scalar types map to `b1`.
|
|
"""
|
|
return TypeVar(None, None, base=self, derived_func='AsBool')
|
|
|
|
def operand_kind(self):
|
|
# When a `TypeVar` object is used to describe the type of an `Operand`
|
|
# in an instruction definition, the kind of that operand is an SSA
|
|
# value.
|
|
return value
|
|
|
|
def free_typevar(self):
|
|
if isinstance(self.base, TypeVar):
|
|
return self.base
|
|
else:
|
|
return self
|