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:
@@ -115,10 +115,15 @@ class ValueType(object):
|
|||||||
or one of its subclasses.
|
or one of its subclasses.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# map name -> ValueType.
|
||||||
|
_registry = dict()
|
||||||
|
|
||||||
def __init__(self, name, membytes, doc):
|
def __init__(self, name, membytes, doc):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.membytes = membytes
|
self.membytes = membytes
|
||||||
self.__doc__ = doc
|
self.__doc__ = doc
|
||||||
|
assert name not in ValueType._registry
|
||||||
|
ValueType._registry[name] = self
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -133,6 +138,13 @@ class ValueType(object):
|
|||||||
def free_typevar(self):
|
def free_typevar(self):
|
||||||
return None
|
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):
|
class ScalarType(ValueType):
|
||||||
"""
|
"""
|
||||||
@@ -637,6 +649,47 @@ class Instruction(object):
|
|||||||
assert isinstance(op, Operand)
|
assert isinstance(op, Operand)
|
||||||
return x
|
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
|
# Defining targets
|
||||||
|
|
||||||
@@ -708,22 +761,25 @@ class Encoding(object):
|
|||||||
variables together with and encoding recipe and encoding bits.
|
variables together with and encoding recipe and encoding bits.
|
||||||
|
|
||||||
:param cpumode: The CPU mode where the encoding is active.
|
:param cpumode: The CPU mode where the encoding is active.
|
||||||
:param inst: The :py:class:`Instruction` being encoded.
|
:param inst: The :py:class:`Instruction` or :py:class:`BoundInstruction`
|
||||||
:param typevars: Concete types for `inst`'s type variables, if any.
|
being encoded.
|
||||||
:param recipe: The :py:class:`EncRecipe` to use.
|
:param recipe: The :py:class:`EncRecipe` to use.
|
||||||
:param encbits: Additional encoding bits to be interpreted by `recipe`.
|
: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(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)
|
assert isinstance(recipe, EncRecipe)
|
||||||
self.cpumode = cpumode
|
self.cpumode = cpumode
|
||||||
assert inst.format == recipe.format, (
|
assert real_inst.format == recipe.format, (
|
||||||
"Format {} must match recipe: {}".format(
|
"Format {} must match recipe: {}".format(
|
||||||
inst.format, recipe.format))
|
inst.format, recipe.format))
|
||||||
self.inst = inst
|
self.inst = inst
|
||||||
self.typevars = self._to_type_tuple(typevars)
|
|
||||||
self.recipe = recipe
|
self.recipe = recipe
|
||||||
self.encbits = encbits
|
self.encbits = encbits
|
||||||
|
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ for inst, f3, f7 in [
|
|||||||
(base.bor, 0b110, 0b0000000),
|
(base.bor, 0b110, 0b0000000),
|
||||||
(base.band, 0b111, 0b0000000)
|
(base.band, 0b111, 0b0000000)
|
||||||
]:
|
]:
|
||||||
RV32.enc(inst, i32, R, OP(f3, f7))
|
RV32.enc(inst.i32, R, OP(f3, f7))
|
||||||
RV64.enc(inst, i64, R, OP(f3, f7))
|
RV64.enc(inst.i64, R, OP(f3, f7))
|
||||||
|
|||||||
Reference in New Issue
Block a user