def test_caching_dynamic_deallocator(): S = lltype.GcStruct("S", ('x', lltype.Signed), rtti=True) S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed), rtti=True) T = lltype.GcStruct("T", ('x', lltype.Signed), rtti=True) def f_S(s): s.x = 1 def f_S1(s1): s1.s.x = 1 s1.y = 2 def f_T(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) def type_info_T(p): return lltype.getRuntimeTypeInfo(T) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S1) pinf = lltype.attachRuntimeTypeInfo(S1, qp, destrptr=dp) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_T) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Void), "destructor_funcptr", _callable=f_T) pinf = lltype.attachRuntimeTypeInfo(T, qp, destrptr=dp) def f(): pass t = TranslationContext() t.buildannotator().build_types(f, []) t.buildrtyper().specialize() transformer = RefcountingGCTransformer(t) p_S = transformer.dynamic_deallocation_funcptr_for_type(S) p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1) p_T = transformer.dynamic_deallocation_funcptr_for_type(T) assert p_S is not p_T assert p_S is p_S1
def g(vobj): vobj = lltype.normalizeptr(vobj) LLV = lltype.typeOf(vobj).TO ACCESS = LLV.ACCESS access = lltype.malloc(ACCESS, immortal=True) fp = lltype.functionptr(ACCESS.parent.get_inst_v0.TO, 'getv0', _callable=getv0) access.parent.get_inst_v0= fp access.get_inst_v1 = lltype.functionptr(ACCESS.get_inst_v1.TO, 'getv1', _callable=getv1) vobj.super.vable_access = access.parent
def g(vobj): vobj = lltype.normalizeptr(vobj) LLV = lltype.typeOf(vobj).TO ACCESS = LLV.ACCESS access = lltype.malloc(ACCESS, immortal=True) fp = lltype.functionptr(ACCESS.parent.get_inst_v0.TO, 'getv0', _callable=getv0) access.parent.get_inst_v0 = fp access.get_inst_v1 = lltype.functionptr(ACCESS.get_inst_v1.TO, 'getv1', _callable=getv1) vobj.super.vable_access = access.parent
def test_caching_dynamic_deallocator(): S = lltype.GcStruct("S", ('x', lltype.Signed)) S1 = lltype.GcStruct("S1", ('s', S), ('y', lltype.Signed)) T = lltype.GcStruct("T", ('x', lltype.Signed)) def f_S(s): s.x = 1 def f_S1(s1): s1.s.x = 1 s1.y = 2 def f_T(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) def type_info_T(p): return lltype.getRuntimeTypeInfo(T) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f_S1) pinf = lltype.attachRuntimeTypeInfo(S1, qp, destrptr=dp) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_T) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(T)], lltype.Void), "destructor_funcptr", _callable=f_T) pinf = lltype.attachRuntimeTypeInfo(T, qp, destrptr=dp) def f(): pass t = TranslationContext() t.buildannotator().build_types(f, []) t.buildrtyper().specialize() transformer = RefcountingGCTransformer(t) p_S = transformer.dynamic_deallocation_funcptr_for_type(S) p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1) p_T = transformer.dynamic_deallocation_funcptr_for_type(T) assert p_S is not p_T assert p_S is p_S1
def test_deallocator_with_destructor(): S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) graph, t = make_deallocator(S)
def test_get_accessor(): G = lltype.FuncType([rclass.OBJECTPTR], lltype.Void) witness = [] def getv(vinst): value = vinst.inst_v witness.append(value) return value def g(vobj): vobj = lltype.normalizeptr(vobj) LLV = lltype.typeOf(vobj).TO ACCESS = LLV.vable_access.TO access = lltype.malloc(ACCESS, immortal=True) access.get_inst_v = lltype.functionptr(ACCESS.get_inst_v.TO, 'getv', _callable=getv) vobj.vable_access = access gptr = lltype.functionptr(G, 'g', _callable=g) def f(v): vinst = V(v) vobj = cast_instance_to_base_ptr(vinst) gptr(vobj) x = vinst.v return x res = interpret(f, [42]) assert res == 42 assert witness == [42]
def newgraph(gv_FUNCTYPE, name): FUNCTYPE = _from_opaque(gv_FUNCTYPE).value # 'name' is just a way to track things name = from_opaque_string(name) inputargs = [] erasedinputargs = [] for ARG in FUNCTYPE.ARGS: v = flowmodel.Variable() v.concretetype = ARG inputargs.append(v) v = flowmodel.Variable() v.concretetype = lltype.erasedType(ARG) erasedinputargs.append(v) startblock = flowmodel.Block(inputargs) # insert an exploding operation here which is removed by # builder.end() to ensure that builder.end() is actually called. startblock.operations.append( flowmodel.SpaceOperation("debug_assert", [ flowmodel.Constant(False, lltype.Bool), flowmodel.Constant("you didn't call builder.end()?", lltype.Void) ], varoftype(lltype.Void))) return_var = flowmodel.Variable() return_var.concretetype = FUNCTYPE.RESULT graph = flowmodel.FunctionGraph(name, startblock, return_var) v1 = flowmodel.Variable() v1.concretetype = lltype.erasedType(FUNCTYPE.RESULT) graph.prereturnblock = flowmodel.Block([v1]) casting_link(graph.prereturnblock, [v1], graph.returnblock) substartblock = flowmodel.Block(erasedinputargs) casting_link(graph.startblock, inputargs, substartblock) fptr = lltype.functionptr(FUNCTYPE, name, graph=graph) return genconst(fptr)
def _setup_repr_final(self): AbstractInstanceRepr._setup_repr_final(self) if self.gcflavor == 'gc': if (self.classdef is not None and self.classdef.classdesc.lookup('__del__') is not None): s_func = self.classdef.classdesc.s_read_attribute('__del__') source_desc = self.classdef.classdesc.lookup('__del__') source_classdef = source_desc.getclassdef(None) source_repr = getinstancerepr(self.rtyper, source_classdef) assert len(s_func.descriptions) == 1 funcdesc, = s_func.descriptions graph = funcdesc.getuniquegraph() self.check_graph_of_del_does_not_call_too_much(graph) FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void) destrptr = functionptr(FUNCTYPE, graph.name, graph=graph, _callable=graph.func) else: destrptr = None OBJECT = OBJECT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT, destrptr) vtable = self.rclass.getvtable() self.rtyper.set_type_for_typeptr(vtable, self.lowleveltype.TO)
def test_boehm_finalizer_nomix___del___and_pyobj(): S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) py.test.raises(Exception, "make_boehm_finalizer(S)")
def test_decode_builtin_call_method(): A = lltype.GcArray(lltype.Signed) def myfoobar(a, i, marker, c): assert marker == 'mymarker' return a[i] * ord(c) myfoobar.oopspec = 'spam.foobar(a, 2, c, i)' TYPE = lltype.FuncType([lltype.Ptr(A), lltype.Signed, lltype.Void, lltype.Char], lltype.Signed) fnobj = lltype.functionptr(TYPE, 'foobar', _callable=myfoobar) vi = Variable('i') vi.concretetype = lltype.Signed vc = Variable('c') vc.concretetype = lltype.Char v_result = Variable('result') v_result.concretetype = lltype.Signed myarray = lltype.malloc(A, 10) myarray[5] = 42 op = SpaceOperation('direct_call', [newconst(fnobj), newconst(myarray), vi, voidconst('mymarker'), vc], v_result) oopspec, opargs = decode_builtin_call(op) assert oopspec == 'spam.foobar' assert opargs == [newconst(myarray), newconst(2), vc, vi]
def test_llexternal(self): from pypy.rpython.lltypesystem.rffi import llexternal from pypy.rpython.lltypesystem import lltype z = llexternal('z', [lltype.Signed], lltype.Signed) def f(x): return z(x) t, ra = self.translate(f, [int]) fgraph = graphof(t, f) backend_optimizations(t) assert fgraph.startblock.operations[0].opname == 'direct_call' result = ra.can_raise(fgraph.startblock.operations[0]) assert not result z = lltype.functionptr(lltype.FuncType([lltype.Signed], lltype.Signed), 'foobar') def g(x): return z(x) t, ra = self.translate(g, [int]) ggraph = graphof(t, g) assert ggraph.startblock.operations[0].opname == 'direct_call' result = ra.can_raise(ggraph.startblock.operations[0]) assert result
def test_set_accessor(): G = lltype.FuncType([rclass.OBJECTPTR], lltype.Void) witness = [] def setv(vinst, val): witness.append(val) vinst.inst_v = val def g(vobj): vobj = lltype.normalizeptr(vobj) LLV = lltype.typeOf(vobj).TO ACCESS = LLV.vable_access.TO access = lltype.malloc(ACCESS, immortal=True) access.set_inst_v = lltype.functionptr(ACCESS.set_inst_v.TO, 'setv', _callable=setv) vobj.vable_access = access gptr = lltype.functionptr(G, 'g', _callable=g) def f(v): vinst = V(v) vobj = cast_instance_to_base_ptr(vinst) gptr(vobj) vinst.v = 33 res = interpret(f, [42]) assert witness == [33]
def newgraph(gv_FUNCTYPE, name): FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value # 'name' is just a way to track things if not isinstance(name, str): name = LLSupport.from_rstr(name) inputargs = [] erasedinputargs = [] for ARG in FUNCTYPE.ARGS: v = flowmodel.Variable() v.concretetype = ARG inputargs.append(v) v = flowmodel.Variable() v.concretetype = lltype.erasedType(ARG) erasedinputargs.append(v) startblock = flowmodel.Block(inputargs) # insert an exploding operation here which is removed by # builder.end() to ensure that builder.end() is actually called. startblock.operations.append( flowmodel.SpaceOperation("debug_assert", [flowmodel.Constant(False, lltype.Bool), flowmodel.Constant("you didn't call builder.end()?", lltype.Void)], varoftype(lltype.Void))) return_var = flowmodel.Variable() return_var.concretetype = FUNCTYPE.RESULT graph = flowmodel.FunctionGraph(name, startblock, return_var) v1 = flowmodel.Variable() v1.concretetype = lltype.erasedType(FUNCTYPE.RESULT) graph.prereturnblock = flowmodel.Block([v1]) casting_link(graph.prereturnblock, [v1], graph.returnblock) substartblock = flowmodel.Block(erasedinputargs) casting_link(graph.startblock, inputargs, substartblock) fptr = lltype.functionptr(FUNCTYPE, name, graph=graph) return genconst(fptr)
def test_assemble_cast_consts(): ssarepr = SSARepr("test") S = lltype.GcStruct('S') s = lltype.malloc(S) F = lltype.FuncType([], lltype.Signed) f = lltype.functionptr(F, 'f') ssarepr.insns = [ ('int_return', Constant('X', lltype.Char)), ('int_return', Constant(unichr(0x1234), lltype.UniChar)), ('int_return', Constant(f, lltype.Ptr(F))), ('ref_return', Constant(s, lltype.Ptr(S))), ] assembler = Assembler() jitcode = assembler.assemble(ssarepr) assert jitcode.code == ("\x00\x58" "\x01\xFF" "\x01\xFE" "\x02\xFF") assert assembler.insns == {'int_return/c': 0, 'int_return/i': 1, 'ref_return/r': 2} f_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(f)) assert jitcode.constants_i == [0x1234, f_int] s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s) assert jitcode.constants_r == [s_gcref]
def test_unicode_concat(): # test that the oopspec is present and correctly transformed PSTR = lltype.Ptr(rstr.UNICODE) FUNC = lltype.FuncType([PSTR, PSTR], PSTR) func = lltype.functionptr(FUNC, 'll_strconcat', _callable=rstr.LLHelpers.ll_strconcat) v1 = varoftype(PSTR) v2 = varoftype(PSTR) v3 = varoftype(PSTR) op = SpaceOperation('direct_call', [const(func), v1, v2], v3) cc = FakeBuiltinCallControl() tr = Transformer(FakeCPU(), cc) op1 = tr.rewrite_operation(op) assert op1.opname == 'residual_call_r_r' assert op1.args[0].value == func assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_UNI_CONCAT assert op1.args[2] == ListOfKind('ref', [v1, v2]) assert op1.result == v3 # # check the callinfo_for_oopspec got = cc.callinfocollection.seen[0] assert got[0] == effectinfo.EffectInfo.OS_UNI_CONCAT assert got[1] == op1.args[1] # the calldescr assert heaptracker.int2adr(got[2]) == llmemory.cast_ptr_to_adr(func)
def specialize_call(self, hop): FUNCTYPE = lltype.FuncType([r.lowleveltype for r in hop.args_r], hop.r_result.lowleveltype) args_v = hop.inputargs(*hop.args_r) funcptr = lltype.functionptr(FUNCTYPE, func.__name__, _callable=func, _debugexc=True) cfunc = hop.inputconst(lltype.Ptr(FUNCTYPE), funcptr) return hop.genop('direct_call', [cfunc] + args_v, hop.r_result)
def test_boehm_finalizer___del__(): S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr(lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) f, t = make_boehm_finalizer(S) assert f is not None
def genexternalcall(self, fnname, args_v, resulttype=None, **flags): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype or Void) f = functionptr(FUNCTYPE, fnname, **flags) cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf]+list(args_v), resulttype)
def get_direct_call_op(argtypes, restype): FUNC = lltype.FuncType(argtypes, restype) fnptr = lltype.functionptr(FUNC, "g") # no graph c_fnptr = const(fnptr) vars = [varoftype(TYPE) for TYPE in argtypes] v_result = varoftype(restype) op = SpaceOperation('direct_call', [c_fnptr] + vars, v_result) return op
def annotate(translator, func, result, args): args = [arg.concretetype for arg in args] graph = translator.rtyper.annotate_helper(func, args) fptr = lltype.functionptr(lltype.FuncType(args, result.concretetype), func.func_name, graph=graph) c = inputconst(lltype.typeOf(fptr), fptr) return c
def g(vobj): vobj = lltype.normalizeptr(vobj) LLV = lltype.typeOf(vobj).TO ACCESS = LLV.vable_access.TO access = lltype.malloc(ACCESS, immortal=True) access.set_inst_v = lltype.functionptr(ACCESS.set_inst_v.TO, 'setv', _callable=setv) vobj.vable_access = access
def genexternalcall(self, fnname, args_v, resulttype=None, **flags): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype or Void) f = functionptr(FUNCTYPE, fnname, **flags) cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf] + list(args_v), resulttype)
def test_half_exceptiontransformed_graphs(): from pypy.translator import exceptiontransform def f1(x): if x < 0: raise ValueError return 754 def g1(x): try: return f1(x) except ValueError: return 5 def f2(x): if x < 0: raise ValueError return 21 def g2(x): try: return f2(x) except ValueError: return 6 f3 = lltype.functionptr(lltype.FuncType([lltype.Signed], lltype.Signed), 'f3', _callable=f1) def g3(x): try: return f3(x) except ValueError: return 7 def f(flag, x): if flag == 1: return g1(x) elif flag == 2: return g2(x) else: return g3(x) t = TranslationContext() t.buildannotator().build_types(f, [int, int]) t.buildrtyper().specialize() etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(graphof(t, f1)) etrafo.create_exception_handling(graphof(t, g2)) etrafo.create_exception_handling(graphof(t, g3)) graph = graphof(t, f) interp = LLInterpreter(t.rtyper) res = interp.eval_graph(graph, [1, -64]) assert res == 5 res = interp.eval_graph(graph, [2, -897]) assert res == 6 res = interp.eval_graph(graph, [3, -9831]) assert res == 7
def test_half_exceptiontransformed_graphs(): from pypy.translator import exceptiontransform def f1(x): if x < 0: raise ValueError return 754 def g1(x): try: return f1(x) except ValueError: return 5 def f2(x): if x < 0: raise ValueError return 21 def g2(x): try: return f2(x) except ValueError: return 6 f3 = lltype.functionptr(lltype.FuncType([lltype.Signed], lltype.Signed), "f3", _callable=f1) def g3(x): try: return f3(x) except ValueError: return 7 def f(flag, x): if flag == 1: return g1(x) elif flag == 2: return g2(x) else: return g3(x) t = TranslationContext() t.buildannotator().build_types(f, [int, int]) t.buildrtyper().specialize() etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(graphof(t, f1)) etrafo.create_exception_handling(graphof(t, g2)) etrafo.create_exception_handling(graphof(t, g3)) graph = graphof(t, f) interp = LLInterpreter(t.rtyper) res = interp.eval_graph(graph, [1, -64]) assert res == 5 res = interp.eval_graph(graph, [2, -897]) assert res == 6 res = interp.eval_graph(graph, [3, -9831]) assert res == 7
def test_boehm_finalizer___del__(): S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) f, t = make_boehm_finalizer(S) assert f is not None
def test_boehm_finalizer_nomix___del___and_pyobj(): S = lltype.GcStruct("S", ('x', lltype.Signed), ('y', lltype.Ptr(lltype.PyObject))) def f(s): s.x = 1 def type_info_S(p): return lltype.getRuntimeTypeInfo(S) qp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Ptr( lltype.RuntimeTypeInfo)), "type_info_S", _callable=type_info_S) dp = lltype.functionptr(lltype.FuncType([lltype.Ptr(S)], lltype.Void), "destructor_funcptr", _callable=f) pinf = lltype.attachRuntimeTypeInfo(S, qp, destrptr=dp) py.test.raises(Exception, "make_boehm_finalizer(S)")
def test_graphs_from_direct_call(): cc = CallControl() F = lltype.FuncType([], lltype.Signed) f = lltype.functionptr(F, 'f', graph='fgraph') v = varoftype(lltype.Signed) op = SpaceOperation('direct_call', [Constant(f, lltype.Ptr(F))], v) # lst = cc.graphs_from(op, {}.__contains__) assert lst is None # residual call # lst = cc.graphs_from(op, {'fgraph': True}.__contains__) assert lst == ['fgraph'] # normal call
def llexternal(name, args, result, _callable=None, sources=[], includes=[], libraries=[], include_dirs=[]): ext_type = lltype.FuncType(args, result) funcptr = lltype.functionptr(ext_type, name, external='C', sources=tuple(sources), includes=tuple(includes), libraries=tuple(libraries), include_dirs=tuple(include_dirs), _callable=_callable) if _callable is None: from pypy.rpython.lltypesystem import ll2ctypes ll2ctypes.make_callable_via_ctypes(funcptr) return funcptr
def ctypes2lltype(T, cobj): """Convert the ctypes object 'cobj' to its lltype equivalent. 'T' is the expected lltype type. """ if isinstance(T, lltype.Ptr): if not cobj: # NULL pointer return lltype.nullptr(T.TO) if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: lgt = getattr(cobj.contents, T.TO._arrayfld).length container = lltype._struct(T.TO, lgt) else: container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): container = _array_of_unknown_length(T.TO) container._storage = cobj.contents else: raise NotImplementedError("array with an explicit length") elif isinstance(T.TO, lltype.FuncType): _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), _callable=_callable) elif isinstance(T.TO, lltype.OpaqueType): container = lltype._opaque(T.TO) else: raise NotImplementedError(T) llobj = lltype._ptr(T, container, solid=True) elif T is lltype.Char: llobj = chr(cobj) elif T is lltype.UniChar: llobj = unichr(cobj) elif T is lltype.Signed: llobj = cobj elif T is lltype.SingleFloat: if isinstance(cobj, ctypes.c_float): cobj = cobj.value llobj = r_singlefloat(cobj) else: from pypy.rpython.lltypesystem import rffi try: inttype = rffi.platform.numbertype_to_rclass[T] except KeyError: llobj = cobj else: llobj = inttype(cobj) assert lltype.typeOf(llobj) == T return llobj
def test_c_callback_with_void_arg_2(self): ftest = [] def f(x): ftest.append(x) F = lltype.FuncType([lltype.Void], lltype.Void) fn = lltype.functionptr(F, 'askjh', _callable=f, _void0=-5) fn(-5) assert ftest == [-5] fn2 = lltype2ctypes(fn) fn2() assert ftest == [-5, -5] fn3 = ctypes2lltype(lltype.Ptr(F), fn2) fn3(-5) assert ftest == [-5, -5, -5]
def specialize_call(self, hop): ARGS = [r.lowleveltype for r in hop.args_r] RESULT = hop.r_result.lowleveltype if hop.rtyper.type_system.name == 'lltypesystem': FUNCTYPE = lltype.FuncType(ARGS, RESULT) funcptr = lltype.functionptr(FUNCTYPE, func.__name__, _callable=func, _debugexc=True) cfunc = hop.inputconst(lltype.Ptr(FUNCTYPE), funcptr) else: FUNCTYPE = ootype.StaticMethod(ARGS, RESULT) sm = ootype._static_meth(FUNCTYPE, _name=func.__name__, _callable=func) cfunc = hop.inputconst(FUNCTYPE, sm) args_v = hop.inputargs(*hop.args_r) return hop.genop('direct_call', [cfunc] + args_v, hop.r_result)
def ctypes2lltype(T, cobj): """Convert the ctypes object 'cobj' to its lltype equivalent. 'T' is the expected lltype type. """ if isinstance(T, lltype.Ptr): if not cobj: # NULL pointer return lltype.nullptr(T.TO) if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: raise NotImplementedError("XXX var-sized structs") container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): container = _array_of_unknown_length(T.TO) container._storage = cobj.contents else: raise NotImplementedError("array with an explicit length") elif isinstance(T.TO, lltype.FuncType): _callable = get_ctypes_trampoline(T.TO, cobj) return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), _callable=_callable) elif isinstance(T.TO, lltype.OpaqueType): container = lltype._opaque(T.TO) else: raise NotImplementedError(T) llobj = lltype._ptr(T, container, solid=True) elif T is lltype.Char: llobj = chr(cobj) elif T is lltype.UniChar: llobj = unichr(cobj) elif T is lltype.Signed: llobj = cobj elif T is lltype.SingleFloat: if isinstance(cobj, ctypes.c_float): cobj = cobj.value llobj = r_singlefloat(cobj) else: from pypy.rpython.lltypesystem import rffi try: inttype = rffi.platform.numbertype_to_rclass[T] except KeyError: llobj = cobj else: llobj = inttype(cobj) assert lltype.typeOf(llobj) == T return llobj
def test_str_concat(): # test that the oopspec is present and correctly transformed PSTR = lltype.Ptr(rstr.STR) FUNC = lltype.FuncType([PSTR, PSTR], PSTR) func = lltype.functionptr(FUNC, "ll_strconcat", _callable=rstr.LLHelpers.ll_strconcat) v1 = varoftype(PSTR) v2 = varoftype(PSTR) v3 = varoftype(PSTR) op = SpaceOperation("direct_call", [const(func), v1, v2], v3) tr = Transformer(FakeCPU(), FakeBuiltinCallControl()) op1 = tr.rewrite_operation(op) assert op1.opname == "residual_call_r_r" assert op1.args[0].value == func assert op1.args[1] == "calldescr-%d" % effectinfo.EffectInfo.OS_STR_CONCAT assert op1.args[2] == ListOfKind("ref", [v1, v2]) assert op1.result == v3
def test_get_accessor_inheritance(): G = lltype.FuncType([rclass.OBJECTPTR], lltype.Void) witness = [] def getv0(vinst): value = vinst.inst_v0 witness.append(value) return value def getv1(vinst): value = lltype.normalizeptr(vinst).inst_v1 witness.append(value) return value def g(vobj): vobj = lltype.normalizeptr(vobj) LLV = lltype.typeOf(vobj).TO ACCESS = LLV.ACCESS access = lltype.malloc(ACCESS, immortal=True) fp = lltype.functionptr(ACCESS.parent.get_inst_v0.TO, 'getv0', _callable=getv0) access.parent.get_inst_v0 = fp access.get_inst_v1 = lltype.functionptr(ACCESS.get_inst_v1.TO, 'getv1', _callable=getv1) vobj.super.vable_access = access.parent gptr = lltype.functionptr(G, 'g', _callable=g) def f(v0, v1): B(0) vinst = C(v0, v1) vobj = cast_instance_to_base_ptr(vinst) gptr(vobj) x = vinst.v0 y = vinst.v1 vinst.x return x + y + len(vinst.x) res = interpret(f, [18, 21]) assert res == 42 assert witness == [18, 21]
def test_str2unicode(): # test that the oopspec is present and correctly transformed PSTR = lltype.Ptr(rstr.STR) PUNICODE = lltype.Ptr(rstr.UNICODE) FUNC = lltype.FuncType([PSTR], PUNICODE) func = lltype.functionptr(FUNC, 'll_str2unicode', _callable=rstr.LLHelpers.ll_str2unicode) v1 = varoftype(PSTR) v2 = varoftype(PUNICODE) op = SpaceOperation('direct_call', [const(func), v1], v2) tr = Transformer(FakeCPU(), FakeBuiltinCallControl()) op1 = tr.rewrite_operation(op) assert op1.opname == 'residual_call_r_r' assert op1.args[0].value == func assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_STR2UNICODE assert op1.args[2] == ListOfKind('ref', [v1]) assert op1.result == v2
def test_math_sqrt(): # test that the oopspec is present and correctly transformed FLOAT = lltype.Float FUNC = lltype.FuncType([FLOAT], FLOAT) func = lltype.functionptr(FUNC, 'll_math', _callable=ll_math.sqrt_nonneg) v1 = varoftype(FLOAT) v2 = varoftype(FLOAT) op = SpaceOperation('direct_call', [const(func), v1], v2) tr = Transformer(FakeCPU(), FakeBuiltinCallControl()) op1 = tr.rewrite_operation(op) assert op1.opname == 'residual_call_irf_f' assert op1.args[0].value == func assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_MATH_SQRT assert op1.args[2] == ListOfKind("int", []) assert op1.args[3] == ListOfKind("ref", []) assert op1.args[4] == ListOfKind('float', [v1]) assert op1.result == v2
def test_malloc_new_with_destructor(): vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) S = lltype.GcStruct("S", ("parent", rclass.OBJECT), rtti=True) DESTRUCTOR = lltype.FuncType([lltype.Ptr(S)], lltype.Void) destructor = lltype.functionptr(DESTRUCTOR, "destructor") lltype.attachRuntimeTypeInfo(S, destrptr=destructor) heaptracker.set_testing_vtable_for_gcstruct(S, vtable, "S") v = varoftype(lltype.Ptr(S)) op = SpaceOperation("malloc", [Constant(S, lltype.Void), Constant({"flavor": "gc"}, lltype.Void)], v) tr = Transformer(FakeCPU(), FakeResidualCallControl()) oplist = tr.rewrite_operation(op) op0, op1 = oplist assert op0.opname == "residual_call_r_r" assert op0.args[0].value == "alloc_with_del" # pseudo-function as a str assert list(op0.args[2]) == [] assert op1.opname == "-live-" assert op1.args == []
def test_math_sqrt(): # test that the oopspec is present and correctly transformed FLOAT = lltype.Float FUNC = lltype.FuncType([FLOAT], FLOAT) func = lltype.functionptr(FUNC, "ll_math", _callable=ll_math.sqrt_nonneg) v1 = varoftype(FLOAT) v2 = varoftype(FLOAT) op = SpaceOperation("direct_call", [const(func), v1], v2) tr = Transformer(FakeCPU(), FakeBuiltinCallControl()) op1 = tr.rewrite_operation(op) assert op1.opname == "residual_call_irf_f" assert op1.args[0].value == func assert op1.args[1] == "calldescr-%d" % effectinfo.EffectInfo.OS_MATH_SQRT assert op1.args[2] == ListOfKind("int", []) assert op1.args[3] == ListOfKind("ref", []) assert op1.args[4] == ListOfKind("float", [v1]) assert op1.result == v2
def create_proxy_graph(self, op): """ creates a graph which calls the original function, checks for raised exceptions, fetches and then raises them again. If this graph is inlined, the correct exception matching blocks are produced.""" # XXX slightly annoying: construct a graph by hand # but better than the alternative result = copyvar(None, op.result) opargs = [] inputargs = [] callargs = [] ARGTYPES = [] for var in op.args: if isinstance(var, Variable): v = Variable() v.concretetype = var.concretetype inputargs.append(v) opargs.append(v) callargs.append(var) ARGTYPES.append(var.concretetype) else: opargs.append(var) newop = SpaceOperation(op.opname, opargs, result) startblock = Block(inputargs) startblock.operations.append(newop) newgraph = FunctionGraph("dummy_exc1", startblock) startblock.closeblock(Link([result], newgraph.returnblock)) newgraph.returnblock.inputargs[0].concretetype = op.result.concretetype self.gen_exc_check(startblock, newgraph.returnblock) excblock = Block([]) llops = rtyper.LowLevelOpList(None) var_value = self.gen_getfield('exc_value', llops) var_type = self.gen_getfield('exc_type' , llops) self.gen_setfield('exc_value', self.c_null_evalue, llops) self.gen_setfield('exc_type', self.c_null_etype, llops) excblock.operations[:] = llops newgraph.exceptblock.inputargs[0].concretetype = self.lltype_of_exception_type newgraph.exceptblock.inputargs[1].concretetype = self.lltype_of_exception_value excblock.closeblock(Link([var_type, var_value], newgraph.exceptblock)) startblock.exits[True].target = excblock startblock.exits[True].args = [] FUNCTYPE = lltype.FuncType(ARGTYPES, op.result.concretetype) fptr = Constant(lltype.functionptr(FUNCTYPE, "dummy_exc1", graph=newgraph), lltype.Ptr(FUNCTYPE)) return newgraph, SpaceOperation("direct_call", [fptr] + callargs, op.result)
def test_decode_builtin_call_nomethod(): def myfoobar(i, marker, c): assert marker == "mymarker" return i * ord(c) myfoobar.oopspec = "foobar(2, c, i)" TYPE = lltype.FuncType([lltype.Signed, lltype.Void, lltype.Char], lltype.Signed) fnobj = lltype.functionptr(TYPE, "foobar", _callable=myfoobar) vi = Variable("i") vi.concretetype = lltype.Signed vc = Variable("c") vc.concretetype = lltype.Char v_result = Variable("result") v_result.concretetype = lltype.Signed op = SpaceOperation("direct_call", [newconst(fnobj), vi, voidconst("mymarker"), vc], v_result) oopspec, opargs = decode_builtin_call(op) assert oopspec == "foobar" assert opargs == [newconst(2), vc, vi]
def test_switch_no_default(): from pypy.objspace.flow.model import FunctionGraph, Block, Constant, Link from pypy.rpython.lltypesystem.lltype import FuncType, Signed, functionptr from pypy.translator.unsimplify import varoftype block = Block([varoftype(Signed)]) block.exitswitch = block.inputargs[0] graph = FunctionGraph("t", block, varoftype(Signed)) links = [] for i in range(10): links.append(Link([Constant(i*i, Signed)], graph.returnblock, i)) links[-1].llexitcase = i block.closeblock(*links) fptr = functionptr(FuncType([Signed], Signed), "t", graph=graph) def func(x): return fptr(x) f = compile_function(func, [int]) res = f(4) assert res == 16
def test_get_accessor_inheritance(): G = lltype.FuncType([rclass.OBJECTPTR], lltype.Void) witness = [] def getv0(vinst): value = vinst.inst_v0 witness.append(value) return value def getv1(vinst): value = lltype.normalizeptr(vinst).inst_v1 witness.append(value) return value def g(vobj): vobj = lltype.normalizeptr(vobj) LLV = lltype.typeOf(vobj).TO ACCESS = LLV.ACCESS access = lltype.malloc(ACCESS, immortal=True) fp = lltype.functionptr(ACCESS.parent.get_inst_v0.TO, 'getv0', _callable=getv0) access.parent.get_inst_v0= fp access.get_inst_v1 = lltype.functionptr(ACCESS.get_inst_v1.TO, 'getv1', _callable=getv1) vobj.super.vable_access = access.parent gptr = lltype.functionptr(G, 'g', _callable=g) def f(v0, v1): B(0) vinst = C(v0, v1) vobj = cast_instance_to_base_ptr(vinst) gptr(vobj) x = vinst.v0 y = vinst.v1 vinst.x return x+y+len(vinst.x) res = interpret(f, [18, 21]) assert res == 42 assert witness == [18, 21]
def test_malloc_new_with_destructor(): vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) S = lltype.GcStruct('S', ('parent', rclass.OBJECT), rtti=True) DESTRUCTOR = lltype.FuncType([lltype.Ptr(S)], lltype.Void) destructor = lltype.functionptr(DESTRUCTOR, 'destructor') lltype.attachRuntimeTypeInfo(S, destrptr=destructor) heaptracker.set_testing_vtable_for_gcstruct(S, vtable, 'S') v = varoftype(lltype.Ptr(S)) op = SpaceOperation( 'malloc', [Constant(S, lltype.Void), Constant({'flavor': 'gc'}, lltype.Void)], v) tr = Transformer(FakeCPU(), FakeResidualCallControl()) oplist = tr.rewrite_operation(op) op0, op1 = oplist assert op0.opname == 'residual_call_r_r' assert op0.args[0].value == 'alloc_with_del' # pseudo-function as a str assert list(op0.args[2]) == [] assert op1.opname == '-live-' assert op1.args == []
def llhelper(F, f): """Gives a low-level function pointer of type F which, when called, invokes the RPython function f(). """ # Example - the following code can be either run or translated: # # def my_rpython_code(): # g = llhelper(F, my_other_rpython_function) # assert typeOf(g) == F # ... # g() # # however the following doesn't translate (xxx could be fixed with hacks): # # prebuilt_g = llhelper(F, f) # def my_rpython_code(): # prebuilt_g() # the next line is the implementation for the purpose of direct running return lltype.functionptr(F.TO, f.func_name, _callable=f)
def specialize_call(self, hop): rtyper = hop.rtyper bk = rtyper.annotator.bookkeeper r_result = rtyper.getrepr(hop.s_result) hop.exception_is_here() args_r = [rtyper.getrepr(s_arg) for s_arg in hop.args_s] _callable = hop.args_s[0].const funcptr = lltype.functionptr(CALLBACK.TO, _callable.func_name, _callable=_callable) func_s = bk.immutablevalue(funcptr) s_args = [func_s, hop.args_s[1]] obj = rtyper.getannmixlevel().delayedfunction( ll_start_new_thread, s_args, annmodel.SomeInteger()) bootstrap = rtyper.getannmixlevel().delayedfunction( _callable, [hop.args_s[1]], annmodel.s_None) vlist = [hop.inputconst(typeOf(obj), obj), hop.inputconst(typeOf(bootstrap), bootstrap), #hop.inputarg(args_r[0], 0), hop.inputarg(args_r[1], 1)] return hop.genop('direct_call', vlist, r_result)
def test_list_ll_arraycopy(): from pypy.rlib.rgc import ll_arraycopy LIST = lltype.GcArray(lltype.Signed) PLIST = lltype.Ptr(LIST) INT = lltype.Signed FUNC = lltype.FuncType([PLIST] * 2 + [INT] * 3, lltype.Void) func = lltype.functionptr(FUNC, 'll_arraycopy', _callable=ll_arraycopy) v1 = varoftype(PLIST) v2 = varoftype(PLIST) v3 = varoftype(INT) v4 = varoftype(INT) v5 = varoftype(INT) v6 = varoftype(lltype.Void) op = SpaceOperation('direct_call', [const(func), v1, v2, v3, v4, v5], v6) tr = Transformer(FakeCPU(), FakeBuiltinCallControl()) op1 = tr.rewrite_operation(op) assert op1.opname == 'residual_call_ir_v' assert op1.args[0].value == func assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_ARRAYCOPY assert op1.args[2] == ListOfKind('int', [v3, v4, v5]) assert op1.args[3] == ListOfKind('ref', [v1, v2])
def test_unicode_slice(): # test that the oopspec is present and correctly transformed PUNICODE = lltype.Ptr(rstr.UNICODE) INT = lltype.Signed FUNC = lltype.FuncType([PUNICODE, INT, INT], PUNICODE) func = lltype.functionptr(FUNC, '_ll_stringslice', _callable=rstr.LLHelpers._ll_stringslice) v1 = varoftype(PUNICODE) v2 = varoftype(INT) v3 = varoftype(INT) v4 = varoftype(PUNICODE) op = SpaceOperation('direct_call', [const(func), v1, v2, v3], v4) tr = Transformer(FakeCPU(), FakeBuiltinCallControl()) op1 = tr.rewrite_operation(op) assert op1.opname == 'residual_call_ir_r' assert op1.args[0].value == func assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_UNI_SLICE assert op1.args[2] == ListOfKind('int', [v2, v3]) assert op1.args[3] == ListOfKind('ref', [v1]) assert op1.result == v4
def _setup_repr_final(self): if self.gcflavor == 'gc': if (self.classdef is not None and self.classdef.classdesc.lookup('__del__') is not None): s_func = self.classdef.classdesc.s_read_attribute('__del__') source_desc = self.classdef.classdesc.lookup('__del__') source_classdef = source_desc.getclassdef(None) source_repr = getinstancerepr(self.rtyper, source_classdef) assert len(s_func.descriptions) == 1 funcdesc = s_func.descriptions.keys()[0] graph = funcdesc.getuniquegraph() FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void) destrptr = functionptr(FUNCTYPE, graph.name, graph=graph, _callable=graph.func) else: destrptr = None OBJECT = OBJECT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT, destrptr)