diff --git a/meta/cretonne/__init__.py b/meta/cretonne/__init__.py index 483fb1f8e3..01b74747b5 100644 --- a/meta/cretonne/__init__.py +++ b/meta/cretonne/__init__.py @@ -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 diff --git a/meta/target/riscv/encodings.py b/meta/target/riscv/encodings.py index 0177cb57f9..fa3f7d055d 100644 --- a/meta/target/riscv/encodings.py +++ b/meta/target/riscv/encodings.py @@ -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))