Skip to content

Commit

Permalink
[mypyc] Merge most name_ref_op with LoadAddress (#9293)
Browse files Browse the repository at this point in the history
This PR replaces name_ref_op: int, str, list, type, NotImplemented with LoadAddress.

The only three remaining name_ref_ops are true, false and none, which should be 
built directly in irbuild
  • Loading branch information
TH3CHARLie authored Aug 12, 2020
1 parent d94853d commit b34f4c6
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 74 deletions.
12 changes: 7 additions & 5 deletions mypyc/irbuild/classdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
)
from mypyc.ir.ops import (
Value, Call, LoadErrorValue, LoadStatic, InitStatic, TupleSet, SetAttr, Return,
BasicBlock, Branch, MethodCall, NAMESPACE_TYPE
BasicBlock, Branch, MethodCall, NAMESPACE_TYPE, LoadAddress
)
from mypyc.ir.rtypes import (
RInstance, object_rprimitive, bool_rprimitive, dict_rprimitive, is_optional_type,
Expand Down Expand Up @@ -227,7 +227,8 @@ def find_non_ext_metaclass(builder: IRBuilder, cdef: ClassDef, bases: Value) ->
if cdef.metaclass:
declared_metaclass = builder.accept(cdef.metaclass)
else:
declared_metaclass = builder.primitive_op(type_object_op, [], cdef.line)
declared_metaclass = builder.add(LoadAddress(type_object_op.type,
type_object_op.src, cdef.line))

return builder.primitive_op(py_calc_meta_op, [declared_metaclass, bases], cdef.line)

Expand Down Expand Up @@ -279,7 +280,7 @@ def add_non_ext_class_attr(builder: IRBuilder,
# which attributes to compute on.
# TODO: Maybe generate more precise types for annotations
key = builder.load_static_unicode(lvalue.name)
typ = builder.primitive_op(type_object_op, [], stmt.line)
typ = builder.add(LoadAddress(type_object_op.type, type_object_op.src, stmt.line))
builder.call_c(dict_set_item_op, [non_ext.anns, key, typ], stmt.line)

# Only add the attribute to the __dict__ if the assignment is of the form:
Expand Down Expand Up @@ -393,7 +394,8 @@ def gen_glue_ne_method(builder: IRBuilder, cls: ClassIR, line: int) -> FuncIR:
# If __eq__ returns NotImplemented, then __ne__ should also
not_implemented_block, regular_block = BasicBlock(), BasicBlock()
eqval = builder.add(MethodCall(args[0], '__eq__', [args[1]], line))
not_implemented = builder.primitive_op(not_implemented_op, [], line)
not_implemented = builder.add(LoadAddress(not_implemented_op.type,
not_implemented_op.src, line))
builder.add(Branch(
builder.binary_op(eqval, not_implemented, 'is', line),
not_implemented_block,
Expand Down Expand Up @@ -521,7 +523,7 @@ def dataclass_non_ext_info(builder: IRBuilder, cdef: ClassDef) -> Optional[NonEx
builder.call_c(dict_new_op, [], cdef.line),
builder.add(TupleSet([], cdef.line)),
builder.call_c(dict_new_op, [], cdef.line),
builder.primitive_op(type_object_op, [], cdef.line),
builder.add(LoadAddress(type_object_op.type, type_object_op.src, cdef.line))
)
else:
return None
14 changes: 6 additions & 8 deletions mypyc/primitives/int_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,18 @@
str_rprimitive, RType
)
from mypyc.primitives.registry import (
name_ref_op, name_emit,
c_unary_op, CFunctionDescription, c_function_op, c_binary_op, c_custom_op
load_address_op, c_unary_op, CFunctionDescription, c_function_op, c_binary_op, c_custom_op
)

# These int constructors produce object_rprimitives that then need to be unboxed
# I guess unboxing ourselves would save a check and branch though?

# Get the type object for 'builtins.int'.
# For ordinary calls to int() we use a name_ref to the type
name_ref_op('builtins.int',
result_type=object_rprimitive,
error_kind=ERR_NEVER,
emit=name_emit('&PyLong_Type', target_type='PyObject *'),
is_borrowed=True)
# For ordinary calls to int() we use a load_address to the type
load_address_op(
name='builtins.int',
type=object_rprimitive,
src='PyLong_Type')

# Convert from a float to int. We could do a bit better directly.
c_function_op(
Expand Down
12 changes: 5 additions & 7 deletions mypyc/primitives/list_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@
c_int_rprimitive
)
from mypyc.primitives.registry import (
name_ref_op, custom_op, name_emit,
call_emit, c_function_op, c_binary_op, c_method_op
custom_op, load_address_op, call_emit, c_function_op, c_binary_op, c_method_op
)


# Get the 'builtins.list' type object.
name_ref_op('builtins.list',
result_type=object_rprimitive,
error_kind=ERR_NEVER,
emit=name_emit('&PyList_Type', target_type='PyObject *'),
is_borrowed=True)
load_address_op(
name='builtins.list',
type=object_rprimitive,
src='PyList_Type')

# list(obj)
to_list = c_function_op(
Expand Down
21 changes: 9 additions & 12 deletions mypyc/primitives/misc_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
)
from mypyc.primitives.registry import (
name_ref_op, simple_emit, unary_op, func_op, custom_op, call_emit, name_emit,
call_negative_magic_emit, c_function_op, c_custom_op
call_negative_magic_emit, c_function_op, c_custom_op, load_address_op
)


Expand Down Expand Up @@ -46,11 +46,10 @@
is_borrowed=True)

# Get the boxed NotImplemented object
not_implemented_op = name_ref_op(name='builtins.NotImplemented',
result_type=object_rprimitive,
error_kind=ERR_NEVER,
emit=name_emit('Py_NotImplemented'),
is_borrowed=True)
not_implemented_op = load_address_op(
name='builtins.NotImplemented',
type=object_rprimitive,
src='_Py_NotImplementedStruct')

# id(obj)
c_function_op(
Expand Down Expand Up @@ -201,12 +200,10 @@
error_kind=ERR_NEVER)

# Get 'builtins.type' (base class of all classes)
type_object_op = name_ref_op(
'builtins.type',
result_type=object_rprimitive,
error_kind=ERR_NEVER,
emit=name_emit('&PyType_Type', target_type='PyObject *'),
is_borrowed=True)
type_object_op = load_address_op(
name='builtins.type',
type=object_rprimitive,
src='PyType_Type')

# Create a heap type based on a template non-heap type.
# See CPyType_FromTemplate for more docs.
Expand Down
28 changes: 6 additions & 22 deletions mypyc/primitives/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,10 @@
('priority', int)])

# A description for C load operations including LoadGlobal and LoadAddress
CLoadDescription = NamedTuple(
'CLoadDescription', [('name', str),
('return_type', RType),
('identifier', str), # name of the target to load
('cast_str', str), # string represents optional type cast
('load_address', bool)]) # True for LoadAddress otherwise LoadGlobal
LoadAddressDescription = NamedTuple(
'LoadAddressDescription', [('name', str),
('type', RType),
('src', str)]) # name of the target to load

# Primitive binary ops (key is operator such as '+')
binary_ops = {} # type: Dict[str, List[OpDescription]]
Expand Down Expand Up @@ -90,9 +88,6 @@
# CallC op for unary ops
c_unary_ops = {} # type: Dict[str, List[CFunctionDescription]]

# LoadGlobal/LoadAddress op for reading global names
c_name_ref_ops = {} # type: Dict[str, CLoadDescription]

builtin_names = {} # type: Dict[str, Tuple[RType, str]]


Expand Down Expand Up @@ -489,23 +484,12 @@ def c_unary_op(name: str,
return desc


def c_name_ref_op(name: str,
return_type: RType,
identifier: str,
cast_str: Optional[str] = None,
load_address: bool = False) -> CLoadDescription:
assert name not in c_name_ref_ops, 'already defined: %s' % name
cast_str = cast_str if cast_str else ""
desc = CLoadDescription(name, return_type, identifier, cast_str, load_address)
c_name_ref_ops[name] = desc
return desc


def load_address_op(name: str,
type: RType,
src: str) -> None:
src: str) -> LoadAddressDescription:
assert name not in builtin_names, 'already defined: %s' % name
builtin_names[name] = (type, src)
return LoadAddressDescription(name, type, src)


# Import various modules that set up global state.
Expand Down
15 changes: 7 additions & 8 deletions mypyc/primitives/str_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,21 @@

from typing import List, Callable

from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER, EmitterInterface, EmitCallback
from mypyc.ir.ops import ERR_MAGIC, EmitterInterface, EmitCallback
from mypyc.ir.rtypes import (
RType, object_rprimitive, str_rprimitive, bool_rprimitive, int_rprimitive, list_rprimitive
)
from mypyc.primitives.registry import (
binary_op, simple_emit, name_ref_op, method_op, call_emit, name_emit,
c_method_op, c_binary_op, c_function_op
binary_op, simple_emit, method_op, call_emit, c_method_op, c_binary_op, c_function_op,
load_address_op
)


# Get the 'str' type object.
name_ref_op('builtins.str',
result_type=object_rprimitive,
error_kind=ERR_NEVER,
emit=name_emit('&PyUnicode_Type', target_type='PyObject *'),
is_borrowed=True)
load_address_op(
name='builtins.str',
type=object_rprimitive,
src='PyUnicode_Type')

# str(obj)
c_function_op(
Expand Down
16 changes: 8 additions & 8 deletions mypyc/test-data/irbuild-basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,7 @@ def call_python_function(x):
r0, r1, r2 :: object
r3 :: int
L0:
r0 = int
r0 = load_address PyLong_Type
r1 = box(int, x)
r2 = py_call(r0, r1)
r3 = unbox(int, r2)
Expand Down Expand Up @@ -1294,7 +1294,7 @@ def call_python_function_with_keyword_arg(x):
r5 :: object
r6 :: int
L0:
r0 = int
r0 = load_address PyLong_Type
r1 = unicode_3 :: static ('base')
r2 = (x) :: tuple
r3 = box(short_int, 4)
Expand Down Expand Up @@ -1696,7 +1696,7 @@ def foo(x):
r3 :: __main__.B
r4 :: __main__.A
L0:
r0 = int
r0 = load_address PyLong_Type
r1 = PyObject_IsInstance(x, r0)
r2 = truncate r1: int32 to builtins.bool
if r2 goto L1 else goto L2 :: bool
Expand Down Expand Up @@ -2688,11 +2688,11 @@ L4:
r23 = CPyDict_SetItem(r11, r22, r21)
r24 = unicode_5 :: static ('Lol')
r25 = unicode_6 :: static ('a')
r26 = int
r26 = load_address PyLong_Type
r27 = (r25, r26)
r28 = box(tuple[str, object], r27)
r29 = unicode_7 :: static ('b')
r30 = str
r30 = load_address PyUnicode_Type
r31 = (r29, r30)
r32 = box(tuple[str, object], r31)
r33 = (r28, r32)
Expand All @@ -2717,7 +2717,7 @@ L4:
r52 = __main__.globals :: static
r53 = unicode_2 :: static ('List')
r54 = CPyDict_GetItem(r52, r53)
r55 = int
r55 = load_address PyLong_Type
r56 = PyObject_GetItem(r54, r55)
r57 = __main__.globals :: static
r58 = unicode_10 :: static ('Foo')
Expand Down Expand Up @@ -2820,7 +2820,7 @@ def A.__eq__(self, x):
self :: __main__.A
x, r0 :: object
L0:
r0 = NotImplemented
r0 = load_address _Py_NotImplementedStruct
return r0
def A.__ne__(self, rhs):
self :: __main__.A
Expand All @@ -2829,7 +2829,7 @@ def A.__ne__(self, rhs):
r4 :: object
L0:
r0 = self.__eq__(rhs)
r1 = NotImplemented
r1 = load_address _Py_NotImplementedStruct
r2 = r0 is r1
if r2 goto L2 else goto L1 :: bool
L1:
Expand Down
4 changes: 2 additions & 2 deletions mypyc/test-data/irbuild-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ def Base.__ne__(self, rhs):
r4 :: object
L0:
r0 = self.__eq__(rhs)
r1 = NotImplemented
r1 = load_address _Py_NotImplementedStruct
r2 = r0 is r1
if r2 goto L2 else goto L1 :: bool
L1:
Expand Down Expand Up @@ -953,7 +953,7 @@ def Derived.__ne__(self, rhs):
r4 :: object
L0:
r0 = self.__eq__(rhs)
r1 = NotImplemented
r1 = load_address _Py_NotImplementedStruct
r2 = r0 is r1
if r2 goto L2 else goto L1 :: bool
L1:
Expand Down
2 changes: 1 addition & 1 deletion mypyc/test-data/irbuild-optional.test
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def f(x):
r5 :: __main__.A
r6 :: int
L0:
r0 = int
r0 = load_address PyLong_Type
r1 = PyObject_IsInstance(x, r0)
r2 = truncate r1: int32 to builtins.bool
if r2 goto L1 else goto L2 :: bool
Expand Down
2 changes: 1 addition & 1 deletion mypyc/test-data/refcount.test
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ def g(x):
r5 :: object
r6 :: int
L0:
r0 = int
r0 = load_address PyLong_Type
r1 = unicode_1 :: static ('base')
r2 = (x) :: tuple
r3 = box(short_int, 4)
Expand Down

0 comments on commit b34f4c6

Please sign in to comment.