Skip to content

Commit

Permalink
[mypyc] Refactor: add two list primitive ops (#17058)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JukkaL authored Mar 25, 2024
1 parent 5db161f commit 433e8c9
Show file tree
Hide file tree
Showing 20 changed files with 883 additions and 979 deletions.
19 changes: 10 additions & 9 deletions mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,8 @@
int_op_to_id,
)
from mypyc.ir.rtypes import (
PyListObject,
PyObject,
PySetObject,
PyVarObject,
RArray,
RInstance,
RPrimitive,
Expand Down Expand Up @@ -163,8 +161,14 @@
ssize_t_to_int_op,
uint8_overflow,
)
from mypyc.primitives.list_ops import list_build_op, list_extend_op, new_list_op
from mypyc.primitives.misc_ops import bool_op, buf_init_item, fast_isinstance_op, none_object_op
from mypyc.primitives.list_ops import list_build_op, list_extend_op, list_items, new_list_op
from mypyc.primitives.misc_ops import (
bool_op,
buf_init_item,
fast_isinstance_op,
none_object_op,
var_object_size,
)
from mypyc.primitives.registry import (
ERR_NEG_INT,
CFunctionDescription,
Expand Down Expand Up @@ -1623,8 +1627,7 @@ def new_list_op(self, values: list[Value], line: int) -> Value:
if not values:
return result_list
args = [self.coerce(item, object_rprimitive, line) for item in values]
ob_item_ptr = self.add(GetElementPtr(result_list, PyListObject, "ob_item", line))
ob_item_base = self.add(LoadMem(pointer_rprimitive, ob_item_ptr, line))
ob_item_base = self.add(PrimitiveOp([result_list], list_items, line))
for i in range(len(values)):
self.primitive_op(
buf_init_item, [ob_item_base, Integer(i, c_pyssize_t_rprimitive), args[i]], line
Expand Down Expand Up @@ -2165,9 +2168,7 @@ def builtin_len(self, val: Value, line: int, use_pyssize_t: bool = False) -> Val
typ = val.type
size_value = None
if is_list_rprimitive(typ) or is_tuple_rprimitive(typ) or is_bytes_rprimitive(typ):
elem_address = self.add(GetElementPtr(val, PyVarObject, "ob_size"))
size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address))
self.add(KeepAlive([val]))
size_value = self.primitive_op(var_object_size, [val], line)
elif is_set_rprimitive(typ):
elem_address = self.add(GetElementPtr(val, PySetObject, "used"))
size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address))
Expand Down
15 changes: 13 additions & 2 deletions mypyc/lower/list_ops.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
from __future__ import annotations

from mypyc.common import PLATFORM_SIZE
from mypyc.ir.ops import Integer, IntOp, SetMem, Value
from mypyc.ir.rtypes import c_pyssize_t_rprimitive, object_rprimitive, pointer_rprimitive
from mypyc.ir.ops import GetElementPtr, Integer, IntOp, LoadMem, SetMem, Value
from mypyc.ir.rtypes import (
PyListObject,
c_pyssize_t_rprimitive,
object_rprimitive,
pointer_rprimitive,
)
from mypyc.irbuild.ll_builder import LowLevelIRBuilder
from mypyc.lower.registry import lower_primitive_op

Expand Down Expand Up @@ -32,3 +37,9 @@ def buf_init_item(builder: LowLevelIRBuilder, args: list[Value], line: int) -> V
)
)
return builder.add(SetMem(object_rprimitive, ptr, value, line))


@lower_primitive_op("list_items")
def list_items(builder: LowLevelIRBuilder, args: list[Value], line: int) -> Value:
ob_item_ptr = builder.add(GetElementPtr(args[0], PyListObject, "ob_item", line))
return builder.add(LoadMem(pointer_rprimitive, ob_item_ptr, line))
12 changes: 12 additions & 0 deletions mypyc/lower/misc_ops.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from __future__ import annotations

from mypyc.ir.ops import GetElementPtr, LoadMem, Value
from mypyc.ir.rtypes import PyVarObject, c_pyssize_t_rprimitive
from mypyc.irbuild.ll_builder import LowLevelIRBuilder
from mypyc.lower.registry import lower_primitive_op


@lower_primitive_op("var_object_size")
def var_object_size(builder: LowLevelIRBuilder, args: list[Value], line: int) -> Value:
elem_address = builder.add(GetElementPtr(args[0], PyVarObject, "ob_size"))
return builder.add(LoadMem(c_pyssize_t_rprimitive, elem_address))
3 changes: 1 addition & 2 deletions mypyc/lower/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ def wrapper(f: LowerFunc) -> LowerFunc:


# Import various modules that set up global state.
import mypyc.lower.int_ops
import mypyc.lower.list_ops # noqa: F401
from mypyc.lower import int_ops, list_ops, misc_ops # noqa: F401
10 changes: 10 additions & 0 deletions mypyc/primitives/list_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
int_rprimitive,
list_rprimitive,
object_rprimitive,
pointer_rprimitive,
short_int_rprimitive,
)
from mypyc.primitives.registry import (
ERR_NEG_INT,
binary_op,
custom_op,
custom_primitive_op,
function_op,
load_address_op,
method_op,
Expand Down Expand Up @@ -60,6 +62,14 @@
steals=True,
)

# Get pointer to list items (ob_item PyListObject field)
list_items = custom_primitive_op(
name="list_items",
arg_types=[list_rprimitive],
return_type=pointer_rprimitive,
error_kind=ERR_NEVER,
)

# list[index] (for an integer index)
list_get_item_op = method_op(
name="__getitem__",
Expand Down
8 changes: 8 additions & 0 deletions mypyc/primitives/misc_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,11 @@
error_kind=ERR_NEVER,
steals=[False, False, True],
)

# Get length of PyVarObject instance (e.g. list or tuple)
var_object_size = custom_primitive_op(
name="var_object_size",
arg_types=[object_rprimitive],
return_type=c_pyssize_t_rprimitive,
error_kind=ERR_NEVER,
)
9 changes: 4 additions & 5 deletions mypyc/test-data/irbuild-any.test
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def f2(a, n, l):
r9, r10 :: bit
r11 :: list
r12 :: object
r13, r14 :: ptr
r13 :: ptr
L0:
r0 = box(int, n)
r1 = PyObject_GetItem(a, r0)
Expand All @@ -121,10 +121,9 @@ L0:
r10 = CPyList_SetItem(l, n, a)
r11 = PyList_New(2)
r12 = box(int, n)
r13 = get_element_ptr r11 ob_item :: PyListObject
r14 = load_mem r13 :: ptr*
buf_init_item r14, 0, a
buf_init_item r14, 1, r12
r13 = list_items r11
buf_init_item r13, 0, a
buf_init_item r13, 1, r12
keep_alive r11
return 1
def f3(a, n):
Expand Down
Loading

0 comments on commit 433e8c9

Please sign in to comment.