[pypy-commit] pypy default: move low-level stuff out of the annotator

rlamy noreply at buildbot.pypy.org
Thu May 15 17:47:34 CEST 2014


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: 
Changeset: r71532:7d6363bb626f
Date: 2014-05-15 16:46 +0100
http://bitbucket.org/pypy/pypy/changeset/7d6363bb626f/

Log:	move low-level stuff out of the annotator

diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py
--- a/rpython/annotator/builtin.py
+++ b/rpython/annotator/builtin.py
@@ -8,15 +8,14 @@
     SomeUnicodeCodePoint, SomeFloat, unionof, SomeUnicodeString,
     SomePBC, SomeInstance, SomeDict, SomeList, SomeWeakRef, SomeIterator,
     SomeOrderedDict, SomeByteArray, add_knowntypedata, s_ImpossibleValue,)
-from rpython.rtyper.llannotation import (
-    SomeAddress, annotation_to_lltype, lltype_to_annotation, ll_to_annotation)
 from rpython.annotator.bookkeeper import (
-        getbookkeeper, immutablevalue, BUILTIN_ANALYZERS, analyzer_for)
+    getbookkeeper, immutablevalue, BUILTIN_ANALYZERS, analyzer_for)
 from rpython.annotator import description
 from rpython.flowspace.model import Constant
 import rpython.rlib.rarithmetic
 import rpython.rlib.objectmodel
 
+
 def constpropagate(func, args_s, s_result):
     """Returns s_result unless all args are constants, in which case the
     func() is called and a constant result is returned (it must be contained
@@ -321,6 +320,7 @@
 
 @analyzer_for(rpython.rlib.objectmodel.hlinvoke)
 def robjmodel_hlinvoke(s_repr, s_llcallable, *args_s):
+    from rpython.rtyper.llannotation import lltype_to_annotation
     from rpython.rtyper import rmodel
     from rpython.rtyper.error import TyperError
 
@@ -343,25 +343,6 @@
 def robjmodel_keepalive_until_here(*args_s):
     return immutablevalue(None)
 
- at analyzer_for(rpython.rtyper.lltypesystem.llmemory.cast_ptr_to_adr)
-def llmemory_cast_ptr_to_adr(s):
-    from rpython.rtyper.llannotation import SomeInteriorPtr
-    assert not isinstance(s, SomeInteriorPtr)
-    return SomeAddress()
-
- at analyzer_for(rpython.rtyper.lltypesystem.llmemory.cast_adr_to_ptr)
-def llmemory_cast_adr_to_ptr(s, s_type):
-    assert s_type.is_constant()
-    return SomePtr(s_type.const)
-
- at analyzer_for(rpython.rtyper.lltypesystem.llmemory.cast_adr_to_int)
-def llmemory_cast_adr_to_int(s, s_mode=None):
-    return SomeInteger() # xxx
-
- at analyzer_for(rpython.rtyper.lltypesystem.llmemory.cast_int_to_adr)
-def llmemory_cast_int_to_adr(s):
-    return SomeAddress()
-
 try:
     import unicodedata
 except ImportError:
@@ -375,131 +356,6 @@
 def analyze():
     return SomeOrderedDict(getbookkeeper().getdictdef())
 
-
-
-# annotation of low-level types
-from rpython.rtyper.llannotation import SomePtr
-from rpython.rtyper.lltypesystem import lltype
-
- at analyzer_for(lltype.malloc)
-def malloc(s_T, s_n=None, s_flavor=None, s_zero=None, s_track_allocation=None,
-           s_add_memory_pressure=None):
-    assert (s_n is None or s_n.knowntype == int
-            or issubclass(s_n.knowntype, rpython.rlib.rarithmetic.base_int))
-    assert s_T.is_constant()
-    if s_n is not None:
-        n = 1
-    else:
-        n = None
-    if s_zero:
-        assert s_zero.is_constant()
-    if s_flavor is None:
-        p = lltype.malloc(s_T.const, n)
-        r = SomePtr(lltype.typeOf(p))
-    else:
-        assert s_flavor.is_constant()
-        assert s_track_allocation is None or s_track_allocation.is_constant()
-        assert (s_add_memory_pressure is None or
-                s_add_memory_pressure.is_constant())
-        # not sure how to call malloc() for the example 'p' in the
-        # presence of s_extraargs
-        r = SomePtr(lltype.Ptr(s_T.const))
-    return r
-
- at analyzer_for(lltype.free)
-def free(s_p, s_flavor, s_track_allocation=None):
-    assert s_flavor.is_constant()
-    assert s_track_allocation is None or s_track_allocation.is_constant()
-    # same problem as in malloc(): some flavors are not easy to
-    # malloc-by-example
-    #T = s_p.ll_ptrtype.TO
-    #p = lltype.malloc(T, flavor=s_flavor.const)
-    #lltype.free(p, flavor=s_flavor.const)
-
- at analyzer_for(lltype.render_immortal)
-def render_immortal(s_p, s_track_allocation=None):
-    assert s_track_allocation is None or s_track_allocation.is_constant()
-
- at analyzer_for(lltype.typeOf)
-def typeOf(s_val):
-    lltype = annotation_to_lltype(s_val, info="in typeOf(): ")
-    return immutablevalue(lltype)
-
- at analyzer_for(lltype.cast_primitive)
-def cast_primitive(T, s_v):
-    assert T.is_constant()
-    return ll_to_annotation(lltype.cast_primitive(T.const, annotation_to_lltype(s_v)._defl()))
-
- at analyzer_for(lltype.nullptr)
-def nullptr(T):
-    assert T.is_constant()
-    p = lltype.nullptr(T.const)
-    return immutablevalue(p)
-
- at analyzer_for(lltype.cast_pointer)
-def cast_pointer(PtrT, s_p):
-    assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p
-    assert PtrT.is_constant()
-    cast_p = lltype.cast_pointer(PtrT.const, s_p.ll_ptrtype._defl())
-    return SomePtr(ll_ptrtype=lltype.typeOf(cast_p))
-
- at analyzer_for(lltype.cast_opaque_ptr)
-def cast_opaque_ptr(PtrT, s_p):
-    assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p
-    assert PtrT.is_constant()
-    cast_p = lltype.cast_opaque_ptr(PtrT.const, s_p.ll_ptrtype._defl())
-    return SomePtr(ll_ptrtype=lltype.typeOf(cast_p))
-
- at analyzer_for(lltype.direct_fieldptr)
-def direct_fieldptr(s_p, s_fieldname):
-    assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p
-    assert s_fieldname.is_constant()
-    cast_p = lltype.direct_fieldptr(s_p.ll_ptrtype._example(),
-                                    s_fieldname.const)
-    return SomePtr(ll_ptrtype=lltype.typeOf(cast_p))
-
- at analyzer_for(lltype.direct_arrayitems)
-def direct_arrayitems(s_p):
-    assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p
-    cast_p = lltype.direct_arrayitems(s_p.ll_ptrtype._example())
-    return SomePtr(ll_ptrtype=lltype.typeOf(cast_p))
-
- at analyzer_for(lltype.direct_ptradd)
-def direct_ptradd(s_p, s_n):
-    assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p
-    # don't bother with an example here: the resulting pointer is the same
-    return s_p
-
- at analyzer_for(lltype.cast_ptr_to_int)
-def cast_ptr_to_int(s_ptr): # xxx
-    return SomeInteger()
-
- at analyzer_for(lltype.cast_int_to_ptr)
-def cast_int_to_ptr(PtrT, s_int):
-    assert PtrT.is_constant()
-    return SomePtr(ll_ptrtype=PtrT.const)
-
- at analyzer_for(lltype.identityhash)
-def identityhash(s_obj):
-    assert isinstance(s_obj, SomePtr)
-    return SomeInteger()
-
- at analyzer_for(lltype.getRuntimeTypeInfo)
-def getRuntimeTypeInfo(T):
-    assert T.is_constant()
-    return immutablevalue(lltype.getRuntimeTypeInfo(T.const))
-
- at analyzer_for(lltype.runtime_type_info)
-def runtime_type_info(s_p):
-    assert isinstance(s_p, SomePtr), "runtime_type_info of non-pointer: %r" % s_p
-    return SomePtr(lltype.typeOf(lltype.runtime_type_info(s_p.ll_ptrtype._example())))
-
- at analyzer_for(lltype.Ptr)
-def constPtr(T):
-    assert T.is_constant()
-    return immutablevalue(lltype.Ptr(T.const))
-
-
 #________________________________
 # weakrefs
 
@@ -514,88 +370,9 @@
                         "a weakref to cannot be None")
     return SomeWeakRef(s_obj.classdef)
 
-
-from rpython.rtyper.lltypesystem import llmemory
-
- at analyzer_for(llmemory.weakref_create)
-def llweakref_create(s_obj):
-    if (not isinstance(s_obj, SomePtr) or
-        s_obj.ll_ptrtype.TO._gckind != 'gc'):
-        raise Exception("bad type for argument to weakref_create(): %r" % (
-            s_obj,))
-    return SomePtr(llmemory.WeakRefPtr)
-
- at analyzer_for(llmemory.weakref_deref )
-def llweakref_deref(s_ptrtype, s_wref):
-    if not (s_ptrtype.is_constant() and
-            isinstance(s_ptrtype.const, lltype.Ptr) and
-            s_ptrtype.const.TO._gckind == 'gc'):
-        raise Exception("weakref_deref() arg 1 must be a constant "
-                        "ptr type, got %s" % (s_ptrtype,))
-    if not (isinstance(s_wref, SomePtr) and
-            s_wref.ll_ptrtype == llmemory.WeakRefPtr):
-        raise Exception("weakref_deref() arg 2 must be a WeakRefPtr, "
-                        "got %s" % (s_wref,))
-    return SomePtr(s_ptrtype.const)
-
- at analyzer_for(llmemory.cast_ptr_to_weakrefptr)
-def llcast_ptr_to_weakrefptr(s_ptr):
-    assert isinstance(s_ptr, SomePtr)
-    return SomePtr(llmemory.WeakRefPtr)
-
- at analyzer_for(llmemory.cast_weakrefptr_to_ptr)
-def llcast_weakrefptr_to_ptr(s_ptrtype, s_wref):
-    if not (s_ptrtype.is_constant() and
-            isinstance(s_ptrtype.const, lltype.Ptr)):
-        raise Exception("cast_weakrefptr_to_ptr() arg 1 must be a constant "
-                        "ptr type, got %s" % (s_ptrtype,))
-    if not (isinstance(s_wref, SomePtr) and
-            s_wref.ll_ptrtype == llmemory.WeakRefPtr):
-        raise Exception("cast_weakrefptr_to_ptr() arg 2 must be a WeakRefPtr, "
-                        "got %s" % (s_wref,))
-    return SomePtr(s_ptrtype.const)
-
 #________________________________
 # non-gc objects
 
 @analyzer_for(rpython.rlib.objectmodel.free_non_gc_object)
 def robjmodel_free_non_gc_object(obj):
     pass
-
-
-#_________________________________
-# memory address
-
- at analyzer_for(llmemory.raw_malloc)
-def raw_malloc(s_size):
-    assert isinstance(s_size, SomeInteger) #XXX add noneg...?
-    return SomeAddress()
-
- at analyzer_for(llmemory.raw_malloc_usage)
-def raw_malloc_usage(s_size):
-    assert isinstance(s_size, SomeInteger) #XXX add noneg...?
-    return SomeInteger(nonneg=True)
-
- at analyzer_for(llmemory.raw_free)
-def raw_free(s_addr):
-    assert isinstance(s_addr, SomeAddress)
-
- at analyzer_for(llmemory.raw_memclear)
-def raw_memclear(s_addr, s_int):
-    assert isinstance(s_addr, SomeAddress)
-    assert isinstance(s_int, SomeInteger)
-
- at analyzer_for(llmemory.raw_memcopy)
-def raw_memcopy(s_addr1, s_addr2, s_int):
-    assert isinstance(s_addr1, SomeAddress)
-    assert isinstance(s_addr2, SomeAddress)
-    assert isinstance(s_int, SomeInteger) #XXX add noneg...?
-
-
-#_________________________________
-# offsetof/sizeof
-
-
- at analyzer_for(llmemory.offsetof)
-def offsetof(TYPE, fldname):
-    return SomeInteger()
diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py
--- a/rpython/annotator/signature.py
+++ b/rpython/annotator/signature.py
@@ -6,9 +6,9 @@
     SomeBool, SomeInteger, SomeString, SomeFloat, SomeList, SomeDict, s_None,
     SomeObject, SomeInstance, SomeTuple, unionof, SomeUnicodeString, SomeType,
     AnnotatorError)
-from rpython.rtyper.llannotation import lltype_to_annotation
 from rpython.annotator.listdef import ListDef
 from rpython.annotator.dictdef import DictDef
+from rpython.rtyper import extregistry
 
 _annotation_cache = {}
 
@@ -40,7 +40,7 @@
 
 def _compute_annotation(t, bookkeeper=None):
     from rpython.rtyper.lltypesystem import lltype
-    from rpython.rtyper import extregistry
+    from rpython.rtyper.llannotation import lltype_to_annotation
     if isinstance(t, SomeObject):
         return t
     elif isinstance(t, lltype.LowLevelType):
diff --git a/rpython/rtyper/llannotation.py b/rpython/rtyper/llannotation.py
--- a/rpython/rtyper/llannotation.py
+++ b/rpython/rtyper/llannotation.py
@@ -1,45 +1,15 @@
 """
 Code for annotating low-level thingies.
 """
-from types import MethodType
 from rpython.tool.pairtype import pair, pairtype
 from rpython.annotator.model import (
     SomeObject, SomeSingleFloat, SomeFloat, SomeLongFloat, SomeChar,
-    SomeUnicodeCodePoint, SomeInteger, SomeString, SomeImpossibleValue,
-    s_None, s_Bool, UnionError, AnnotatorError, SomeBool)
+    SomeUnicodeCodePoint, SomeInteger, SomeImpossibleValue,
+    s_None, s_Bool, UnionError, AnnotatorError)
 from rpython.rtyper.lltypesystem import lltype, llmemory
-
-class SomeAddress(SomeObject):
-    immutable = True
-
-    def can_be_none(self):
-        return False
-
-    def is_null_address(self):
-        return self.is_immutable_constant() and not self.const
-
-    def getattr(self, s_attr):
-        assert s_attr.is_constant()
-        assert isinstance(s_attr, SomeString)
-        assert s_attr.const in llmemory.supported_access_types
-        return SomeTypedAddressAccess(
-            llmemory.supported_access_types[s_attr.const])
-    getattr.can_only_throw = []
-
-    def bool(self):
-        return s_Bool
-
-class SomeTypedAddressAccess(SomeObject):
-    """This class is used to annotate the intermediate value that
-    appears in expressions of the form:
-    addr.signed[offset] and addr.signed[offset] = value
-    """
-
-    def __init__(self, type):
-        self.type = type
-
-    def can_be_none(self):
-        return False
+from rpython.rtyper.lltypesystem.lltype import SomePtr
+from rpython.rtyper.lltypesystem.llmemory import (
+    SomeAddress, SomeTypedAddressAccess)
 
 
 class __extend__(pairtype(SomeAddress, SomeAddress)):
@@ -98,69 +68,6 @@
         raise UnionError(s_obj, s_addr)
 
 
-class SomePtr(SomeObject):
-    knowntype = lltype._ptr
-    immutable = True
-
-    def __init__(self, ll_ptrtype):
-        assert isinstance(ll_ptrtype, lltype.Ptr)
-        self.ll_ptrtype = ll_ptrtype
-
-    def can_be_none(self):
-        return False
-
-    def getattr(self, s_attr):
-        from rpython.annotator.bookkeeper import getbookkeeper
-        if not s_attr.is_constant():
-            raise AnnotatorError("getattr on ptr %r with non-constant "
-                                 "field-name" % self.ll_ptrtype)
-        example = self.ll_ptrtype._example()
-        try:
-            v = example._lookup_adtmeth(s_attr.const)
-        except AttributeError:
-            v = getattr(example, s_attr.const)
-            return ll_to_annotation(v)
-        else:
-            if isinstance(v, MethodType):
-                ll_ptrtype = lltype.typeOf(v.im_self)
-                assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr))
-                return SomeLLADTMeth(ll_ptrtype, v.im_func)
-            return getbookkeeper().immutablevalue(v)
-    getattr.can_only_throw = []
-
-    def len(self):
-        from rpython.annotator.bookkeeper import getbookkeeper
-        length = self.ll_ptrtype._example()._fixedlength()
-        if length is None:
-            return SomeObject.len(self)
-        else:
-            return getbookkeeper().immutablevalue(length)
-
-    def setattr(self, s_attr, s_value): # just doing checking
-        if not s_attr.is_constant():
-            raise AnnotatorError("setattr on ptr %r with non-constant "
-                                 "field-name" % self.ll_ptrtype)
-        example = self.ll_ptrtype._example()
-        if getattr(example, s_attr.const) is not None:  # ignore Void s_value
-            v_lltype = annotation_to_lltype(s_value)
-            setattr(example, s_attr.const, v_lltype._defl())
-
-    def call(self, args):
-        args_s, kwds_s = args.unpack()
-        if kwds_s:
-            raise Exception("keyword arguments to call to a low-level fn ptr")
-        info = 'argument to ll function pointer call'
-        llargs = [annotation_to_lltype(s_arg, info)._defl() for s_arg in args_s]
-        v = self.ll_ptrtype._example()(*llargs)
-        return ll_to_annotation(v)
-
-    def bool(self):
-        result = SomeBool()
-        if self.is_constant():
-            result.const = bool(self.const)
-        return result
-
-
 class SomeInteriorPtr(SomePtr):
     def __init__(self, ll_ptrtype):
         assert isinstance(ll_ptrtype, lltype.InteriorPtr)
diff --git a/rpython/rtyper/lltypesystem/llmemory.py b/rpython/rtyper/lltypesystem/llmemory.py
--- a/rpython/rtyper/lltypesystem/llmemory.py
+++ b/rpython/rtyper/lltypesystem/llmemory.py
@@ -5,8 +5,11 @@
 # sizeof, offsetof
 
 import weakref
+from rpython.annotator.bookkeeper import analyzer_for
+from rpython.annotator.model import SomeInteger, SomeObject, SomeString, s_Bool
 from rpython.rlib.objectmodel import Symbolic, specialize
 from rpython.rtyper.lltypesystem import lltype
+from rpython.rtyper.lltypesystem.lltype import SomePtr
 from rpython.tool.uid import uid
 from rpython.rlib.rarithmetic import is_valid_int
 from rpython.rtyper.extregistry import ExtRegistryEntry
@@ -401,6 +404,11 @@
     assert fldname in TYPE._flds
     return FieldOffset(TYPE, fldname)
 
+ at analyzer_for(offsetof)
+def ann_offsetof(TYPE, fldname):
+    return SomeInteger()
+
+
 @specialize.memo()
 def itemoffsetof(TYPE, n=0):
     result = ArrayItemsOffset(TYPE)
@@ -537,6 +545,37 @@
         from rpython.rtyper.llannotation import SomeAddress
         return SomeAddress()
 
+class SomeAddress(SomeObject):
+    immutable = True
+
+    def can_be_none(self):
+        return False
+
+    def is_null_address(self):
+        return self.is_immutable_constant() and not self.const
+
+    def getattr(self, s_attr):
+        assert s_attr.is_constant()
+        assert isinstance(s_attr, SomeString)
+        assert s_attr.const in supported_access_types
+        return SomeTypedAddressAccess(supported_access_types[s_attr.const])
+    getattr.can_only_throw = []
+
+    def bool(self):
+        return s_Bool
+
+class SomeTypedAddressAccess(SomeObject):
+    """This class is used to annotate the intermediate value that
+    appears in expressions of the form:
+    addr.signed[offset] and addr.signed[offset] = value
+    """
+
+    def __init__(self, type):
+        self.type = type
+
+    def can_be_none(self):
+        return False
+
 # ____________________________________________________________
 
 class AddressAsInt(Symbolic):
@@ -683,9 +722,22 @@
     assert isinstance(lltype.typeOf(obj), lltype.Ptr)
     return obj._cast_to_adr()
 
+ at analyzer_for(cast_ptr_to_adr)
+def ann_cast_ptr_to_adr(s):
+    from rpython.rtyper.llannotation import SomeInteriorPtr
+    assert not isinstance(s, SomeInteriorPtr)
+    return SomeAddress()
+
+
 def cast_adr_to_ptr(adr, EXPECTED_TYPE):
     return adr._cast_to_ptr(EXPECTED_TYPE)
 
+ at analyzer_for(cast_adr_to_ptr)
+def ann_cast_adr_to_ptr(s, s_type):
+    assert s_type.is_constant()
+    return SomePtr(s_type.const)
+
+
 def cast_adr_to_int(adr, mode="emulated"):
     # The following modes are supported before translation (after
     # translation, it's all just a cast):
@@ -702,6 +754,11 @@
         res = cast(lltype.Signed, res)
     return res
 
+ at analyzer_for(cast_adr_to_int)
+def ann_cast_adr_to_int(s, s_mode=None):
+    return SomeInteger()  # xxx
+
+
 _NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF'))
 def cast_int_to_adr(int):
     if isinstance(int, AddressAsInt):
@@ -713,6 +770,10 @@
         ptr = ll2ctypes._int2obj[int]._as_ptr()
     return cast_ptr_to_adr(ptr)
 
+ at analyzer_for(cast_int_to_adr)
+def ann_cast_int_to_adr(s):
+    return SomeAddress()
+
 # ____________________________________________________________
 # Weakrefs.
 #
@@ -722,6 +783,7 @@
 
 class _WeakRefType(lltype.ContainerType):
     _gckind = 'gc'
+
     def __str__(self):
         return "WeakRef"
 
@@ -736,6 +798,15 @@
     assert ptarget
     return _wref(ptarget)._as_ptr()
 
+ at analyzer_for(weakref_create)
+def ann_weakref_create(s_obj):
+    if (not isinstance(s_obj, SomePtr) or
+            s_obj.ll_ptrtype.TO._gckind != 'gc'):
+        raise Exception("bad type for argument to weakref_create(): %r" % (
+            s_obj,))
+    return SomePtr(WeakRefPtr)
+
+
 def weakref_deref(PTRTYPE, pwref):
     # pwref should not be a nullptr
     assert isinstance(PTRTYPE, lltype.Ptr)
@@ -747,6 +818,20 @@
     else:
         return cast_any_ptr(PTRTYPE, p)
 
+ at analyzer_for(weakref_deref)
+def ann_weakref_deref(s_ptrtype, s_wref):
+    if not (s_ptrtype.is_constant() and
+            isinstance(s_ptrtype.const, lltype.Ptr) and
+            s_ptrtype.const.TO._gckind == 'gc'):
+        raise Exception("weakref_deref() arg 1 must be a constant "
+                        "ptr type, got %s" % (s_ptrtype,))
+    if not (isinstance(s_wref, SomePtr) and
+            s_wref.ll_ptrtype == WeakRefPtr):
+        raise Exception("weakref_deref() arg 2 must be a WeakRefPtr, "
+                        "got %s" % (s_wref,))
+    return SomePtr(s_ptrtype.const)
+
+
 class _wref(lltype._container):
     _gckind = 'gc'
     _TYPE = WeakRef
@@ -789,6 +874,12 @@
     else:
         return lltype.nullptr(WeakRef)
 
+ at analyzer_for(cast_ptr_to_weakrefptr)
+def llcast_ptr_to_weakrefptr(s_ptr):
+    assert isinstance(s_ptr, SomePtr)
+    return SomePtr(WeakRefPtr)
+
+
 def cast_weakrefptr_to_ptr(PTRTYPE, pwref):
     assert lltype.typeOf(pwref) == WeakRefPtr
     if pwref:
@@ -799,6 +890,18 @@
     else:
         return lltype.nullptr(PTRTYPE.TO)
 
+ at analyzer_for(cast_weakrefptr_to_ptr)
+def llcast_weakrefptr_to_ptr(s_ptrtype, s_wref):
+    if not (s_ptrtype.is_constant() and
+            isinstance(s_ptrtype.const, lltype.Ptr)):
+        raise Exception("cast_weakrefptr_to_ptr() arg 1 must be a constant "
+                        "ptr type, got %s" % (s_ptrtype,))
+    if not (isinstance(s_wref, SomePtr) and s_wref.ll_ptrtype == WeakRefPtr):
+        raise Exception("cast_weakrefptr_to_ptr() arg 2 must be a WeakRefPtr, "
+                        "got %s" % (s_wref,))
+    return SomePtr(s_ptrtype.const)
+
+
 class _gctransformed_wref(lltype._container):
     _gckind = 'gc'
     _TYPE = WeakRef
@@ -820,6 +923,12 @@
         raise NotImplementedError(size)
     return size._raw_malloc([], zero=False)
 
+ at analyzer_for(raw_malloc)
+def ann_raw_malloc(s_size):
+    assert isinstance(s_size, SomeInteger)  # XXX add noneg...?
+    return SomeAddress()
+
+
 def raw_free(adr):
     # try to free the whole object if 'adr' is the address of the header
     from rpython.memory.gcheader import GCHeaderBuilder
@@ -832,6 +941,10 @@
     assert isinstance(adr.ref()._obj, lltype._parentable)
     adr.ptr._as_obj()._free()
 
+ at analyzer_for(raw_free)
+def ann_raw_free(s_addr):
+    assert isinstance(s_addr, SomeAddress)
+
 def raw_malloc_usage(size):
     if isinstance(size, AddressOffset):
         # ouah
@@ -839,6 +952,12 @@
         size = convert_offset_to_int(size)
     return size
 
+ at analyzer_for(raw_malloc_usage)
+def ann_raw_malloc_usage(s_size):
+    assert isinstance(s_size, SomeInteger)  # XXX add noneg...?
+    return SomeInteger(nonneg=True)
+
+
 def raw_memclear(adr, size):
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)
@@ -846,17 +965,43 @@
     zeroadr = size._raw_malloc([], zero=True)
     size.raw_memcopy(zeroadr, adr)
 
+ at analyzer_for(raw_memclear)
+def ann_raw_memclear(s_addr, s_int):
+    assert isinstance(s_addr, SomeAddress)
+    assert isinstance(s_int, SomeInteger)
+
+
 def raw_memcopy(source, dest, size):
     assert lltype.typeOf(source) == Address
-    assert lltype.typeOf(dest)   == Address
+    assert lltype.typeOf(dest) == Address
     size.raw_memcopy(source, dest)
 
+ at analyzer_for(raw_memcopy)
+def ann_raw_memcopy(s_addr1, s_addr2, s_int):
+    assert isinstance(s_addr1, SomeAddress)
+    assert isinstance(s_addr2, SomeAddress)
+    assert isinstance(s_int, SomeInteger)  # XXX add noneg...?
+
+
 def raw_memmove(source, dest, size):
     # for now let's assume that raw_memmove is the same as raw_memcopy,
     # when run on top of fake addresses, but we _free the source object
     raw_memcopy(source, dest, size)
     source.ptr._as_obj()._free()
 
+class RawMemmoveEntry(ExtRegistryEntry):
+    _about_ = raw_memmove
+
+    def compute_result_annotation(self, s_from, s_to, s_size):
+        assert isinstance(s_from, SomeAddress)
+        assert isinstance(s_to, SomeAddress)
+        assert isinstance(s_size, SomeInteger)
+
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        v_list = hop.inputargs(Address, Address, lltype.Signed)
+        return hop.genop('raw_memmove', v_list)
+
 def cast_any_ptr(EXPECTED_TYPE, ptr):
     # this is a generalization of the various cast_xxx_ptr() functions.
     PTRTYPE = lltype.typeOf(ptr)
@@ -868,7 +1013,7 @@
         ptr = cast_weakrefptr_to_ptr(None, ptr)
         return cast_any_ptr(EXPECTED_TYPE, ptr)
     elif (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
-        isinstance(PTRTYPE.TO, lltype.OpaqueType)):
+            isinstance(PTRTYPE.TO, lltype.OpaqueType)):
         return lltype.cast_opaque_ptr(EXPECTED_TYPE, ptr)
     else:
         # regular case
@@ -906,19 +1051,3 @@
                 setattr(dest._obj, name, llvalue)
     else:
         raise TypeError(T)
-
-
-class RawMemmoveEntry(ExtRegistryEntry):
-    _about_ = raw_memmove
-
-    def compute_result_annotation(self, s_from, s_to, s_size):
-        from rpython.annotator.model import SomeInteger
-        from rpython.rtyper.llannotation import SomeAddress
-        assert isinstance(s_from, SomeAddress)
-        assert isinstance(s_to, SomeAddress)
-        assert isinstance(s_size, SomeInteger)
-
-    def specialize_call(self, hop):
-        hop.exception_cannot_occur()
-        v_list = hop.inputargs(Address, Address, lltype.Signed)
-        return hop.genop('raw_memmove', v_list)
diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py
--- a/rpython/rtyper/lltypesystem/lltype.py
+++ b/rpython/rtyper/lltypesystem/lltype.py
@@ -1,12 +1,15 @@
-from rpython.rlib.rarithmetic import (r_int, r_uint, intmask, r_singlefloat,
-                                   r_ulonglong, r_longlong, r_longfloat, r_longlonglong,
-                                   base_int, normalizedinttype, longlongmask, longlonglongmask)
+from types import NoneType, MethodType
+import weakref
+from rpython.annotator.model import (
+        SomeInteger, SomeBool, SomeObject, AnnotatorError)
+from rpython.rlib.rarithmetic import (
+    r_int, r_uint, intmask, r_singlefloat, r_ulonglong, r_longlong,
+    r_longfloat, r_longlonglong, base_int, normalizedinttype, longlongmask,
+    longlonglongmask, maxint, is_valid_int, is_emulated_long)
 from rpython.rlib.objectmodel import Symbolic
 from rpython.tool.identity_dict import identity_dict
 from rpython.tool import leakfinder
-from types import NoneType
-from rpython.rlib.rarithmetic import maxint, is_valid_int, is_emulated_long
-import weakref
+from rpython.annotator.bookkeeper import analyzer_for, immutablevalue
 from rpython.rtyper.extregistry import ExtRegistryEntry
 
 class State(object):
@@ -768,6 +771,12 @@
                          hints={'interior_ptr_type':True})
         return R
 
+ at analyzer_for(Ptr)
+def constPtr(T):
+    assert T.is_constant()
+    return immutablevalue(Ptr(T.const))
+
+
 class InteriorPtr(LowLevelType):
     def __init__(self, PARENTTYPE, TO, offsets):
         self.PARENTTYPE = PARENTTYPE
@@ -826,6 +835,13 @@
         # in an illegal way!
         raise TypeError("typeOf(%r object)" % (tp.__name__,))
 
+ at analyzer_for(typeOf)
+def ann_typeOf(s_val):
+    from rpython.rtyper.llannotation import annotation_to_lltype
+    lltype = annotation_to_lltype(s_val, info="in typeOf(): ")
+    return immutablevalue(lltype)
+
+
 _to_primitive = {
     Char: chr,
     UniChar: unichr,
@@ -858,6 +874,13 @@
         return float(value)
     raise TypeError("unsupported cast")
 
+ at analyzer_for(cast_primitive)
+def ann_cast_primitive(T, s_v):
+    from rpython.rtyper.llannotation import annotation_to_lltype, ll_to_annotation
+    assert T.is_constant()
+    return ll_to_annotation(cast_primitive(T.const, annotation_to_lltype(s_v)._defl()))
+
+
 def _cast_whatever(TGT, value):
     from rpython.rtyper.lltypesystem import llmemory, rffi
     ORIG = typeOf(value)
@@ -930,12 +953,21 @@
         raise InvalidCast(CURTYPE, PTRTYPE)
     return -u
 
+
 def cast_pointer(PTRTYPE, ptr):
     CURTYPE = typeOf(ptr)
     if not isinstance(CURTYPE, Ptr) or not isinstance(PTRTYPE, Ptr):
         raise TypeError("can only cast pointers to other pointers")
     return ptr._cast_to(PTRTYPE)
 
+ at analyzer_for(cast_pointer)
+def ann_cast_pointer(PtrT, s_p):
+    assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p
+    assert PtrT.is_constant()
+    cast_p = cast_pointer(PtrT.const, s_p.ll_ptrtype._defl())
+    return SomePtr(ll_ptrtype=typeOf(cast_p))
+
+
 def cast_opaque_ptr(PTRTYPE, ptr):
     CURTYPE = typeOf(ptr)
     if not isinstance(CURTYPE, Ptr) or not isinstance(PTRTYPE, Ptr):
@@ -982,6 +1014,14 @@
         raise TypeError("invalid cast_opaque_ptr(): %r -> %r" %
                         (CURTYPE, PTRTYPE))
 
+ at analyzer_for(cast_opaque_ptr)
+def ann_cast_opaque_ptr(PtrT, s_p):
+    assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p
+    assert PtrT.is_constant()
+    cast_p = cast_opaque_ptr(PtrT.const, s_p.ll_ptrtype._defl())
+    return SomePtr(ll_ptrtype=typeOf(cast_p))
+
+
 def direct_fieldptr(structptr, fieldname):
     """Get a pointer to a field in the struct.  The resulting
     pointer is actually of type Ptr(FixedSizeArray(FIELD, 1)).
@@ -997,6 +1037,15 @@
         raise RuntimeError("direct_fieldptr: NULL argument")
     return _subarray._makeptr(structptr._obj, fieldname, structptr._solid)
 
+ at analyzer_for(direct_fieldptr)
+def ann_direct_fieldptr(s_p, s_fieldname):
+    assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p
+    assert s_fieldname.is_constant()
+    cast_p = direct_fieldptr(s_p.ll_ptrtype._example(),
+                                    s_fieldname.const)
+    return SomePtr(ll_ptrtype=typeOf(cast_p))
+
+
 def direct_arrayitems(arrayptr):
     """Get a pointer to the first item of the array.  The resulting
     pointer is actually of type Ptr(FixedSizeArray(ITEM, 1)) but can
@@ -1010,6 +1059,13 @@
         raise RuntimeError("direct_arrayitems: NULL argument")
     return _subarray._makeptr(arrayptr._obj, 0, arrayptr._solid)
 
+ at analyzer_for(direct_arrayitems)
+def ann_direct_arrayitems(s_p):
+    assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p
+    cast_p = direct_arrayitems(s_p.ll_ptrtype._example())
+    return SomePtr(ll_ptrtype=typeOf(cast_p))
+
+
 def direct_ptradd(ptr, n):
     """Shift a pointer forward or backward by n items.  The pointer must
     have been built by direct_arrayitems(), or it must be directly a
@@ -1024,6 +1080,13 @@
     parent, base = parentlink(ptr._obj)
     return _subarray._makeptr(parent, base + n, ptr._solid)
 
+ at analyzer_for(direct_ptradd)
+def ann_direct_ptradd(s_p, s_n):
+    assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p
+    # don't bother with an example here: the resulting pointer is the same
+    return s_p
+
+
 def parentlink(container):
     parent = container._parentstructure()
     if parent is not None:
@@ -1415,6 +1478,69 @@
         from rpython.rtyper.llannotation import SomePtr
         return SomePtr(typeOf(self.instance))
 
+class SomePtr(SomeObject):
+    knowntype = _ptr
+    immutable = True
+
+    def __init__(self, ll_ptrtype):
+        assert isinstance(ll_ptrtype, Ptr)
+        self.ll_ptrtype = ll_ptrtype
+
+    def can_be_none(self):
+        return False
+
+    def getattr(self, s_attr):
+        from rpython.rtyper.llannotation import SomeLLADTMeth, ll_to_annotation
+        if not s_attr.is_constant():
+            raise AnnotatorError("getattr on ptr %r with non-constant "
+                                 "field-name" % self.ll_ptrtype)
+        example = self.ll_ptrtype._example()
+        try:
+            v = example._lookup_adtmeth(s_attr.const)
+        except AttributeError:
+            v = getattr(example, s_attr.const)
+            return ll_to_annotation(v)
+        else:
+            if isinstance(v, MethodType):
+                ll_ptrtype = typeOf(v.im_self)
+                assert isinstance(ll_ptrtype, (Ptr, InteriorPtr))
+                return SomeLLADTMeth(ll_ptrtype, v.im_func)
+            return immutablevalue(v)
+    getattr.can_only_throw = []
+
+    def len(self):
+        length = self.ll_ptrtype._example()._fixedlength()
+        if length is None:
+            return SomeObject.len(self)
+        else:
+            return immutablevalue(length)
+
+    def setattr(self, s_attr, s_value): # just doing checking
+        from rpython.rtyper.llannotation import annotation_to_lltype
+        if not s_attr.is_constant():
+            raise AnnotatorError("setattr on ptr %r with non-constant "
+                                 "field-name" % self.ll_ptrtype)
+        example = self.ll_ptrtype._example()
+        if getattr(example, s_attr.const) is not None:  # ignore Void s_value
+            v_lltype = annotation_to_lltype(s_value)
+            setattr(example, s_attr.const, v_lltype._defl())
+
+    def call(self, args):
+        from rpython.rtyper.llannotation import annotation_to_lltype, ll_to_annotation
+        args_s, kwds_s = args.unpack()
+        if kwds_s:
+            raise Exception("keyword arguments to call to a low-level fn ptr")
+        info = 'argument to ll function pointer call'
+        llargs = [annotation_to_lltype(s_arg, info)._defl() for s_arg in args_s]
+        v = self.ll_ptrtype._example()(*llargs)
+        return ll_to_annotation(v)
+
+    def bool(self):
+        result = SomeBool()
+        if self.is_constant():
+            result.const = bool(self.const)
+        return result
+
 
 class _interior_ptr(_abstract_ptr):
     __slots__ = ('_parent', '_offsets')
@@ -1994,6 +2120,32 @@
     solid = immortal or flavor == 'raw'
     return _ptr(Ptr(T), o, solid)
 
+ at analyzer_for(malloc)
+def ann_malloc(s_T, s_n=None, s_flavor=None, s_zero=None, s_track_allocation=None,
+           s_add_memory_pressure=None):
+    assert (s_n is None or s_n.knowntype == int
+            or issubclass(s_n.knowntype, base_int))
+    assert s_T.is_constant()
+    if s_n is not None:
+        n = 1
+    else:
+        n = None
+    if s_zero:
+        assert s_zero.is_constant()
+    if s_flavor is None:
+        p = malloc(s_T.const, n)
+        r = SomePtr(typeOf(p))
+    else:
+        assert s_flavor.is_constant()
+        assert s_track_allocation is None or s_track_allocation.is_constant()
+        assert (s_add_memory_pressure is None or
+                s_add_memory_pressure.is_constant())
+        # not sure how to call malloc() for the example 'p' in the
+        # presence of s_extraargs
+        r = SomePtr(Ptr(s_T.const))
+    return r
+
+
 def free(p, flavor, track_allocation=True):
     if flavor.startswith('gc'):
         raise TypeError("gc flavor free")
@@ -2004,6 +2156,17 @@
         leakfinder.remember_free(p._obj0)
     p._obj0._free()
 
+ at analyzer_for(free)
+def ann_free(s_p, s_flavor, s_track_allocation=None):
+    assert s_flavor.is_constant()
+    assert s_track_allocation is None or s_track_allocation.is_constant()
+    # same problem as in malloc(): some flavors are not easy to
+    # malloc-by-example
+    #T = s_p.ll_ptrtype.TO
+    #p = malloc(T, flavor=s_flavor.const)
+    #free(p, flavor=s_flavor.const)
+
+
 def render_immortal(p, track_allocation=True):
     T = typeOf(p)
     if not isinstance(T, Ptr) or p._togckind() != 'raw':
@@ -2011,6 +2174,10 @@
     if track_allocation:
         leakfinder.remember_free(p._obj0)
 
+ at analyzer_for(render_immortal)
+def ann_render_immortal(s_p, s_track_allocation=None):
+    assert s_track_allocation is None or s_track_allocation.is_constant()
+
 def _make_scoped_allocator(T):
     class ScopedAlloc:
         def __init__(self, n=None, zero=False):
@@ -2050,9 +2217,17 @@
     o = _func(TYPE, _name=name, **attrs)
     return _ptr(Ptr(TYPE), o)
 
+
 def nullptr(T):
     return Ptr(T)._defl()
 
+ at analyzer_for(nullptr)
+def ann_nullptr(T):
+    assert T.is_constant()
+    p = nullptr(T.const)
+    return immutablevalue(p)
+
+
 def opaqueptr(TYPE, name, **attrs):
     if not isinstance(TYPE, OpaqueType):
         raise TypeError("opaqueptr() for OpaqueTypes only")
@@ -2063,6 +2238,11 @@
 def cast_ptr_to_int(ptr):
     return ptr._cast_to_int()
 
+ at analyzer_for(cast_ptr_to_int)
+def ann_cast_ptr_to_int(s_ptr): # xxx
+    return SomeInteger()
+
+
 def cast_int_to_ptr(PTRTYPE, oddint):
     if oddint == 0:
         return nullptr(PTRTYPE.TO)
@@ -2070,6 +2250,12 @@
         raise ValueError("only odd integers can be cast back to ptr")
     return _ptr(PTRTYPE, oddint, solid=True)
 
+ at analyzer_for(cast_int_to_ptr)
+def ann_cast_int_to_ptr(PtrT, s_int):
+    assert PtrT.is_constant()
+    return SomePtr(ll_ptrtype=PtrT.const)
+
+
 def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None,
                           customtraceptr=None):
     if not isinstance(GCSTRUCT, RttiStruct):
@@ -2086,6 +2272,12 @@
                            GCSTRUCT._name)
     return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
 
+ at analyzer_for(getRuntimeTypeInfo)
+def ann_getRuntimeTypeInfo(T):
+    assert T.is_constant()
+    return immutablevalue(getRuntimeTypeInfo(T.const))
+
+
 def runtime_type_info(p):
     T = typeOf(p)
     if not isinstance(T, Ptr) or not isinstance(T.TO, RttiStruct):
@@ -2104,6 +2296,12 @@
                                  "should have been: %s" % (p, result2, result))
     return result
 
+ at analyzer_for(runtime_type_info)
+def ann_runtime_type_info(s_p):
+    assert isinstance(s_p, SomePtr), "runtime_type_info of non-pointer: %r" % s_p
+    return SomePtr(typeOf(runtime_type_info(s_p.ll_ptrtype._example())))
+
+
 def identityhash(p):
     """Returns the lltype-level hash of the given GcStruct.
     Not for NULL. See rlib.objectmodel.compute_identity_hash() for more
@@ -2112,6 +2310,12 @@
     assert p
     return p._identityhash()
 
+ at analyzer_for(identityhash)
+def ann_identityhash(s_obj):
+    assert isinstance(s_obj, SomePtr)
+    return SomeInteger()
+
+
 def identityhash_nocache(p):
     """Version of identityhash() to use from backends that don't care about
     caching."""


More information about the pypy-commit mailing list