Use dot syntax to bind type variables on instructions.

Encodings need to refer to concrete instances of polymorphic instructions by
binding type variables. Allow dot syntax like iadd.i32 to do that.
This commit is contained in:
Jakob Stoklund Olesen
2016-08-03 16:30:47 -07:00
parent 4987282bbb
commit a1cc8af186
2 changed files with 64 additions and 8 deletions

View File

@@ -115,10 +115,15 @@ class ValueType(object):
or one of its subclasses.
"""
# map name -> ValueType.
_registry = dict()
def __init__(self, name, membytes, doc):
self.name = name
self.membytes = membytes
self.__doc__ = doc
assert name not in ValueType._registry
ValueType._registry[name] = self
def __str__(self):
return self.name
@@ -133,6 +138,13 @@ class ValueType(object):
def free_typevar(self):
return None
@staticmethod
def by_name(name):
if name in ValueType._registry:
return ValueType._registry[name]
else:
raise AttributeError("No type named '{}'".format(name))
class ScalarType(ValueType):
"""
@@ -637,6 +649,47 @@ class Instruction(object):
assert isinstance(op, Operand)
return x
def bind(self, *args):
"""
Bind a polymorphic instruction to a concrete list of type variable
values.
"""
assert self.is_polymorphic
return BoundInstruction(self, args)
def __getattr__(self, name):
"""
Bind a polymorphic instruction to a single type variable with dot
syntax:
>>> iadd.i32
"""
return self.bind(ValueType.by_name(name))
class BoundInstruction(object):
"""
A polymorphic `Instruction` bound to concrete type variables.
"""
def __init__(self, inst, typevars):
self.inst = inst
self.typevars = typevars
def bind(self, *args):
"""
Bind additional typevars.
"""
return BoundInstruction(self.inst, self.typevars + args)
def __getattr__(self, name):
"""
Bind an additional typevar dot syntax:
>>> uext.i32.i8
"""
return self.bind(ValueType.by_name(name))
# Defining targets
@@ -708,22 +761,25 @@ class Encoding(object):
variables together with and encoding recipe and encoding bits.
:param cpumode: The CPU mode where the encoding is active.
:param inst: The :py:class:`Instruction` being encoded.
:param typevars: Concete types for `inst`'s type variables, if any.
:param inst: The :py:class:`Instruction` or :py:class:`BoundInstruction`
being encoded.
:param recipe: The :py:class:`EncRecipe` to use.
:param encbits: Additional encoding bits to be interpreted by `recipe`.
"""
def __init__(self, cpumode, inst, typevars, recipe, encbits):
def __init__(self, cpumode, inst, recipe, encbits):
assert isinstance(cpumode, CPUMode)
assert isinstance(inst, Instruction)
if isinstance(inst, BoundInstruction):
real_inst = inst.inst
else:
real_inst = inst
assert isinstance(real_inst, Instruction)
assert isinstance(recipe, EncRecipe)
self.cpumode = cpumode
assert inst.format == recipe.format, (
assert real_inst.format == recipe.format, (
"Format {} must match recipe: {}".format(
inst.format, recipe.format))
self.inst = inst
self.typevars = self._to_type_tuple(typevars)
self.recipe = recipe
self.encbits = encbits

View File

@@ -17,5 +17,5 @@ for inst, f3, f7 in [
(base.bor, 0b110, 0b0000000),
(base.band, 0b111, 0b0000000)
]:
RV32.enc(inst, i32, R, OP(f3, f7))
RV64.enc(inst, i64, R, OP(f3, f7))
RV32.enc(inst.i32, R, OP(f3, f7))
RV64.enc(inst.i64, R, OP(f3, f7))