[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