Skip to content

Commit

Permalink
[mypyc] Support unary_ops, add int_neg_op as an example (#8933)
Browse files Browse the repository at this point in the history
Related mypyc/mypyc#709, mypyc/mypyc#734

Support unary ops and provide int_neg_op as an example.
  • Loading branch information
TH3CHARLie authored Jun 3, 2020
1 parent 63f2fed commit dfcff68
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 16 deletions.
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:
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

0 comments on commit dfcff68

Please sign in to comment.