diff --git a/mypyc/common.py b/mypyc/common.py index 9689e2c4aa18..3cbc79f74a6a 100644 --- a/mypyc/common.py +++ b/mypyc/common.py @@ -1,5 +1,6 @@ import sys from typing import Dict, Any +import sys from typing_extensions import Final @@ -22,7 +23,11 @@ # Max short int we accept as a literal is based on 32-bit platforms, # so that we can just always emit the same code. -MAX_LITERAL_SHORT_INT = (1 << 30) - 1 # type: Final + +# Maximum value for a short tagged integer. +# +# Note: Assume that the compiled code uses the same bit width as mypyc. +MAX_LITERAL_SHORT_INT = sys.maxsize >> 1 # type: Final TOP_LEVEL_NAME = '__top_level__' # type: Final # Special function representing module top level diff --git a/mypyc/doc/list_operations.rst b/mypyc/doc/list_operations.rst index 5092fdacb2c7..94c75773329d 100644 --- a/mypyc/doc/list_operations.rst +++ b/mypyc/doc/list_operations.rst @@ -29,6 +29,10 @@ Get item by integer index: * ``lst[n]`` +Slicing: + +* ``lst[n:m]``, ``lst[n:]``, ``lst[:m]``, ``lst[:]`` + Repeat list ``n`` times: * ``lst * n``, ``n * lst`` diff --git a/mypyc/doc/str_operations.rst b/mypyc/doc/str_operations.rst index 1fb9c10aa719..a7c2b842c39e 100644 --- a/mypyc/doc/str_operations.rst +++ b/mypyc/doc/str_operations.rst @@ -24,6 +24,10 @@ Indexing: * ``s[n]`` (integer index) +Slicing: + +* ``s[n:m]``, ``s[n:]``, ``s[:m]`` + Comparisons: * ``s1 == s2``, ``s1 != s2`` diff --git a/mypyc/doc/tuple_operations.rst b/mypyc/doc/tuple_operations.rst index b07c8711dd6a..fca9e63fc210 100644 --- a/mypyc/doc/tuple_operations.rst +++ b/mypyc/doc/tuple_operations.rst @@ -20,6 +20,7 @@ Operators --------- * ``tup[n]`` (integer index) +* ``tup[n:m]``, ``tup[n:]``, ``tup[:m]`` (slicing) Statements ---------- diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index d50dcc671277..ae6008274087 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -185,6 +185,9 @@ def py_get_attr(self, obj: Value, attr: str, line: int) -> Value: def load_static_unicode(self, value: str) -> Value: return self.builder.load_static_unicode(value) + def load_static_int(self, value: int) -> Value: + return self.builder.load_static_int(value) + def primitive_op(self, desc: OpDescription, args: List[Value], line: int) -> Value: return self.builder.primitive_op(desc, args, line) diff --git a/mypyc/irbuild/expression.py b/mypyc/irbuild/expression.py index 5c61b267a71f..d6989d36a699 100644 --- a/mypyc/irbuild/expression.py +++ b/mypyc/irbuild/expression.py @@ -15,18 +15,22 @@ ) from mypy.types import TupleType, get_proper_type +from mypyc.common import MAX_LITERAL_SHORT_INT from mypyc.ir.ops import ( Value, TupleGet, TupleSet, BasicBlock, Assign, LoadAddress ) -from mypyc.ir.rtypes import RTuple, object_rprimitive, is_none_rprimitive, is_int_rprimitive +from mypyc.ir.rtypes import ( + RTuple, object_rprimitive, is_none_rprimitive, int_rprimitive, is_int_rprimitive +) from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD from mypyc.primitives.registry import CFunctionDescription, builtin_names from mypyc.primitives.generic_ops import iter_op from mypyc.primitives.misc_ops import new_slice_op, ellipsis_op, type_op -from mypyc.primitives.list_ops import list_append_op, list_extend_op -from mypyc.primitives.tuple_ops import list_tuple_op +from mypyc.primitives.list_ops import list_append_op, list_extend_op, list_slice_op +from mypyc.primitives.tuple_ops import list_tuple_op, tuple_slice_op from mypyc.primitives.dict_ops import dict_new_op, dict_set_item_op from mypyc.primitives.set_ops import new_set_op, set_add_op, set_update_op +from mypyc.primitives.str_ops import str_slice_op from mypyc.primitives.int_ops import int_comparison_op_mapping from mypyc.irbuild.specialize import specializers from mypyc.irbuild.builder import IRBuilder @@ -323,15 +327,59 @@ def transform_op_expr(builder: IRBuilder, expr: OpExpr) -> Value: def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value: base = builder.accept(expr.base) + index = expr.index + + if isinstance(base.type, RTuple) and isinstance(index, IntExpr): + return builder.add(TupleGet(base, index.value, expr.line)) - if isinstance(base.type, RTuple) and isinstance(expr.index, IntExpr): - return builder.add(TupleGet(base, expr.index.value, expr.line)) + if isinstance(index, SliceExpr): + value = try_gen_slice_op(builder, base, index) + if value: + return value index_reg = builder.accept(expr.index) return builder.gen_method_call( base, '__getitem__', [index_reg], builder.node_type(expr), expr.line) +def try_gen_slice_op(builder: IRBuilder, base: Value, index: SliceExpr) -> Optional[Value]: + """Generate specialized slice op for some index expressions. + + Return None if a specialized op isn't available. + + This supports obj[x:y], obj[:x], and obj[x:] for a few types. + """ + if index.stride: + # We can only handle the default stride of 1. + return None + + if index.begin_index: + begin_type = builder.node_type(index.begin_index) + else: + begin_type = int_rprimitive + if index.end_index: + end_type = builder.node_type(index.end_index) + else: + end_type = int_rprimitive + + # Both begin and end index must be int (or missing). + if is_int_rprimitive(begin_type) and is_int_rprimitive(end_type): + if index.begin_index: + begin = builder.accept(index.begin_index) + else: + begin = builder.load_static_int(0) + if index.end_index: + end = builder.accept(index.end_index) + else: + # Replace missing end index with the largest short integer + # (a sequence can't be longer). + end = builder.load_static_int(MAX_LITERAL_SHORT_INT) + candidates = [list_slice_op, tuple_slice_op, str_slice_op] + return builder.builder.matching_call_c(candidates, [base, begin, end], index.line) + + return None + + def transform_conditional_expr(builder: IRBuilder, expr: ConditionalExpr) -> Value: if_body, else_body, next = BasicBlock(), BasicBlock(), BasicBlock() diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index e5fb8601e558..c0f998b15c42 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -303,6 +303,7 @@ CPyTagged CPyObject_Hash(PyObject *o); PyObject *CPyObject_GetAttr3(PyObject *v, PyObject *name, PyObject *defl); PyObject *CPyIter_Next(PyObject *iter); PyObject *CPyNumber_Power(PyObject *base, PyObject *index); +PyObject *CPyObject_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); // List operations @@ -318,6 +319,7 @@ CPyTagged CPyList_Count(PyObject *obj, PyObject *value); PyObject *CPyList_Extend(PyObject *o1, PyObject *o2); PyObject *CPySequence_Multiply(PyObject *seq, CPyTagged t_size); PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq); +PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); // Dict operations @@ -367,6 +369,7 @@ static inline char CPyDict_CheckSize(PyObject *dict, CPyTagged size) { PyObject *CPyStr_GetItem(PyObject *str, CPyTagged index); PyObject *CPyStr_Split(PyObject *str, PyObject *sep, CPyTagged max_split); PyObject *CPyStr_Append(PyObject *o1, PyObject *o2); +PyObject *CPyStr_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); // Set operations @@ -379,6 +382,7 @@ bool CPySet_Remove(PyObject *set, PyObject *key); PyObject *CPySequenceTuple_GetItem(PyObject *tuple, CPyTagged index); +PyObject *CPySequenceTuple_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); // Exception operations diff --git a/mypyc/lib-rt/generic_ops.c b/mypyc/lib-rt/generic_ops.c index c619e56d0c1f..1dff949dcfcf 100644 --- a/mypyc/lib-rt/generic_ops.c +++ b/mypyc/lib-rt/generic_ops.c @@ -40,3 +40,20 @@ PyObject *CPyNumber_Power(PyObject *base, PyObject *index) { return PyNumber_Power(base, index, Py_None); } + +PyObject *CPyObject_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) { + PyObject *start_obj = CPyTagged_AsObject(start); + PyObject *end_obj = CPyTagged_AsObject(end); + if (unlikely(start_obj == NULL || end_obj == NULL)) { + return NULL; + } + PyObject *slice = PySlice_New(start_obj, end_obj, NULL); + Py_DECREF(start_obj); + Py_DECREF(end_obj); + if (unlikely(slice == NULL)) { + return NULL; + } + PyObject *result = PyObject_GetItem(obj, slice); + Py_DECREF(slice); + return result; +} diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index 92fa3228d398..5c8fa42fc683 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -123,3 +123,19 @@ PyObject *CPySequence_Multiply(PyObject *seq, CPyTagged t_size) { PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq) { return CPySequence_Multiply(seq, t_size); } + +PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) { + if (likely(PyList_CheckExact(obj) + && CPyTagged_CheckShort(start) && CPyTagged_CheckShort(end))) { + Py_ssize_t startn = CPyTagged_ShortAsSsize_t(start); + Py_ssize_t endn = CPyTagged_ShortAsSsize_t(end); + if (startn < 0) { + startn += PyList_GET_SIZE(obj); + } + if (endn < 0) { + endn += PyList_GET_SIZE(obj); + } + return PyList_GetSlice(obj, startn, endn); + } + return CPyObject_GetSlice(obj, start, end); +} diff --git a/mypyc/lib-rt/setup.py b/mypyc/lib-rt/setup.py index c6df43ad11f2..482db5ded8f7 100644 --- a/mypyc/lib-rt/setup.py +++ b/mypyc/lib-rt/setup.py @@ -17,7 +17,7 @@ version='0.1', ext_modules=[Extension( 'test_capi', - ['test_capi.cc', 'init.c', 'int_ops.c', 'list_ops.c', 'exc_ops.c'], + ['test_capi.cc', 'init.c', 'int_ops.c', 'list_ops.c', 'exc_ops.c', 'generic_ops.c'], depends=['CPy.h', 'mypyc_util.h', 'pythonsupport.h'], extra_compile_args=['-Wno-unused-function', '-Wno-sign-compare'] + compile_args, library_dirs=['../external/googletest/make'], diff --git a/mypyc/lib-rt/str_ops.c b/mypyc/lib-rt/str_ops.c index 00835d6d81d2..fe892bb110b6 100644 --- a/mypyc/lib-rt/str_ops.c +++ b/mypyc/lib-rt/str_ops.c @@ -58,3 +58,25 @@ PyObject *CPyStr_Append(PyObject *o1, PyObject *o2) { PyUnicode_Append(&o1, o2); return o1; } + +PyObject *CPyStr_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) { + if (likely(PyUnicode_CheckExact(obj) + && CPyTagged_CheckShort(start) && CPyTagged_CheckShort(end))) { + Py_ssize_t startn = CPyTagged_ShortAsSsize_t(start); + Py_ssize_t endn = CPyTagged_ShortAsSsize_t(end); + if (startn < 0) { + startn += PyUnicode_GET_LENGTH(obj); + if (startn < 0) { + startn = 0; + } + } + if (endn < 0) { + endn += PyUnicode_GET_LENGTH(obj); + if (endn < 0) { + endn = 0; + } + } + return PyUnicode_Substring(obj, startn, endn); + } + return CPyObject_GetSlice(obj, start, end); +} diff --git a/mypyc/lib-rt/tuple_ops.c b/mypyc/lib-rt/tuple_ops.c index bd08f9bf172c..01f9c7ff951b 100644 --- a/mypyc/lib-rt/tuple_ops.c +++ b/mypyc/lib-rt/tuple_ops.c @@ -29,3 +29,19 @@ PyObject *CPySequenceTuple_GetItem(PyObject *tuple, CPyTagged index) { return NULL; } } + +PyObject *CPySequenceTuple_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) { + if (likely(PyTuple_CheckExact(obj) + && CPyTagged_CheckShort(start) && CPyTagged_CheckShort(end))) { + Py_ssize_t startn = CPyTagged_ShortAsSsize_t(start); + Py_ssize_t endn = CPyTagged_ShortAsSsize_t(end); + if (startn < 0) { + startn += PyTuple_GET_SIZE(obj); + } + if (endn < 0) { + endn += PyTuple_GET_SIZE(obj); + } + return PyTuple_GetSlice(obj, startn, endn); + } + return CPyObject_GetSlice(obj, start, end); +} diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index e295c247ad93..8a135dc394bf 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -128,3 +128,11 @@ def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: emitter.emit_declaration('Py_ssize_t %s;' % temp) emitter.emit_line('%s = PyList_GET_SIZE(%s);' % (temp, args[0])) emitter.emit_line('%s = CPyTagged_ShortFromSsize_t(%s);' % (dest, temp)) + + +# list[begin:end] +list_slice_op = c_custom_op( + arg_types=[list_rprimitive, int_rprimitive, int_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyList_GetSlice', + error_kind=ERR_MAGIC,) diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index 04b65e6d046c..2ca0b534c6bf 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -151,7 +151,8 @@ def custom_op(arg_types: List[RType], format_str: Optional[str] = None, steals: StealsDescription = False, is_borrowed: bool = False, - is_var_arg: bool = False) -> OpDescription: + is_var_arg: bool = False, + priority: int = 1) -> OpDescription: """Create a one-off op that can't be automatically generated from the AST. Note that if the format_str argument is not provided, then a @@ -174,7 +175,7 @@ def custom_op(arg_types: List[RType], typename) assert format_str is not None return OpDescription('', arg_types, result_type, is_var_arg, error_kind, format_str, - emit, steals, is_borrowed, 0) + emit, steals, is_borrowed, priority) def c_method_op(name: str, diff --git a/mypyc/primitives/str_ops.py b/mypyc/primitives/str_ops.py index e9d4461784dc..51b1056cdca2 100644 --- a/mypyc/primitives/str_ops.py +++ b/mypyc/primitives/str_ops.py @@ -79,9 +79,15 @@ error_kind=ERR_MAGIC, steals=[True, False]) - unicode_compare = c_custom_op( arg_types=[str_rprimitive, str_rprimitive], return_type=c_int_rprimitive, c_function_name='PyUnicode_Compare', error_kind=ERR_NEVER) + +# str[begin:end] +str_slice_op = c_custom_op( + arg_types=[str_rprimitive, int_rprimitive, int_rprimitive], + return_type=object_rprimitive, + c_function_name='CPyStr_GetSlice', + error_kind=ERR_MAGIC) diff --git a/mypyc/primitives/tuple_ops.py b/mypyc/primitives/tuple_ops.py index edd3d91a70a4..2a44fb65912d 100644 --- a/mypyc/primitives/tuple_ops.py +++ b/mypyc/primitives/tuple_ops.py @@ -8,9 +8,7 @@ from mypyc.ir.rtypes import ( tuple_rprimitive, int_rprimitive, list_rprimitive, object_rprimitive, c_pyssize_t_rprimitive ) -from mypyc.primitives.registry import ( - c_method_op, c_function_op, c_custom_op -) +from mypyc.primitives.registry import c_method_op, c_function_op, c_custom_op # tuple[index] (for an int index) @@ -45,3 +43,10 @@ return_type=tuple_rprimitive, c_function_name='PySequence_Tuple', error_kind=ERR_MAGIC) + +# tuple[begin:end] +tuple_slice_op = c_custom_op( + arg_types=[tuple_rprimitive, int_rprimitive, int_rprimitive], + return_type=object_rprimitive, + c_function_name='CPySequenceTuple_GetSlice', + error_kind=ERR_MAGIC) diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index e80ee29c29da..2050427a51d2 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -45,6 +45,9 @@ def __le__(self, n: int) -> bool: pass def __ge__(self, n: int) -> bool: pass class str: + @overload + def __init__(self) -> None: pass + @overload def __init__(self, x: object) -> None: pass def __add__(self, x: str) -> str: pass def __eq__(self, x: object) -> bool: pass @@ -53,7 +56,10 @@ def __lt__(self, x: str) -> bool: ... def __le__(self, x: str) -> bool: ... def __gt__(self, x: str) -> bool: ... def __ge__(self, x: str) -> bool: ... + @overload def __getitem__(self, i: int) -> str: pass + @overload + def __getitem__(self, i: slice) -> str: pass def __contains__(self, item: str) -> bool: pass def __iter__(self) -> Iterator[str]: ... def split(self, sep: Optional[str] = None, max: Optional[int] = None) -> List[str]: pass @@ -89,7 +95,10 @@ def __init__(self, o: object = ...) -> None: ... class tuple(Generic[T_co], Sequence[T_co], Iterable[T_co]): def __init__(self, i: Iterable[T_co]) -> None: pass + @overload def __getitem__(self, i: int) -> T_co: pass + @overload + def __getitem__(self, i: slice) -> Tuple[T_co, ...]: pass def __len__(self) -> int: pass def __iter__(self) -> Iterator[T_co]: ... def __contains__(self, item: object) -> int: ... diff --git a/mypyc/test-data/irbuild-basic.test b/mypyc/test-data/irbuild-basic.test index 831c5c512316..62a93e62c829 100644 --- a/mypyc/test-data/irbuild-basic.test +++ b/mypyc/test-data/irbuild-basic.test @@ -1114,7 +1114,35 @@ L0: r2 = PyNumber_Add(r0, r1) return r2 -[case testBigIntLiteral] +[case testBigIntLiteral_64bit] +def big_int() -> None: + a_62_bit = 4611686018427387902 + max_62_bit = 4611686018427387903 + b_63_bit = 4611686018427387904 + c_63_bit = 9223372036854775806 + max_63_bit = 9223372036854775807 + d_64_bit = 9223372036854775808 + max_32_bit = 2147483647 + max_31_bit = 1073741823 +[out] +def big_int(): + a_62_bit, max_62_bit, r0, b_63_bit, r1, c_63_bit, r2, max_63_bit, r3, d_64_bit, max_32_bit, max_31_bit :: int +L0: + a_62_bit = 9223372036854775804 + max_62_bit = 9223372036854775806 + r0 = load_global CPyStatic_int_1 :: static (4611686018427387904) + b_63_bit = r0 + r1 = load_global CPyStatic_int_2 :: static (9223372036854775806) + c_63_bit = r1 + r2 = load_global CPyStatic_int_3 :: static (9223372036854775807) + max_63_bit = r2 + r3 = load_global CPyStatic_int_4 :: static (9223372036854775808) + d_64_bit = r3 + max_32_bit = 4294967294 + max_31_bit = 2147483646 + return 1 + +[case testBigIntLiteral_32bit] def big_int() -> None: a_62_bit = 4611686018427387902 max_62_bit = 4611686018427387903 diff --git a/mypyc/test-data/run-lists.test b/mypyc/test-data/run-lists.test index 25fb993e601b..ed9cfa72c586 100644 --- a/mypyc/test-data/run-lists.test +++ b/mypyc/test-data/run-lists.test @@ -126,3 +126,26 @@ print(g()) [out] 6 7 + +[case testListOps] +def test_slicing() -> None: + # Use dummy adds to avoid constant folding + zero = int() + two = zero + 2 + s = ["f", "o", "o", "b", "a", "r"] + assert s[two:] == ["o", "b", "a", "r"] + assert s[:two] == ["f", "o"] + assert s[two:-two] == ["o", "b"] + assert s[two:two] == [] + assert s[two:two + 1] == ["o"] + assert s[-two:] == ["a", "r"] + assert s[:-two] == ["f", "o", "o", "b"] + assert s[:] == ["f", "o", "o", "b", "a", "r"] + assert s[two:333] == ["o", "b", "a", "r"] + assert s[333:two] == [] + assert s[two:-333] == [] + assert s[-333:two] == ["f", "o"] + long_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 + assert s[1:long_int] == ["o", "o", "b", "a", "r"] + assert s[long_int:] == [] + assert s[-long_int:-1] == ["f", "o", "o", "b", "a"] diff --git a/mypyc/test-data/run-strings.test b/mypyc/test-data/run-strings.test index 0208b534c0a2..50960aeac1c4 100644 --- a/mypyc/test-data/run-strings.test +++ b/mypyc/test-data/run-strings.test @@ -117,3 +117,25 @@ def test_str_to_int() -> None: assert str_to_int("1a", 16) == 26 with assertRaises(ValueError, "invalid literal for int() with base 10: 'xyz'"): str_to_int("xyz") + +def test_slicing() -> None: + # Use dummy adds to avoid constant folding + zero = int() + two = zero + 2 + s = "foobar" + str() + assert s[two:] == "obar" + assert s[:two] == "fo" + assert s[two:-two] == "ob" + assert s[two:two] == "" + assert s[two:two + 1] == "o" + assert s[-two:] == "ar" + assert s[:-two] == "foob" + assert s[:] == "foobar" + assert s[two:333] == "obar" + assert s[333:two] == "" + assert s[two:-333] == "" + assert s[-333:two] == "fo" + big_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 + assert s[1:big_int] == "oobar" + assert s[big_int:] == "" + assert s[-big_int:-1] == "fooba" diff --git a/mypyc/test-data/run-tuples.test b/mypyc/test-data/run-tuples.test index adfe3063b9da..addccc767f66 100644 --- a/mypyc/test-data/run-tuples.test +++ b/mypyc/test-data/run-tuples.test @@ -156,3 +156,25 @@ def foo(x: bool, y: bool) -> Tuple[Optional[A], bool]: z = lol() return None if y else z, x + +def test_slicing() -> None: + # Use dummy adds to avoid constant folding + zero = int() + two = zero + 2 + s: Tuple[str, ...] = ("f", "o", "o", "b", "a", "r") + assert s[two:] == ("o", "b", "a", "r") + assert s[:two] == ("f", "o") + assert s[two:-two] == ("o", "b") + assert s[two:two] == () + assert s[two:two + 1] == ("o",) + assert s[-two:] == ("a", "r") + assert s[:-two] == ("f", "o", "o", "b") + assert s[:] == ("f", "o", "o", "b", "a", "r") + assert s[two:333] == ("o", "b", "a", "r") + assert s[333:two] == () + assert s[two:-333] == () + assert s[-333:two] == ("f", "o") + long_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 + assert s[1:long_int] == ("o", "o", "b", "a", "r") + assert s[long_int:] == () + assert s[-long_int:-1] == ("f", "o", "o", "b", "a") diff --git a/mypyc/test/test_irbuild.py b/mypyc/test/test_irbuild.py index adc7a66f9462..bb2f34ed0503 100644 --- a/mypyc/test/test_irbuild.py +++ b/mypyc/test/test_irbuild.py @@ -6,7 +6,7 @@ from mypy.test.data import DataDrivenTestCase from mypy.errors import CompileError -from mypyc.common import TOP_LEVEL_NAME +from mypyc.common import TOP_LEVEL_NAME, IS_32_BIT_PLATFORM from mypyc.ir.func_ir import format_func from mypyc.test.testutil import ( ICODE_GEN_BUILTINS, use_custom_builtins, MypycDataSuite, build_ir_for_single_file, @@ -46,6 +46,12 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: expected_output = remove_comment_lines(testcase.output) expected_output = replace_native_int(expected_output) expected_output = replace_word_size(expected_output) + name = testcase.name + # If this is specific to some bit width, always pass if platform doesn't match. + if name.endswith('_64bit') and IS_32_BIT_PLATFORM: + return + if name.endswith('_32bit') and not IS_32_BIT_PLATFORM: + return try: ir = build_ir_for_single_file(testcase.input, options) except CompileError as e: @@ -54,7 +60,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: actual = [] for fn in ir: if (fn.name == TOP_LEVEL_NAME - and not testcase.name.endswith('_toplevel')): + and not name.endswith('_toplevel')): continue actual.extend(format_func(fn))