from pypy.tool.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow import model as flowmodel from pypy.rpython.lltypesystem import lltype from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IntegerRepr from pypy.rlib.rarithmetic import r_uint class __extend__(annmodel.SomePtr): def rtyper_makerepr(self, rtyper): ## if self.is_constant() and not self.const: # constant NULL ## return nullptr_repr ## else: return PtrRepr(self.ll_ptrtype) def rtyper_makekey(self): ## if self.is_constant() and not self.const: ## return None ## else: return self.__class__, self.ll_ptrtype class __extend__(annmodel.SomeInteriorPtr): def rtyper_makerepr(self, rtyper): return InteriorPtrRepr(self.ll_ptrtype) class PtrRepr(Repr): def __init__(self, ptrtype): assert isinstance(ptrtype, lltype.Ptr) self.lowleveltype = ptrtype def ll_str(self, p): from pypy.rpython.lltypesystem.rstr import ll_str id = lltype.cast_ptr_to_int(p) return ll_str.ll_int2hex(r_uint(id), True) def rtype_getattr(self, hop): attr = hop.args_s[1].const if isinstance(hop.s_result, annmodel.SomeLLADTMeth): return hop.inputarg(hop.r_result, arg=0) try: self.lowleveltype._example()._lookup_adtmeth(attr) except AttributeError: pass else: assert hop.s_result.is_constant() return hop.inputconst(hop.r_result, hop.s_result.const) assert attr in self.lowleveltype.TO._flds # check that the field exists FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, lltype.ContainerType): if (attr, FIELD_TYPE) == self.lowleveltype.TO._first_struct(): return hop.genop('cast_pointer', [hop.inputarg(self, 0)], resulttype=hop.r_result.lowleveltype) elif isinstance(hop.r_result, InteriorPtrRepr): return hop.inputarg(self, 0) else: newopname = 'getsubstruct' else: newopname = 'getfield' vlist = hop.inputargs(self, lltype.Void) return hop.genop(newopname, vlist, resulttype = hop.r_result.lowleveltype) def rtype_setattr(self, hop): attr = hop.args_s[1].const FIELD_TYPE = getattr(self.lowleveltype.TO, attr) assert not isinstance(FIELD_TYPE, lltype.ContainerType) vlist = hop.inputargs(self, lltype.Void, hop.args_r[2]) hop.genop('setfield', vlist) def rtype_len(self, hop): ARRAY = hop.args_r[0].lowleveltype.TO if isinstance(ARRAY, lltype.FixedSizeArray): return hop.inputconst(lltype.Signed, ARRAY.length) else: vlist = hop.inputargs(self) return hop.genop('getarraysize', vlist, resulttype = hop.r_result.lowleveltype) def rtype_is_true(self, hop): vlist = hop.inputargs(self) return hop.genop('ptr_nonzero', vlist, resulttype=lltype.Bool) def rtype_simple_call(self, hop): if not isinstance(self.lowleveltype.TO, lltype.FuncType): raise TyperError("calling a non-function %r", self.lowleveltype.TO) vlist = hop.inputargs(*hop.args_r) nexpected = len(self.lowleveltype.TO.ARGS) nactual = len(vlist)-1 if nactual != nexpected: raise TyperError("argcount mismatch: expected %d got %d" % (nexpected, nactual)) if isinstance(vlist[0], flowmodel.Constant): if hasattr(vlist[0].value, 'graph'): hop.llops.record_extra_call(vlist[0].value.graph) opname = 'direct_call' else: opname = 'indirect_call' vlist.append(hop.inputconst(lltype.Void, None)) hop.exception_is_here() return hop.genop(opname, vlist, resulttype = self.lowleveltype.TO.RESULT) def rtype_call_args(self, hop): from pypy.rpython.rbuiltin import call_args_expand hop, _ = call_args_expand(hop, takes_kwds=False) hop.swap_fst_snd_args() hop.r_s_popfirstarg() return self.rtype_simple_call(hop) class __extend__(pairtype(PtrRepr, IntegerRepr)): def rtype_getitem((r_ptr, r_int), hop): ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, lltype.ContainerType): if isinstance(hop.r_result, InteriorPtrRepr): v_array, v_index = hop.inputargs(r_ptr, lltype.Signed) INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'}) args = [flowmodel.Constant(INTERIOR_PTR_TYPE, lltype.Void), cflags] v_interior_ptr = hop.genop('malloc', args, resulttype=lltype.Ptr(INTERIOR_PTR_TYPE)) hop.genop('setfield', [v_interior_ptr, flowmodel.Constant('ptr', lltype.Void), v_array]) hop.genop('setfield', [v_interior_ptr, flowmodel.Constant('index', lltype.Void), v_index]) return v_interior_ptr else: newopname = 'getarraysubstruct' else: newopname = 'getarrayitem' vlist = hop.inputargs(r_ptr, lltype.Signed) return hop.genop(newopname, vlist, resulttype = hop.r_result.lowleveltype) def rtype_setitem((r_ptr, r_int), hop): ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF assert not isinstance(ITEM_TYPE, lltype.ContainerType) vlist = hop.inputargs(r_ptr, lltype.Signed, hop.args_r[2]) hop.genop('setarrayitem', vlist) # ____________________________________________________________ # # Null Pointers ##class NullPtrRepr(Repr): ## lowleveltype = lltype.Void ## def rtype_is_true(self, hop): ## return hop.inputconst(lltype.Bool, False) ##nullptr_repr = NullPtrRepr() ##class __extend__(pairtype(NullPtrRepr, PtrRepr)): ## def convert_from_to((r_null, r_ptr), v, llops): ## # nullptr to general pointer ## return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None)) # ____________________________________________________________ # # Comparisons class __extend__(pairtype(PtrRepr, Repr)): def rtype_eq((r_ptr, r_any), hop): vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool) def rtype_ne((r_ptr, r_any), hop): vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool) class __extend__(pairtype(Repr, PtrRepr)): def rtype_eq((r_any, r_ptr), hop): vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool) def rtype_ne((r_any, r_ptr), hop): vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool) # ________________________________________________________________ # ADT methods class __extend__(annmodel.SomeLLADTMeth): def rtyper_makerepr(self, rtyper): return LLADTMethRepr(self, rtyper) def rtyper_makekey(self): return self.__class__, self.ll_ptrtype, self.func class LLADTMethRepr(Repr): def __init__(self, adtmeth, rtyper): self.func = adtmeth.func self.lowleveltype = adtmeth.ll_ptrtype self.ll_ptrtype = adtmeth.ll_ptrtype self.lowleveltype = rtyper.getrepr(annmodel.lltype_to_annotation(adtmeth.ll_ptrtype)).lowleveltype def rtype_simple_call(self, hop): hop2 = hop.copy() func = self.func s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func) v_ptr = hop2.args_v[0] hop2.r_s_popfirstarg() hop2.v_s_insertfirstarg( v_ptr, annmodel.lltype_to_annotation(self.ll_ptrtype)) hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func) return hop2.dispatch() class __extend__(pairtype(PtrRepr, LLADTMethRepr)): def convert_from_to((r_from, r_to), v, llops): if r_from.lowleveltype == r_to.lowleveltype: return v return NotImplemented class InteriorPtrRepr(Repr): def __init__(self, ptrtype): assert isinstance(ptrtype, lltype.InteriorPtr) self.v_offsets = [] numitemoffsets = 0 for i, offset in enumerate(ptrtype.offsets): if isinstance(offset, int): numitemoffsets += 1 self.v_offsets.append(None) else: assert isinstance(offset, str) self.v_offsets.append(flowmodel.Constant(offset, lltype.Void)) self.parentptrtype = lltype.Ptr(ptrtype.PARENTTYPE) self.resulttype = lltype.Ptr(ptrtype.TO) assert numitemoffsets <= 1 if numitemoffsets > 0: self.lowleveltype = lltype.Ptr(self.parentptrtype._interior_ptr_type_with_index(self.resulttype.TO)) else: self.lowleveltype = self.parentptrtype def getinteriorfieldargs(self, hop, v_self): vlist = [] if None in self.v_offsets: INTERIOR_TYPE = v_self.concretetype.TO nameiter = iter(INTERIOR_TYPE._names) name = nameiter.next() vlist.append( hop.genop('getfield', [v_self, flowmodel.Constant(name, lltype.Void)], resulttype=INTERIOR_TYPE._flds[name])) else: vlist.append(v_self) for v_offset in self.v_offsets: if v_offset is None: name = nameiter.next() vlist.append( hop.genop('getfield', [v_self, flowmodel.Constant(name, lltype.Void)], resulttype=INTERIOR_TYPE._flds[name])) else: vlist.append(v_offset) if None in self.v_offsets: try: nameiter.next() except StopIteration: pass else: assert False return vlist def rtype_len(self, hop): v_self, = hop.inputargs(self) vlist = self.getinteriorfieldargs(hop, v_self) return hop.genop('getinteriorarraysize', vlist, resulttype=lltype.Signed) def rtype_getattr(self, hop): attr = hop.args_s[1].const if isinstance(hop.s_result, annmodel.SomeLLADTMeth): return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.resulttype.TO, attr) if isinstance(FIELD_TYPE, lltype.ContainerType): return hop.inputarg(self, 0) else: v_self, v_attr = hop.inputargs(self, lltype.Void) vlist = self.getinteriorfieldargs(hop, v_self) + [v_attr] return hop.genop('getinteriorfield', vlist, resulttype=hop.r_result.lowleveltype) def rtype_setattr(self, hop): attr = hop.args_s[1].const FIELD_TYPE = getattr(self.resulttype.TO, attr) assert not isinstance(FIELD_TYPE, lltype.ContainerType) v_self, v_fieldname, v_value = hop.inputargs(self, lltype.Void, hop.args_r[2]) vlist = self.getinteriorfieldargs(hop, v_self) + [v_fieldname, v_value] return hop.genop('setinteriorfield', vlist) class __extend__(pairtype(InteriorPtrRepr, IntegerRepr)): def rtype_getitem((r_ptr, r_item), hop): ARRAY = r_ptr.resulttype.TO ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, lltype.ContainerType): v_array, v_index = hop.inputargs(r_ptr, lltype.Signed) INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE) cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'}) args = [flowmodel.Constant(INTERIOR_PTR_TYPE, lltype.Void), cflags] v_interior_ptr = hop.genop('malloc', args, resulttype=lltype.Ptr(INTERIOR_PTR_TYPE)) hop.genop('setfield', [v_interior_ptr, flowmodel.Constant('ptr', lltype.Void), v_array]) hop.genop('setfield', [v_interior_ptr, flowmodel.Constant('index', lltype.Void), v_index]) return v_interior_ptr else: v_self, v_index = hop.inputargs(r_ptr, lltype.Signed) vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index] return hop.genop('getinteriorfield', vlist, resulttype=ITEM_TYPE) def rtype_setitem((r_ptr, r_index), hop): ARRAY = r_ptr.resulttype.TO ITEM_TYPE = ARRAY.OF assert not isinstance(ITEM_TYPE, lltype.ContainerType) v_self, v_index, v_value = hop.inputargs(r_ptr, lltype.Signed, hop.args_r[2]) vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index, v_value] hop.genop('setinteriorfield', vlist) class __extend__(pairtype(InteriorPtrRepr, LLADTMethRepr)): def convert_from_to((r_from, r_to), v, llops): if r_from.lowleveltype == r_to.lowleveltype: return v return NotImplemented