def test_func_simple(): # -------------------- flowgraph building -------------------- # def f(x): # return x+1 x = Variable("x") x.concretetype = Signed result = Variable("result") result.concretetype = Signed one = Constant(1) one.concretetype = Signed op = SpaceOperation("int_add", [x, one], result) block = Block([x]) graph = FunctionGraph("f", block) block.operations.append(op) block.closeblock(Link([result], graph.returnblock)) graph.getreturnvar().concretetype = Signed # -------------------- end -------------------- F = FuncType([Signed], Signed) f = functionptr(F, "f", graph=graph) db = LowLevelDatabase() db.get(f) db.complete() dump_on_stdout(db) S = GcStruct('testing', ('fptr', Ptr(F))) s = malloc(S) s.fptr = f db = LowLevelDatabase() db.get(s) db.complete() dump_on_stdout(db)
def test_func_simple(): # -------------------- flowgraph building -------------------- # def f(x): # return x+1 x = Variable("x") x.concretetype = Signed result = Variable("result") result.concretetype = Signed one = Constant(1) one.concretetype = Signed op = SpaceOperation("int_add", [x, one], result) block = Block([x]) graph = FunctionGraph("f", block) block.operations.append(op) block.closeblock(Link([result], graph.returnblock)) graph.getreturnvar().concretetype = Signed # -------------------- end -------------------- F = FuncType([Signed], Signed) f = functionptr(F, "f", graph=graph) db = LowLevelDatabase() db.get(f) db.complete() dump_on_stdout(db) S = GcStruct('testing', ('fptr', Ptr(F))) s = malloc(S) s.fptr = f db = LowLevelDatabase() db.get(s) db.complete() dump_on_stdout(db)
def create_instantiate_function(annotator, classdef): # build the graph of a function that looks like # # def my_instantiate(): # return instantiate(cls) # if hasattr(classdef, 'my_instantiate_graph'): return v = Variable() block = Block([]) block.operations.append(SpaceOperation('instantiate1', [], v)) name = valid_identifier('instantiate_'+classdef.name) graph = FunctionGraph(name, block) block.closeblock(Link([v], graph.returnblock)) annotator.setbinding(v, annmodel.SomeInstance(classdef)) annotator.annotated[block] = graph # force the result to be converted to a generic OBJECTPTR generalizedresult = annmodel.SomeInstance(classdef=None) annotator.setbinding(graph.getreturnvar(), generalizedresult) classdef.my_instantiate_graph = graph annotator.translator.graphs.append(graph)
def create_instantiate_function(annotator, classdef): # build the graph of a function that looks like # # def my_instantiate(): # return instantiate(cls) # if hasattr(classdef, 'my_instantiate_graph'): return v = Variable() block = Block([]) block.operations.append(SpaceOperation('instantiate1', [], v)) name = valid_identifier('instantiate_'+classdef.name) graph = FunctionGraph(name, block) block.closeblock(Link([v], graph.returnblock)) annotator.setbinding(v, annmodel.SomeInstance(classdef)) annotator.annotated[block] = graph # force the result to be converted to a generic OBJECTPTR generalizedresult = annmodel.SomeInstance(classdef=None) annotator.setbinding(graph.getreturnvar(), generalizedresult) classdef.my_instantiate_graph = graph annotator.translator.graphs.append(graph)
def build_callback_graph(self, graph, metadesccls=False): args_v = [copyvar(None, v) for v in graph.getargs()] v_res = copyvar(None, graph.getreturnvar()) rtyper = self.bookkeeper.annotator.base_translator.rtyper # fish fnptr = rtyper.getcallable(graph) v_ptr = Constant(fnptr, lltype.typeOf(fnptr)) newstartblock = Block(args_v) if metadesccls: v_metadesccls = Constant(metadesccls, lltype.Void) args_v = [v_metadesccls] + args_v opname = 'ts_metacall' suffix = 'ts_metacall' else: opname = 'direct_call' suffix = 'ts_stub' newstartblock.operations.append( SpaceOperation(opname, [v_ptr] + args_v, v_res)) newgraph = FunctionGraph('%s_%s' % (graph.name, suffix), newstartblock) newgraph.getreturnvar().concretetype = v_res.concretetype newstartblock.closeblock(Link([v_res], newgraph.returnblock)) return newgraph
def new_wrapper(func, translator, newname=None): # The basic idea is to produce a flow graph from scratch, using the # help of the rtyper for the conversion of the arguments after they # have been decoded. bk = translator.annotator.bookkeeper graph = bk.getdesc(func).getuniquegraph() f = getfunctionptr(graph) FUNCTYPE = typeOf(f).TO newops = LowLevelOpList(translator.rtyper) varguments = [] for var in graph.startblock.inputargs: v = Variable(var) v.concretetype = PyObjPtr varguments.append(v) wrapper_inputargs = varguments[:] # use the rtyper to produce the conversions inputargs = f._obj.graph.getargs() for i in range(len(varguments)): if FUNCTYPE.ARGS[i] != PyObjPtr: rtyper = translator.rtyper r_arg = rtyper.bindingrepr(inputargs[i]) # give the rtyper a chance to know which function we are wrapping rtyper.set_wrapper_context(func) varguments[i] = newops.convertvar(varguments[i], r_from = pyobj_repr, r_to = r_arg) rtyper.set_wrapper_context(None) vlist = [inputconst(typeOf(f), f)] + varguments vresult = newops.genop('direct_call', vlist, resulttype=FUNCTYPE.RESULT) if FUNCTYPE.RESULT != PyObjPtr: # convert "result" back to a PyObject rtyper = translator.rtyper assert rtyper is not None, ( "needs the rtyper to perform function result conversions") r_result = rtyper.bindingrepr(f._obj.graph.getreturnvar()) vresult = newops.convertvar(vresult, r_from = r_result, r_to = pyobj_repr) # "return result" block = Block(wrapper_inputargs) wgraph = FunctionGraph('pyfn_' + (newname or func.func_name), block) translator.update_call_graph(wgraph, graph, object()) translator.graphs.append(wgraph) block.operations[:] = newops block.closeblock(Link([vresult], wgraph.returnblock)) wgraph.getreturnvar().concretetype = PyObjPtr checkgraph(wgraph) # the above convertvar()s may have created and annotated new helpers # that need to be specialized now translator.rtyper.specialize_more_blocks() return functionptr(FuncType([PyObjPtr] * len(wrapper_inputargs), PyObjPtr), wgraph.name, graph = wgraph, exception_policy = "CPython")
def build_pytypeobject(r_inst): rtyper = r_inst.rtyper cache = rtyper.classdef_to_pytypeobject try: return cache[r_inst.classdef] except KeyError: for parentdef in r_inst.classdef.getmro(): cpytype = parentdef._cpy_exported_type_ if cpytype is not None: break else: # for classes that cannot be exported at all return lltype.nullptr(lltype.PyObject) from pypy.rpython.lltypesystem.rclass import CPYOBJECTPTR from pypy.rpython.rtyper import LowLevelOpList typetype = lltype.pyobjectptr(type) # XXX default tp_new should go away # make the graph of tp_new manually v1 = Variable('tp'); v1.concretetype = lltype.Ptr(PY_TYPE_OBJECT) v2 = Variable('args'); v2.concretetype = PyObjPtr v3 = Variable('kwds'); v3.concretetype = PyObjPtr block = Block([v1, v2, v3]) llops = LowLevelOpList(None) v4 = r_inst.new_instance(llops, v_cpytype = v1) v5 = llops.genop('cast_pointer', [v4], resulttype = PyObjPtr) block.operations = list(llops) tp_new_graph = FunctionGraph('ll_tp_new', block) block.closeblock(Link([v5], tp_new_graph.returnblock)) tp_new_graph.getreturnvar().concretetype = v5.concretetype # build the PyTypeObject structure pytypeobj = lltype.malloc(PY_TYPE_OBJECT, flavor='cpy', extra_args=(typetype,)) name = cpytype.name T = lltype.FixedSizeArray(lltype.Char, len(name)+1) p = lltype.malloc(T, immortal=True) for i in range(len(name)): p[i] = name[i] p[len(name)] = '\x00' pytypeobj.c_tp_name = lltype.direct_arrayitems(p) pytypeobj.c_tp_basicsize = llmemory.sizeof(r_inst.lowleveltype.TO) if cpytype.subclassable and False: # XXX deallocation of subclass object segfaults! pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_BASETYPE)''') else: pytypeobj.c_tp_flags = CDefinedIntSymbolic('''(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES)''') pytypeobj.c_tp_new = rtyper.type_system.getcallable(tp_new_graph) pytypeobj.c_tp_dealloc = rtyper.annotate_helper_fn(ll_tp_dealloc, [PyObjPtr]) pytypeobj.c_tp_as_number = lltype.malloc(PyNumberMethods, immortal=True) pytypeobj.c_tp_as_sequence = lltype.malloc(PySequenceMethods, immortal=True) pytypeobj.c_tp_as_mapping = lltype.malloc(PyMappingMethods, immortal=True) result = lltype.cast_pointer(PyObjPtr, pytypeobj) # the llsetup function that will store the 'objects' into the # type's tp_dict Py_TPFLAGS_HEAPTYPE = CDefinedIntSymbolic('Py_TPFLAGS_HEAPTYPE') if cpytype.objects: objects = [(lltype.pyobjectptr(name), value) for name, value in cpytype.objects.items() if name != '__new__'] if '__new__' in cpytype.objects: new = cpytype.objects['__new__']._obj.value objects.append((lltype.pyobjectptr('__new__'), lltype.pyobjectptr(staticmethod(new)))) def ll_type_setup(p): tp = lltype.cast_pointer(lltype.Ptr(PY_TYPE_OBJECT), p) old_flags = tp.c_tp_flags tp.c_tp_flags |= Py_TPFLAGS_HEAPTYPE for name, value in objects: llop.setattr(PyObjPtr, tp, name, value) tp.c_tp_flags = old_flags result._obj.setup_fnptr = rtyper.annotate_helper_fn(ll_type_setup, [PyObjPtr]) cache[r_inst.classdef] = result return result