Skip to content

[mypyc] Refactor: use new-style primitives for unary ops #18213

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

Merged
merged 1 commit into from
Nov 29, 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
2 changes: 1 addition & 1 deletion mypyc/ir/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ def __init__(
assert error_kind == ERR_NEVER

def __repr__(self) -> str:
return f"<PrimitiveDescription {self.name}>"
return f"<PrimitiveDescription {self.name!r}: {self.arg_types}>"


class PrimitiveOp(RegisterOp):
Expand Down
4 changes: 2 additions & 2 deletions mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -1601,8 +1601,8 @@ def unary_op(self, value: Value, expr_op: str, line: int) -> Value:
result = self.dunder_op(value, None, expr_op, line)
if result is not None:
return result
call_c_ops_candidates = unary_ops.get(expr_op, [])
target = self.matching_call_c(call_c_ops_candidates, [value], line)
primitive_ops_candidates = unary_ops.get(expr_op, [])
target = self.matching_primitive_op(primitive_ops_candidates, [value], line)
assert target, "Unsupported unary operation: %s" % expr_op
return target

Expand Down
11 changes: 2 additions & 9 deletions mypyc/primitives/int_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,7 @@
str_rprimitive,
void_rtype,
)
from mypyc.primitives.registry import (
CFunctionDescription,
binary_op,
custom_op,
function_op,
load_address_op,
unary_op,
)
from mypyc.primitives.registry import binary_op, custom_op, function_op, load_address_op, unary_op

# Constructors for builtins.int and native int types have the same behavior. In
# interpreted mode, native int types are just aliases to 'int'.
Expand Down Expand Up @@ -176,7 +169,7 @@ def int_binary_op(
int_binary_op("<<=", "CPyTagged_Lshift", error_kind=ERR_MAGIC)


def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription:
def int_unary_op(name: str, c_function_name: str) -> PrimitiveDescription:
return unary_op(
name=name,
arg_type=int_rprimitive,
Expand Down
28 changes: 14 additions & 14 deletions mypyc/primitives/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ class LoadAddressDescription(NamedTuple):
# Primitive ops for binary operations
binary_ops: dict[str, list[PrimitiveDescription]] = {}

# CallC op for unary ops
unary_ops: dict[str, list[CFunctionDescription]] = {}
# Primitive ops for unary ops
unary_ops: dict[str, list[PrimitiveDescription]] = {}

builtin_names: dict[str, tuple[RType, str]] = {}

Expand Down Expand Up @@ -327,8 +327,8 @@ def unary_op(
is_borrowed: bool = False,
priority: int = 1,
is_pure: bool = False,
) -> CFunctionDescription:
"""Define a c function call op for an unary operation.
) -> PrimitiveDescription:
"""Define a primitive op for an unary operation.

This will be automatically generated by matching against the AST.

Expand All @@ -338,19 +338,19 @@ def unary_op(
if extra_int_constants is None:
extra_int_constants = []
ops = unary_ops.setdefault(name, [])
desc = CFunctionDescription(
desc = PrimitiveDescription(
name,
[arg_type],
return_type,
None,
truncated_type,
c_function_name,
error_kind,
steals,
is_borrowed,
ordering,
extra_int_constants,
priority,
var_arg_type=None,
truncated_type=truncated_type,
c_function_name=c_function_name,
error_kind=error_kind,
steals=steals,
is_borrowed=is_borrowed,
ordering=ordering,
extra_int_constants=extra_int_constants,
priority=priority,
is_pure=is_pure,
)
ops.append(desc)
Expand Down
20 changes: 19 additions & 1 deletion mypyc/test-data/irbuild-int.test
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,31 @@ def int_to_int(n):
L0:
return n

[case testIntUnaryPlus]
[case testIntUnaryOps]
def unary_minus(n: int) -> int:
x = -n
return x
def unary_plus(n: int) -> int:
x = +n
return x
def unary_invert(n: int) -> int:
x = ~n
return x
[out]
def unary_minus(n):
n, r0, x :: int
L0:
r0 = CPyTagged_Negate(n)
x = r0
return x
def unary_plus(n):
n, x :: int
L0:
x = n
return x
def unary_invert(n):
n, r0, x :: int
L0:
r0 = CPyTagged_Invert(n)
x = r0
return x
8 changes: 6 additions & 2 deletions mypyc/test/test_cheader.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ def check_name(name: str) -> None:
rf"\b{name}\b", header
), f'"{name}" is used in mypyc.primitives but not declared in CPy.h'

for old_values in [registry.method_call_ops.values(), registry.unary_ops.values()]:
for old_values in [registry.method_call_ops.values()]:
for old_ops in old_values:
if isinstance(old_ops, CFunctionDescription):
old_ops = [old_ops]
for old_op in old_ops:
check_name(old_op.c_function_name)

for values in [registry.binary_ops.values(), registry.function_ops.values()]:
for values in [
registry.binary_ops.values(),
registry.unary_ops.values(),
registry.function_ops.values(),
]:
for ops in values:
if isinstance(ops, PrimitiveDescription):
ops = [ops]
Expand Down
1 change: 1 addition & 0 deletions mypyc/test/test_emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ def test_int_sub(self) -> None:
)

def test_int_neg(self) -> None:
assert int_neg_op.c_function_name is not None
self.assert_emit(
CallC(
int_neg_op.c_function_name,
Expand Down