From 5201a1e33699daa486cc5532e0c35101c53f9f57 Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Tue, 4 Aug 2020 15:59:54 +0800 Subject: [PATCH 1/4] [mypyc] Implement GetElementPtr --- mypyc/analysis/dataflow.py | 5 ++++- mypyc/codegen/emitfunc.py | 13 +++++++++++-- mypyc/ir/ops.py | 29 ++++++++++++++++++++++++++++- mypyc/test/test_emitfunc.py | 15 +++++++++++++-- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/mypyc/analysis/dataflow.py b/mypyc/analysis/dataflow.py index 75942cb04a34..90a2e4d20a31 100644 --- a/mypyc/analysis/dataflow.py +++ b/mypyc/analysis/dataflow.py @@ -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 + Truncate, BinaryIntOp, LoadMem, GetElementPtr ) @@ -211,6 +211,9 @@ def visit_binary_int_op(self, op: BinaryIntOp) -> GenAndKill: def visit_load_mem(self, op: LoadMem) -> GenAndKill: return self.visit_register_op(op) + def visit_get_element_ptr(self, op: GetElementPtr) -> GenAndKill: + return self.visit_register_op(op) + class DefinedVisitor(BaseAnalysisVisitor): """Visitor for finding defined registers. diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index 0b560839c0b9..aa798554d869 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -12,10 +12,10 @@ 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 + BinaryIntOp, LoadMem, GetElementPtr ) from mypyc.ir.rtypes import ( - RType, RTuple, is_tagged, is_int32_rprimitive, is_int64_rprimitive + RType, RTuple, is_tagged, is_int32_rprimitive, is_int64_rprimitive, RStruct ) from mypyc.ir.func_ir import FuncIR, FuncDecl, FUNC_STATICMETHOD, FUNC_CLASSMETHOD from mypyc.ir.class_ir import ClassIR @@ -471,6 +471,15 @@ def visit_load_mem(self, op: LoadMem) -> None: type = self.ctype(op.type) self.emit_line('%s = *(%s *)%s;' % (dest, type, src)) + def visit_get_element_ptr(self, op: GetElementPtr) -> None: + dest = self.reg(op) + src = self.reg(op.src) + # TODO: support tuple type + assert isinstance(op.src_type, RStruct) + assert op.index < len(op.src_type.offsets), "Invalid element index." + offset = op.src_type.offsets[op.index] + self.emit_line('%s = (char *)%s + %s;' % (dest, src, offset)) + # Helpers def label(self, label: BasicBlock) -> str: diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index 9b871ad6309c..bb5d9c2df07e 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -25,7 +25,8 @@ from mypyc.ir.rtypes import ( RType, RInstance, RTuple, RVoid, is_bool_rprimitive, is_int_rprimitive, is_short_int_rprimitive, is_none_rprimitive, object_rprimitive, bool_rprimitive, - short_int_rprimitive, int_rprimitive, void_rtype, is_c_py_ssize_t_rprimitive + short_int_rprimitive, int_rprimitive, void_rtype, is_c_py_ssize_t_rprimitive, + c_pyssize_t_rprimitive ) from mypyc.common import short_name @@ -1372,6 +1373,28 @@ def accept(self, visitor: 'OpVisitor[T]') -> T: return visitor.visit_load_mem(self) +class GetElementPtr(RegisterOp): + """Get the address of a struct element""" + error_kind = ERR_NEVER + + def __init__(self, src: Value, src_type: RType, index: int, line: int = -1) -> None: + super().__init__(line) + self.type = c_pyssize_t_rprimitive + self.src = src + self.src_type = src_type + self.index = index + + def sources(self) -> List[Value]: + return [self.src] + + def to_str(self, env: Environment) -> str: + return env.format("%r = get_element_ptr %r %r :: %r", self, self.src, + self.index, self.src_type) + + def accept(self, visitor: 'OpVisitor[T]') -> T: + return visitor.visit_get_element_ptr(self) + + @trait class OpVisitor(Generic[T]): """Generic visitor over ops (uses the visitor design pattern).""" @@ -1482,6 +1505,10 @@ def visit_binary_int_op(self, op: BinaryIntOp) -> T: def visit_load_mem(self, op: LoadMem) -> T: raise NotImplementedError + @abstractmethod + def visit_get_element_ptr(self, op: GetElementPtr) -> T: + raise NotImplementedError + # TODO: Should this live somewhere else? LiteralsMap = Dict[Tuple[Type[object], Union[int, float, str, bytes, complex]], str] diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index e83c604df850..a10f8ea14836 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -10,12 +10,12 @@ 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 + SetAttr, Op, Value, CallC, BinaryIntOp, LoadMem, GetElementPtr ) from mypyc.ir.rtypes import ( RTuple, RInstance, int_rprimitive, bool_rprimitive, list_rprimitive, dict_rprimitive, object_rprimitive, c_int_rprimitive, short_int_rprimitive, int32_rprimitive, - int64_rprimitive + int64_rprimitive, StructInfo, RStruct ) from mypyc.ir.func_ir import FuncIR, FuncDecl, RuntimeArg, FuncSignature from mypyc.ir.class_ir import ClassIR @@ -282,6 +282,17 @@ def test_load_mem(self) -> None: self.assert_emit(LoadMem(bool_rprimitive, self.i64), """cpy_r_r0 = *(char *)cpy_r_i64;""") + def test_get_element_ptr(self) -> None: + info = StructInfo("", [], [bool_rprimitive, int32_rprimitive, int64_rprimitive]) + r = RStruct(info) + self.assert_emit(GetElementPtr(self.o, r, 0), + """cpy_r_r0 = (char *)cpy_r_o + 0;""") + self.assert_emit(GetElementPtr(self.o, r, 1), + """cpy_r_r00 = (char *)cpy_r_o + 4;""") + self.assert_emit(GetElementPtr(self.o, r, 2), + """cpy_r_r01 = (char *)cpy_r_o + 8;""") + + def assert_emit(self, op: Op, expected: str) -> None: self.emitter.fragments = [] self.declarations.fragments = [] From 90fc31b6242e24d35ab1a893587f2bb08682a1d6 Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Tue, 4 Aug 2020 16:30:31 +0800 Subject: [PATCH 2/4] fix lint --- mypyc/test/test_emitfunc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index a10f8ea14836..b43518b45e40 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -292,7 +292,6 @@ def test_get_element_ptr(self) -> None: self.assert_emit(GetElementPtr(self.o, r, 2), """cpy_r_r01 = (char *)cpy_r_o + 8;""") - def assert_emit(self, op: Op, expected: str) -> None: self.emitter.fragments = [] self.declarations.fragments = [] From 807ab93a7098ae1f7e57c2086cf383aae4aa2a6d Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Tue, 4 Aug 2020 18:39:17 +0800 Subject: [PATCH 3/4] using field name instead of field index --- mypyc/codegen/emitfunc.py | 5 ++--- mypyc/ir/ops.py | 6 +++--- mypyc/test/test_emitfunc.py | 14 +++++++------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/mypyc/codegen/emitfunc.py b/mypyc/codegen/emitfunc.py index aa798554d869..0dc0dd96900c 100644 --- a/mypyc/codegen/emitfunc.py +++ b/mypyc/codegen/emitfunc.py @@ -476,9 +476,8 @@ def visit_get_element_ptr(self, op: GetElementPtr) -> None: src = self.reg(op.src) # TODO: support tuple type assert isinstance(op.src_type, RStruct) - assert op.index < len(op.src_type.offsets), "Invalid element index." - offset = op.src_type.offsets[op.index] - self.emit_line('%s = (char *)%s + %s;' % (dest, src, offset)) + assert op.field in op.src_type.names, "Invalid field name." + self.emit_line('%s = &%s.%s;' % (dest, src, op.field)) # Helpers diff --git a/mypyc/ir/ops.py b/mypyc/ir/ops.py index bb5d9c2df07e..12d7e32db230 100644 --- a/mypyc/ir/ops.py +++ b/mypyc/ir/ops.py @@ -1377,19 +1377,19 @@ class GetElementPtr(RegisterOp): """Get the address of a struct element""" error_kind = ERR_NEVER - def __init__(self, src: Value, src_type: RType, index: int, line: int = -1) -> None: + def __init__(self, src: Value, src_type: RType, field: str, line: int = -1) -> None: super().__init__(line) self.type = c_pyssize_t_rprimitive self.src = src self.src_type = src_type - self.index = index + self.field = field def sources(self) -> List[Value]: return [self.src] def to_str(self, env: Environment) -> str: return env.format("%r = get_element_ptr %r %r :: %r", self, self.src, - self.index, self.src_type) + self.field, self.src_type) def accept(self, visitor: 'OpVisitor[T]') -> T: return visitor.visit_get_element_ptr(self) diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index b43518b45e40..2d069c49bae5 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -283,14 +283,14 @@ def test_load_mem(self) -> None: """cpy_r_r0 = *(char *)cpy_r_i64;""") def test_get_element_ptr(self) -> None: - info = StructInfo("", [], [bool_rprimitive, int32_rprimitive, int64_rprimitive]) + info = StructInfo("Foo", ["b", "i32", "i64"], [bool_rprimitive, int32_rprimitive, int64_rprimitive]) r = RStruct(info) - self.assert_emit(GetElementPtr(self.o, r, 0), - """cpy_r_r0 = (char *)cpy_r_o + 0;""") - self.assert_emit(GetElementPtr(self.o, r, 1), - """cpy_r_r00 = (char *)cpy_r_o + 4;""") - self.assert_emit(GetElementPtr(self.o, r, 2), - """cpy_r_r01 = (char *)cpy_r_o + 8;""") + self.assert_emit(GetElementPtr(self.o, r, "b"), + """cpy_r_r0 = &cpy_r_o.b;""") + self.assert_emit(GetElementPtr(self.o, r, "i32"), + """cpy_r_r00 = &cpy_r_o.i32;""") + self.assert_emit(GetElementPtr(self.o, r, "i64"), + """cpy_r_r01 = &cpy_r_o.i64;""") def assert_emit(self, op: Op, expected: str) -> None: self.emitter.fragments = [] From 76d34cc3c1c9a81a7c7ab1fe2858297310fa6009 Mon Sep 17 00:00:00 2001 From: Xuanda Yang Date: Tue, 4 Aug 2020 18:52:07 +0800 Subject: [PATCH 4/4] fix lint --- mypyc/test/test_emitfunc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypyc/test/test_emitfunc.py b/mypyc/test/test_emitfunc.py index 2d069c49bae5..a2e821e9148b 100644 --- a/mypyc/test/test_emitfunc.py +++ b/mypyc/test/test_emitfunc.py @@ -283,7 +283,8 @@ def test_load_mem(self) -> None: """cpy_r_r0 = *(char *)cpy_r_i64;""") def test_get_element_ptr(self) -> None: - info = StructInfo("Foo", ["b", "i32", "i64"], [bool_rprimitive, int32_rprimitive, int64_rprimitive]) + info = StructInfo("Foo", ["b", "i32", "i64"], [bool_rprimitive, + int32_rprimitive, int64_rprimitive]) r = RStruct(info) self.assert_emit(GetElementPtr(self.o, r, "b"), """cpy_r_r0 = &cpy_r_o.b;""") 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