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) PR9 - MI Operations #2519

Merged
merged 1 commit into from
May 2, 2024
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
15 changes: 15 additions & 0 deletions tests/filecheck/dialects/x86/x86_assembly_emission.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,18 @@ x86.mr.xor %0, %1, 8 : (!x86.reg<rax>, !x86.reg<rdx>) -> ()
// CHECK: xor [rax+8], rdx
x86.mr.mov %0, %1, 8 : (!x86.reg<rax>, !x86.reg<rdx>) -> ()
// CHECK: mov [rax+8], rdx

x86.mi.add %0, 2 : (!x86.reg<rax>) -> ()
// CHECK: add [rax], 2
x86.mi.add %0, 2, 8 : (!x86.reg<rax>) -> ()
// CHECK: add [rax+8], 2
x86.mi.sub %0, 2, -8 : (!x86.reg<rax>) -> ()
// CHECK: sub [rax-8], 2
x86.mi.and %0, 2, 8 : (!x86.reg<rax>) -> ()
// CHECK: and [rax+8], 2
x86.mi.or %0, 2, 8 : (!x86.reg<rax>) -> ()
// CHECK: or [rax+8], 2
x86.mi.xor %0, 2, 8 : (!x86.reg<rax>) -> ()
// CHECK: xor [rax+8], 2
x86.mi.mov %0, 2, 8 : (!x86.reg<rax>) -> ()
// CHECK: mov [rax+8], 2
15 changes: 15 additions & 0 deletions tests/filecheck/dialects/x86/x86_ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,18 @@ x86.mr.xor %0, %1, 8 : (!x86.reg<>, !x86.reg<>) -> ()
// CHECK-NEXT: x86.mr.xor %{{.*}}, %{{.*}}, 8 : (!x86.reg<>, !x86.reg<>) -> ()
x86.mr.mov %0, %1, 8 : (!x86.reg<>, !x86.reg<>) -> ()
// CHECK-NEXT: x86.mr.mov %{{.*}}, %{{.*}}, 8 : (!x86.reg<>, !x86.reg<>) -> ()

x86.mi.add %0, 2 : (!x86.reg<>) -> ()
// CHECK-NEXT: x86.mi.add %{{.*}}, 2 : (!x86.reg<>) -> ()
x86.mi.add %0, 2, 8 : (!x86.reg<>) -> ()
// CHECK-NEXT: x86.mi.add %{{.*}}, 2, 8 : (!x86.reg<>) -> ()
x86.mi.sub %0, 2, -8 : (!x86.reg<>) -> ()
// CHECK-NEXT: x86.mi.sub %{{.*}}, 2, -8 : (!x86.reg<>) -> ()
x86.mi.and %0, 2, 8 : (!x86.reg<>) -> ()
// CHECK-NEXT: x86.mi.and %{{.*}}, 2, 8 : (!x86.reg<>) -> ()
x86.mi.or %0, 2, 8 : (!x86.reg<>) -> ()
// CHECK-NEXT: x86.mi.or %{{.*}}, 2, 8 : (!x86.reg<>) -> ()
x86.mi.xor %0, 2, 8 : (!x86.reg<>) -> ()
// CHECK-NEXT: x86.mi.xor %{{.*}}, 2, 8 : (!x86.reg<>) -> ()
x86.mi.mov %0, 2, 8 : (!x86.reg<>) -> ()
// CHECK-NEXT: x86.mi.mov %{{.*}}, 2, 8 : (!x86.reg<>) -> ()
12 changes: 12 additions & 0 deletions xdsl/dialects/x86/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

from .ops import (
GetRegisterOp,
MI_AddOp,
MI_AndOp,
MI_MovOp,
MI_OrOp,
MI_SubOp,
MI_XorOp,
MR_AddOp,
MR_AndOp,
MR_MovOp,
Expand Down Expand Up @@ -66,6 +72,12 @@
MR_OrOp,
MR_XorOp,
MR_MovOp,
MI_AddOp,
MI_SubOp,
MI_AndOp,
MI_OrOp,
MI_XorOp,
MI_MovOp,
GetRegisterOp,
],
[
Expand Down
165 changes: 163 additions & 2 deletions xdsl/dialects/x86/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,23 @@
Signedness,
StringAttr,
)
from xdsl.dialects.riscv import LabelAttr
from xdsl.ir import (
Attribute,
Data,
Operation,
SSAValue,
)
from xdsl.irdl import (
ConstraintVar,
IRDLOperation,
attr_def,
irdl_attr_definition,
irdl_op_definition,
operand_def,
opt_attr_def,
result_def,
)
from xdsl.parser import Parser, UnresolvedOperand
from xdsl.parser import AttrParser, Parser, UnresolvedOperand
from xdsl.printer import Printer
from xdsl.utils.hints import isa

Expand Down Expand Up @@ -129,6 +130,20 @@ def print_op_type(self, printer: Printer) -> None:
)


@irdl_attr_definition
class LabelAttr(Data[str]):
name = "x86.label"

@classmethod
def parse_parameter(cls, parser: AttrParser) -> str:
with parser.in_angle_brackets():
return parser.parse_str_literal()

def print_parameter(self, printer: Printer) -> None:
with printer.in_angle_brackets():
printer.print_string_literal(self.data)


class X86Instruction(X86Op):
"""
Base class for operations that can be a part of x86 assembly printing. Must
Expand Down Expand Up @@ -796,6 +811,143 @@ class MR_MovOp(M_MR_Operation[GeneralRegisterType, GeneralRegisterType]):
name = "x86.mr.mov"


class M_MI_Operation(Generic[R1InvT], IRDLOperation, X86Instruction, ABC):
"""
A base class for x86 operations that have one memory reference and an immediate value.
"""

r1 = operand_def(R1InvT)
immediate: AnyIntegerAttr = attr_def(AnyIntegerAttr)
offset: AnyIntegerAttr | None = opt_attr_def(AnyIntegerAttr)

def __init__(
self,
r1: Operation | SSAValue,
offset: int | AnyIntegerAttr | None,
immediate: int | AnyIntegerAttr,
*,
comment: str | StringAttr | None = None,
):
if isinstance(immediate, int):
immediate = IntegerAttr(
immediate, 32
) # the deault immediate size is 32 bits
if isinstance(offset, int):
offset = IntegerAttr(offset, 64)
if isinstance(comment, str):
comment = StringAttr(comment)

super().__init__(
operands=[r1],
attributes={
"immediate": immediate,
"offset": offset,
"comment": comment,
},
result_types=[],
)

def assembly_line_args(self) -> tuple[AssemblyInstructionArg | None, ...]:
destination = _assembly_arg_str(self.r1)
immediate = _assembly_arg_str(self.immediate)
if self.offset is not None:
offset = _assembly_arg_str(self.offset)
if self.offset.value.data > 0:
destination = f"[{destination}+{offset}]"
else:
destination = f"[{destination}{offset}]"
else:
destination = f"[{destination}]"
return destination, immediate

@classmethod
def custom_parse_attributes(cls, parser: Parser) -> dict[str, Attribute]:
attributes = dict[str, Attribute]()
temp = _parse_immediate_value(parser, IntegerType(64, Signedness.SIGNED))
attributes["immediate"] = temp
if parser.parse_optional_punctuation(",") is not None:
temp2 = _parse_optional_immediate_value(
parser, IntegerType(32, Signedness.SIGNED)
)
if temp2 is not None:
attributes["offset"] = temp2
return attributes

def custom_print_attributes(self, printer: Printer) -> Set[str]:
printer.print(", ")
_print_immediate_value(printer, self.immediate)
if self.offset is not None:
printer.print(", ")
_print_immediate_value(printer, self.offset)
return {"immediate", "offset"}


@irdl_op_definition
class MI_AddOp(M_MI_Operation[GeneralRegisterType]):
"""
Adds the immediate value to the memory location pointed to by r1.
[x[r1]] = [x[r1]] + immediate
https://www.felixcloutier.com/x86/add
"""

name = "x86.mi.add"


@irdl_op_definition
class MI_SubOp(M_MI_Operation[GeneralRegisterType]):
"""
Subtracts the immediate value from the memory location pointed to by r1.
[x[r1]] = [x[r1]] - immediate
https://www.felixcloutier.com/x86/sub
"""

name = "x86.mi.sub"


@irdl_op_definition
class MI_AndOp(M_MI_Operation[GeneralRegisterType]):
"""
bitwise and of immediate and [r1], stored in [r1]
[x[r1]] = [x[r1]] & immediate
https://www.felixcloutier.com/x86/and
"""

name = "x86.mi.and"


@irdl_op_definition
class MI_OrOp(M_MI_Operation[GeneralRegisterType]):
"""
bitwise or of immediate and [r1], stored in [r1]
[x[r1]] = [x[r1]] | immediate
https://www.felixcloutier.com/x86/or
"""

name = "x86.mi.or"


@irdl_op_definition
class MI_XorOp(M_MI_Operation[GeneralRegisterType]):
"""
bitwise xor of immediate and [r1], stored in [r1]
[x[r1]] = [x[r1]] ^ immediate
https://www.felixcloutier.com/x86/xor
"""

name = "x86.mi.xor"


@irdl_op_definition
class MI_MovOp(M_MI_Operation[GeneralRegisterType]):
"""
Copies the immediate value into the memory location pointed to by r1.
[x[r1]] = immediate
https://www.felixcloutier.com/x86/mov
"""

name = "x86.mi.mov"


# region Assembly printing
def _append_comment(line: str, comment: StringAttr | None) -> str:
if comment is None:
Expand Down Expand Up @@ -851,6 +1003,15 @@ def x86_code(module: ModuleOp) -> str:
return stream.getvalue()


def _parse_immediate_value(
parser: Parser, integer_type: IntegerType | IndexType
) -> IntegerAttr[IntegerType | IndexType] | LabelAttr:
return parser.expect(
lambda: _parse_optional_immediate_value(parser, integer_type),
"Expected immediate",
)


def _parse_optional_immediate_value(
parser: Parser, integer_type: IntegerType | IndexType
) -> IntegerAttr[IntegerType | IndexType] | LabelAttr | None:
Expand Down
Loading