Files
wasmtime/meta/cretonne/typevar.py
Jakob Stoklund Olesen 8cbaacac48 Move TypeVar and TypeSet into their own Python package.
These classes are not very entangled with the rest of __init__, and
we'll be expanding them a bit.
2016-09-27 10:53:53 -07:00

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