Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dialects: (x86_func) add x86_func dialect #3867

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions tests/filecheck/dialects/x86_func/x86_ops.mlir
Original file line number Diff line number Diff line change
@@ -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 = () -> ()} : () -> ()
6 changes: 6 additions & 0 deletions xdsl/dialects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -386,6 +391,7 @@ def get_transform():
"vector": get_vector,
"wasm": get_wasm,
"x86": get_x86,
"x86_func": get_x86_func,
"transform": get_transform,
}

Expand Down
158 changes: 158 additions & 0 deletions xdsl/dialects/x86_func.py
Original file line number Diff line number Diff line change
@@ -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,
],
)