Skip to content

[mypyc] Implement LoadAddress #9287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion mypyc/analysis/dataflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
BasicBlock, OpVisitor, Assign, LoadInt, LoadErrorValue, RegisterOp, Goto, Branch, Return, Call,
Environment, Box, Unbox, Cast, Op, Unreachable, TupleGet, TupleSet, GetAttr, SetAttr,
LoadStatic, InitStatic, PrimitiveOp, MethodCall, RaiseStandardError, CallC, LoadGlobal,
Truncate, BinaryIntOp, LoadMem, GetElementPtr
Truncate, BinaryIntOp, LoadMem, GetElementPtr, LoadAddress
)


Expand Down Expand Up @@ -214,6 +214,9 @@ def visit_load_mem(self, op: LoadMem) -> GenAndKill:
def visit_get_element_ptr(self, op: GetElementPtr) -> GenAndKill:
return self.visit_register_op(op)

def visit_load_address(self, op: LoadAddress) -> GenAndKill:
return self.visit_register_op(op)


class DefinedVisitor(BaseAnalysisVisitor):
"""Visitor for finding defined registers.
Expand Down
7 changes: 6 additions & 1 deletion mypyc/codegen/emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
LoadStatic, InitStatic, TupleGet, TupleSet, Call, IncRef, DecRef, Box, Cast, Unbox,
BasicBlock, Value, MethodCall, PrimitiveOp, EmitterInterface, Unreachable, NAMESPACE_STATIC,
NAMESPACE_TYPE, NAMESPACE_MODULE, RaiseStandardError, CallC, LoadGlobal, Truncate,
BinaryIntOp, LoadMem, GetElementPtr
BinaryIntOp, LoadMem, GetElementPtr, LoadAddress
)
from mypyc.ir.rtypes import (
RType, RTuple, is_tagged, is_int32_rprimitive, is_int64_rprimitive, RStruct
Expand Down Expand Up @@ -480,6 +480,11 @@ def visit_get_element_ptr(self, op: GetElementPtr) -> None:
self.emit_line('%s = (%s)&((%s *)%s)->%s;' % (dest, op.type._ctype, op.src_type.name,
src, op.field))

def visit_load_address(self, op: LoadAddress) -> None:
typ = op.type
dest = self.reg(op)
self.emit_line('%s = (%s)&%s;' % (dest, typ._ctype, op.src))

# Helpers

def label(self, label: BasicBlock) -> str:
Expand Down
23 changes: 23 additions & 0 deletions mypyc/ir/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,25 @@ def accept(self, visitor: 'OpVisitor[T]') -> T:
return visitor.visit_get_element_ptr(self)


class LoadAddress(RegisterOp):
error_kind = ERR_NEVER
is_borrowed = True

def __init__(self, type: RType, src: str, line: int = -1) -> None:
super().__init__(line)
self.type = type
self.src = src

def sources(self) -> List[Value]:
return []

def to_str(self, env: Environment) -> str:
return env.format("%r = load_address %s", self, self.src)

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


@trait
class OpVisitor(Generic[T]):
"""Generic visitor over ops (uses the visitor design pattern)."""
Expand Down Expand Up @@ -1508,6 +1527,10 @@ def visit_load_mem(self, op: LoadMem) -> T:
def visit_get_element_ptr(self, op: GetElementPtr) -> T:
raise NotImplementedError

@abstractmethod
def visit_load_address(self, op: LoadAddress) -> T:
raise NotImplementedError


# TODO: Should this live somewhere else?
LiteralsMap = Dict[Tuple[Type[object], Union[int, float, str, bytes, complex]], str]
Expand Down
7 changes: 5 additions & 2 deletions mypyc/irbuild/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
from mypy.types import TupleType, get_proper_type

from mypyc.ir.ops import (
Value, TupleGet, TupleSet, PrimitiveOp, BasicBlock, OpDescription, Assign
Value, TupleGet, TupleSet, PrimitiveOp, BasicBlock, OpDescription, Assign, LoadAddress
)
from mypyc.ir.rtypes import RTuple, object_rprimitive, is_none_rprimitive, is_int_rprimitive
from mypyc.ir.func_ir import FUNC_CLASSMETHOD, FUNC_STATICMETHOD
from mypyc.primitives.registry import name_ref_ops, CFunctionDescription
from mypyc.primitives.registry import name_ref_ops, 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 new_list_op, list_append_op, list_extend_op
Expand All @@ -39,6 +39,9 @@
def transform_name_expr(builder: IRBuilder, expr: NameExpr) -> Value:
assert expr.node, "RefExpr not resolved"
fullname = expr.node.fullname
if fullname in builtin_names:
typ, src = builtin_names[fullname]
return builder.add(LoadAddress(typ, src, expr.line))
if fullname in name_ref_ops:
# Use special access op for this particular name.
desc = name_ref_ops[fullname]
Expand Down
13 changes: 5 additions & 8 deletions mypyc/primitives/dict_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@
)

from mypyc.primitives.registry import (
name_ref_op, method_op,
simple_emit, name_emit, c_custom_op, c_method_op, c_function_op, c_binary_op
method_op, simple_emit, c_custom_op, c_method_op, c_function_op, c_binary_op, load_address_op
)


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

# dict[key]
dict_get_item_op = c_method_op(
Expand Down
10 changes: 10 additions & 0 deletions mypyc/primitives/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
# LoadGlobal/LoadAddress op for reading global names
c_name_ref_ops = {} # type: Dict[str, CLoadDescription]

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


def simple_emit(template: str) -> EmitCallback:
"""Construct a simple PrimitiveOp emit callback function.
Expand Down Expand Up @@ -498,6 +500,14 @@ def c_name_ref_op(name: str,
c_name_ref_ops[name] = desc
return desc


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


# Import various modules that set up global state.
import mypyc.primitives.int_ops # noqa
import mypyc.primitives.str_ops # noqa
Expand Down
12 changes: 12 additions & 0 deletions mypyc/test-data/irbuild-dict.test
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,15 @@ L12:
r34 = None
return r34

[case testDictLoadAddress]
def f() -> None:
x = dict
[out]
def f():
r0, x :: object
r1 :: None
L0:
r0 = load_address PyDict_Type
x = r0
r1 = None
return r1
6 changes: 5 additions & 1 deletion mypyc/test/test_emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from mypyc.ir.ops import (
Environment, BasicBlock, Goto, Return, LoadInt, Assign, IncRef, DecRef, Branch,
Call, Unbox, Box, TupleGet, GetAttr, PrimitiveOp, RegisterOp,
SetAttr, Op, Value, CallC, BinaryIntOp, LoadMem, GetElementPtr
SetAttr, Op, Value, CallC, BinaryIntOp, LoadMem, GetElementPtr, LoadAddress
)
from mypyc.ir.rtypes import (
RTuple, RInstance, int_rprimitive, bool_rprimitive, list_rprimitive,
Expand Down Expand Up @@ -281,6 +281,10 @@ def test_get_element_ptr(self) -> None:
self.assert_emit(GetElementPtr(self.o, r, "i64"),
"""cpy_r_r01 = (CPyPtr)&((Foo *)cpy_r_o)->i64;""")

def test_load_address(self) -> None:
self.assert_emit(LoadAddress(object_rprimitive, "PyDict_Type"),
"""cpy_r_r0 = (PyObject *)&PyDict_Type;""")

def assert_emit(self, op: Op, expected: str) -> None:
self.emitter.fragments = []
self.declarations.fragments = []
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy