def _setup_repr_final(self): self._setup_immutable_field_list() self._check_for_immutable_conflicts() 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( self.rtyper, graph) FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void) destrptr = functionptr(FUNCTYPE, graph.name, graph=graph, _callable=graph.func) else: destrptr = None self.rtyper.call_all_setups() # compute ForwardReferences now args_s = [SomePtr(Ptr(OBJECT))] graph = self.rtyper.annotate_helper(ll_runtime_type_info, args_s) s = self.rtyper.annotation(graph.getreturnvar()) if (not isinstance(s, SomePtr) or s.ll_ptrtype != Ptr(RuntimeTypeInfo)): raise TyperError("runtime type info function returns %r, " "expected Ptr(RuntimeTypeInfo)" % (s)) funcptr = self.rtyper.getcallable(graph) attachRuntimeTypeInfo(self.object_type, funcptr, destrptr) vtable = self.rclass.getvtable() self.rtyper.set_type_for_typeptr(vtable, self.lowleveltype.TO)
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, variant=None): if variant is not None: raise TyperError("unsupported %r iterator over a range list" % (variant, )) return RangeIteratorRepr(self)
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 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: ll_value = r.convert_desc_or_const(value) # don't write NULL GC pointers: we know that the malloc # done above initialized at least the GC Ptr fields to # NULL already, and that's true for all our GCs if (isinstance(r.lowleveltype, Ptr) and r.lowleveltype.TO._gckind == 'gc' and not ll_value): continue cvalue = inputconst(r.lowleveltype, ll_value) self.setfield(vptr, fldname, cvalue, llops, flags={'access_directly': True}) return vptr
class UnicodeIteratorRepr(BaseStringIteratorRepr): external_item_repr = unichar_repr lowleveltype = Ptr(GcStruct('unicodeiter', ('string', unicode_repr.lowleveltype), ('length', Signed), ('index', Signed)))
class StringIteratorRepr(BaseStringIteratorRepr): external_item_repr = char_repr lowleveltype = Ptr(GcStruct('stringiter', ('string', string_repr.lowleveltype), ('length', Signed), ('index', Signed)))
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 _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, "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, "_ll_resize_hint": _ll_list_resize_hint, }), hints = {'list': True}) )
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 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: if TYPE._hints.get("nolength", False) and hasattr( obj, "items"): length = len(obj.items) else: print "couldn't find size of", ptr return 0 else: length = None if type(TYPE) is llgroup.GroupType: return sum(guess_size_obj(m) for m in obj.members) #print obj, ', length =', length r = convert_offset_to_int(llmemory.sizeof(TYPE, length)) #print '\tr =', r return r
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, hints={ 'nolength': True, 'immutable': True, 'static_immutable': True }) 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 __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 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 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 = [SomePtr(Ptr(ARG_GCSTRUCT))] graph = self.annotate_helper(func, args_s) s = self.annotation(graph.getreturnvar()) if (not isinstance(s, 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)
def __init__(self, r_list): self.r_list = r_list self.lowleveltype = Ptr(GcStruct('revlistiter', ('list', r_list.lowleveltype), ('index', Signed), )) self.ll_listnext = ll_revlistnext self.ll_listiter = ll_revlistiter
def ll_strconcat(s1, s2): len1 = s1.length() len2 = s2.length() # a single '+' like this is allowed to overflow: it gets # a negative result, and the gc will complain # the typechecks below are if TP == BYTEARRAY if typeOf(s1) == Ptr(STR): newstr = s2.malloc(len1 + len2) newstr.copy_contents_from_str(s1, newstr, 0, 0, len1) else: newstr = s1.malloc(len1 + len2) newstr.copy_contents(s1, newstr, 0, 0, len1) if typeOf(s2) == Ptr(STR): newstr.copy_contents_from_str(s2, newstr, 0, len1, len2) else: newstr.copy_contents(s2, newstr, 0, len1, len2) return newstr
def OP_DEBUG_PRINT(self, op): # XXX from rpython.rtyper.lltypesystem.rstr import STR format = [] argv = [] if self.db.reverse_debugger: format.append('{%d} ') argv.append('(int)getpid()') 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 == INT: format.append('%d') 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))
def OP_DEBUG_FATALERROR(self, op): # XXX from rpython.rtyper.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, rtyper, classdef, gcflavor='gc'): self.rtyper = rtyper self.classdef = 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 __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 = {}
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 name_gcref(value, db): if value: obj = value._obj if isinstance(obj, int): # a tagged pointer return _name_tagged(obj, db) realobj = obj.container if isinstance(realobj, int): return _name_tagged(realobj, db) realvalue = cast_opaque_ptr(Ptr(typeOf(realobj)), value) return db.get(realvalue) else: return 'NULL'
def __init__(self, r_list): self.r_list = r_list self.external_item_repr = r_list.external_item_repr 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
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 rtype_getattr(self, hop): if hop.s_result.is_constant(): return hop.inputconst(hop.r_result, hop.s_result.const) else: attr = hop.args_s[1].const if attr == '__name__': from rpython.rtyper.lltypesystem import rstr class_repr = self.rtyper.rootclass_repr vcls, vattr = hop.inputargs(class_repr, Void) cname = inputconst(Void, 'name') return hop.genop('getfield', [vcls, cname], resulttype=Ptr(rstr.STR)) access_set, class_repr = self.get_access_set(attr) vcls, vattr = hop.inputargs(class_repr, Void) v_res = class_repr.getpbcfield(vcls, access_set, attr, hop.llops) s_res = access_set.s_value r_res = self.rtyper.getrepr(s_res) return hop.llops.convertvar(v_res, r_res, hop.r_result)
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 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") 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]
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 #print obj, ', length =', length r = convert_offset_to_int(llmemory.sizeof(TYPE, length)) #print '\tr =', r return r
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_unicode(self, s): if s: return s else: return self.ll.ll_constant_unicode(u'None') @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 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, hints={'nolength': True}), 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, hints={'nolength': True})), t) r_from._conversion_tables[r_to] = r return r
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