Skip to content

Riscv func

riscv_func

RISCV_Func = Dialect('riscv_func', [SyscallOp, CallOp, FuncOp, ReturnOp], []) module-attribute

RiscvFunctionCallMemoryEffect dataclass

Bases: MemoryEffect

An assembly operation that corresponds to a function call in the RISC-V ABI, overwwriting the A, T, FA, and FT registers.

Source code in xdsl/dialects/riscv_func.py
class RiscvFunctionCallMemoryEffect(MemoryEffect):
    """
    An assembly operation that corresponds to a function call in the RISC-V ABI,
    overwwriting the A, T, FA, and FT registers.
    """

    @classmethod
    def get_effects(cls, op: Operation) -> frozenset[EffectInstance]:
        return _FUNCTION_CALL_EFFECTS

get_effects(op: Operation) -> frozenset[EffectInstance] classmethod

Source code in xdsl/dialects/riscv_func.py
@classmethod
def get_effects(cls, op: Operation) -> frozenset[EffectInstance]:
    return _FUNCTION_CALL_EFFECTS

SyscallOp

Bases: IRDLOperation

Source code in xdsl/dialects/riscv_func.py
@irdl_op_definition
class SyscallOp(IRDLOperation):
    name = "riscv_func.syscall"
    args = var_operand_def(riscv.IntRegisterType)
    syscall_num = prop_def(IntegerAttr[I32])
    result = opt_result_def(riscv.IntRegisterType)

    # Function calls can have arbitrary memory effects, and may overwrite the
    # A, T, FA, and FT registers
    traits = traits_def(
        MemoryAllocEffect(),
        MemoryFreeEffect(),
        MemoryReadEffect(),
        MemoryWriteEffect(),
        RiscvFunctionCallMemoryEffect(),
    )

    def __init__(
        self,
        num: int | IntegerAttr[I32],
        has_result: bool = False,
        operands: list[SSAValue | Operation] = [],
    ):
        if isinstance(num, int):
            num = IntegerAttr(num, i32)
        super().__init__(
            operands=[operands],
            properties={"syscall_num": num},
            result_types=[riscv.Registers.UNALLOCATED_INT if has_result else None],
        )

    def verify_(self):
        if len(self.args) >= 7:
            raise VerifyException(
                f"Syscall op has too many operands ({len(self.args)}), expected fewer than 7"
            )
        if len(self.results) >= 3:
            raise VerifyException(
                f"Syscall op has too many results ({len(self.results)}), expected fewer than 3"
            )

name = 'riscv_func.syscall' class-attribute instance-attribute

args = var_operand_def(riscv.IntRegisterType) class-attribute instance-attribute

syscall_num = prop_def(IntegerAttr[I32]) class-attribute instance-attribute

result = opt_result_def(riscv.IntRegisterType) class-attribute instance-attribute

traits = traits_def(MemoryAllocEffect(), MemoryFreeEffect(), MemoryReadEffect(), MemoryWriteEffect(), RiscvFunctionCallMemoryEffect()) class-attribute instance-attribute

__init__(num: int | IntegerAttr[I32], has_result: bool = False, operands: list[SSAValue | Operation] = [])

Source code in xdsl/dialects/riscv_func.py
def __init__(
    self,
    num: int | IntegerAttr[I32],
    has_result: bool = False,
    operands: list[SSAValue | Operation] = [],
):
    if isinstance(num, int):
        num = IntegerAttr(num, i32)
    super().__init__(
        operands=[operands],
        properties={"syscall_num": num},
        result_types=[riscv.Registers.UNALLOCATED_INT if has_result else None],
    )

verify_()

Source code in xdsl/dialects/riscv_func.py
def verify_(self):
    if len(self.args) >= 7:
        raise VerifyException(
            f"Syscall op has too many operands ({len(self.args)}), expected fewer than 7"
        )
    if len(self.results) >= 3:
        raise VerifyException(
            f"Syscall op has too many results ({len(self.results)}), expected fewer than 3"
        )

CallOp

Bases: RISCVInstruction

RISC-V function call operation

Source code in xdsl/dialects/riscv_func.py
@irdl_op_definition
class CallOp(riscv.RISCVInstruction):
    """RISC-V function call operation"""

    name = "riscv_func.call"
    args = var_operand_def(riscv.RISCVRegisterType)
    callee = attr_def(SymbolRefAttr)
    ress = var_result_def(riscv.RISCVRegisterType)

    assembly_format = (
        "$callee `(` $args `)` attr-dict `:` functional-type($args, $ress)"
    )

    # Function calls can have arbitrary memory effects, and may overwrite the
    # A, T, FA, and FT registers
    traits = traits_def(
        MemoryAllocEffect(),
        MemoryFreeEffect(),
        MemoryReadEffect(),
        MemoryWriteEffect(),
        RiscvFunctionCallMemoryEffect(),
    )

    def __init__(
        self,
        callee: str | StringAttr | SymbolRefAttr,
        args: Sequence[Operation | SSAValue],
        result_types: Sequence[riscv.RISCVRegisterType],
        comment: StringAttr | None = None,
    ):
        super().__init__(
            operands=[args],
            result_types=[result_types],
            attributes={
                "callee": SymbolRefAttr.get(callee),
                "comment": comment,
            },
        )

    def verify_(self):
        if len(self.args) >= 9:
            raise VerifyException(
                f"Function op has too many operands ({len(self.args)}), expected fewer than 9"
            )

        if len(self.results) >= 3:
            raise VerifyException(
                f"Function op has too many results ({len(self.results)}), expected fewer than 3"
            )

    def assembly_instruction_name(self) -> str:
        return "jal"

    def assembly_line_args(self) -> tuple[riscv.AssemblyInstructionArg | None, ...]:
        return (self.callee.string_value(),)

name = 'riscv_func.call' class-attribute instance-attribute

args = var_operand_def(riscv.RISCVRegisterType) class-attribute instance-attribute

callee = attr_def(SymbolRefAttr) class-attribute instance-attribute

ress = var_result_def(riscv.RISCVRegisterType) class-attribute instance-attribute

assembly_format = '$callee `(` $args `)` attr-dict `:` functional-type($args, $ress)' class-attribute instance-attribute

traits = traits_def(MemoryAllocEffect(), MemoryFreeEffect(), MemoryReadEffect(), MemoryWriteEffect(), RiscvFunctionCallMemoryEffect()) class-attribute instance-attribute

__init__(callee: str | StringAttr | SymbolRefAttr, args: Sequence[Operation | SSAValue], result_types: Sequence[riscv.RISCVRegisterType], comment: StringAttr | None = None)

Source code in xdsl/dialects/riscv_func.py
def __init__(
    self,
    callee: str | StringAttr | SymbolRefAttr,
    args: Sequence[Operation | SSAValue],
    result_types: Sequence[riscv.RISCVRegisterType],
    comment: StringAttr | None = None,
):
    super().__init__(
        operands=[args],
        result_types=[result_types],
        attributes={
            "callee": SymbolRefAttr.get(callee),
            "comment": comment,
        },
    )

verify_()

Source code in xdsl/dialects/riscv_func.py
def verify_(self):
    if len(self.args) >= 9:
        raise VerifyException(
            f"Function op has too many operands ({len(self.args)}), expected fewer than 9"
        )

    if len(self.results) >= 3:
        raise VerifyException(
            f"Function op has too many results ({len(self.results)}), expected fewer than 3"
        )

assembly_instruction_name() -> str

Source code in xdsl/dialects/riscv_func.py
def assembly_instruction_name(self) -> str:
    return "jal"

assembly_line_args() -> tuple[riscv.AssemblyInstructionArg | None, ...]

Source code in xdsl/dialects/riscv_func.py
def assembly_line_args(self) -> tuple[riscv.AssemblyInstructionArg | None, ...]:
    return (self.callee.string_value(),)

FuncOpCallableInterface dataclass

Bases: CallableOpInterface

Source code in xdsl/dialects/riscv_func.py
class FuncOpCallableInterface(CallableOpInterface):
    @classmethod
    def get_callable_region(cls, op: Operation) -> Region:
        assert isinstance(op, FuncOp)
        return op.body

    @classmethod
    def get_argument_types(cls, op: Operation) -> tuple[Attribute, ...]:
        assert isinstance(op, FuncOp)
        return op.function_type.inputs.data

    @classmethod
    def get_result_types(cls, op: Operation) -> tuple[Attribute, ...]:
        assert isinstance(op, FuncOp)
        return op.function_type.outputs.data

get_callable_region(op: Operation) -> Region classmethod

Source code in xdsl/dialects/riscv_func.py
@classmethod
def get_callable_region(cls, op: Operation) -> Region:
    assert isinstance(op, FuncOp)
    return op.body

get_argument_types(op: Operation) -> tuple[Attribute, ...] classmethod

Source code in xdsl/dialects/riscv_func.py
@classmethod
def get_argument_types(cls, op: Operation) -> tuple[Attribute, ...]:
    assert isinstance(op, FuncOp)
    return op.function_type.inputs.data

get_result_types(op: Operation) -> tuple[Attribute, ...] classmethod

Source code in xdsl/dialects/riscv_func.py
@classmethod
def get_result_types(cls, op: Operation) -> tuple[Attribute, ...]:
    assert isinstance(op, FuncOp)
    return op.function_type.outputs.data

FuncOp

Bases: IRDLOperation, AssemblyPrintable

RISC-V function definition operation

Source code in xdsl/dialects/riscv_func.py
@irdl_op_definition
class FuncOp(IRDLOperation, AssemblyPrintable):
    """RISC-V function definition operation"""

    name = "riscv_func.func"
    sym_name = attr_def(SymbolNameConstraint())
    body = region_def()
    function_type = attr_def(FunctionType)
    sym_visibility = opt_attr_def(StringAttr)
    p2align = opt_attr_def(IntegerAttr[I8])

    traits = traits_def(
        SymbolOpInterface(),
        FuncOpCallableInterface(),
        IsolatedFromAbove(),
    )

    def __init__(
        self,
        name: str | StringAttr,
        region: Region,
        function_type: FunctionType | tuple[Sequence[Attribute], Sequence[Attribute]],
        visibility: StringAttr | str | None = None,
        p2align: int | IntegerAttr[I8] | None = None,
    ):
        if isinstance(function_type, tuple):
            inputs, outputs = function_type
            function_type = FunctionType.from_lists(inputs, outputs)
        if isinstance(visibility, str):
            visibility = StringAttr(visibility)
        if isinstance(p2align, int):
            p2align = IntegerAttr(p2align, i8)
        attributes: dict[str, Attribute | None] = {
            "sym_name": StringAttr.get(name),
            "function_type": function_type,
            "sym_visibility": visibility,
            "p2align": p2align,
        }

        super().__init__(attributes=attributes, regions=[region])

    @classmethod
    def parse(cls, parser: Parser) -> FuncOp:
        visibility = parser.parse_optional_visibility_keyword()
        (name, input_types, return_types, region, extra_attrs, arg_attrs, res_attrs) = (
            parse_func_op_like(
                parser,
                reserved_attr_names=("sym_name", "function_type", "sym_visibility"),
            )
        )
        if arg_attrs:
            raise NotImplementedError("arg_attrs not implemented in riscv_func")
        if res_attrs:
            raise NotImplementedError("res_attrs not implemented in riscv_func")
        func = FuncOp(name, region, (input_types, return_types), visibility)
        if extra_attrs is not None:
            func.attributes |= extra_attrs.data
        return func

    def print(self, printer: Printer):
        if self.sym_visibility:
            visibility = self.sym_visibility.data
            printer.print_string(" ")
            printer.print_string(visibility)

        print_func_op_like(
            printer,
            self.sym_name,
            self.function_type,
            self.body,
            self.attributes,
            reserved_attr_names=("sym_name", "function_type", "sym_visibility"),
        )

    def print_assembly(self, printer: AssemblyPrinter) -> None:
        if not self.body.blocks:
            # Print nothing for function declaration
            return

        printer.emit_section(".text")

        if self.sym_visibility is not None:
            match self.sym_visibility.data:
                case "public":
                    printer.print_string(f".globl {self.sym_name.data}\n", indent=0)
                case "private":
                    printer.print_string(f".local {self.sym_name.data}\n", indent=0)
                case _:
                    raise DiagnosticException(
                        f"Unexpected visibility {self.sym_visibility.data} for function {self.sym_name}"
                    )

        if self.p2align is not None:
            printer.print_string(f".p2align {self.p2align.value.data}\n", indent=0)
        printer.print_string(f"{self.sym_name.data}:\n")

name = 'riscv_func.func' class-attribute instance-attribute

sym_name = attr_def(SymbolNameConstraint()) class-attribute instance-attribute

body = region_def() class-attribute instance-attribute

function_type = attr_def(FunctionType) class-attribute instance-attribute

sym_visibility = opt_attr_def(StringAttr) class-attribute instance-attribute

p2align = opt_attr_def(IntegerAttr[I8]) class-attribute instance-attribute

traits = traits_def(SymbolOpInterface(), FuncOpCallableInterface(), IsolatedFromAbove()) class-attribute instance-attribute

__init__(name: str | StringAttr, region: Region, function_type: FunctionType | tuple[Sequence[Attribute], Sequence[Attribute]], visibility: StringAttr | str | None = None, p2align: int | IntegerAttr[I8] | None = None)

Source code in xdsl/dialects/riscv_func.py
def __init__(
    self,
    name: str | StringAttr,
    region: Region,
    function_type: FunctionType | tuple[Sequence[Attribute], Sequence[Attribute]],
    visibility: StringAttr | str | None = None,
    p2align: int | IntegerAttr[I8] | None = None,
):
    if isinstance(function_type, tuple):
        inputs, outputs = function_type
        function_type = FunctionType.from_lists(inputs, outputs)
    if isinstance(visibility, str):
        visibility = StringAttr(visibility)
    if isinstance(p2align, int):
        p2align = IntegerAttr(p2align, i8)
    attributes: dict[str, Attribute | None] = {
        "sym_name": StringAttr.get(name),
        "function_type": function_type,
        "sym_visibility": visibility,
        "p2align": p2align,
    }

    super().__init__(attributes=attributes, regions=[region])

parse(parser: Parser) -> FuncOp classmethod

Source code in xdsl/dialects/riscv_func.py
@classmethod
def parse(cls, parser: Parser) -> FuncOp:
    visibility = parser.parse_optional_visibility_keyword()
    (name, input_types, return_types, region, extra_attrs, arg_attrs, res_attrs) = (
        parse_func_op_like(
            parser,
            reserved_attr_names=("sym_name", "function_type", "sym_visibility"),
        )
    )
    if arg_attrs:
        raise NotImplementedError("arg_attrs not implemented in riscv_func")
    if res_attrs:
        raise NotImplementedError("res_attrs not implemented in riscv_func")
    func = FuncOp(name, region, (input_types, return_types), visibility)
    if extra_attrs is not None:
        func.attributes |= extra_attrs.data
    return func

print(printer: Printer)

Source code in xdsl/dialects/riscv_func.py
def print(self, printer: Printer):
    if self.sym_visibility:
        visibility = self.sym_visibility.data
        printer.print_string(" ")
        printer.print_string(visibility)

    print_func_op_like(
        printer,
        self.sym_name,
        self.function_type,
        self.body,
        self.attributes,
        reserved_attr_names=("sym_name", "function_type", "sym_visibility"),
    )

print_assembly(printer: AssemblyPrinter) -> None

Source code in xdsl/dialects/riscv_func.py
def print_assembly(self, printer: AssemblyPrinter) -> None:
    if not self.body.blocks:
        # Print nothing for function declaration
        return

    printer.emit_section(".text")

    if self.sym_visibility is not None:
        match self.sym_visibility.data:
            case "public":
                printer.print_string(f".globl {self.sym_name.data}\n", indent=0)
            case "private":
                printer.print_string(f".local {self.sym_name.data}\n", indent=0)
            case _:
                raise DiagnosticException(
                    f"Unexpected visibility {self.sym_visibility.data} for function {self.sym_name}"
                )

    if self.p2align is not None:
        printer.print_string(f".p2align {self.p2align.value.data}\n", indent=0)
    printer.print_string(f"{self.sym_name.data}:\n")

ReturnOp

Bases: RISCVInstruction

RISC-V function return operation

Source code in xdsl/dialects/riscv_func.py
@irdl_op_definition
class ReturnOp(riscv.RISCVInstruction):
    """RISC-V function return operation"""

    name = "riscv_func.return"
    values = var_operand_def(riscv.RISCVRegisterType)
    comment = opt_attr_def(StringAttr)

    traits = traits_def(
        IsTerminator(),
        HasParent(FuncOp),
        ReturnLike(),
    )

    assembly_format = "attr-dict ($values^ `:` type($values))?"

    def __init__(
        self,
        *values: Operation | SSAValue,
        comment: str | StringAttr | None = None,
    ):
        if isinstance(comment, str):
            comment = StringAttr(comment)
        super().__init__(
            operands=[values],
            attributes={
                "comment": comment,
            },
        )

    def verify_(self):
        if len(self.results) >= 3:
            raise VerifyException(
                f"Function op has too many results ({len(self.results)}), expected fewer than 3"
            )

    def assembly_instruction_name(self) -> str:
        return "ret"

    def assembly_line_args(self) -> tuple[riscv.AssemblyInstructionArg | None, ...]:
        return ()

name = 'riscv_func.return' class-attribute instance-attribute

values = var_operand_def(riscv.RISCVRegisterType) class-attribute instance-attribute

comment = opt_attr_def(StringAttr) class-attribute instance-attribute

traits = traits_def(IsTerminator(), HasParent(FuncOp), ReturnLike()) class-attribute instance-attribute

assembly_format = 'attr-dict ($values^ `:` type($values))?' class-attribute instance-attribute

__init__(*values: Operation | SSAValue, comment: str | StringAttr | None = None)

Source code in xdsl/dialects/riscv_func.py
def __init__(
    self,
    *values: Operation | SSAValue,
    comment: str | StringAttr | None = None,
):
    if isinstance(comment, str):
        comment = StringAttr(comment)
    super().__init__(
        operands=[values],
        attributes={
            "comment": comment,
        },
    )

verify_()

Source code in xdsl/dialects/riscv_func.py
def verify_(self):
    if len(self.results) >= 3:
        raise VerifyException(
            f"Function op has too many results ({len(self.results)}), expected fewer than 3"
        )

assembly_instruction_name() -> str

Source code in xdsl/dialects/riscv_func.py
def assembly_instruction_name(self) -> str:
    return "ret"

assembly_line_args() -> tuple[riscv.AssemblyInstructionArg | None, ...]

Source code in xdsl/dialects/riscv_func.py
def assembly_line_args(self) -> tuple[riscv.AssemblyInstructionArg | None, ...]:
    return ()