Skip to content

Commit 433e8c9

Browse files
authored
[mypyc] Refactor: add two list primitive ops (#17058)
Add ops for getting list size and a pointer to list item data. This simplifies the IR generated in the main irbuild pass. Continue work on mypyc/mypyc#854.
1 parent 5db161f commit 433e8c9

20 files changed

+883
-979
lines changed

mypyc/irbuild/ll_builder.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,8 @@
7878
int_op_to_id,
7979
)
8080
from mypyc.ir.rtypes import (
81-
PyListObject,
8281
PyObject,
8382
PySetObject,
84-
PyVarObject,
8583
RArray,
8684
RInstance,
8785
RPrimitive,
@@ -163,8 +161,14 @@
163161
ssize_t_to_int_op,
164162
uint8_overflow,
165163
)
166-
from mypyc.primitives.list_ops import list_build_op, list_extend_op, new_list_op
167-
from mypyc.primitives.misc_ops import bool_op, buf_init_item, fast_isinstance_op, none_object_op
164+
from mypyc.primitives.list_ops import list_build_op, list_extend_op, list_items, new_list_op
165+
from mypyc.primitives.misc_ops import (
166+
bool_op,
167+
buf_init_item,
168+
fast_isinstance_op,
169+
none_object_op,
170+
var_object_size,
171+
)
168172
from mypyc.primitives.registry import (
169173
ERR_NEG_INT,
170174
CFunctionDescription,
@@ -1623,8 +1627,7 @@ def new_list_op(self, values: list[Value], line: int) -> Value:
16231627
if not values:
16241628
return result_list
16251629
args = [self.coerce(item, object_rprimitive, line) for item in values]
1626-
ob_item_ptr = self.add(GetElementPtr(result_list, PyListObject, "ob_item", line))
1627-
ob_item_base = self.add(LoadMem(pointer_rprimitive, ob_item_ptr, line))
1630+
ob_item_base = self.add(PrimitiveOp([result_list], list_items, line))
16281631
for i in range(len(values)):
16291632
self.primitive_op(
16301633
buf_init_item, [ob_item_base, Integer(i, c_pyssize_t_rprimitive), args[i]], line
@@ -2165,9 +2168,7 @@ def builtin_len(self, val: Value, line: int, use_pyssize_t: bool = False) -> Val
21652168
typ = val.type
21662169
size_value = None
21672170
if is_list_rprimitive(typ) or is_tuple_rprimitive(typ) or is_bytes_rprimitive(typ):
2168-
elem_address = self.add(GetElementPtr(val, PyVarObject, "ob_size"))
2169-
size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address))
2170-
self.add(KeepAlive([val]))
2171+
size_value = self.primitive_op(var_object_size, [val], line)
21712172
elif is_set_rprimitive(typ):
21722173
elem_address = self.add(GetElementPtr(val, PySetObject, "used"))
21732174
size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address))

mypyc/lower/list_ops.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
from __future__ import annotations
22

33
from mypyc.common import PLATFORM_SIZE
4-
from mypyc.ir.ops import Integer, IntOp, SetMem, Value
5-
from mypyc.ir.rtypes import c_pyssize_t_rprimitive, object_rprimitive, pointer_rprimitive
4+
from mypyc.ir.ops import GetElementPtr, Integer, IntOp, LoadMem, SetMem, Value
5+
from mypyc.ir.rtypes import (
6+
PyListObject,
7+
c_pyssize_t_rprimitive,
8+
object_rprimitive,
9+
pointer_rprimitive,
10+
)
611
from mypyc.irbuild.ll_builder import LowLevelIRBuilder
712
from mypyc.lower.registry import lower_primitive_op
813

@@ -32,3 +37,9 @@ def buf_init_item(builder: LowLevelIRBuilder, args: list[Value], line: int) -> V
3237
)
3338
)
3439
return builder.add(SetMem(object_rprimitive, ptr, value, line))
40+
41+
42+
@lower_primitive_op("list_items")
43+
def list_items(builder: LowLevelIRBuilder, args: list[Value], line: int) -> Value:
44+
ob_item_ptr = builder.add(GetElementPtr(args[0], PyListObject, "ob_item", line))
45+
return builder.add(LoadMem(pointer_rprimitive, ob_item_ptr, line))

mypyc/lower/misc_ops.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from __future__ import annotations
2+
3+
from mypyc.ir.ops import GetElementPtr, LoadMem, Value
4+
from mypyc.ir.rtypes import PyVarObject, c_pyssize_t_rprimitive
5+
from mypyc.irbuild.ll_builder import LowLevelIRBuilder
6+
from mypyc.lower.registry import lower_primitive_op
7+
8+
9+
@lower_primitive_op("var_object_size")
10+
def var_object_size(builder: LowLevelIRBuilder, args: list[Value], line: int) -> Value:
11+
elem_address = builder.add(GetElementPtr(args[0], PyVarObject, "ob_size"))
12+
return builder.add(LoadMem(c_pyssize_t_rprimitive, elem_address))

mypyc/lower/registry.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,4 @@ def wrapper(f: LowerFunc) -> LowerFunc:
2323

2424

2525
# Import various modules that set up global state.
26-
import mypyc.lower.int_ops
27-
import mypyc.lower.list_ops # noqa: F401
26+
from mypyc.lower import int_ops, list_ops, misc_ops # noqa: F401

mypyc/primitives/list_ops.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
int_rprimitive,
1212
list_rprimitive,
1313
object_rprimitive,
14+
pointer_rprimitive,
1415
short_int_rprimitive,
1516
)
1617
from mypyc.primitives.registry import (
1718
ERR_NEG_INT,
1819
binary_op,
1920
custom_op,
21+
custom_primitive_op,
2022
function_op,
2123
load_address_op,
2224
method_op,
@@ -60,6 +62,14 @@
6062
steals=True,
6163
)
6264

65+
# Get pointer to list items (ob_item PyListObject field)
66+
list_items = custom_primitive_op(
67+
name="list_items",
68+
arg_types=[list_rprimitive],
69+
return_type=pointer_rprimitive,
70+
error_kind=ERR_NEVER,
71+
)
72+
6373
# list[index] (for an integer index)
6474
list_get_item_op = method_op(
6575
name="__getitem__",

mypyc/primitives/misc_ops.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,11 @@
257257
error_kind=ERR_NEVER,
258258
steals=[False, False, True],
259259
)
260+
261+
# Get length of PyVarObject instance (e.g. list or tuple)
262+
var_object_size = custom_primitive_op(
263+
name="var_object_size",
264+
arg_types=[object_rprimitive],
265+
return_type=c_pyssize_t_rprimitive,
266+
error_kind=ERR_NEVER,
267+
)

mypyc/test-data/irbuild-any.test

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def f2(a, n, l):
106106
r9, r10 :: bit
107107
r11 :: list
108108
r12 :: object
109-
r13, r14 :: ptr
109+
r13 :: ptr
110110
L0:
111111
r0 = box(int, n)
112112
r1 = PyObject_GetItem(a, r0)
@@ -121,10 +121,9 @@ L0:
121121
r10 = CPyList_SetItem(l, n, a)
122122
r11 = PyList_New(2)
123123
r12 = box(int, n)
124-
r13 = get_element_ptr r11 ob_item :: PyListObject
125-
r14 = load_mem r13 :: ptr*
126-
buf_init_item r14, 0, a
127-
buf_init_item r14, 1, r12
124+
r13 = list_items r11
125+
buf_init_item r13, 0, a
126+
buf_init_item r13, 1, r12
128127
keep_alive r11
129128
return 1
130129
def f3(a, n):

0 commit comments

Comments
 (0)