def __init__(self, db, T, obj): self.db = db self.T = T self.obj = obj #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) self.implementationtypename = db.gettype(T, varlength=self.getlength()) parent, parentindex = parentlink(obj) if parent is None: self.name = db.namespace.uniquename('g_' + self.basename()) self.globalcontainer = True else: self.globalcontainer = False parentnode = db.getcontainernode(parent) defnode = db.gettypedefnode(parentnode.T) self.name = defnode.access_expr(parentnode.name, parentindex) self.ptrname = '(&%s)' % self.name if self.typename != self.implementationtypename: ptrtypename = db.gettype(Ptr(T)) self.ptrname = '((%s)(void*)%s)' % (cdecl(ptrtypename, ''), self.ptrname)
def _setup_repr(self): if self.s_pbc.subset_of: assert self.s_pbc.can_be_None == self.s_pbc.subset_of.can_be_None r = self.rtyper.getrepr(self.s_pbc.subset_of) if r is not self: r.setup() self.descriptions = r.descriptions self.c_pointer_table = r.c_pointer_table return self.descriptions = list(self.s_pbc.descriptions) if self.s_pbc.can_be_None: self.descriptions.insert(0, None) POINTER_TABLE = Array(self.pointer_repr.lowleveltype) pointer_table = malloc(POINTER_TABLE, len(self.descriptions), immortal=True) for i, desc in enumerate(self.descriptions): if desc is not None: pointer_table[i] = self.pointer_repr.convert_desc(desc) else: pointer_table[i] = self.pointer_repr.convert_const(None) self.c_pointer_table = inputconst(Ptr(POINTER_TABLE), pointer_table)
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)
def OP_DEBUG_PRINT(self, op): # XXX from pypy.rpython.lltypesystem.rstr import STR format = [] argv = [] free_line = "" for arg in op.args: T = arg.concretetype if T == Ptr(STR): if isinstance(arg, Constant): format.append(''.join(arg.value.chars).replace('%', '%%')) else: format.append('%s') argv.append('RPyString_AsCharP(%s)' % self.expr(arg)) free_line = "RPyString_FreeCache();" continue elif T == Signed: format.append('%ld') elif T == Float: format.append('%f') elif isinstance(T, Ptr) or T == Address: format.append('%p') elif T == Char: if isinstance(arg, Constant): format.append(arg.value.replace('%', '%%')) continue format.append('%c') elif T == Bool: format.append('%s') argv.append('(%s) ? "True" : "False"' % self.expr(arg)) continue else: raise Exception("don't know how to debug_print %r" % (T, )) argv.append(self.expr(arg)) argv.insert(0, c_string_constant(' '.join(format) + '\n')) return ( "if (PYPY_HAVE_DEBUG_PRINTS) { fprintf(PYPY_DEBUG_FILE, %s); %s}" % (', '.join(argv), free_line))
def _setup_repr(self): if 'item_repr' not in self.__dict__: self.external_item_repr, self.item_repr = externalvsinternal( self.rtyper, self._item_repr_computer()) if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype ITEMARRAY = self.get_itemarray_lowleveltype() # XXX we might think of turning length stuff into Unsigned self.LIST.become( GcStruct("list", ("length", Signed), ("items", Ptr(ITEMARRAY)), adtmeths=ADTIList({ "ll_newlist": ll_newlist, "ll_newemptylist": ll_newemptylist, "ll_length": ll_length, "ll_items": ll_items, "ITEM": ITEM, "ll_getitem_fast": ll_getitem_fast, "ll_setitem_fast": ll_setitem_fast, "_ll_resize_ge": _ll_list_resize_ge, "_ll_resize_le": _ll_list_resize_le, "_ll_resize": _ll_list_resize, }), hints={'list': True}))
def _find_exception_type(block): #XXX slightly brittle: find the exception type for simple cases #(e.g. if you do only raise XXXError) by doing pattern matching currvar = block.exits[0].args[1] ops = block.operations i = len(ops)-1 while True: if isinstance(currvar, Constant): value = currvar.value if isinstance(typeOf(value), ootype.Instance): TYPE = ootype.dynamicType(value) else: TYPE = typeOf(normalizeptr(value)) return TYPE, block.exits[0] if i < 0: return None, None op = ops[i] i -= 1 if op.opname in ("same_as", "cast_pointer", "ooupcast", "oodowncast") and op.result is currvar: currvar = op.args[0] elif op.opname == "malloc" and op.result is currvar: return Ptr(op.args[0].value), block.exits[0] elif op.opname == "new" and op.result is currvar: return op.args[0].value, block.exits[0]
class UnicodeRepr(BaseLLStringRepr, AbstractUnicodeRepr): lowleveltype = Ptr(UNICODE) basetype = basestring base = UniChar CACHE = CONST_UNICODE_CACHE def __init__(self, *args): AbstractUnicodeRepr.__init__(self, *args) self.ll = LLHelpers self.malloc = mallocunicode @jit.elidable def ll_str(self, s): # XXX crazy that this is here, but I don't want to break # rmodel logic if not s: return self.ll.ll_constant('None') lgt = len(s.chars) result = mallocstr(lgt) for i in range(lgt): c = s.chars[i] if ord(c) > 127: raise UnicodeEncodeError("character not in ascii range") result.chars[i] = cast_primitive(Char, c) return result @jit.elidable def ll_encode_latin1(self, s): length = len(s.chars) result = mallocstr(length) for i in range(length): c = s.chars[i] if ord(c) > 255: raise UnicodeEncodeError("character not in latin1 range") result.chars[i] = cast_primitive(Char, c) return result
def new_instance(self, llops, classcallhop=None): """Build a new instance, without calling __init__.""" flavor = self.gcflavor flags = {'flavor': flavor} ctype = inputconst(Void, self.object_type) cflags = inputconst(Void, flags) vlist = [ctype, cflags] cnonmovable = self.classdef.classdesc.read_attribute( '_alloc_nonmovable_', Constant(False)) if cnonmovable.value: opname = 'malloc_nonmovable' else: opname = 'malloc' vptr = llops.genop(opname, vlist, resulttype=Ptr(self.object_type)) ctypeptr = inputconst(CLASSTYPE, self.rclass.getvtable()) self.setfield(vptr, '__class__', ctypeptr, llops) # initialize instance attributes from their defaults from the class if self.classdef is not None: flds = self.allinstancefields.keys() flds.sort() for fldname in flds: if fldname == '__class__': continue mangled_name, r = self.allinstancefields[fldname] if r.lowleveltype is Void: continue value = self.classdef.classdesc.read_attribute(fldname, None) if value is not None: cvalue = inputconst(r.lowleveltype, r.convert_desc_or_const(value)) self.setfield(vptr, fldname, cvalue, llops, flags={'access_directly': True}) return vptr
def annotation(x): T = typeOf(x) if T == Ptr(PyObject) and someobjects: return object else: return lltype_to_annotation(T)
from pypy.translator.c.support import c_string_constant, barebonearray from pypy.objspace.flow.model import Variable, Constant, Block from pypy.objspace.flow.model import c_last_exception, copygraph from pypy.rpython.lltypesystem.lltype import Ptr, PyObject, Void, Bool, Signed from pypy.rpython.lltypesystem.lltype import Unsigned, SignedLongLong, Float from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray from pypy.rpython.lltypesystem.lltype import ForwardReference, FuncType from pypy.rpython.lltypesystem.llmemory import Address from pypy.translator.backendopt.ssa import SSI_to_SSA from pypy.translator.backendopt.innerloop import find_inner_loops from pypy.tool.identity_dict import identity_dict PyObjPtr = Ptr(PyObject) LOCALVAR = 'l_%s' KEEP_INLINED_GRAPHS = False class FunctionCodeGenerator(object): """ Collects information about a function which we have to generate from a flow graph. """ if USESLOTS: __slots__ = """graph db gcpolicy exception_policy more_ll_values vars all_cached_consts
from pypy.rpython.lltypesystem import rffi, lltype from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP, PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP, Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE) from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref from pypy.module.cpyext.modsupport import PyMethodDef P, FT, PyO = Ptr, FuncType, PyObject PyOPtr = Ptr(lltype.Array(PyO, hints={'nolength': True})) freefunc = P(FT([rffi.VOIDP], Void)) destructor = P(FT([PyO], Void)) printfunc = P(FT([PyO, FILEP, rffi.INT_real], rffi.INT)) getattrfunc = P(FT([PyO, rffi.CCHARP], PyO)) getattrofunc = P(FT([PyO, PyO], PyO)) setattrfunc = P(FT([PyO, rffi.CCHARP, PyO], rffi.INT_real)) setattrofunc = P(FT([PyO, PyO, PyO], rffi.INT_real)) cmpfunc = P(FT([PyO, PyO], rffi.INT_real)) reprfunc = P(FT([PyO], PyO)) hashfunc = P(FT([PyO], lltype.Signed)) richcmpfunc = P(FT([PyO, PyO, rffi.INT_real], PyO)) getiterfunc = P(FT([PyO], PyO)) iternextfunc = P(FT([PyO], PyO)) descrgetfunc = P(FT([PyO, PyO, PyO], PyO)) descrsetfunc = P(FT([PyO, PyO, PyO], rffi.INT_real)) initproc = P(FT([PyO, PyO, PyO], rffi.INT_real)) newfunc = P(FT([PyTypeObjectPtr, PyO, PyO], PyO)) allocfunc = P(FT([PyTypeObjectPtr, Py_ssize_t], PyO))
return "type" if s_obj.is_constant(): return "const" return "pyobj" class PyObjRepr(Repr): def convert_const(self, value): return pyobjectptr(value) def make_iterator_repr(self): return pyobj_repr pyobj_repr = PyObjRepr() pyobj_repr.lowleveltype = Ptr(PyObject) constpyobj_repr = PyObjRepr() constpyobj_repr.lowleveltype = Void class __extend__(pairtype(VoidRepr, PyObjRepr)): # conversion used to return a PyObject* when a function can really only # raise an exception, in which case the return value is a VoidRepr def convert_from_to(_, v, llops): return inputconst(Ptr(PyObject), nullptr(PyObject)) # ____________________________________________________________ # # All operations involving a PyObjRepr are "replaced" by themselves, # after converting all other arguments to PyObjRepr as well. This
class StringIteratorRepr(BaseStringIteratorRepr): lowleveltype = Ptr( GcStruct('stringiter', ('string', string_repr.lowleveltype), ('index', Signed)))
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
def get_lltype_of_exception_value(self): if self.translator is not None and self.translator.rtyper is not None: exceptiondata = self.translator.rtyper.getexceptiondata() return exceptiondata.lltype_of_exception_value else: return Ptr(PyObject)
def __init__(self, rtyper, access_set): self.rtyper = rtyper self.access_set = access_set self.pbc_type = ForwardReference() self.lowleveltype = Ptr(self.pbc_type) self.pbc_cache = {}
def setup_specfunc(self): fields = [] for row in self.uniquerows: fields.append((row.attrname, row.fntype)) kwds = {'hints': {'immutable': True}} return Ptr(Struct('specfunc', *fields, **kwds))
def convert_from_to(_, v, llops): return inputconst(Ptr(PyObject), nullptr(PyObject))
def __init__(self, r_tuple): self.r_tuple = r_tuple self.lowleveltype = Ptr( GcStruct('tuple1iter', ('tuple', r_tuple.lowleveltype))) self.ll_tupleiter = ll_tupleiter self.ll_tuplenext = ll_tuplenext
# struct slice { # Signed start; # Signed stop; # // step is always 1 # } SLICE = GcStruct("slice", ("start", Signed), ("stop", Signed), hints={'immutable': True}) class SliceRepr(AbstractSliceRepr): pass startstop_slice_repr = SliceRepr() startstop_slice_repr.lowleveltype = Ptr(SLICE) startonly_slice_repr = SliceRepr() startonly_slice_repr.lowleveltype = Signed minusone_slice_repr = SliceRepr() minusone_slice_repr.lowleveltype = Void # only for [:-1] # ____________________________________________________________ def ll_newslice(start, stop): s = malloc(SLICE) s.start = start s.stop = stop return s
inputconst(Bool, False)) else: raise TyperError, "%%%s is not RPython" % (code, ) else: from pypy.rpython.lltypesystem.rstr import string_repr vchunk = inputconst(string_repr, thing) i = inputconst(Signed, i) hop.genop('setarrayitem', [vtemp, i, vchunk]) hop.exception_cannot_occur() # to ignore the ZeroDivisionError of '%' return hop.gendirectcall(cls.ll_join_strs, size, vtemp) do_stringformat = classmethod(do_stringformat) TEMP = GcArray(Ptr(STR)) # TODO: make the public interface of the rstr module cleaner ll_strconcat = LLHelpers.ll_strconcat ll_join = LLHelpers.ll_join do_stringformat = LLHelpers.do_stringformat string_repr = StringRepr() char_repr = CharRepr() unichar_repr = UniCharRepr() char_repr.ll = LLHelpers unichar_repr.ll = LLHelpers unicode_repr = UnicodeRepr() emptystr = string_repr.convert_const("") emptyunicode = unicode_repr.convert_const(u'')
# The type of the instances is: # # struct object { // for the root class # struct object_vtable* typeptr; # } # # struct X { # struct Y super; // inlined # ... // extra instance attributes # } # # there's also a nongcobject OBJECT_VTABLE = lltype.ForwardReference() CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), 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)),
class UnicodeIteratorRepr(BaseStringIteratorRepr): lowleveltype = Ptr( GcStruct('unicodeiter', ('string', unicode_repr.lowleveltype), ('index', Signed)))
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))