From 62530df198282080b5d06a3b951f01d2babd17f0 Mon Sep 17 00:00:00 2001 From: Sasha Lopoukhine Date: Fri, 7 Feb 2025 14:50:27 +0000 Subject: [PATCH] dialects: (x86_func) add x86_func dialect --- .../filecheck/dialects/x86_func/x86_ops.mlir | 16 ++ xdsl/dialects/__init__.py | 6 + xdsl/dialects/x86_func.py | 158 ++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 tests/filecheck/dialects/x86_func/x86_ops.mlir create mode 100644 xdsl/dialects/x86_func.py diff --git a/tests/filecheck/dialects/x86_func/x86_ops.mlir b/tests/filecheck/dialects/x86_func/x86_ops.mlir new file mode 100644 index 0000000000..607cf20293 --- /dev/null +++ b/tests/filecheck/dialects/x86_func/x86_ops.mlir @@ -0,0 +1,16 @@ +// RUN: XDSL_ROUNDTRIP +// RUN: XDSL_GENERIC_ROUNDTRIP +// RUN: xdsl-opt -t x86-asm %s | filecheck %s --check-prefix=CHECK-ASM + +// CHECK: x86_func.func @noarg_void() { +// CHECK-NEXT: x86_func.ret {comment = "this is a return instruction"} +// CHECK-NEXT: } +// CHECK-ASM: noarg_void: +// CHECK-ASM: ret # this is a return instruction +x86_func.func @noarg_void() { + x86_func.ret {"comment" = "this is a return instruction"} +} + +// CHECK-GENERIC: "x86_func.func"() ({ +// CHECK-GENERIC-NEXT: "x86_func.ret"() {comment = "this is a return instruction"} : () -> () +// CHECK-GENERIC-NEXT: }) {sym_name = "noarg_void", function_type = () -> ()} : () -> () diff --git a/xdsl/dialects/__init__.py b/xdsl/dialects/__init__.py index 651f20e6b3..a18495fa4c 100644 --- a/xdsl/dialects/__init__.py +++ b/xdsl/dialects/__init__.py @@ -318,6 +318,11 @@ def get_x86(): return X86 + def get_x86_func(): + from xdsl.dialects.x86_func import X86_FUNC + + return X86_FUNC + def get_transform(): from xdsl.dialects.transform import Transform @@ -386,6 +391,7 @@ def get_transform(): "vector": get_vector, "wasm": get_wasm, "x86": get_x86, + "x86_func": get_x86_func, "transform": get_transform, } diff --git a/xdsl/dialects/x86_func.py b/xdsl/dialects/x86_func.py new file mode 100644 index 0000000000..901aa48356 --- /dev/null +++ b/xdsl/dialects/x86_func.py @@ -0,0 +1,158 @@ +from __future__ import annotations + +from collections.abc import Sequence + +from xdsl.dialects.builtin import FunctionType, StringAttr +from xdsl.dialects.utils import ( + parse_func_op_like, + print_func_op_like, +) +from xdsl.dialects.x86.ops import X86AsmOperation, X86Instruction +from xdsl.ir import Attribute, Dialect, Operation, Region +from xdsl.irdl import ( + attr_def, + irdl_op_definition, + opt_attr_def, + region_def, + traits_def, +) +from xdsl.parser import Parser +from xdsl.printer import Printer +from xdsl.traits import ( + CallableOpInterface, + HasParent, + IsolatedFromAbove, + IsTerminator, + SymbolOpInterface, +) + + +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 + + +@irdl_op_definition +class FuncOp(X86AsmOperation): + """x86 function definition operation""" + + name = "x86_func.func" + sym_name = attr_def(StringAttr) + body = region_def() + function_type = attr_def(FunctionType) + sym_visibility = opt_attr_def(StringAttr) + + traits = traits_def( + SymbolOpInterface(), + FuncOpCallableInterface(), + IsolatedFromAbove(), + ) + + def __init__( + self, + name: str, + region: Region, + function_type: FunctionType | tuple[Sequence[Attribute], Sequence[Attribute]], + visibility: StringAttr | str | 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) + attributes: dict[str, Attribute | None] = { + "sym_name": StringAttr(name), + "function_type": function_type, + "sym_visibility": visibility, + } + + 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 x86_func") + if res_attrs: + raise NotImplementedError("res_attrs not implemented in x86_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(f" {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 assembly_line(self) -> str | None: + if self.body.blocks: + return f"{self.sym_name.data}:" + else: + return None + + +@irdl_op_definition +class RetOp(X86Instruction): + """ + Return from subroutine. + """ + + name = "x86_func.ret" + + assembly_format = "attr-dict" + + traits = traits_def(IsTerminator(), HasParent(FuncOp)) + + def __init__( + self, + *, + comment: str | StringAttr | None = None, + ): + if isinstance(comment, str): + comment = StringAttr(comment) + + super().__init__( + attributes={ + "comment": comment, + }, + ) + + def assembly_line_args(self): + return () + + +X86_FUNC = Dialect( + "x86_func", + [ + FuncOp, + RetOp, + ], +)