Skip to content

Irdl

irdl

IRDLFunctions dataclass

Bases: InterpreterFunctions

Source code in xdsl/interpreters/irdl.py
@register_impls
class IRDLFunctions(InterpreterFunctions):
    @staticmethod
    def get_dialect(interpreter: Interpreter, name: str) -> Dialect:
        """
        Get a dialect by name from the interpreter's state
        """
        return interpreter.get_data(IRDLFunctions, "irdl.dialects", dict)[name]

    @staticmethod
    def set_dialect(interpreter: Interpreter, name: str, dialect: Dialect) -> None:
        """
        Set or create a dialect by name in the interpreter's state
        """
        interpreter.get_data(IRDLFunctions, "irdl.dialects", dict)[name] = dialect

    @staticmethod
    def get_op(interpreter: Interpreter, name: str) -> type[Operation]:
        """
        Get an operation type by name from the interpreter's state
        """
        ops = IRDLFunctions.get_dialect(
            interpreter, Dialect.split_name(name)[0]
        ).operations
        for op in ops:
            if op.name == name:
                return op
        raise ValueError(f"Operation {name} not found")

    @staticmethod
    def get_attr(interpreter: Interpreter, name: str) -> type[ParametrizedAttribute]:
        """
        Get an attribute type by name from the interpreter's state
        """
        attrs = IRDLFunctions.get_dialect(
            interpreter, Dialect.split_name(name)[0]
        ).attributes
        for attr in attrs:
            if attr.name == name:
                if not issubclass(attr, ParametrizedAttribute):
                    raise ValueError(f"Attribute {name} is not parametrized")
                return attr
        raise ValueError(f"Attribute {name} not found")

    @staticmethod
    def _get_op_def(interpreter: Interpreter, name: str) -> OpDef:
        """
        Get an operation definition by name from the interpreter's state
        """
        return interpreter.get_data(IRDLFunctions, "irdl.op_defs", dict)[name]

    @staticmethod
    def _set_op_def(interpreter: Interpreter, name: str, op_def: OpDef) -> None:
        """
        Set or create an operation definition by name in the interpreter's state
        """
        interpreter.get_data(IRDLFunctions, "irdl.op_defs", dict)[name] = op_def

    @staticmethod
    def _get_attr_def(interpreter: Interpreter, name: str) -> ParamAttrDef:
        """
        Get an attribute definition by name from the interpreter's state
        """
        return interpreter.get_data(IRDLFunctions, "irdl.attr_defs", dict)[name]

    @staticmethod
    def _set_attr_def(
        interpreter: Interpreter, name: str, attr_def: ParamAttrDef
    ) -> None:
        """
        Set or create an attribute definition by name in the interpreter's state
        """
        interpreter.get_data(IRDLFunctions, "irdl.attr_defs", dict)[name] = attr_def

    @staticmethod
    def next_variable_counter(interpreter: Interpreter) -> int:
        counter = interpreter.get_data(
            IRDLFunctions, "irdl.variable_counters", lambda: 0
        )
        interpreter.set_data(IRDLFunctions, "irdl.variable_counters", counter + 1)
        return counter

    @staticmethod
    def variable_wrap(interpreter: Interpreter, constr: AttrConstraint):
        counter = IRDLFunctions.next_variable_counter(interpreter)
        return VarConstraint(f"V{counter}", constr)

    @impl(irdl.IsOp)
    def run_is(self, interpreter: Interpreter, op: irdl.IsOp, args: PythonValues):
        constr = EqAttrConstraint(op.expected)
        if op.output.has_more_than_one_use():
            constr = self.variable_wrap(interpreter, constr)
        return (constr,)

    @impl(irdl.AnyOfOp)
    def run_any_of(
        self, interpreter: Interpreter, op: irdl.AnyOfOp, args: PythonValues
    ):
        constr = AnyOf[Attribute](args)
        if op.output.has_more_than_one_use():
            constr = self.variable_wrap(interpreter, constr)
        return (constr,)

    @impl(irdl.AnyOp)
    def run_any(self, interpreter: Interpreter, op: irdl.AnyOp, args: PythonValues):
        constr = AnyAttr()
        if op.output.has_more_than_one_use():
            constr = self.variable_wrap(interpreter, constr)
        return (constr,)

    @impl(irdl.ParametricOp)
    def run_parametric(
        self, interpreter: Interpreter, op: irdl.ParametricOp, args: PythonValues
    ):
        base_attr_op = SymbolTable.lookup_symbol(op, op.base_type)
        if not isinstance(base_attr_op, irdl.AttributeOp | irdl.TypeOp):
            raise ValueError(
                f"Expected AttributeOp or TypeOp, got {type(base_attr_op)}"
            )
        base_type = self.get_attr(interpreter, base_attr_op.qualified_name)
        constr = ParamAttrConstraint(base_type, args)
        if op.output.has_more_than_one_use():
            constr = self.variable_wrap(interpreter, constr)
        return (constr,)

    @impl(irdl.TypeOp)
    def run_type(self, interpreter: Interpreter, op: irdl.TypeOp, args: PythonValues):
        name = op.qualified_name
        self._set_attr_def(interpreter, name, ParamAttrDef(name, []))
        interpreter.run_ssacfg_region(op.body, ())

        attr = self.get_attr(interpreter, name)
        attr_def = self._get_attr_def(interpreter, name)

        @classmethod
        def get_irdl_definition(cls: type[ParametrizedAttribute]):
            return attr_def

        setattr(attr, "get_irdl_definition", get_irdl_definition)
        return ()

    @impl(irdl.OperandsOp)
    def run_operands(
        self, interpreter: Interpreter, op: irdl.OperandsOp, args: PythonValues
    ):
        op_op = cast(irdl.OperationOp, op.parent_op())
        op_name = op_op.qualified_name
        self._get_op_def(interpreter, op_name).operands = list(
            (python_name(name.data), OperandDef(a)) for name, a in zip(op.names, args)
        )
        return ()

    @impl(irdl.ResultsOp)
    def run_results(
        self, interpreter: Interpreter, op: irdl.ResultsOp, args: PythonValues
    ):
        op_op = cast(irdl.OperationOp, op.parent_op())
        op_name = op_op.qualified_name
        self._get_op_def(interpreter, op_name).results = list(
            (python_name(name.data), ResultDef(a)) for name, a in zip(op.names, args)
        )
        return ()

    @impl(irdl.OperationOp)
    def run_operation(
        self, interpreter: Interpreter, op: irdl.OperationOp, args: PythonValues
    ):
        name = op.qualified_name
        self._set_op_def(interpreter, name, OpDef(name))
        interpreter.run_ssacfg_region(op.body, ())
        op_def = self._get_op_def(interpreter, name)
        op_type = self.get_op(interpreter, name)

        to_inject = get_accessors_from_op_def(op_def, None)
        for k, v in to_inject.items():
            setattr(op_type, k, v)
        return ()

    @impl(irdl.ParametersOp)
    def run_parameters(
        self, interpreter: Interpreter, op: irdl.ParametersOp, args: PythonValues
    ):
        attr_op = cast(irdl.AttributeOp | irdl.TypeOp, op.parent_op())
        attr_name = attr_op.qualified_name
        self._get_attr_def(interpreter, attr_name).parameters = list(
            (python_name(name.data), ParamDef(a)) for name, a in zip(op.names, args)
        )
        return ()

    @impl(irdl.DialectOp)
    def run_dialect(
        self, interpreter: Interpreter, op: irdl.DialectOp, args: PythonValues
    ):
        operations: list[type[Operation]] = []
        attributes: list[type[Attribute]] = []
        for entry in op.body.block.ops:
            match entry:
                case irdl.OperationOp():
                    operations.append(
                        type(
                            entry.get_py_class_name(),
                            (IRDLOperation,),
                            dict(IRDLOperation.__dict__)
                            | {"name": entry.qualified_name},
                        )
                    )

                case irdl.TypeOp():
                    attributes.append(
                        type(
                            entry.sym_name.data,
                            (TypeAttribute, ParametrizedAttribute),
                            dict(ParametrizedAttribute.__dict__)
                            | {"name": entry.qualified_name},
                        )
                    )

                case _:
                    pass

        self.set_dialect(
            interpreter,
            op.sym_name.data,
            Dialect(op.sym_name.data, operations, attributes),
        )
        interpreter.run_ssacfg_region(op.body, ())
        return ()

get_dialect(interpreter: Interpreter, name: str) -> Dialect staticmethod

Get a dialect by name from the interpreter's state

Source code in xdsl/interpreters/irdl.py
@staticmethod
def get_dialect(interpreter: Interpreter, name: str) -> Dialect:
    """
    Get a dialect by name from the interpreter's state
    """
    return interpreter.get_data(IRDLFunctions, "irdl.dialects", dict)[name]

set_dialect(interpreter: Interpreter, name: str, dialect: Dialect) -> None staticmethod

Set or create a dialect by name in the interpreter's state

Source code in xdsl/interpreters/irdl.py
@staticmethod
def set_dialect(interpreter: Interpreter, name: str, dialect: Dialect) -> None:
    """
    Set or create a dialect by name in the interpreter's state
    """
    interpreter.get_data(IRDLFunctions, "irdl.dialects", dict)[name] = dialect

get_op(interpreter: Interpreter, name: str) -> type[Operation] staticmethod

Get an operation type by name from the interpreter's state

Source code in xdsl/interpreters/irdl.py
@staticmethod
def get_op(interpreter: Interpreter, name: str) -> type[Operation]:
    """
    Get an operation type by name from the interpreter's state
    """
    ops = IRDLFunctions.get_dialect(
        interpreter, Dialect.split_name(name)[0]
    ).operations
    for op in ops:
        if op.name == name:
            return op
    raise ValueError(f"Operation {name} not found")

get_attr(interpreter: Interpreter, name: str) -> type[ParametrizedAttribute] staticmethod

Get an attribute type by name from the interpreter's state

Source code in xdsl/interpreters/irdl.py
@staticmethod
def get_attr(interpreter: Interpreter, name: str) -> type[ParametrizedAttribute]:
    """
    Get an attribute type by name from the interpreter's state
    """
    attrs = IRDLFunctions.get_dialect(
        interpreter, Dialect.split_name(name)[0]
    ).attributes
    for attr in attrs:
        if attr.name == name:
            if not issubclass(attr, ParametrizedAttribute):
                raise ValueError(f"Attribute {name} is not parametrized")
            return attr
    raise ValueError(f"Attribute {name} not found")

next_variable_counter(interpreter: Interpreter) -> int staticmethod

Source code in xdsl/interpreters/irdl.py
@staticmethod
def next_variable_counter(interpreter: Interpreter) -> int:
    counter = interpreter.get_data(
        IRDLFunctions, "irdl.variable_counters", lambda: 0
    )
    interpreter.set_data(IRDLFunctions, "irdl.variable_counters", counter + 1)
    return counter

variable_wrap(interpreter: Interpreter, constr: AttrConstraint) staticmethod

Source code in xdsl/interpreters/irdl.py
@staticmethod
def variable_wrap(interpreter: Interpreter, constr: AttrConstraint):
    counter = IRDLFunctions.next_variable_counter(interpreter)
    return VarConstraint(f"V{counter}", constr)

run_is(interpreter: Interpreter, op: irdl.IsOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.IsOp)
def run_is(self, interpreter: Interpreter, op: irdl.IsOp, args: PythonValues):
    constr = EqAttrConstraint(op.expected)
    if op.output.has_more_than_one_use():
        constr = self.variable_wrap(interpreter, constr)
    return (constr,)

run_any_of(interpreter: Interpreter, op: irdl.AnyOfOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.AnyOfOp)
def run_any_of(
    self, interpreter: Interpreter, op: irdl.AnyOfOp, args: PythonValues
):
    constr = AnyOf[Attribute](args)
    if op.output.has_more_than_one_use():
        constr = self.variable_wrap(interpreter, constr)
    return (constr,)

run_any(interpreter: Interpreter, op: irdl.AnyOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.AnyOp)
def run_any(self, interpreter: Interpreter, op: irdl.AnyOp, args: PythonValues):
    constr = AnyAttr()
    if op.output.has_more_than_one_use():
        constr = self.variable_wrap(interpreter, constr)
    return (constr,)

run_parametric(interpreter: Interpreter, op: irdl.ParametricOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.ParametricOp)
def run_parametric(
    self, interpreter: Interpreter, op: irdl.ParametricOp, args: PythonValues
):
    base_attr_op = SymbolTable.lookup_symbol(op, op.base_type)
    if not isinstance(base_attr_op, irdl.AttributeOp | irdl.TypeOp):
        raise ValueError(
            f"Expected AttributeOp or TypeOp, got {type(base_attr_op)}"
        )
    base_type = self.get_attr(interpreter, base_attr_op.qualified_name)
    constr = ParamAttrConstraint(base_type, args)
    if op.output.has_more_than_one_use():
        constr = self.variable_wrap(interpreter, constr)
    return (constr,)

run_type(interpreter: Interpreter, op: irdl.TypeOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.TypeOp)
def run_type(self, interpreter: Interpreter, op: irdl.TypeOp, args: PythonValues):
    name = op.qualified_name
    self._set_attr_def(interpreter, name, ParamAttrDef(name, []))
    interpreter.run_ssacfg_region(op.body, ())

    attr = self.get_attr(interpreter, name)
    attr_def = self._get_attr_def(interpreter, name)

    @classmethod
    def get_irdl_definition(cls: type[ParametrizedAttribute]):
        return attr_def

    setattr(attr, "get_irdl_definition", get_irdl_definition)
    return ()

run_operands(interpreter: Interpreter, op: irdl.OperandsOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.OperandsOp)
def run_operands(
    self, interpreter: Interpreter, op: irdl.OperandsOp, args: PythonValues
):
    op_op = cast(irdl.OperationOp, op.parent_op())
    op_name = op_op.qualified_name
    self._get_op_def(interpreter, op_name).operands = list(
        (python_name(name.data), OperandDef(a)) for name, a in zip(op.names, args)
    )
    return ()

run_results(interpreter: Interpreter, op: irdl.ResultsOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.ResultsOp)
def run_results(
    self, interpreter: Interpreter, op: irdl.ResultsOp, args: PythonValues
):
    op_op = cast(irdl.OperationOp, op.parent_op())
    op_name = op_op.qualified_name
    self._get_op_def(interpreter, op_name).results = list(
        (python_name(name.data), ResultDef(a)) for name, a in zip(op.names, args)
    )
    return ()

run_operation(interpreter: Interpreter, op: irdl.OperationOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.OperationOp)
def run_operation(
    self, interpreter: Interpreter, op: irdl.OperationOp, args: PythonValues
):
    name = op.qualified_name
    self._set_op_def(interpreter, name, OpDef(name))
    interpreter.run_ssacfg_region(op.body, ())
    op_def = self._get_op_def(interpreter, name)
    op_type = self.get_op(interpreter, name)

    to_inject = get_accessors_from_op_def(op_def, None)
    for k, v in to_inject.items():
        setattr(op_type, k, v)
    return ()

run_parameters(interpreter: Interpreter, op: irdl.ParametersOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.ParametersOp)
def run_parameters(
    self, interpreter: Interpreter, op: irdl.ParametersOp, args: PythonValues
):
    attr_op = cast(irdl.AttributeOp | irdl.TypeOp, op.parent_op())
    attr_name = attr_op.qualified_name
    self._get_attr_def(interpreter, attr_name).parameters = list(
        (python_name(name.data), ParamDef(a)) for name, a in zip(op.names, args)
    )
    return ()

run_dialect(interpreter: Interpreter, op: irdl.DialectOp, args: PythonValues)

Source code in xdsl/interpreters/irdl.py
@impl(irdl.DialectOp)
def run_dialect(
    self, interpreter: Interpreter, op: irdl.DialectOp, args: PythonValues
):
    operations: list[type[Operation]] = []
    attributes: list[type[Attribute]] = []
    for entry in op.body.block.ops:
        match entry:
            case irdl.OperationOp():
                operations.append(
                    type(
                        entry.get_py_class_name(),
                        (IRDLOperation,),
                        dict(IRDLOperation.__dict__)
                        | {"name": entry.qualified_name},
                    )
                )

            case irdl.TypeOp():
                attributes.append(
                    type(
                        entry.sym_name.data,
                        (TypeAttribute, ParametrizedAttribute),
                        dict(ParametrizedAttribute.__dict__)
                        | {"name": entry.qualified_name},
                    )
                )

            case _:
                pass

    self.set_dialect(
        interpreter,
        op.sym_name.data,
        Dialect(op.sym_name.data, operations, attributes),
    )
    interpreter.run_ssacfg_region(op.body, ())
    return ()

make_dialect(op: irdl.DialectOp) -> Dialect

Source code in xdsl/interpreters/irdl.py
def make_dialect(op: irdl.DialectOp) -> Dialect:
    module = op.get_toplevel_object()
    if not isinstance(module, ModuleOp):
        raise ValueError("Expected dialect to be nested in a ModuleOp")

    interpreter = Interpreter(module)
    irdl_impl = IRDLFunctions()
    interpreter.register_implementations(irdl_impl)
    interpreter.run_op(op, ())
    return interpreter.get_data(IRDLFunctions, "irdl.dialects", dict)[op.sym_name.data]