def ARRAY_ITER(ARRAY, INDEXARRAY, ITEM): ndim = dim_of_ARRAY(ARRAY) unroll_ndim = unrolling_iterable(range(ndim)) def ll_iter_reset(it, dataptr): it.index = 0 it.dataptr = dataptr for i in unroll_ndim: it.coordinates[i] = 0 ll_iter_reset._always_inline_ = True unroll_ndim_rev = unrolling_iterable(reversed(range(ndim))) def ll_iter_next(it): it.index += 1 for i in unroll_ndim_rev: if it.coordinates[i] < it.dims_m1[i]: it.coordinates[i] += 1 it.dataptr = direct_ptradd(it.dataptr, it.strides[i]) break it.coordinates[i] = 0 it.dataptr = direct_ptradd(it.dataptr, -it.backstrides[i]) ll_iter_next._always_inline_ = True DATA_PTR = Ptr(FixedSizeArray(ITEM, 1)) ADTIIter = ADTInterface(None, { 'll_reset': (['self', DATA_PTR], Void), 'll_next': (['self'], Void), }) ITER = Ptr( GcStruct( "array_iter", ("nd_m1", Signed), # number of dimensions - 1 ("index", NPY_INTP), ("size", NPY_INTP), ("coordinates", INDEXARRAY), ("dims_m1", INDEXARRAY), # array of dimensions - 1 ("strides", INDEXARRAY), ("backstrides", INDEXARRAY), #("factors", INDEXARRAY), #("ao", ARRAY), # not needed.. ("dataptr", DATA_PTR), # pointer to current item #("contiguous", Bool), adtmeths=ADTIIter({ 'll_next': ll_iter_next, 'll_reset': ll_iter_reset, }), )) return ITER
def __init__(self, step, *args): self.RANGE = Ptr( GcStruct("range", ("start", Signed), ("stop", Signed), adtmeths={ "ll_length": ll_length, "ll_getitem_fast": ll_getitem_fast, "step": step, }, hints={'immutable': True})) self.RANGEITER = Ptr( GcStruct("range", ("next", Signed), ("stop", Signed))) AbstractRangeRepr.__init__(self, step, *args) self.ll_newrange = ll_newrange self.ll_newrangest = ll_newrangest
def generic_initializationexpr(db, value, access_expr, decoration): if isinstance(typeOf(value), ContainerType): node = db.getcontainernode(value) lines = list(node.initializationexpr(decoration + '.')) lines[-1] += ',' return lines else: comma = ',' if typeOf(value) == Ptr(PyObject) and value: # cannot just write 'gxxx' as a constant in a structure :-( node = db.getcontainernode(value._obj) expr = 'NULL /*%s*/' % node.name node.where_to_copy_me.append('&%s' % access_expr) elif typeOf(value) == Float and (isinf(value) or isnan(value)): db.late_initializations.append(('%s' % access_expr, db.get(value))) expr = '0.0 /* patched later by %sinfinity */' % ('-+'[value > 0]) else: expr = db.get(value) if typeOf(value) is Void: comma = '' expr += comma i = expr.find('\n') if i < 0: i = len(expr) expr = '%s\t/* %s */%s' % (expr[:i], decoration, expr[i:]) return expr.split('\n')
def TUPLE_TYPE(field_lltypes): if len(field_lltypes) == 0: return Void # empty tuple else: fields = [('item%d' % i, TYPE) for i, TYPE in enumerate(field_lltypes)] kwds = {'hints': {'immutable': True, 'noidentity': True}} return Ptr(GcStruct('tuple%d' % len(field_lltypes), *fields, **kwds))
def OP_DEBUG_PRINT(self, op): # XXX from pypy.rpython.lltypesystem.rstr import STR format = [] argv = [] 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)) continue elif T == Signed: format.append('%d') 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)) return "fprintf(stderr, %s%s); RPyString_FreeCache();" % ( c_string_constant(' '.join(format) + '\n\000'), ''.join( [', ' + s for s in argv]))
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_newlist_hint": ll_newlist_hint, "ll_newemptylist": ll_newemptylist, "ll_length": ll_length, "ll_items": ll_items, ##"list_builder": self.list_builder, "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, })))
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]
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] vptr = llops.genop('malloc', 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
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 def ll_str(self, s): # XXX crazy that this is here, but I don't want to break # rmodel logic 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 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 __init__(self, r_list): self.r_list = r_list self.lowleveltype = Ptr( GcStruct('listiter', ('list', r_list.lowleveltype), ('index', Signed))) self.ll_listiter = ll_listiter self.ll_listnext = ll_listnext
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 __init__(self, rtyper, classdef): AbstractClassRepr.__init__(self, rtyper, classdef) if classdef is None: # 'object' root type self.vtable_type = OBJECT_VTABLE else: self.vtable_type = lltype.ForwardReference() self.lowleveltype = Ptr(self.vtable_type)
def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None, destrptr=None): self.call_all_setups() # compute ForwardReferences now if ARG_GCSTRUCT is None: ARG_GCSTRUCT = GCSTRUCT args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))] graph = self.annotate_helper(func, args_s) s = self.annotator.binding(graph.getreturnvar()) if (not isinstance(s, annmodel.SomePtr) or s.ll_ptrtype != Ptr(RuntimeTypeInfo)): raise TyperError("runtime type info function %r returns %r, " "excepted Ptr(RuntimeTypeInfo)" % (func, s)) funcptr = self.getcallable(graph) attachRuntimeTypeInfo(GCSTRUCT, funcptr, destrptr, None)
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 make_types(cls, ndim, ITEM): DATA_PTR = Ptr(FixedSizeArray(ITEM, 1)) ITEMARRAY = GcArray(ITEM, hints={'nolength': True}) INDEXARRAY = FixedSizeArray(NPY_INTP, ndim) STRUCT = GcStruct( "array", ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer ("dataptr", DATA_PTR), # pointer to first element ("ndim", Signed), # number of dimensions ("shape", INDEXARRAY), # size in each dimension ("strides", INDEXARRAY), # elements to jump to get to the # next element in each dimension adtmeths=ADTIArray({ "ll_allocate": ll_allocate, }), ) ARRAY = Ptr(STRUCT) return ARRAY, INDEXARRAY
class __extend__(pairtype(PyObjRepr, AbstractStringRepr)): def convert_from_to((r_from, r_to), v, llops): v_len = llops.gencapicall('PyString_Size', [v], resulttype=Signed) cstr = inputconst(Void, STR) cflags = inputconst(Void, {'flavor': 'gc'}) v_result = llops.genop('malloc_varsize', [cstr, cflags, v_len], resulttype=Ptr(STR)) llops.gencapicall('PyString_ToRPyString', [v, v_result]) string_repr = llops.rtyper.type_system.rstr.string_repr v_result = llops.convertvar(v_result, string_repr, r_to) return v_result
def __init__(self, rtyper, classdef, gcflavor='gc'): AbstractInstanceRepr.__init__(self, rtyper, classdef) if classdef is None: self.object_type = OBJECT_BY_FLAVOR[LLFLAVOR[gcflavor]] else: ForwardRef = lltype.FORWARDREF_BY_FLAVOR[LLFLAVOR[gcflavor]] self.object_type = ForwardRef() self.iprebuiltinstances = identity_dict() self.lowleveltype = Ptr(self.object_type) self.gcflavor = gcflavor
def OP_DEBUG_FATALERROR(self, op): # XXX from pypy.rpython.lltypesystem.rstr import STR msg = op.args[0] assert msg.concretetype == Ptr(STR) if isinstance(msg, Constant): msg = c_string_constant(''.join(msg.value.chars)) else: msg = 'RPyString_AsCharP(%s)' % self.expr(msg) return 'fprintf(stderr, "%%s\\n", %s); abort();' % msg
def __init__(self, r_list): self.r_list = r_list self.lowleveltype = Ptr( GcStruct('listiter', ('list', r_list.lowleveltype), ('index', Signed))) self.ll_listiter = ll_listiter if (isinstance(r_list, FixedSizeListRepr) and not r_list.listitem.mutated): self.ll_listnext = ll_listnext_foldable else: self.ll_listnext = ll_listnext self.ll_getnextindex = ll_getnextindex
def __init__(self, rtyper, item_repr, listitem=None): self.rtyper = rtyper self.LIST = GcForwardReference() self.lowleveltype = Ptr(self.LIST) if not isinstance(item_repr, Repr): # not computed yet, done by setup() assert callable(item_repr) self._item_repr_computer = item_repr else: self.external_item_repr, self.item_repr = externalvsinternal( rtyper, item_repr) self.listitem = listitem self.list_cache = {}
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 == Unsigned: format.append('%lu') 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 elif T == SignedLongLong: if sys.platform == 'win32': format.append('%I64d') else: format.append('%lld') elif T == UnsignedLongLong: if sys.platform == 'win32': format.append('%I64u') else: format.append('%llu') 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))
class RangeRepr(AbstractRangeRepr): RANGEST = Ptr(RANGEST) RANGESTITER = Ptr(RANGESTITER) getfield_opname = "getfield" def __init__(self, step, *args): self.RANGE = Ptr( GcStruct("range", ("start", Signed), ("stop", Signed), adtmeths={ "ll_length": ll_length, "ll_getitem_fast": ll_getitem_fast, "step": step, }, hints={'immutable': True})) self.RANGEITER = Ptr( GcStruct("range", ("next", Signed), ("stop", Signed))) AbstractRangeRepr.__init__(self, step, *args) self.ll_newrange = ll_newrange self.ll_newrangest = ll_newrangest def make_iterator_repr(self): return RangeIteratorRepr(self)
def do_stringformat(cls, hop, sourcevarsrepr): s_str = hop.args_s[0] assert s_str.is_constant() s = s_str.const things = cls.parse_fmt_string(s) size = inputconst(Signed, len(things)) # could be unsigned? cTEMP = inputconst(Void, TEMP) cflags = inputconst(Void, {'flavor': 'gc'}) vtemp = hop.genop("malloc_varsize", [cTEMP, cflags, size], resulttype=Ptr(TEMP)) argsiter = iter(sourcevarsrepr) InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr for i, thing in enumerate(things): if isinstance(thing, tuple): code = thing[0] vitem, r_arg = argsiter.next() if not hasattr(r_arg, 'll_str'): raise TyperError("ll_str unsupported for: %r" % r_arg) if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)): vchunk = hop.gendirectcall(r_arg.ll_str, vitem) elif code == 'd': assert isinstance(r_arg, IntegerRepr) #vchunk = hop.gendirectcall(r_arg.ll_str, vitem) vchunk = hop.gendirectcall(ll_str.ll_int2dec, vitem) elif code == 'f': #assert isinstance(r_arg, FloatRepr) vchunk = hop.gendirectcall(r_arg.ll_str, vitem) elif code == 'x': assert isinstance(r_arg, IntegerRepr) vchunk = hop.gendirectcall(ll_str.ll_int2hex, vitem, inputconst(Bool, False)) elif code == 'o': assert isinstance(r_arg, IntegerRepr) vchunk = hop.gendirectcall(ll_str.ll_int2oct, vitem, 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)
def guess_size_obj(obj): TYPE = typeOf(obj) ptr = _ptr(Ptr(TYPE), obj) if TYPE._is_varsize(): arrayfld = getattr(TYPE, '_arrayfld', None) if arrayfld: length = len(getattr(ptr, arrayfld)) else: try: length = len(ptr) except TypeError: print "couldn't find size of", ptr return 0 else: length = None return convert_offset_to_int(llmemory.sizeof(TYPE, length))
class StringRepr(BaseLLStringRepr, AbstractStringRepr): lowleveltype = Ptr(STR) basetype = str base = Char CACHE = CONST_STR_CACHE def __init__(self, *args): AbstractStringRepr.__init__(self, *args) self.ll = LLHelpers self.malloc = mallocstr def ll_decode_latin1(self, value): lgt = len(value.chars) s = mallocunicode(lgt) for i in range(lgt): s.chars[i] = cast_primitive(UniChar, value.chars[i]) return s
def conversion_table(r_from, r_to): if r_to in r_from._conversion_tables: return r_from._conversion_tables[r_to] else: t = malloc(Array(Char), len(r_from.descriptions), immortal=True) l = [] for i, d in enumerate(r_from.descriptions): if d in r_to.descriptions: j = r_to.descriptions.index(d) l.append(j) t[i] = chr(j) else: l.append(None) if l == range(len(r_from.descriptions)): r = None else: r = inputconst(Ptr(Array(Char)), t) r_from._conversion_tables[r_to] = r return r
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)
class __extend__(pairtype(SliceRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops): null = inputconst(Ptr(PyObject), nullptr(PyObject)) def pyint(v): return llops.gencapicall('PyInt_FromLong', [v], resulttype=r_to) v_step = v_start = v_stop = null if r_from.lowleveltype is Signed: v_start = pyint(v) elif r_from.lowleveltype is Void: v_stop = inputconst(r_to, -1) else: v_start = pyint( llops.genop('getfield', [v, inputconst(Void, 'start')], resulttype=Signed)) v_stop = pyint( llops.genop('getfield', [v, inputconst(Void, 'stop')], resulttype=Signed)) return llops.gencapicall('PySlice_New', [v_start, v_stop, v_step], resulttype=pyobj_repr)