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 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 OP_ADR_CALL(self, op): ARGTYPES = [v.concretetype for v in op.args[1:]] RESTYPE = op.result.concretetype FUNC = Ptr(FuncType(ARGTYPES, RESTYPE)) typename = self.db.gettype(FUNC) fnaddr = op.args[0] fnexpr = '((%s)%s)' % (cdecl(typename, ''), self.expr(fnaddr)) return self.generic_call(FUNC, fnexpr, op.args[1:], op.result)
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 _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)
hints={ 'immutable': True, 'shouldntbenull': True, 'typeptr': True }, rtti=True) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become( Struct( 'object_vtable', #('parenttypeptr', CLASSTYPE), ('subclassrange_min', Signed), ('subclassrange_max', Signed), ('rtti', Ptr(RuntimeTypeInfo)), ('name', Ptr(Array(Char))), ('instantiate', Ptr(FuncType([], OBJECTPTR))), hints={'immutable': True})) # non-gc case NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE)) NONGCOBJECTPTR = Ptr(NONGCOBJECT) OBJECT_BY_FLAVOR = {'gc': OBJECT, 'raw': NONGCOBJECT} LLFLAVOR = { 'gc': 'gc', 'raw': 'raw', 'stack': 'raw', } def cast_vtable_to_typeptr(vtable):
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 create_low_leveltype(self): l_args = [r_arg.lowleveltype for r_arg in self.args_r] l_retval = self.r_result.lowleveltype return Ptr(FuncType(l_args, l_retval))
def make_pyexcclass2exc(self, rtyper): # ll_pyexcclass2exc(python_exception_class) -> exception_instance table = {} Exception_def = rtyper.annotator.bookkeeper.getuniqueclassdef( Exception) for clsdef in rtyper.class_reprs: if (clsdef and clsdef is not Exception_def and clsdef.issubclass(Exception_def)): if not hasattr(clsdef.classdesc, 'pyobj'): continue cls = clsdef.classdesc.pyobj if cls in self.standardexceptions and cls not in FORCE_ATTRIBUTES_INTO_CLASSES: is_standard = True assert not clsdef.attrs, ( "%r should not have grown attributes" % (cls, )) else: is_standard = (cls.__module__ == 'exceptions' and not clsdef.attrs) if is_standard: example = self.get_standard_ll_exc_instance(rtyper, clsdef) table[cls] = example #else: # assert cls.__module__ != 'exceptions', ( # "built-in exceptions should not grow attributes") r_inst = rclass.getinstancerepr(rtyper, None) r_inst.setup() default_excinst = malloc(self.lltype_of_exception_value.TO, immortal=True) default_excinst.typeptr = r_inst.rclass.getvtable() # build the table in order base classes first, subclasses last sortedtable = [] def add_class(cls): if cls in table: for base in cls.__bases__: add_class(base) sortedtable.append((cls, table[cls])) del table[cls] for cls in table.keys(): add_class(cls) assert table == {} #print sortedtable A = Array(('pycls', Ptr(PyObject)), ('excinst', self.lltype_of_exception_value)) pycls2excinst = malloc(A, len(sortedtable), immortal=True) for i in range(len(sortedtable)): cls, example = sortedtable[i] pycls2excinst[i].pycls = pyobjectptr(cls) pycls2excinst[i].excinst = example FUNCTYPE = FuncType([Ptr(PyObject), Ptr(PyObject)], Signed) PyErr_GivenExceptionMatches = functionptr( FUNCTYPE, "PyErr_GivenExceptionMatches", external="C", _callable=lambda pyobj1, pyobj2: int( issubclass(pyobj1._obj.value, pyobj2._obj.value))) initial_value_of_i = len(pycls2excinst) - 1 def ll_pyexcclass2exc(python_exception_class): """Return an RPython instance of the best approximation of the Python exception identified by its Python class. """ i = initial_value_of_i while i >= 0: if PyErr_GivenExceptionMatches(python_exception_class, pycls2excinst[i].pycls): return pycls2excinst[i].excinst i -= 1 return default_excinst s_pyobj = annmodel.SomePtr(Ptr(PyObject)) helper_fn = rtyper.annotate_helper_fn(ll_pyexcclass2exc, [s_pyobj]) return helper_fn