From d296eb264d2ea79a18a9925d0b9ca356c7c3afc1 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:11:13 +0000 Subject: [PATCH 01/10] Rename function_op to legacy_function_op --- mypyc/primitives/bytes_ops.py | 6 +++--- mypyc/primitives/dict_ops.py | 8 ++++---- mypyc/primitives/float_ops.py | 34 ++++++++++++++++----------------- mypyc/primitives/generic_ops.py | 22 ++++++++++----------- mypyc/primitives/int_ops.py | 12 ++++++------ mypyc/primitives/list_ops.py | 6 +++--- mypyc/primitives/misc_ops.py | 14 +++++++------- mypyc/primitives/registry.py | 2 +- mypyc/primitives/set_ops.py | 8 ++++---- mypyc/primitives/str_ops.py | 4 ++-- mypyc/primitives/tuple_ops.py | 6 +++--- 11 files changed, 61 insertions(+), 61 deletions(-) diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index d7a7f3e2f59b..02206e631489 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -18,7 +18,7 @@ ERR_NEG_INT, binary_op, custom_op, - function_op, + legacy_function_op, load_address_op, method_op, ) @@ -27,7 +27,7 @@ load_address_op(name="builtins.bytes", type=object_rprimitive, src="PyBytes_Type") # bytes(obj) -function_op( +legacy_function_op( name="builtins.bytes", arg_types=[RUnion([list_rprimitive, dict_rprimitive, str_rprimitive])], return_type=bytes_rprimitive, @@ -36,7 +36,7 @@ ) # bytearray(obj) -function_op( +legacy_function_op( name="builtins.bytearray", arg_types=[object_rprimitive], return_type=bytes_rprimitive, diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index ce7b9bb8d70e..bc6080026a32 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -19,7 +19,7 @@ ERR_NEG_INT, binary_op, custom_op, - function_op, + legacy_function_op, load_address_op, method_op, ) @@ -28,7 +28,7 @@ load_address_op(name="builtins.dict", type=object_rprimitive, src="PyDict_Type") # Construct an empty dictionary via dict(). -function_op( +legacy_function_op( name="builtins.dict", arg_types=[], return_type=dict_rprimitive, @@ -53,7 +53,7 @@ ) # Construct a dictionary from another dictionary. -function_op( +legacy_function_op( name="builtins.dict", arg_types=[dict_rprimitive], return_type=dict_rprimitive, @@ -63,7 +63,7 @@ ) # Generic one-argument dict constructor: dict(obj) -dict_copy = function_op( +dict_copy = legacy_function_op( name="builtins.dict", arg_types=[object_rprimitive], return_type=dict_rprimitive, diff --git a/mypyc/primitives/float_ops.py b/mypyc/primitives/float_ops.py index 14e8d4caf09c..200e13b4fee4 100644 --- a/mypyc/primitives/float_ops.py +++ b/mypyc/primitives/float_ops.py @@ -10,7 +10,7 @@ object_rprimitive, str_rprimitive, ) -from mypyc.primitives.registry import binary_op, function_op, load_address_op +from mypyc.primitives.registry import binary_op, legacy_function_op, load_address_op # Get the 'builtins.float' type object. load_address_op(name="builtins.float", type=object_rprimitive, src="PyFloat_Type") @@ -24,7 +24,7 @@ ) # float(int) -int_to_float_op = function_op( +int_to_float_op = legacy_function_op( name="builtins.float", arg_types=[int_rprimitive], return_type=float_rprimitive, @@ -33,7 +33,7 @@ ) # float(str) -function_op( +legacy_function_op( name="builtins.float", arg_types=[str_rprimitive], return_type=object_rprimitive, @@ -42,7 +42,7 @@ ) # abs(float) -function_op( +legacy_function_op( name="builtins.abs", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -51,7 +51,7 @@ ) # math.sin(float) -function_op( +legacy_function_op( name="math.sin", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -60,7 +60,7 @@ ) # math.cos(float) -function_op( +legacy_function_op( name="math.cos", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -69,7 +69,7 @@ ) # math.tan(float) -function_op( +legacy_function_op( name="math.tan", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -78,7 +78,7 @@ ) # math.sqrt(float) -function_op( +legacy_function_op( name="math.sqrt", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -87,7 +87,7 @@ ) # math.exp(float) -function_op( +legacy_function_op( name="math.exp", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -96,7 +96,7 @@ ) # math.log(float) -function_op( +legacy_function_op( name="math.log", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -105,7 +105,7 @@ ) # math.floor(float) -function_op( +legacy_function_op( name="math.floor", arg_types=[float_rprimitive], return_type=int_rprimitive, @@ -114,7 +114,7 @@ ) # math.ceil(float) -function_op( +legacy_function_op( name="math.ceil", arg_types=[float_rprimitive], return_type=int_rprimitive, @@ -123,7 +123,7 @@ ) # math.fabs(float) -function_op( +legacy_function_op( name="math.fabs", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -132,7 +132,7 @@ ) # math.pow(float, float) -pow_op = function_op( +pow_op = legacy_function_op( name="math.pow", arg_types=[float_rprimitive, float_rprimitive], return_type=float_rprimitive, @@ -141,7 +141,7 @@ ) # math.copysign(float, float) -copysign_op = function_op( +copysign_op = legacy_function_op( name="math.copysign", arg_types=[float_rprimitive, float_rprimitive], return_type=float_rprimitive, @@ -150,7 +150,7 @@ ) # math.isinf(float) -function_op( +legacy_function_op( name="math.isinf", arg_types=[float_rprimitive], return_type=bool_rprimitive, @@ -159,7 +159,7 @@ ) # math.isnan(float) -function_op( +legacy_function_op( name="math.isnan", arg_types=[float_rprimitive], return_type=bool_rprimitive, diff --git a/mypyc/primitives/generic_ops.py b/mypyc/primitives/generic_ops.py index fe42767db11e..d21dc36a71bf 100644 --- a/mypyc/primitives/generic_ops.py +++ b/mypyc/primitives/generic_ops.py @@ -26,7 +26,7 @@ ERR_NEG_INT, binary_op, custom_op, - function_op, + legacy_function_op, method_op, unary_op, ) @@ -76,7 +76,7 @@ ) -function_op( +legacy_function_op( name="builtins.divmod", arg_types=[object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -120,7 +120,7 @@ ) for arg_count, c_function in ((2, "CPyNumber_Power"), (3, "PyNumber_Power")): - function_op( + legacy_function_op( name="builtins.pow", arg_types=[object_rprimitive] * arg_count, return_type=object_rprimitive, @@ -168,7 +168,7 @@ ) # abs(obj) -function_op( +legacy_function_op( name="builtins.abs", arg_types=[object_rprimitive], return_type=object_rprimitive, @@ -208,7 +208,7 @@ ) # hash(obj) -function_op( +legacy_function_op( name="builtins.hash", arg_types=[object_rprimitive], return_type=int_rprimitive, @@ -217,7 +217,7 @@ ) # getattr(obj, attr) -py_getattr_op = function_op( +py_getattr_op = legacy_function_op( name="builtins.getattr", arg_types=[object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -226,7 +226,7 @@ ) # getattr(obj, attr, default) -function_op( +legacy_function_op( name="builtins.getattr", arg_types=[object_rprimitive, object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -235,7 +235,7 @@ ) # setattr(obj, attr, value) -py_setattr_op = function_op( +py_setattr_op = legacy_function_op( name="builtins.setattr", arg_types=[object_rprimitive, object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, @@ -244,7 +244,7 @@ ) # hasattr(obj, attr) -py_hasattr_op = function_op( +py_hasattr_op = legacy_function_op( name="builtins.hasattr", arg_types=[object_rprimitive, object_rprimitive], return_type=bool_rprimitive, @@ -253,7 +253,7 @@ ) # del obj.attr -py_delattr_op = function_op( +py_delattr_op = legacy_function_op( name="builtins.delattr", arg_types=[object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, @@ -336,7 +336,7 @@ ) # iter(obj) -iter_op = function_op( +iter_op = legacy_function_op( name="builtins.iter", arg_types=[object_rprimitive], return_type=object_rprimitive, diff --git a/mypyc/primitives/int_ops.py b/mypyc/primitives/int_ops.py index 2eff233403f4..fe8d14feff43 100644 --- a/mypyc/primitives/int_ops.py +++ b/mypyc/primitives/int_ops.py @@ -35,7 +35,7 @@ CFunctionDescription, binary_op, custom_op, - function_op, + legacy_function_op, load_address_op, unary_op, ) @@ -58,7 +58,7 @@ load_address_op(name=int_name, type=object_rprimitive, src="PyLong_Type") # int(float). We could do a bit better directly. - function_op( + legacy_function_op( name=int_name, arg_types=[float_rprimitive], return_type=int_rprimitive, @@ -67,7 +67,7 @@ ) # int(string) - function_op( + legacy_function_op( name=int_name, arg_types=[str_rprimitive], return_type=object_rprimitive, @@ -76,7 +76,7 @@ ) # int(string, base) - function_op( + legacy_function_op( name=int_name, arg_types=[str_rprimitive, int_rprimitive], return_type=object_rprimitive, @@ -85,7 +85,7 @@ ) # str(int) -int_to_str_op = function_op( +int_to_str_op = legacy_function_op( name="builtins.str", arg_types=[int_rprimitive], return_type=str_rprimitive, @@ -95,7 +95,7 @@ ) # We need a specialization for str on bools also since the int one is wrong... -function_op( +legacy_function_op( name="builtins.str", arg_types=[bool_rprimitive], return_type=str_rprimitive, diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index cb75e19a8dea..07a125287f2f 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -19,7 +19,7 @@ binary_op, custom_op, custom_primitive_op, - function_op, + legacy_function_op, load_address_op, method_op, ) @@ -28,7 +28,7 @@ load_address_op(name="builtins.list", type=object_rprimitive, src="PyList_Type") # list(obj) -to_list = function_op( +to_list = legacy_function_op( name="builtins.list", arg_types=[object_rprimitive], return_type=list_rprimitive, @@ -37,7 +37,7 @@ ) # Construct an empty list via list(). -function_op( +legacy_function_op( name="builtins.list", arg_types=[], return_type=list_rprimitive, diff --git a/mypyc/primitives/misc_ops.py b/mypyc/primitives/misc_ops.py index e9016e24c46d..fcaa34ac9980 100644 --- a/mypyc/primitives/misc_ops.py +++ b/mypyc/primitives/misc_ops.py @@ -21,7 +21,7 @@ ERR_NEG_INT, custom_op, custom_primitive_op, - function_op, + legacy_function_op, load_address_op, ) @@ -48,7 +48,7 @@ ) # id(obj) -function_op( +legacy_function_op( name="builtins.id", arg_types=[object_rprimitive], return_type=int_rprimitive, @@ -161,7 +161,7 @@ ) # isinstance(obj, cls) -slow_isinstance_op = function_op( +slow_isinstance_op = legacy_function_op( name="builtins.isinstance", arg_types=[object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, @@ -172,7 +172,7 @@ # Faster isinstance(obj, cls) that only works with native classes and doesn't perform # type checking of the type argument. -fast_isinstance_op = function_op( +fast_isinstance_op = legacy_function_op( "builtins.isinstance", arg_types=[object_rprimitive, object_rprimitive], return_type=bool_rprimitive, @@ -182,7 +182,7 @@ ) # bool(obj) with unboxed result -bool_op = function_op( +bool_op = legacy_function_op( name="builtins.bool", arg_types=[object_rprimitive], return_type=c_int_rprimitive, @@ -192,7 +192,7 @@ ) # slice(start, stop, step) -new_slice_op = function_op( +new_slice_op = legacy_function_op( name="builtins.slice", arg_types=[object_rprimitive, object_rprimitive, object_rprimitive], c_function_name="PySlice_New", @@ -201,7 +201,7 @@ ) # type(obj) -type_op = function_op( +type_op = legacy_function_op( name="builtins.type", arg_types=[object_rprimitive], c_function_name="PyObject_Type", diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index 5190b01adf4a..484c00e3fc2f 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -148,7 +148,7 @@ def method_op( return desc -def function_op( +def legacy_function_op( name: str, arg_types: list[RType], return_type: RType, diff --git a/mypyc/primitives/set_ops.py b/mypyc/primitives/set_ops.py index fcfb7847dc7d..b4cb4120cc40 100644 --- a/mypyc/primitives/set_ops.py +++ b/mypyc/primitives/set_ops.py @@ -14,7 +14,7 @@ from mypyc.primitives.registry import ( ERR_NEG_INT, binary_op, - function_op, + legacy_function_op, load_address_op, method_op, ) @@ -26,7 +26,7 @@ load_address_op(name="builtins.frozenset", type=object_rprimitive, src="PyFrozenSet_Type") # Construct an empty set. -new_set_op = function_op( +new_set_op = legacy_function_op( name="builtins.set", arg_types=[], return_type=set_rprimitive, @@ -36,7 +36,7 @@ ) # set(obj) -function_op( +legacy_function_op( name="builtins.set", arg_types=[object_rprimitive], return_type=set_rprimitive, @@ -45,7 +45,7 @@ ) # frozenset(obj) -function_op( +legacy_function_op( name="builtins.frozenset", arg_types=[object_rprimitive], return_type=object_rprimitive, diff --git a/mypyc/primitives/str_ops.py b/mypyc/primitives/str_ops.py index 2ff1fbdb4b3e..1860c1b556e9 100644 --- a/mypyc/primitives/str_ops.py +++ b/mypyc/primitives/str_ops.py @@ -20,7 +20,7 @@ ERR_NEG_INT, binary_op, custom_op, - function_op, + legacy_function_op, load_address_op, method_op, ) @@ -29,7 +29,7 @@ load_address_op(name="builtins.str", type=object_rprimitive, src="PyUnicode_Type") # str(obj) -str_op = function_op( +str_op = legacy_function_op( name="builtins.str", arg_types=[object_rprimitive], return_type=str_rprimitive, diff --git a/mypyc/primitives/tuple_ops.py b/mypyc/primitives/tuple_ops.py index 0ea0243dc18b..efb56fef6c99 100644 --- a/mypyc/primitives/tuple_ops.py +++ b/mypyc/primitives/tuple_ops.py @@ -15,7 +15,7 @@ object_rprimitive, tuple_rprimitive, ) -from mypyc.primitives.registry import custom_op, function_op, load_address_op, method_op +from mypyc.primitives.registry import custom_op, legacy_function_op, load_address_op, method_op # Get the 'builtins.tuple' type object. load_address_op(name="builtins.tuple", type=object_rprimitive, src="PyTuple_Type") @@ -56,7 +56,7 @@ ) # Construct tuple from a list. -list_tuple_op = function_op( +list_tuple_op = legacy_function_op( name="builtins.tuple", arg_types=[list_rprimitive], return_type=tuple_rprimitive, @@ -66,7 +66,7 @@ ) # Construct tuple from an arbitrary (iterable) object. -function_op( +legacy_function_op( name="builtins.tuple", arg_types=[object_rprimitive], return_type=tuple_rprimitive, From f5aeb808eb39f9ddfe90edb42f56476417854d03 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:15:20 +0000 Subject: [PATCH 02/10] Continue refactoring --- mypyc/irbuild/builder.py | 4 ++-- mypyc/primitives/registry.py | 4 ++-- mypyc/test/test_cheader.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 4a5647b9ffdf..d43c4c8f5f75 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -134,7 +134,7 @@ from mypyc.primitives.generic_ops import iter_op, next_op, py_setattr_op from mypyc.primitives.list_ops import list_get_item_unsafe_op, list_pop_last, to_list from mypyc.primitives.misc_ops import check_unpack_count_op, get_module_dict_op, import_op -from mypyc.primitives.registry import CFunctionDescription, function_ops +from mypyc.primitives.registry import CFunctionDescription, legacy_function_ops # These int binary operations can borrow their operands safely, since the # primitives take this into consideration. @@ -1051,7 +1051,7 @@ def call_refexpr_with_args( # Handle data-driven special-cased primitive call ops. if callee.fullname and expr.arg_kinds == [ARG_POS] * len(arg_values): fullname = get_call_target_fullname(callee) - call_c_ops_candidates = function_ops.get(fullname, []) + call_c_ops_candidates = legacy_function_ops.get(fullname, []) target = self.builder.matching_call_c( call_c_ops_candidates, arg_values, expr.line, self.node_type(expr) ) diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index 484c00e3fc2f..4705647cbc62 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -74,7 +74,7 @@ class LoadAddressDescription(NamedTuple): method_call_ops: dict[str, list[CFunctionDescription]] = {} # CallC op for top level function call(such as 'builtins.list') -function_ops: dict[str, list[CFunctionDescription]] = {} +legacy_function_ops: dict[str, list[CFunctionDescription]] = {} # CallC op for binary ops binary_ops: dict[str, list[PrimitiveDescription]] = {} @@ -174,7 +174,7 @@ def legacy_function_op( """ if extra_int_constants is None: extra_int_constants = [] - ops = function_ops.setdefault(name, []) + ops = legacy_function_ops.setdefault(name, []) desc = CFunctionDescription( name, arg_types, diff --git a/mypyc/test/test_cheader.py b/mypyc/test/test_cheader.py index f2af41c22ea9..00cc46826d49 100644 --- a/mypyc/test/test_cheader.py +++ b/mypyc/test/test_cheader.py @@ -28,7 +28,7 @@ def check_name(name: str) -> None: for old_values in [ registry.method_call_ops.values(), - registry.function_ops.values(), + registry.legacy_function_ops.values(), registry.unary_ops.values(), ]: for old_ops in old_values: From 9fb256edcc431f8283cbb0bcb51cfeb7bf1e64e5 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:24:39 +0000 Subject: [PATCH 03/10] [mypyc] Migrate a single call to use new-style function_op --- mypyc/irbuild/builder.py | 8 ++++- mypyc/primitives/list_ops.py | 3 +- mypyc/primitives/registry.py | 57 ++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index d43c4c8f5f75..e54446fb93fb 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -134,7 +134,7 @@ from mypyc.primitives.generic_ops import iter_op, next_op, py_setattr_op from mypyc.primitives.list_ops import list_get_item_unsafe_op, list_pop_last, to_list from mypyc.primitives.misc_ops import check_unpack_count_op, get_module_dict_op, import_op -from mypyc.primitives.registry import CFunctionDescription, legacy_function_ops +from mypyc.primitives.registry import CFunctionDescription, function_ops, legacy_function_ops # These int binary operations can borrow their operands safely, since the # primitives take this into consideration. @@ -1057,6 +1057,12 @@ def call_refexpr_with_args( ) if target: return target + primitive_candidates = function_ops.get(fullname, []) + target = self.builder.matching_primitive_op( + primitive_candidates, arg_values, expr.line, self.node_type(expr) + ) + if target: + return target # Standard native call if signature and fullname are good and all arguments are positional # or named. diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index 07a125287f2f..c0329e0cc001 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -19,6 +19,7 @@ binary_op, custom_op, custom_primitive_op, + function_op, legacy_function_op, load_address_op, method_op, @@ -28,7 +29,7 @@ load_address_op(name="builtins.list", type=object_rprimitive, src="PyList_Type") # list(obj) -to_list = legacy_function_op( +to_list = function_op( name="builtins.list", arg_types=[object_rprimitive], return_type=list_rprimitive, diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index 4705647cbc62..0500cb4ba1bd 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -70,10 +70,13 @@ class LoadAddressDescription(NamedTuple): src: str # name of the target to load -# CallC op for method call(such as 'str.join') +# CallC op for method call (such as 'str.join') method_call_ops: dict[str, list[CFunctionDescription]] = {} -# CallC op for top level function call(such as 'builtins.list') +# Primitive ops for top level function call (such as 'builtins.list') +function_ops: dict[str, list[PrimitiveDescription]] = {} + +# Legacy CallC ops for top level function call (such as 'builtins.list') legacy_function_ops: dict[str, list[CFunctionDescription]] = {} # CallC op for binary ops @@ -162,7 +165,9 @@ def legacy_function_op( is_borrowed: bool = False, priority: int = 1, ) -> CFunctionDescription: - """Define a c function call op that replaces a function call. + """Define a C function call op that replaces a function call. + + NOTE: Use function_op instead for new use cases. This will be automatically generated by matching against the AST. @@ -194,6 +199,52 @@ def legacy_function_op( return desc +def function_op( + name: str, + arg_types: list[RType], + return_type: RType, + c_function_name: str, + error_kind: int, + var_arg_type: RType | None = None, + truncated_type: RType | None = None, + ordering: list[int] | None = None, + extra_int_constants: list[tuple[int, RType]] | None = None, + steals: StealsDescription = False, + is_borrowed: bool = False, + priority: int = 1, +) -> PrimitiveDescription: + """Define a C function call op that replaces a function call. + + This will be automatically generated by matching against the AST. + + Most arguments are similar to method_op(). + + Args: + name: full name of the function + arg_types: positional argument types for which this applies + """ + if extra_int_constants is None: + extra_int_constants = [] + ops = function_ops.setdefault(name, []) + desc = PrimitiveDescription( + name, + arg_types, + return_type, + var_arg_type=var_arg_type, + 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=False, + ) + ops.append(desc) + return desc + + def binary_op( name: str, arg_types: list[RType], From 5cd7b3c103ae5be15989fa0be73cca9739498db9 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:27:50 +0000 Subject: [PATCH 04/10] Use more new-style primitive ops --- mypyc/primitives/int_ops.py | 12 ++++++------ mypyc/primitives/str_ops.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mypyc/primitives/int_ops.py b/mypyc/primitives/int_ops.py index fe8d14feff43..2eff233403f4 100644 --- a/mypyc/primitives/int_ops.py +++ b/mypyc/primitives/int_ops.py @@ -35,7 +35,7 @@ CFunctionDescription, binary_op, custom_op, - legacy_function_op, + function_op, load_address_op, unary_op, ) @@ -58,7 +58,7 @@ load_address_op(name=int_name, type=object_rprimitive, src="PyLong_Type") # int(float). We could do a bit better directly. - legacy_function_op( + function_op( name=int_name, arg_types=[float_rprimitive], return_type=int_rprimitive, @@ -67,7 +67,7 @@ ) # int(string) - legacy_function_op( + function_op( name=int_name, arg_types=[str_rprimitive], return_type=object_rprimitive, @@ -76,7 +76,7 @@ ) # int(string, base) - legacy_function_op( + function_op( name=int_name, arg_types=[str_rprimitive, int_rprimitive], return_type=object_rprimitive, @@ -85,7 +85,7 @@ ) # str(int) -int_to_str_op = legacy_function_op( +int_to_str_op = function_op( name="builtins.str", arg_types=[int_rprimitive], return_type=str_rprimitive, @@ -95,7 +95,7 @@ ) # We need a specialization for str on bools also since the int one is wrong... -legacy_function_op( +function_op( name="builtins.str", arg_types=[bool_rprimitive], return_type=str_rprimitive, diff --git a/mypyc/primitives/str_ops.py b/mypyc/primitives/str_ops.py index 1860c1b556e9..2ff1fbdb4b3e 100644 --- a/mypyc/primitives/str_ops.py +++ b/mypyc/primitives/str_ops.py @@ -20,7 +20,7 @@ ERR_NEG_INT, binary_op, custom_op, - legacy_function_op, + function_op, load_address_op, method_op, ) @@ -29,7 +29,7 @@ load_address_op(name="builtins.str", type=object_rprimitive, src="PyUnicode_Type") # str(obj) -str_op = legacy_function_op( +str_op = function_op( name="builtins.str", arg_types=[object_rprimitive], return_type=str_rprimitive, From 4fa8df7a1e9cbcebef9955b533b921026bb2251a Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:29:36 +0000 Subject: [PATCH 05/10] Replace more legacy function ops --- mypyc/primitives/float_ops.py | 34 ++++++++++++++++----------------- mypyc/primitives/generic_ops.py | 22 ++++++++++----------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/mypyc/primitives/float_ops.py b/mypyc/primitives/float_ops.py index 200e13b4fee4..14e8d4caf09c 100644 --- a/mypyc/primitives/float_ops.py +++ b/mypyc/primitives/float_ops.py @@ -10,7 +10,7 @@ object_rprimitive, str_rprimitive, ) -from mypyc.primitives.registry import binary_op, legacy_function_op, load_address_op +from mypyc.primitives.registry import binary_op, function_op, load_address_op # Get the 'builtins.float' type object. load_address_op(name="builtins.float", type=object_rprimitive, src="PyFloat_Type") @@ -24,7 +24,7 @@ ) # float(int) -int_to_float_op = legacy_function_op( +int_to_float_op = function_op( name="builtins.float", arg_types=[int_rprimitive], return_type=float_rprimitive, @@ -33,7 +33,7 @@ ) # float(str) -legacy_function_op( +function_op( name="builtins.float", arg_types=[str_rprimitive], return_type=object_rprimitive, @@ -42,7 +42,7 @@ ) # abs(float) -legacy_function_op( +function_op( name="builtins.abs", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -51,7 +51,7 @@ ) # math.sin(float) -legacy_function_op( +function_op( name="math.sin", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -60,7 +60,7 @@ ) # math.cos(float) -legacy_function_op( +function_op( name="math.cos", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -69,7 +69,7 @@ ) # math.tan(float) -legacy_function_op( +function_op( name="math.tan", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -78,7 +78,7 @@ ) # math.sqrt(float) -legacy_function_op( +function_op( name="math.sqrt", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -87,7 +87,7 @@ ) # math.exp(float) -legacy_function_op( +function_op( name="math.exp", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -96,7 +96,7 @@ ) # math.log(float) -legacy_function_op( +function_op( name="math.log", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -105,7 +105,7 @@ ) # math.floor(float) -legacy_function_op( +function_op( name="math.floor", arg_types=[float_rprimitive], return_type=int_rprimitive, @@ -114,7 +114,7 @@ ) # math.ceil(float) -legacy_function_op( +function_op( name="math.ceil", arg_types=[float_rprimitive], return_type=int_rprimitive, @@ -123,7 +123,7 @@ ) # math.fabs(float) -legacy_function_op( +function_op( name="math.fabs", arg_types=[float_rprimitive], return_type=float_rprimitive, @@ -132,7 +132,7 @@ ) # math.pow(float, float) -pow_op = legacy_function_op( +pow_op = function_op( name="math.pow", arg_types=[float_rprimitive, float_rprimitive], return_type=float_rprimitive, @@ -141,7 +141,7 @@ ) # math.copysign(float, float) -copysign_op = legacy_function_op( +copysign_op = function_op( name="math.copysign", arg_types=[float_rprimitive, float_rprimitive], return_type=float_rprimitive, @@ -150,7 +150,7 @@ ) # math.isinf(float) -legacy_function_op( +function_op( name="math.isinf", arg_types=[float_rprimitive], return_type=bool_rprimitive, @@ -159,7 +159,7 @@ ) # math.isnan(float) -legacy_function_op( +function_op( name="math.isnan", arg_types=[float_rprimitive], return_type=bool_rprimitive, diff --git a/mypyc/primitives/generic_ops.py b/mypyc/primitives/generic_ops.py index d21dc36a71bf..fe42767db11e 100644 --- a/mypyc/primitives/generic_ops.py +++ b/mypyc/primitives/generic_ops.py @@ -26,7 +26,7 @@ ERR_NEG_INT, binary_op, custom_op, - legacy_function_op, + function_op, method_op, unary_op, ) @@ -76,7 +76,7 @@ ) -legacy_function_op( +function_op( name="builtins.divmod", arg_types=[object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -120,7 +120,7 @@ ) for arg_count, c_function in ((2, "CPyNumber_Power"), (3, "PyNumber_Power")): - legacy_function_op( + function_op( name="builtins.pow", arg_types=[object_rprimitive] * arg_count, return_type=object_rprimitive, @@ -168,7 +168,7 @@ ) # abs(obj) -legacy_function_op( +function_op( name="builtins.abs", arg_types=[object_rprimitive], return_type=object_rprimitive, @@ -208,7 +208,7 @@ ) # hash(obj) -legacy_function_op( +function_op( name="builtins.hash", arg_types=[object_rprimitive], return_type=int_rprimitive, @@ -217,7 +217,7 @@ ) # getattr(obj, attr) -py_getattr_op = legacy_function_op( +py_getattr_op = function_op( name="builtins.getattr", arg_types=[object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -226,7 +226,7 @@ ) # getattr(obj, attr, default) -legacy_function_op( +function_op( name="builtins.getattr", arg_types=[object_rprimitive, object_rprimitive, object_rprimitive], return_type=object_rprimitive, @@ -235,7 +235,7 @@ ) # setattr(obj, attr, value) -py_setattr_op = legacy_function_op( +py_setattr_op = function_op( name="builtins.setattr", arg_types=[object_rprimitive, object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, @@ -244,7 +244,7 @@ ) # hasattr(obj, attr) -py_hasattr_op = legacy_function_op( +py_hasattr_op = function_op( name="builtins.hasattr", arg_types=[object_rprimitive, object_rprimitive], return_type=bool_rprimitive, @@ -253,7 +253,7 @@ ) # del obj.attr -py_delattr_op = legacy_function_op( +py_delattr_op = function_op( name="builtins.delattr", arg_types=[object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, @@ -336,7 +336,7 @@ ) # iter(obj) -iter_op = legacy_function_op( +iter_op = function_op( name="builtins.iter", arg_types=[object_rprimitive], return_type=object_rprimitive, From 88a59d52046a17b891c22a173d56bf9524425c94 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:33:05 +0000 Subject: [PATCH 06/10] Fix C header test --- mypyc/test/test_cheader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/test/test_cheader.py b/mypyc/test/test_cheader.py index 00cc46826d49..3536dc0fc5bb 100644 --- a/mypyc/test/test_cheader.py +++ b/mypyc/test/test_cheader.py @@ -37,7 +37,7 @@ def check_name(name: str) -> None: for old_op in old_ops: check_name(old_op.c_function_name) - for values in [registry.binary_ops.values()]: + for values in [registry.binary_ops.values(), registry.function_ops.values()]: for ops in values: if isinstance(ops, PrimitiveDescription): ops = [ops] From f72480ef6734073944130e7420a167d54ed00f3d Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:36:46 +0000 Subject: [PATCH 07/10] Remove remaining legacy function ops --- mypyc/irbuild/builder.py | 8 +----- mypyc/primitives/bytes_ops.py | 6 ++-- mypyc/primitives/dict_ops.py | 8 +++--- mypyc/primitives/list_ops.py | 3 +- mypyc/primitives/misc_ops.py | 14 ++++----- mypyc/primitives/registry.py | 53 +---------------------------------- mypyc/primitives/set_ops.py | 8 +++--- mypyc/primitives/tuple_ops.py | 6 ++-- mypyc/test/test_cheader.py | 6 +--- 9 files changed, 25 insertions(+), 87 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index e54446fb93fb..057ea3321f5e 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -134,7 +134,7 @@ from mypyc.primitives.generic_ops import iter_op, next_op, py_setattr_op from mypyc.primitives.list_ops import list_get_item_unsafe_op, list_pop_last, to_list from mypyc.primitives.misc_ops import check_unpack_count_op, get_module_dict_op, import_op -from mypyc.primitives.registry import CFunctionDescription, function_ops, legacy_function_ops +from mypyc.primitives.registry import CFunctionDescription, function_ops # These int binary operations can borrow their operands safely, since the # primitives take this into consideration. @@ -1051,12 +1051,6 @@ def call_refexpr_with_args( # Handle data-driven special-cased primitive call ops. if callee.fullname and expr.arg_kinds == [ARG_POS] * len(arg_values): fullname = get_call_target_fullname(callee) - call_c_ops_candidates = legacy_function_ops.get(fullname, []) - target = self.builder.matching_call_c( - call_c_ops_candidates, arg_values, expr.line, self.node_type(expr) - ) - if target: - return target primitive_candidates = function_ops.get(fullname, []) target = self.builder.matching_primitive_op( primitive_candidates, arg_values, expr.line, self.node_type(expr) diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index 02206e631489..d7a7f3e2f59b 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -18,7 +18,7 @@ ERR_NEG_INT, binary_op, custom_op, - legacy_function_op, + function_op, load_address_op, method_op, ) @@ -27,7 +27,7 @@ load_address_op(name="builtins.bytes", type=object_rprimitive, src="PyBytes_Type") # bytes(obj) -legacy_function_op( +function_op( name="builtins.bytes", arg_types=[RUnion([list_rprimitive, dict_rprimitive, str_rprimitive])], return_type=bytes_rprimitive, @@ -36,7 +36,7 @@ ) # bytearray(obj) -legacy_function_op( +function_op( name="builtins.bytearray", arg_types=[object_rprimitive], return_type=bytes_rprimitive, diff --git a/mypyc/primitives/dict_ops.py b/mypyc/primitives/dict_ops.py index bc6080026a32..ce7b9bb8d70e 100644 --- a/mypyc/primitives/dict_ops.py +++ b/mypyc/primitives/dict_ops.py @@ -19,7 +19,7 @@ ERR_NEG_INT, binary_op, custom_op, - legacy_function_op, + function_op, load_address_op, method_op, ) @@ -28,7 +28,7 @@ load_address_op(name="builtins.dict", type=object_rprimitive, src="PyDict_Type") # Construct an empty dictionary via dict(). -legacy_function_op( +function_op( name="builtins.dict", arg_types=[], return_type=dict_rprimitive, @@ -53,7 +53,7 @@ ) # Construct a dictionary from another dictionary. -legacy_function_op( +function_op( name="builtins.dict", arg_types=[dict_rprimitive], return_type=dict_rprimitive, @@ -63,7 +63,7 @@ ) # Generic one-argument dict constructor: dict(obj) -dict_copy = legacy_function_op( +dict_copy = function_op( name="builtins.dict", arg_types=[object_rprimitive], return_type=dict_rprimitive, diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index c0329e0cc001..cb75e19a8dea 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -20,7 +20,6 @@ custom_op, custom_primitive_op, function_op, - legacy_function_op, load_address_op, method_op, ) @@ -38,7 +37,7 @@ ) # Construct an empty list via list(). -legacy_function_op( +function_op( name="builtins.list", arg_types=[], return_type=list_rprimitive, diff --git a/mypyc/primitives/misc_ops.py b/mypyc/primitives/misc_ops.py index fcaa34ac9980..e9016e24c46d 100644 --- a/mypyc/primitives/misc_ops.py +++ b/mypyc/primitives/misc_ops.py @@ -21,7 +21,7 @@ ERR_NEG_INT, custom_op, custom_primitive_op, - legacy_function_op, + function_op, load_address_op, ) @@ -48,7 +48,7 @@ ) # id(obj) -legacy_function_op( +function_op( name="builtins.id", arg_types=[object_rprimitive], return_type=int_rprimitive, @@ -161,7 +161,7 @@ ) # isinstance(obj, cls) -slow_isinstance_op = legacy_function_op( +slow_isinstance_op = function_op( name="builtins.isinstance", arg_types=[object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, @@ -172,7 +172,7 @@ # Faster isinstance(obj, cls) that only works with native classes and doesn't perform # type checking of the type argument. -fast_isinstance_op = legacy_function_op( +fast_isinstance_op = function_op( "builtins.isinstance", arg_types=[object_rprimitive, object_rprimitive], return_type=bool_rprimitive, @@ -182,7 +182,7 @@ ) # bool(obj) with unboxed result -bool_op = legacy_function_op( +bool_op = function_op( name="builtins.bool", arg_types=[object_rprimitive], return_type=c_int_rprimitive, @@ -192,7 +192,7 @@ ) # slice(start, stop, step) -new_slice_op = legacy_function_op( +new_slice_op = function_op( name="builtins.slice", arg_types=[object_rprimitive, object_rprimitive, object_rprimitive], c_function_name="PySlice_New", @@ -201,7 +201,7 @@ ) # type(obj) -type_op = legacy_function_op( +type_op = function_op( name="builtins.type", arg_types=[object_rprimitive], c_function_name="PyObject_Type", diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index 0500cb4ba1bd..25ad83be14f5 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -76,10 +76,7 @@ class LoadAddressDescription(NamedTuple): # Primitive ops for top level function call (such as 'builtins.list') function_ops: dict[str, list[PrimitiveDescription]] = {} -# Legacy CallC ops for top level function call (such as 'builtins.list') -legacy_function_ops: dict[str, list[CFunctionDescription]] = {} - -# CallC op for binary ops +# Primitive ops for binary operations binary_ops: dict[str, list[PrimitiveDescription]] = {} # CallC op for unary ops @@ -151,54 +148,6 @@ def method_op( return desc -def legacy_function_op( - name: str, - arg_types: list[RType], - return_type: RType, - c_function_name: str, - error_kind: int, - var_arg_type: RType | None = None, - truncated_type: RType | None = None, - ordering: list[int] | None = None, - extra_int_constants: list[tuple[int, RType]] | None = None, - steals: StealsDescription = False, - is_borrowed: bool = False, - priority: int = 1, -) -> CFunctionDescription: - """Define a C function call op that replaces a function call. - - NOTE: Use function_op instead for new use cases. - - This will be automatically generated by matching against the AST. - - Most arguments are similar to method_op(). - - Args: - name: full name of the function - arg_types: positional argument types for which this applies - """ - if extra_int_constants is None: - extra_int_constants = [] - ops = legacy_function_ops.setdefault(name, []) - desc = CFunctionDescription( - name, - arg_types, - return_type, - var_arg_type, - truncated_type, - c_function_name, - error_kind, - steals, - is_borrowed, - ordering, - extra_int_constants, - priority, - is_pure=False, - ) - ops.append(desc) - return desc - - def function_op( name: str, arg_types: list[RType], diff --git a/mypyc/primitives/set_ops.py b/mypyc/primitives/set_ops.py index b4cb4120cc40..fcfb7847dc7d 100644 --- a/mypyc/primitives/set_ops.py +++ b/mypyc/primitives/set_ops.py @@ -14,7 +14,7 @@ from mypyc.primitives.registry import ( ERR_NEG_INT, binary_op, - legacy_function_op, + function_op, load_address_op, method_op, ) @@ -26,7 +26,7 @@ load_address_op(name="builtins.frozenset", type=object_rprimitive, src="PyFrozenSet_Type") # Construct an empty set. -new_set_op = legacy_function_op( +new_set_op = function_op( name="builtins.set", arg_types=[], return_type=set_rprimitive, @@ -36,7 +36,7 @@ ) # set(obj) -legacy_function_op( +function_op( name="builtins.set", arg_types=[object_rprimitive], return_type=set_rprimitive, @@ -45,7 +45,7 @@ ) # frozenset(obj) -legacy_function_op( +function_op( name="builtins.frozenset", arg_types=[object_rprimitive], return_type=object_rprimitive, diff --git a/mypyc/primitives/tuple_ops.py b/mypyc/primitives/tuple_ops.py index efb56fef6c99..0ea0243dc18b 100644 --- a/mypyc/primitives/tuple_ops.py +++ b/mypyc/primitives/tuple_ops.py @@ -15,7 +15,7 @@ object_rprimitive, tuple_rprimitive, ) -from mypyc.primitives.registry import custom_op, legacy_function_op, load_address_op, method_op +from mypyc.primitives.registry import custom_op, function_op, load_address_op, method_op # Get the 'builtins.tuple' type object. load_address_op(name="builtins.tuple", type=object_rprimitive, src="PyTuple_Type") @@ -56,7 +56,7 @@ ) # Construct tuple from a list. -list_tuple_op = legacy_function_op( +list_tuple_op = function_op( name="builtins.tuple", arg_types=[list_rprimitive], return_type=tuple_rprimitive, @@ -66,7 +66,7 @@ ) # Construct tuple from an arbitrary (iterable) object. -legacy_function_op( +function_op( name="builtins.tuple", arg_types=[object_rprimitive], return_type=tuple_rprimitive, diff --git a/mypyc/test/test_cheader.py b/mypyc/test/test_cheader.py index 3536dc0fc5bb..08b5a4648ca5 100644 --- a/mypyc/test/test_cheader.py +++ b/mypyc/test/test_cheader.py @@ -26,11 +26,7 @@ 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.legacy_function_ops.values(), - registry.unary_ops.values(), - ]: + for old_values in [registry.method_call_ops.values(), registry.unary_ops.values()]: for old_ops in old_values: if isinstance(old_ops, CFunctionDescription): old_ops = [old_ops] From 35e300e628b670ea1740b274abb44f2fa1384cfd Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:44:18 +0000 Subject: [PATCH 08/10] Fix some call_c call sites --- mypyc/irbuild/builder.py | 5 ++++- mypyc/irbuild/classdef.py | 8 ++++---- mypyc/irbuild/expression.py | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 057ea3321f5e..26581099015a 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -134,7 +134,7 @@ from mypyc.primitives.generic_ops import iter_op, next_op, py_setattr_op from mypyc.primitives.list_ops import list_get_item_unsafe_op, list_pop_last, to_list from mypyc.primitives.misc_ops import check_unpack_count_op, get_module_dict_op, import_op -from mypyc.primitives.registry import CFunctionDescription, function_ops +from mypyc.primitives.registry import CFunctionDescription, PrimitiveDescription, function_ops # These int binary operations can borrow their operands safely, since the # primitives take this into consideration. @@ -381,6 +381,9 @@ def load_module(self, name: str) -> Value: def call_c(self, desc: CFunctionDescription, args: list[Value], line: int) -> Value: return self.builder.call_c(desc, args, line) + def primitive_op(self, desc: PrimitiveDescription, args: list[Value], line: int) -> Value: + return self.builder.primitive_op(desc, args, line) + def int_op(self, type: RType, lhs: Value, rhs: Value, op: int, line: int) -> Value: return self.builder.int_op(type, lhs, rhs, op, line) diff --git a/mypyc/irbuild/classdef.py b/mypyc/irbuild/classdef.py index 5fd55ff4b5a4..58be87c88a3f 100644 --- a/mypyc/irbuild/classdef.py +++ b/mypyc/irbuild/classdef.py @@ -292,7 +292,7 @@ def add_attr(self, lvalue: NameExpr, stmt: AssignmentStmt) -> None: return typ = self.builder.load_native_type_object(self.cdef.fullname) value = self.builder.accept(stmt.rvalue) - self.builder.call_c( + self.builder.primitive_op( py_setattr_op, [typ, self.builder.load_str(lvalue.name), value], stmt.line ) if self.builder.non_function_scope() and stmt.is_final_def: @@ -452,7 +452,7 @@ def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value: ) ) # Populate a '__mypyc_attrs__' field containing the list of attrs - builder.call_c( + builder.primitive_op( py_setattr_op, [ tp, @@ -483,7 +483,7 @@ def make_generic_base_class( for tv, type_param in zip(tvs, type_args): if type_param.kind == TYPE_VAR_TUPLE_KIND: # Evaluate *Ts for a TypeVarTuple - it = builder.call_c(iter_op, [tv], line) + it = builder.primitive_op(iter_op, [tv], line) tv = builder.call_c(next_op, [it], line) args.append(tv) @@ -603,7 +603,7 @@ def setup_non_ext_dict( This class dictionary is passed to the metaclass constructor. """ # Check if the metaclass defines a __prepare__ method, and if so, call it. - has_prepare = builder.call_c( + has_prepare = builder.primitive_op( py_hasattr_op, [metaclass, builder.load_str("__prepare__")], cdef.line ) diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 8d7c089e20cd..e2502475424e 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -1045,12 +1045,12 @@ def get_arg(arg: Expression | None) -> Value: return builder.accept(arg) args = [get_arg(expr.begin_index), get_arg(expr.end_index), get_arg(expr.stride)] - return builder.call_c(new_slice_op, args, expr.line) + return builder.primitive_op(new_slice_op, args, expr.line) def transform_generator_expr(builder: IRBuilder, o: GeneratorExpr) -> Value: builder.warning("Treating generator comprehension as list", o.line) - return builder.call_c(iter_op, [translate_list_comprehension(builder, o)], o.line) + return builder.primitive_op(iter_op, [translate_list_comprehension(builder, o)], o.line) def transform_assignment_expr(builder: IRBuilder, o: AssignmentExpr) -> Value: From 2ec689dfb7674a8cca6e2f354df1900ba7c0f5fc Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 15:52:23 +0000 Subject: [PATCH 09/10] Update more call_c call sites --- mypyc/irbuild/builder.py | 9 +++++---- mypyc/irbuild/expression.py | 4 ++-- mypyc/irbuild/for_helpers.py | 2 +- mypyc/irbuild/format_str_tokenizer.py | 6 +++--- mypyc/irbuild/function.py | 6 +++--- mypyc/irbuild/match.py | 4 ++-- mypyc/irbuild/statement.py | 10 +++++++--- 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 26581099015a..7561070b012f 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -84,6 +84,7 @@ IntOp, LoadStatic, Op, + PrimitiveDescription, RaiseStandardError, Register, SetAttr, @@ -134,7 +135,7 @@ from mypyc.primitives.generic_ops import iter_op, next_op, py_setattr_op from mypyc.primitives.list_ops import list_get_item_unsafe_op, list_pop_last, to_list from mypyc.primitives.misc_ops import check_unpack_count_op, get_module_dict_op, import_op -from mypyc.primitives.registry import CFunctionDescription, PrimitiveDescription, function_ops +from mypyc.primitives.registry import CFunctionDescription, function_ops # These int binary operations can borrow their operands safely, since the # primitives take this into consideration. @@ -694,7 +695,7 @@ def assign(self, target: Register | AssignmentTarget, rvalue_reg: Value, line: i else: key = self.load_str(target.attr) boxed_reg = self.builder.box(rvalue_reg) - self.call_c(py_setattr_op, [target.obj, key, boxed_reg], line) + self.primitive_op(py_setattr_op, [target.obj, key, boxed_reg], line) elif isinstance(target, AssignmentTargetIndex): target_reg2 = self.gen_method_call( target.base, "__setitem__", [target.index, rvalue_reg], None, line @@ -771,7 +772,7 @@ def process_iterator_tuple_assignment_helper( def process_iterator_tuple_assignment( self, target: AssignmentTargetTuple, rvalue_reg: Value, line: int ) -> None: - iterator = self.call_c(iter_op, [rvalue_reg], line) + iterator = self.primitive_op(iter_op, [rvalue_reg], line) # This may be the whole lvalue list if there is no starred value split_idx = target.star_idx if target.star_idx is not None else len(target.items) @@ -797,7 +798,7 @@ def process_iterator_tuple_assignment( # Assign the starred value and all values after it if target.star_idx is not None: post_star_vals = target.items[split_idx + 1 :] - iter_list = self.call_c(to_list, [iterator], line) + iter_list = self.primitive_op(to_list, [iterator], line) iter_list_len = self.builtin_len(iter_list, line) post_star_len = Integer(len(post_star_vals)) condition = self.binary_op(post_star_len, iter_list_len, "<=", line) diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index e2502475424e..a2a3203d12ca 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -476,7 +476,7 @@ def translate_super_method_call(builder: IRBuilder, expr: CallExpr, callee: Supe # Grab first argument vself: Value = builder.self() if decl.kind == FUNC_CLASSMETHOD: - vself = builder.call_c(type_op, [vself], expr.line) + vself = builder.primitive_op(type_op, [vself], expr.line) elif builder.fn_info.is_generator: # For generator classes, the self target is the 6th value # in the symbol table (which is an ordered dict). This is sort @@ -953,7 +953,7 @@ def transform_tuple_expr(builder: IRBuilder, expr: TupleExpr) -> Value: def _visit_tuple_display(builder: IRBuilder, expr: TupleExpr) -> Value: """Create a list, then turn it into a tuple.""" val_as_list = _visit_list_display(builder, expr.items, expr.line) - return builder.call_c(list_tuple_op, [val_as_list], expr.line) + return builder.primitive_op(list_tuple_op, [val_as_list], expr.line) def transform_dict_expr(builder: IRBuilder, expr: DictExpr) -> Value: diff --git a/mypyc/irbuild/for_helpers.py b/mypyc/irbuild/for_helpers.py index ffb1fc15f228..b37c39e70f11 100644 --- a/mypyc/irbuild/for_helpers.py +++ b/mypyc/irbuild/for_helpers.py @@ -586,7 +586,7 @@ def init(self, expr_reg: Value, target_type: RType) -> None: # for the for-loop. If we are inside of a generator function, spill these into the # environment class. builder = self.builder - iter_reg = builder.call_c(iter_op, [expr_reg], self.line) + iter_reg = builder.primitive_op(iter_op, [expr_reg], self.line) builder.maybe_spill(expr_reg) self.iter_target = builder.maybe_spill(iter_reg) self.target_type = target_type diff --git a/mypyc/irbuild/format_str_tokenizer.py b/mypyc/irbuild/format_str_tokenizer.py index 0b46887811fb..eaa4027ed768 100644 --- a/mypyc/irbuild/format_str_tokenizer.py +++ b/mypyc/irbuild/format_str_tokenizer.py @@ -146,12 +146,12 @@ def convert_format_expr_to_str( if is_str_rprimitive(node_type): var_str = builder.accept(x) elif is_int_rprimitive(node_type) or is_short_int_rprimitive(node_type): - var_str = builder.call_c(int_to_str_op, [builder.accept(x)], line) + var_str = builder.primitive_op(int_to_str_op, [builder.accept(x)], line) else: - var_str = builder.call_c(str_op, [builder.accept(x)], line) + var_str = builder.primitive_op(str_op, [builder.accept(x)], line) elif format_op == FormatOp.INT: if is_int_rprimitive(node_type) or is_short_int_rprimitive(node_type): - var_str = builder.call_c(int_to_str_op, [builder.accept(x)], line) + var_str = builder.primitive_op(int_to_str_op, [builder.accept(x)], line) else: return None else: diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index 8678c1d89c58..76fdef4b5693 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -433,7 +433,7 @@ def handle_ext_method(builder: IRBuilder, cdef: ClassDef, fdef: FuncDef) -> None # Set the callable object representing the decorated method as an attribute of the # extension class. - builder.call_c(py_setattr_op, [typ, builder.load_str(name), decorated_func], fdef.line) + builder.primitive_op(py_setattr_op, [typ, builder.load_str(name), decorated_func], fdef.line) if fdef.is_property: # If there is a property setter, it will be processed after the getter, @@ -973,7 +973,7 @@ def generate_singledispatch_callable_class_ctor(builder: IRBuilder) -> None: cache_dict = builder.call_c(dict_new_op, [], line) dispatch_cache_str = builder.load_str("dispatch_cache") # use the py_setattr_op instead of SetAttr so that it also gets added to our __dict__ - builder.call_c(py_setattr_op, [builder.self(), dispatch_cache_str, cache_dict], line) + builder.primitive_op(py_setattr_op, [builder.self(), dispatch_cache_str, cache_dict], line) # the generated C code seems to expect that __init__ returns a char, so just return 1 builder.add(Return(Integer(1, bool_rprimitive, line), line)) @@ -1016,7 +1016,7 @@ def maybe_insert_into_registry_dict(builder: IRBuilder, fitem: FuncDef) -> None: registry_dict = builder.builder.make_dict([(loaded_object_type, main_func_obj)], line) dispatch_func_obj = builder.load_global_str(fitem.name, line) - builder.call_c( + builder.primitive_op( py_setattr_op, [dispatch_func_obj, builder.load_str("registry"), registry_dict], line ) diff --git a/mypyc/irbuild/match.py b/mypyc/irbuild/match.py index a1e671911ea5..976a8810b327 100644 --- a/mypyc/irbuild/match.py +++ b/mypyc/irbuild/match.py @@ -131,7 +131,7 @@ def visit_class_pattern(self, pattern: ClassPattern) -> None: else slow_isinstance_op ) - cond = self.builder.call_c( + cond = self.builder.primitive_op( isinstance_op, [self.subject, self.builder.accept(pattern.class_ref)], pattern.line ) @@ -246,7 +246,7 @@ def visit_mapping_pattern(self, pattern: MappingPattern) -> None: self.builder.activate_block(self.code_block) self.code_block = BasicBlock() - rest = self.builder.call_c(dict_copy, [self.subject], pattern.rest.line) + rest = self.builder.primitive_op(dict_copy, [self.subject], pattern.rest.line) target = self.builder.get_assignment_target(pattern.rest) diff --git a/mypyc/irbuild/statement.py b/mypyc/irbuild/statement.py index ac3fa33f36ca..bd4acccf077a 100644 --- a/mypyc/irbuild/statement.py +++ b/mypyc/irbuild/statement.py @@ -58,6 +58,7 @@ LoadLiteral, LoadStatic, MethodCall, + PrimitiveDescription, RaiseStandardError, Register, Return, @@ -757,7 +758,7 @@ def transform_with( value = builder.add(MethodCall(mgr_v, f"__{al}enter__", args=[], line=line)) exit_ = None else: - typ = builder.call_c(type_op, [mgr_v], line) + typ = builder.primitive_op(type_op, [mgr_v], line) exit_ = builder.maybe_spill(builder.py_get_attr(typ, f"__{al}exit__", line)) value = builder.py_call(builder.py_get_attr(typ, f"__{al}enter__", line), [mgr_v], line) @@ -876,7 +877,7 @@ def transform_del_item(builder: IRBuilder, target: AssignmentTarget, line: int) line, ) key = builder.load_str(target.attr) - builder.call_c(py_delattr_op, [target.obj, key], line) + builder.primitive_op(py_delattr_op, [target.obj, key], line) elif isinstance(target, AssignmentTargetRegister): # Delete a local by assigning an error value to it, which will # prompt the insertion of uninit checks. @@ -924,7 +925,10 @@ def emit_yield_from_or_await( received_reg = Register(object_rprimitive) get_op = coro_op if is_await else iter_op - iter_val = builder.call_c(get_op, [val], line) + if isinstance(get_op, PrimitiveDescription): + iter_val = builder.primitive_op(get_op, [val], line) + else: + iter_val = builder.call_c(get_op, [val], line) iter_reg = builder.maybe_spill_assignable(iter_val) From f3a53621827f26d670346c7dad488a5866297bec Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 29 Nov 2024 16:14:20 +0000 Subject: [PATCH 10/10] Update remaining call sites --- mypyc/irbuild/function.py | 4 +++- mypyc/irbuild/ll_builder.py | 20 +++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index 76fdef4b5693..4d04c549d392 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -433,7 +433,9 @@ def handle_ext_method(builder: IRBuilder, cdef: ClassDef, fdef: FuncDef) -> None # Set the callable object representing the decorated method as an attribute of the # extension class. - builder.primitive_op(py_setattr_op, [typ, builder.load_str(name), decorated_func], fdef.line) + builder.primitive_op( + py_setattr_op, [typ, builder.load_str(name), decorated_func], fdef.line + ) if fdef.is_property: # If there is a property setter, it will be processed after the getter, diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index cb23a74c69c6..df73f8481751 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -620,7 +620,7 @@ def py_get_attr(self, obj: Value, attr: str, line: int) -> Value: Prefer get_attr() which generates optimized code for native classes. """ key = self.load_str(attr) - return self.call_c(py_getattr_op, [obj, key], line) + return self.primitive_op(py_getattr_op, [obj, key], line) # isinstance() checks @@ -656,7 +656,9 @@ def isinstance_native(self, obj: Value, class_ir: ClassIR, line: int) -> Value: """ concrete = all_concrete_classes(class_ir) if concrete is None or len(concrete) > FAST_ISINSTANCE_MAX_SUBCLASSES + 1: - return self.call_c(fast_isinstance_op, [obj, self.get_native_type(class_ir)], line) + return self.primitive_op( + fast_isinstance_op, [obj, self.get_native_type(class_ir)], line + ) if not concrete: # There can't be any concrete instance that matches this. return self.false() @@ -857,7 +859,7 @@ def _construct_varargs( if star_result is None: star_result = self.new_tuple(star_values, line) else: - star_result = self.call_c(list_tuple_op, [star_result], line) + star_result = self.primitive_op(list_tuple_op, [star_result], line) if has_star2 and star2_result is None: star2_result = self._create_dict(star2_keys, star2_values, line) @@ -1515,7 +1517,7 @@ def compare_tuples(self, lhs: Value, rhs: Value, op: str, line: int = -1) -> Val # Cast to bool if necessary since most types uses comparison returning a object type # See generic_ops.py for more information if not is_bool_rprimitive(compare.type): - compare = self.call_c(bool_op, [compare], line) + compare = self.primitive_op(bool_op, [compare], line) if i < len(lhs.type.types) - 1: branch = Branch(compare, early_stop, check_blocks[i + 1], Branch.BOOL) else: @@ -1534,7 +1536,7 @@ def compare_tuples(self, lhs: Value, rhs: Value, op: str, line: int = -1) -> Val def translate_instance_contains(self, inst: Value, item: Value, op: str, line: int) -> Value: res = self.gen_method_call(inst, "__contains__", [item], None, line) if not is_bool_rprimitive(res.type): - res = self.call_c(bool_op, [res], line) + res = self.primitive_op(bool_op, [res], line) if op == "not in": res = self.bool_bitwise_op(res, Integer(1, rtype=bool_rprimitive), "^", line) return res @@ -1667,7 +1669,7 @@ def new_list_op(self, values: list[Value], line: int) -> Value: return result_list def new_set_op(self, values: list[Value], line: int) -> Value: - return self.call_c(new_set_op, values, line) + return self.primitive_op(new_set_op, values, line) def setup_rarray( self, item_type: RType, values: Sequence[Value], *, object_ptr: bool = False @@ -1775,7 +1777,7 @@ def bool_value(self, value: Value) -> Value: self.goto(end) self.activate_block(end) else: - result = self.call_c(bool_op, [value], value.line) + result = self.primitive_op(bool_op, [value], value.line) return result def add_bool_branch(self, value: Value, true: BasicBlock, false: BasicBlock) -> None: @@ -2065,7 +2067,7 @@ def float_mod(self, lhs: Value, rhs: Value, line: int) -> Value: self.activate_block(copysign) # If the remainder is zero, CPython ensures the result has the # same sign as the denominator. - adj = self.call_c(copysign_op, [Float(0.0), rhs], line) + adj = self.primitive_op(copysign_op, [Float(0.0), rhs], line) self.add(Assign(res, adj)) self.add(Goto(done)) self.activate_block(done) @@ -2260,7 +2262,7 @@ def new_tuple_with_length(self, length: Value, line: int) -> Value: return self.call_c(new_tuple_with_length_op, [length], line) def int_to_float(self, n: Value, line: int) -> Value: - return self.call_c(int_to_float_op, [n], line) + return self.primitive_op(int_to_float_op, [n], line) # Internal helpers