|
20 | 20 | BasicBlock, Environment, Op, LoadInt, Value, Register, |
21 | 21 | Assign, Branch, Goto, Call, Box, Unbox, Cast, GetAttr, |
22 | 22 | LoadStatic, MethodCall, PrimitiveOp, OpDescription, RegisterOp, |
23 | | - NAMESPACE_TYPE, NAMESPACE_MODULE, LoadErrorValue, |
| 23 | + NAMESPACE_TYPE, NAMESPACE_MODULE, LoadErrorValue, CallC |
24 | 24 | ) |
25 | 25 | from mypyc.ir.rtypes import ( |
26 | 26 | RType, RUnion, RInstance, optional_value_type, int_rprimitive, float_rprimitive, |
27 | | - bool_rprimitive, list_rprimitive, str_rprimitive, is_none_rprimitive, object_rprimitive |
| 27 | + bool_rprimitive, list_rprimitive, str_rprimitive, is_none_rprimitive, object_rprimitive, |
| 28 | + void_rtype |
28 | 29 | ) |
29 | 30 | from mypyc.ir.func_ir import FuncDecl, FuncSignature |
30 | 31 | from mypyc.ir.class_ir import ClassIR, all_concrete_classes |
31 | 32 | from mypyc.common import ( |
32 | 33 | FAST_ISINSTANCE_MAX_SUBCLASSES, MAX_LITERAL_SHORT_INT, |
33 | 34 | ) |
34 | | -from mypyc.primitives.registry import binary_ops, unary_ops, method_ops, func_ops |
| 35 | +from mypyc.primitives.registry import ( |
| 36 | + binary_ops, unary_ops, method_ops, func_ops, |
| 37 | + c_method_call_ops, CFunctionDescription |
| 38 | +) |
35 | 39 | from mypyc.primitives.list_ops import ( |
36 | 40 | list_extend_op, list_len_op, new_list_op |
37 | 41 | ) |
@@ -644,6 +648,41 @@ def add_bool_branch(self, value: Value, true: BasicBlock, false: BasicBlock) -> |
644 | 648 | value = self.primitive_op(bool_op, [value], value.line) |
645 | 649 | self.add(Branch(value, true, false, Branch.BOOL_EXPR)) |
646 | 650 |
|
| 651 | + def call_c(self, |
| 652 | + function_name: str, |
| 653 | + args: List[Value], |
| 654 | + line: int, |
| 655 | + result_type: Optional[RType]) -> Value: |
| 656 | + # handle void function via singleton RVoid instance |
| 657 | + ret_type = void_rtype if result_type is None else result_type |
| 658 | + target = self.add(CallC(function_name, args, ret_type, line)) |
| 659 | + return target |
| 660 | + |
| 661 | + def matching_call_c(self, |
| 662 | + candidates: List[CFunctionDescription], |
| 663 | + args: List[Value], |
| 664 | + line: int, |
| 665 | + result_type: Optional[RType] = None) -> Optional[Value]: |
| 666 | + # TODO: this function is very similar to matching_primitive_op |
| 667 | + # we should remove the old one or refactor both them into only as we move forward |
| 668 | + matching = None # type: Optional[CFunctionDescription] |
| 669 | + for desc in candidates: |
| 670 | + if len(desc.arg_types) != len(args): |
| 671 | + continue |
| 672 | + if all(is_subtype(actual.type, formal) |
| 673 | + for actual, formal in zip(args, desc.arg_types)): |
| 674 | + if matching: |
| 675 | + assert matching.priority != desc.priority, 'Ambiguous:\n1) %s\n2) %s' % ( |
| 676 | + matching, desc) |
| 677 | + if desc.priority > matching.priority: |
| 678 | + matching = desc |
| 679 | + else: |
| 680 | + matching = desc |
| 681 | + if matching: |
| 682 | + target = self.call_c(matching.c_function_name, args, line, result_type) |
| 683 | + return target |
| 684 | + return None |
| 685 | + |
647 | 686 | # Internal helpers |
648 | 687 |
|
649 | 688 | def decompose_union_helper(self, |
@@ -728,6 +767,11 @@ def translate_special_method_call(self, |
728 | 767 | Return None if no translation found; otherwise return the target register. |
729 | 768 | """ |
730 | 769 | ops = method_ops.get(name, []) |
| 770 | + call_c_ops_candidates = c_method_call_ops.get(name, []) |
| 771 | + call_c_op = self.matching_call_c(call_c_ops_candidates, [base_reg] + args, line, |
| 772 | + result_type=result_type) |
| 773 | + if call_c_op is not None: |
| 774 | + return call_c_op |
731 | 775 | return self.matching_primitive_op(ops, [base_reg] + args, line, result_type=result_type) |
732 | 776 |
|
733 | 777 | def translate_eq_cmp(self, |
|
0 commit comments