Skip to content

Support unary op via CallC #8933

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
Jun 3, 2020
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
6 changes: 5 additions & 1 deletion mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from mypyc.primitives.registry import (
binary_ops, unary_ops, method_ops, func_ops,
c_method_call_ops, CFunctionDescription, c_function_ops,
c_binary_ops
c_binary_ops, c_unary_ops
)
from mypyc.primitives.list_ops import (
list_extend_op, list_len_op, new_list_op
Expand Down Expand Up @@ -555,6 +555,10 @@ def unary_op(self,
lreg: Value,
expr_op: str,
line: int) -> Value:
call_c_ops_candidates = c_unary_ops.get(expr_op, [])
target = self.matching_call_c(call_c_ops_candidates, [lreg], line)
if target:
return target
ops = unary_ops.get(expr_op, [])
target = self.matching_primitive_op(ops, [lreg], line)
assert target, 'Unsupported unary operation: %s' % expr_op
Expand Down
19 changes: 9 additions & 10 deletions mypyc/primitives/int_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
See also the documentation for mypyc.rtypes.int_rprimitive.
"""

from mypyc.ir.ops import OpDescription, ERR_NEVER, ERR_MAGIC
from mypyc.ir.ops import ERR_NEVER, ERR_MAGIC
from mypyc.ir.rtypes import (
int_rprimitive, bool_rprimitive, float_rprimitive, object_rprimitive, short_int_rprimitive,
str_rprimitive, RType
)
from mypyc.primitives.registry import (
name_ref_op, binary_op, unary_op, func_op, custom_op,
simple_emit, call_emit, name_emit,
name_ref_op, binary_op, func_op, custom_op,
simple_emit, call_emit, name_emit, c_unary_op, CFunctionDescription
)

# These int constructors produce object_rprimitives that then need to be unboxed
Expand Down Expand Up @@ -131,13 +131,12 @@ def int_compare_op(op: str, c_func_name: str) -> None:
emit=simple_emit('{dest} = {args[0]} + {args[1]};'))


def int_unary_op(op: str, c_func_name: str) -> OpDescription:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some thoughts: I think the original design somehow reflects or predicts what we are doing now

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the new approach fits in very nicely here.

return unary_op(op=op,
arg_type=int_rprimitive,
result_type=int_rprimitive,
error_kind=ERR_NEVER,
format_str='{dest} = %s{args[0]} :: int' % op,
emit=call_emit(c_func_name))
def int_unary_op(name: str, c_function_name: str) -> CFunctionDescription:
return c_unary_op(name=name,
arg_type=int_rprimitive,
return_type=int_rprimitive,
c_function_name=c_function_name,
error_kind=ERR_NEVER)


int_neg_op = int_unary_op('-', 'CPyTagged_Negate')
16 changes: 16 additions & 0 deletions mypyc/primitives/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
# CallC op for binary ops
c_binary_ops = {} # type: Dict[str, List[CFunctionDescription]]

# CallC op for unary ops
c_unary_ops = {} # type: Dict[str, List[CFunctionDescription]]


def simple_emit(template: str) -> EmitCallback:
"""Construct a simple PrimitiveOp emit callback function.
Expand Down Expand Up @@ -371,6 +374,19 @@ def c_binary_op(name: str,
return desc


def c_unary_op(name: str,
arg_type: RType,
return_type: RType,
c_function_name: str,
error_kind: int,
steals: StealsDescription = False,
priority: int = 1) -> CFunctionDescription:
ops = c_unary_ops.setdefault(name, [])
desc = CFunctionDescription(name, [arg_type], return_type,
c_function_name, error_kind, steals, priority)
ops.append(desc)
return desc

# Import various modules that set up global state.
import mypyc.primitives.int_ops # noqa
import mypyc.primitives.str_ops # noqa
Expand Down
2 changes: 1 addition & 1 deletion mypyc/test-data/analysis.test
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ L3:
if r5 goto L4 else goto L5 :: bool
L4:
r6 = 1
r7 = -r6 :: int
r7 = CPyTagged_Negate(r6)
restore_exc_info r1
return r7
L5:
Expand Down
4 changes: 2 additions & 2 deletions mypyc/test-data/irbuild-basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ def f(n):
r1 :: int
L0:
r0 = 1
r1 = -r0 :: int
r1 = CPyTagged_Negate(r0)
return r1

[case testConditionalExpr]
Expand Down Expand Up @@ -1027,7 +1027,7 @@ L1:
r2 = x
goto L3
L2:
r3 = -x :: int
r3 = CPyTagged_Negate(x)
r2 = r3
L3:
return r2
Expand Down
5 changes: 3 additions & 2 deletions mypyc/test/test_emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from mypyc.ir.ops import (
Environment, BasicBlock, Goto, Return, LoadInt, Assign, IncRef, DecRef, Branch,
Call, Unbox, Box, TupleGet, GetAttr, PrimitiveOp, RegisterOp,
SetAttr, Op, Value
SetAttr, Op, Value, CallC
)
from mypyc.ir.rtypes import (
RTuple, RInstance, int_rprimitive, bool_rprimitive, list_rprimitive,
Expand Down Expand Up @@ -98,7 +98,8 @@ def test_int_sub(self) -> None:
"cpy_r_r0 = CPyTagged_Subtract(cpy_r_m, cpy_r_k);")

def test_int_neg(self) -> None:
self.assert_emit(PrimitiveOp([self.m], int_neg_op, 55),
self.assert_emit(CallC(int_neg_op.c_function_name, [self.m], int_neg_op.return_type,
int_neg_op.steals, int_neg_op.error_kind, 55),
"cpy_r_r0 = CPyTagged_Negate(cpy_r_m);")

def test_list_len(self) -> None:
Expand Down