Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d066e44

Browse files
authored
[mypyc] Merge new_list_op and new_set_op (#9378)
This PR builds new_list_op in irbuild. For empty list, we introduce a c_custom_op to do the job. To set the following list item, we rely on pointer addition and SetMem.
1 parent d7553fe commit d066e44

22 files changed

Lines changed: 492 additions & 346 deletions

mypyc/codegen/emitfunc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,11 +481,11 @@ def visit_load_mem(self, op: LoadMem) -> None:
481481
def visit_set_mem(self, op: SetMem) -> None:
482482
dest = self.reg(op.dest)
483483
src = self.reg(op.src)
484-
type = self.ctype(op.type)
484+
dest_type = self.ctype(op.dest_type)
485485
# clang whines about self assignment (which we might generate
486486
# for some casts), so don't emit it.
487487
if dest != src:
488-
self.emit_line('*(%s *)%s = %s;' % (type, dest, src))
488+
self.emit_line('*(%s *)%s = %s;' % (dest_type, dest, src))
489489

490490
def visit_get_element_ptr(self, op: GetElementPtr) -> None:
491491
dest = self.reg(op)

mypyc/ir/ops.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,12 +1433,13 @@ class SetMem(Op):
14331433

14341434
def __init__(self,
14351435
type: RType,
1436-
dest: Register,
1436+
dest: Value,
14371437
src: Value,
14381438
base: Optional[Value],
14391439
line: int = -1) -> None:
14401440
super().__init__(line)
1441-
self.type = type
1441+
self.type = void_rtype
1442+
self.dest_type = type
14421443
self.src = src
14431444
self.dest = dest
14441445
self.base = base
@@ -1457,7 +1458,7 @@ def to_str(self, env: Environment) -> str:
14571458
base = env.format(', %r', self.base)
14581459
else:
14591460
base = ''
1460-
return env.format("%r = set_mem %r%s :: %r*", self.dest, self.src, base, self.type)
1461+
return env.format("set_mem %r, %r%s :: %r*", self.dest, self.src, base, self.dest_type)
14611462

14621463
def accept(self, visitor: 'OpVisitor[T]') -> T:
14631464
return visitor.visit_set_mem(self)

mypyc/ir/rtypes.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,9 @@ def is_optional_type(rtype: RType) -> bool:
699699
types=[PyObject, c_pyssize_t_rprimitive, c_pyssize_t_rprimitive, c_pyssize_t_rprimitive,
700700
pointer_rprimitive, c_pyssize_t_rprimitive, c_pyssize_t_rprimitive, smalltable,
701701
pointer_rprimitive])
702+
703+
PyListObject = RStruct(
704+
name='PyListObject',
705+
names=['ob_base', 'ob_item', 'allocated'],
706+
types=[PyObject, pointer_rprimitive, c_pyssize_t_rprimitive]
707+
)

mypyc/irbuild/builder.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ def true(self) -> Value:
209209
def false(self) -> Value:
210210
return self.builder.false()
211211

212+
def new_list_op(self, values: List[Value], line: int) -> Value:
213+
return self.builder.new_list_op(values, line)
214+
215+
def new_set_op(self, values: List[Value], line: int) -> Value:
216+
return self.builder.new_set_op(values, line)
217+
212218
def translate_is_op(self,
213219
lreg: Value,
214220
rreg: Value,

mypyc/irbuild/expression.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
and mypyc.irbuild.builder.
55
"""
66

7-
from typing import List, Optional, Union
7+
from typing import List, Optional, Union, Callable
88

99
from mypy.nodes import (
1010
Expression, NameExpr, MemberExpr, SuperExpr, CallExpr, UnaryExpr, OpExpr, IndexExpr,
@@ -16,14 +16,14 @@
1616
from mypy.types import TupleType, get_proper_type
1717

1818
from mypyc.ir.ops import (
19-
Value, TupleGet, TupleSet, BasicBlock, OpDescription, Assign, LoadAddress
19+
Value, TupleGet, TupleSet, BasicBlock, Assign, LoadAddress
2020
)
2121
from mypyc.ir.rtypes import RTuple, object_rprimitive, is_none_rprimitive, is_int_rprimitive
2222
from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD
2323
from mypyc.primitives.registry import CFunctionDescription, builtin_names
2424
from mypyc.primitives.generic_ops import iter_op
2525
from mypyc.primitives.misc_ops import new_slice_op, ellipsis_op, type_op
26-
from mypyc.primitives.list_ops import new_list_op, list_append_op, list_extend_op
26+
from mypyc.primitives.list_ops import list_append_op, list_extend_op
2727
from mypyc.primitives.tuple_ops import list_tuple_op
2828
from mypyc.primitives.dict_ops import dict_new_op, dict_set_item_op
2929
from mypyc.primitives.set_ops import new_set_op, set_add_op, set_update_op
@@ -443,10 +443,11 @@ def _visit_list_display(builder: IRBuilder, items: List[Expression], line: int)
443443
return _visit_display(
444444
builder,
445445
items,
446-
new_list_op,
446+
builder.new_list_op,
447447
list_append_op,
448448
list_extend_op,
449-
line
449+
line,
450+
True
450451
)
451452

452453

@@ -490,19 +491,21 @@ def transform_set_expr(builder: IRBuilder, expr: SetExpr) -> Value:
490491
return _visit_display(
491492
builder,
492493
expr.items,
493-
new_set_op,
494+
builder.new_set_op,
494495
set_add_op,
495496
set_update_op,
496-
expr.line
497+
expr.line,
498+
False
497499
)
498500

499501

500502
def _visit_display(builder: IRBuilder,
501503
items: List[Expression],
502-
constructor_op: OpDescription,
504+
constructor_op: Callable[[List[Value], int], Value],
503505
append_op: CFunctionDescription,
504506
extend_op: CFunctionDescription,
505-
line: int
507+
line: int,
508+
is_list: bool
506509
) -> Value:
507510
accepted_items = []
508511
for item in items:
@@ -514,17 +517,17 @@ def _visit_display(builder: IRBuilder,
514517
result = None # type: Union[Value, None]
515518
initial_items = []
516519
for starred, value in accepted_items:
517-
if result is None and not starred and constructor_op.is_var_arg:
520+
if result is None and not starred and is_list:
518521
initial_items.append(value)
519522
continue
520523

521524
if result is None:
522-
result = builder.primitive_op(constructor_op, initial_items, line)
525+
result = constructor_op(initial_items, line)
523526

524527
builder.call_c(extend_op if starred else append_op, [result, value], line)
525528

526529
if result is None:
527-
result = builder.primitive_op(constructor_op, initial_items, line)
530+
result = constructor_op(initial_items, line)
528531

529532
return result
530533

@@ -538,7 +541,7 @@ def transform_list_comprehension(builder: IRBuilder, o: ListComprehension) -> Va
538541

539542
def transform_set_comprehension(builder: IRBuilder, o: SetComprehension) -> Value:
540543
gen = o.generator
541-
set_ops = builder.primitive_op(new_set_op, [], o.line)
544+
set_ops = builder.call_c(new_set_op, [], o.line)
542545
loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))
543546

544547
def gen_inner_stmts() -> None:

mypyc/irbuild/for_helpers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
dict_next_key_op, dict_next_value_op, dict_next_item_op, dict_check_size_op,
2525
dict_key_iter_op, dict_value_iter_op, dict_item_iter_op
2626
)
27-
from mypyc.primitives.list_ops import new_list_op, list_append_op, list_get_item_unsafe_op
27+
from mypyc.primitives.list_ops import list_append_op, list_get_item_unsafe_op
2828
from mypyc.primitives.generic_ops import iter_op, next_op
2929
from mypyc.primitives.exc_ops import no_err_occurred_op
3030
from mypyc.irbuild.builder import IRBuilder
@@ -87,7 +87,7 @@ def for_loop_helper(builder: IRBuilder, index: Lvalue, expr: Expression,
8787

8888

8989
def translate_list_comprehension(builder: IRBuilder, gen: GeneratorExpr) -> Value:
90-
list_ops = builder.primitive_op(new_list_op, [], gen.line)
90+
list_ops = builder.new_list_op([], gen.line)
9191
loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))
9292

9393
def gen_inner_stmts() -> None:

mypyc/irbuild/ll_builder.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,21 @@
2222
LoadStatic, MethodCall, PrimitiveOp, OpDescription, RegisterOp, CallC, Truncate,
2323
RaiseStandardError, Unreachable, LoadErrorValue, LoadGlobal,
2424
NAMESPACE_TYPE, NAMESPACE_MODULE, NAMESPACE_STATIC, BinaryIntOp, GetElementPtr,
25-
LoadMem, ComparisonOp, LoadAddress, TupleGet
25+
LoadMem, ComparisonOp, LoadAddress, TupleGet, SetMem
2626
)
2727
from mypyc.ir.rtypes import (
2828
RType, RUnion, RInstance, optional_value_type, int_rprimitive, float_rprimitive,
2929
bool_rprimitive, list_rprimitive, str_rprimitive, is_none_rprimitive, object_rprimitive,
3030
c_pyssize_t_rprimitive, is_short_int_rprimitive, is_tagged, PyVarObject, short_int_rprimitive,
3131
is_list_rprimitive, is_tuple_rprimitive, is_dict_rprimitive, is_set_rprimitive, PySetObject,
3232
none_rprimitive, RTuple, is_bool_rprimitive, is_str_rprimitive, c_int_rprimitive,
33-
pointer_rprimitive
33+
pointer_rprimitive, PyListObject
3434
)
3535
from mypyc.ir.func_ir import FuncDecl, FuncSignature
3636
from mypyc.ir.class_ir import ClassIR, all_concrete_classes
3737
from mypyc.common import (
3838
FAST_ISINSTANCE_MAX_SUBCLASSES, MAX_LITERAL_SHORT_INT,
39-
STATIC_PREFIX
39+
STATIC_PREFIX, PLATFORM_SIZE
4040
)
4141
from mypyc.primitives.registry import (
4242
func_ops, c_method_call_ops, CFunctionDescription, c_function_ops,
@@ -58,6 +58,7 @@
5858
from mypyc.primitives.int_ops import int_comparison_op_mapping
5959
from mypyc.primitives.exc_ops import err_occurred_op, keep_propagating_op
6060
from mypyc.primitives.str_ops import unicode_compare
61+
from mypyc.primitives.set_ops import new_set_op
6162
from mypyc.rt_subtype import is_runtime_subtype
6263
from mypyc.subtype import is_subtype
6364
from mypyc.sametype import is_same_type
@@ -273,7 +274,7 @@ def py_call(self,
273274
else:
274275
# Otherwise we construct a list and call extend it with the star args, since tuples
275276
# don't have an extend method.
276-
pos_args_list = self.primitive_op(new_list_op, pos_arg_values, line)
277+
pos_args_list = self.new_list_op(pos_arg_values, line)
277278
for star_arg_value in star_arg_values:
278279
self.call_c(list_extend_op, [pos_args_list, star_arg_value], line)
279280
pos_args_tuple = self.call_c(list_tuple_op, [pos_args_list], line)
@@ -755,6 +756,27 @@ def make_dict(self, key_value_pairs: Sequence[DictEntry], line: int) -> Value:
755756

756757
return result
757758

759+
def new_list_op(self, values: List[Value], line: int) -> Value:
760+
length = self.add(LoadInt(len(values), line, rtype=c_pyssize_t_rprimitive))
761+
result_list = self.call_c(new_list_op, [length], line)
762+
if len(values) == 0:
763+
return result_list
764+
args = [self.coerce(item, object_rprimitive, line) for item in values]
765+
ob_item_ptr = self.add(GetElementPtr(result_list, PyListObject, 'ob_item', line))
766+
ob_item_base = self.add(LoadMem(pointer_rprimitive, ob_item_ptr, result_list, line))
767+
for i in range(len(values)):
768+
if i == 0:
769+
item_address = ob_item_base
770+
else:
771+
offset = self.add(LoadInt(PLATFORM_SIZE * i, line, rtype=c_pyssize_t_rprimitive))
772+
item_address = self.add(BinaryIntOp(pointer_rprimitive, ob_item_base, offset,
773+
BinaryIntOp.ADD, line))
774+
self.add(SetMem(object_rprimitive, item_address, args[i], result_list, line))
775+
return result_list
776+
777+
def new_set_op(self, values: List[Value], line: int) -> Value:
778+
return self.call_c(new_set_op, values, line)
779+
758780
def builtin_call(self,
759781
args: List[Value],
760782
fn_op: str,

mypyc/primitives/list_ops.py

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER, ERR_FALSE, ERR_NEG_INT, EmitterInterface
66
from mypyc.ir.rtypes import (
77
int_rprimitive, short_int_rprimitive, list_rprimitive, object_rprimitive, bool_rprimitive,
8-
c_int_rprimitive
8+
c_int_rprimitive, c_pyssize_t_rprimitive
99
)
1010
from mypyc.primitives.registry import (
11-
custom_op, load_address_op, c_function_op, c_binary_op, c_method_op, c_custom_op
11+
load_address_op, c_function_op, c_binary_op, c_method_op, c_custom_op
1212
)
1313

1414

@@ -27,25 +27,11 @@
2727
error_kind=ERR_MAGIC,
2828
)
2929

30-
31-
def emit_new(emitter: EmitterInterface, args: List[str], dest: str) -> None:
32-
# TODO: This would be better split into multiple smaller ops.
33-
emitter.emit_line('%s = PyList_New(%d); ' % (dest, len(args)))
34-
emitter.emit_line('if (likely(%s != NULL)) {' % dest)
35-
for i, arg in enumerate(args):
36-
emitter.emit_line('PyList_SET_ITEM(%s, %s, %s);' % (dest, i, arg))
37-
emitter.emit_line('}')
38-
39-
40-
# Construct a list from values: [item1, item2, ....]
41-
new_list_op = custom_op(arg_types=[object_rprimitive],
42-
result_type=list_rprimitive,
43-
is_var_arg=True,
44-
error_kind=ERR_MAGIC,
45-
steals=True,
46-
format_str='{dest} = [{comma_args}]',
47-
emit=emit_new)
48-
30+
new_list_op = c_custom_op(
31+
arg_types=[c_pyssize_t_rprimitive],
32+
return_type=list_rprimitive,
33+
c_function_name='PyList_New',
34+
error_kind=ERR_MAGIC)
4935

5036
# list[index] (for an integer index)
5137
list_get_item_op = c_method_op(

mypyc/primitives/set_ops.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
"""Primitive set (and frozenset) ops."""
22

33
from mypyc.primitives.registry import (
4-
func_op, simple_emit, c_function_op, c_method_op, c_binary_op
4+
c_function_op, c_method_op, c_binary_op
55
)
66
from mypyc.ir.ops import ERR_MAGIC, ERR_FALSE, ERR_NEG_INT
77
from mypyc.ir.rtypes import (
8-
object_rprimitive, bool_rprimitive, set_rprimitive, c_int_rprimitive
8+
object_rprimitive, bool_rprimitive, set_rprimitive, c_int_rprimitive, pointer_rprimitive
99
)
1010

1111

1212
# Construct an empty set.
13-
new_set_op = func_op(
13+
new_set_op = c_function_op(
1414
name='builtins.set',
1515
arg_types=[],
16-
result_type=set_rprimitive,
16+
return_type=set_rprimitive,
17+
c_function_name='PySet_New',
1718
error_kind=ERR_MAGIC,
18-
emit=simple_emit('{dest} = PySet_New(NULL);')
19-
)
19+
extra_int_constants=[(0, pointer_rprimitive)])
2020

2121
# set(obj)
2222
c_function_op(

mypyc/test-data/irbuild-any.test

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ def f2(a, n, l):
101101
r6 :: object
102102
r7 :: int32
103103
r8 :: bool
104-
r9 :: object
105-
r10 :: list
104+
r9 :: list
105+
r10 :: object
106+
r11, r12, r13 :: ptr
106107
L0:
107108
r0 = box(int, n)
108109
r1 = PyObject_GetItem(a, r0)
@@ -113,8 +114,13 @@ L0:
113114
r6 = box(int, n)
114115
r7 = PyObject_SetItem(l, a, r6)
115116
r8 = CPyList_SetItem(l, n, a)
116-
r9 = box(int, n)
117-
r10 = [a, r9]
117+
r9 = PyList_New(2)
118+
r10 = box(int, n)
119+
r11 = get_element_ptr r9 ob_item :: PyListObject
120+
r12 = load_mem r11, r9 :: ptr*
121+
set_mem r12, a, r9 :: builtins.object*
122+
r13 = r12 + WORD_SIZE*1
123+
set_mem r13, r10, r9 :: builtins.object*
118124
return 1
119125
def f3(a, n):
120126
a :: object

0 commit comments

Comments
 (0)