[pypy-commit] pypy default: moving ll2ctypes plus tests to default. Not a trivial thing that works
ctismer
noreply at buildbot.pypy.org
Wed Mar 14 06:54:06 CET 2012
Author: Christian Tismer <tismer at stackless.com>
Branch:
Changeset: r53532:4db2ee86e087
Date: 2012-03-13 21:48 -0700
http://bitbucket.org/pypy/pypy/changeset/4db2ee86e087/
Log: moving ll2ctypes plus tests to default. Not a trivial thing that
works
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -14,12 +14,14 @@
else:
load_library_kwargs = {}
-import os
+import os, platform as host_platform
+from pypy import conftest
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.extfunc import ExtRegistryEntry
from pypy.rlib.objectmodel import Symbolic, ComputedIntSymbolic
from pypy.tool.uid import fixid
from pypy.rlib.rarithmetic import r_singlefloat, r_longfloat, base_int, intmask
+from pypy.rlib.rarithmetic import is_emulated_long, maxint
from pypy.annotation import model as annmodel
from pypy.rpython.llinterp import LLInterpreter, LLException
from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
@@ -32,6 +34,12 @@
class tlsobject(object):
pass
+_POSIX = os.name == "posix"
+_MS_WINDOWS = os.name == "nt"
+_LINUX = "linux" in sys.platform
+_64BIT = "64bit" in host_platform.architecture()[0]
+
+
# ____________________________________________________________
far_regions = None
@@ -68,17 +76,22 @@
global far_regions
if not far_regions:
from pypy.rlib import rmmap
- if sys.maxint > 0x7FFFFFFF:
+ if _64BIT:
PIECESIZE = 0x80000000
else:
- if sys.platform == 'linux':
+ if _LINUX:
PIECESIZE = 0x10000000
else:
PIECESIZE = 0x08000000
PIECES = 10
- m = rmmap.mmap(-1, PIECES * PIECESIZE,
- rmmap.MAP_PRIVATE|rmmap.MAP_ANONYMOUS|rmmap.MAP_NORESERVE,
- rmmap.PROT_READ|rmmap.PROT_WRITE)
+ flags = 0
+ if _LINUX:
+ flags = (rmmap.MAP_PRIVATE|rmmap.MAP_ANONYMOUS|rmmap.MAP_NORESERVE,
+ rmmap.PROT_READ|rmmap.PROT_WRITE)
+ if _MS_WINDOWS:
+ flags = rmmap.MEM_RESERVE
+ # XXX seems not to work
+ m = rmmap.mmap(-1, PIECES * PIECESIZE, flags)
m.close = lambda : None # leak instead of giving a spurious
# error at CPython's shutdown
m._ll2ctypes_pieces = []
@@ -93,9 +106,17 @@
def _setup_ctypes_cache():
from pypy.rpython.lltypesystem import rffi
+
+ if is_emulated_long:
+ signed_as_ctype = ctypes.c_longlong
+ unsigned_as_ctypes = ctypes.c_ulonglong
+ else:
+ signed_as_ctype = ctypes.c_long
+ unsigned_as_ctypes = ctypes.c_ulong
+
_ctypes_cache.update({
- lltype.Signed: ctypes.c_long,
- lltype.Unsigned: ctypes.c_ulong,
+ lltype.Signed: signed_as_ctype,
+ lltype.Unsigned: unsigned_as_ctypes,
lltype.Char: ctypes.c_ubyte,
rffi.DOUBLE: ctypes.c_double,
rffi.FLOAT: ctypes.c_float,
@@ -176,10 +197,26 @@
assert max_n >= 0
ITEM = A.OF
ctypes_item = get_ctypes_type(ITEM, delayed_builders)
+ # Python 2.5 ctypes can raise OverflowError on 64-bit builds
+ for n in [maxint, 2**31]:
+ MAX_SIZE = n/64
+ try:
+ PtrType = ctypes.POINTER(MAX_SIZE * ctypes_item)
+ except (OverflowError, AttributeError), e:
+ pass # ^^^ bah, blame ctypes
+ else:
+ break
+ else:
+ raise e
class CArray(ctypes.Structure):
+ if is_emulated_long:
+ lentype = ctypes.c_longlong
+ else:
+ lentype = ctypes.c_long
+
if not A._hints.get('nolength'):
- _fields_ = [('length', ctypes.c_long),
+ _fields_ = [('length', lentype),
('items', max_n * ctypes_item)]
else:
_fields_ = [('items', max_n * ctypes_item)]
@@ -201,11 +238,16 @@
if cls._ptrtype:
return cls._ptrtype
# ctypes can raise OverflowError on 64-bit builds
- for n in [sys.maxint, 2**31]:
+ # on windows it raises AttributeError even for 2**31 (_length_ missing)
+ if _MS_WINDOWS:
+ other_limit = 2**31-1
+ else:
+ other_limit = 2**31
+ for n in [maxint, other_limit]:
cls.MAX_SIZE = n / ctypes.sizeof(ctypes_item)
try:
cls._ptrtype = ctypes.POINTER(cls.MAX_SIZE * ctypes_item)
- except OverflowError, e:
+ except (OverflowError, AttributeError), e:
pass
else:
break
@@ -566,7 +608,7 @@
def getbounds(self):
# we have no clue, so we allow whatever index
- return 0, sys.maxint
+ return 0, maxint
def getitem(self, index, uninitialized_ok=False):
res = self._storage.contents._getitem(index, boundscheck=False)
@@ -1326,8 +1368,8 @@
res = force_cast(lltype.Signed, addr.ptr)
else:
res = addr._cast_to_int()
- if res > sys.maxint:
- res = res - 2*(sys.maxint + 1)
+ if res > maxint:
+ res = res - 2*(maxint + 1)
assert int(res) == res
return int(res)
return res
diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
--- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
@@ -16,12 +16,28 @@
from pypy.rpython.test.test_llinterp import interpret
from pypy.annotation.annrpython import RPythonAnnotator
from pypy.rpython.rtyper import RPythonTyper
-
+from pypy.rlib.rarithmetic import r_uint, get_long_pattern, is_emulated_long
+from pypy.rlib.rarithmetic import is_valid_int
if False: # for now, please keep it False by default
from pypy.rpython.lltypesystem import ll2ctypes
ll2ctypes.do_allocation_in_far_regions()
+"""
+Win64:
+To decouple the cpython machine level long from the faked integer
+of the target rpython, I replaced most 'lltype.Signed' by 'rffi.LONG'.
+It would be nicer to replace all lltypes constants by rffi equivalents,
+or better if we had a way to address the specific different types of
+the current and the target system layout explicitly.
+Let's think of that when we go further and make the target completely
+independent and configurable.
+Why most and not all replaced?
+Tests with direct tests become cumbersome, instead of direct number
+assignment rffi.setintfield(s, 'x', 123) must be used.
+So in cases with number constants, where the size is not relevant,
+I kept lltype.signed .
+"""
class TestLL2Ctypes(object):
@@ -46,15 +62,15 @@
res = ctypes2lltype(lltype.SingleFloat, ctypes.c_float(-3.5))
assert isinstance(res, rffi.r_singlefloat)
assert float(res) == -3.5
- assert lltype2ctypes(rffi.r_ulong(-1)) == sys.maxint * 2 + 1
+ assert lltype2ctypes(rffi.r_ulong(-1)) == (1 << rffi.r_ulong.BITS) - 1
res = ctypes2lltype(lltype.Unsigned, sys.maxint * 2 + 1)
- assert (res, type(res)) == (rffi.r_ulong(-1), rffi.r_ulong)
+ assert (res, type(res)) == (r_uint(-1), r_uint)
assert ctypes2lltype(lltype.Bool, 0) is False
assert ctypes2lltype(lltype.Bool, 1) is True
- res = lltype2ctypes(llmemory.sizeof(lltype.Signed))
+ res = lltype2ctypes(llmemory.sizeof(rffi.LONG))
assert res == struct.calcsize("l")
- S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+ S = lltype.Struct('S', ('x', rffi.LONG), ('y', rffi.LONG))
res = lltype2ctypes(llmemory.sizeof(S))
assert res == struct.calcsize("ll")
@@ -69,7 +85,7 @@
def test_simple_struct(self):
S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
s = lltype.malloc(S, flavor='raw')
- s.x = 123
+ rffi.setintfield(s, 'x', 123)
sc = lltype2ctypes(s)
assert isinstance(sc.contents, ctypes.Structure)
assert sc.contents.x == 123
@@ -133,7 +149,11 @@
ac = lltype2ctypes(a, normalize=False)
assert isinstance(ac.contents, ctypes.Structure)
assert ac.contents.length == 10
- assert ac.contents._fields_[0] == ('length', ctypes.c_long)
+ if is_emulated_long:
+ lentype = ctypes.c_longlong
+ else:
+ lentype = ctypes.c_long
+ assert ac.contents._fields_[0] == ('length', lentype)
assert ac.contents.items[1] == 101
ac.contents.items[2] = 456
assert a[2] == 456
@@ -144,7 +164,7 @@
def test_array_inside_struct(self):
# like rstr.STR, but not Gc
- STR = lltype.Struct('STR', ('x', lltype.Signed), ('y', lltype.Array(lltype.Char)))
+ STR = lltype.Struct('STR', ('x', rffi.LONG), ('y', lltype.Array(lltype.Char)))
a = lltype.malloc(STR, 3, flavor='raw')
a.y[0] = 'x'
a.y[1] = 'y'
@@ -171,7 +191,7 @@
assert a[2] == 456
a[3] = 789
assert ac.contents.items[3] == 789
- assert ctypes.sizeof(ac.contents) == 10 * ctypes.sizeof(ctypes.c_long)
+ assert ctypes.sizeof(ac.contents) == 10 * rffi.sizeof(lltype.Signed)
lltype.free(a, flavor='raw')
assert not ALLOCATED # detects memory leaks in the test
@@ -223,20 +243,20 @@
def test_func_not_in_clib(self):
eci = ExternalCompilationInfo(libraries=['m'])
- foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed)
+ foobar = rffi.llexternal('I_really_dont_exist', [], rffi.LONG)
py.test.raises(NotImplementedError, foobar)
- foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed,
+ foobar = rffi.llexternal('I_really_dont_exist', [], rffi.LONG,
compilation_info=eci) # math library
py.test.raises(NotImplementedError, foobar)
eci = ExternalCompilationInfo(libraries=['m', 'z'])
- foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed,
+ foobar = rffi.llexternal('I_really_dont_exist', [], rffi.LONG,
compilation_info=eci) # math and zlib
py.test.raises(NotImplementedError, foobar)
eci = ExternalCompilationInfo(libraries=['I_really_dont_exist_either'])
- foobar = rffi.llexternal('I_really_dont_exist', [], lltype.Signed,
+ foobar = rffi.llexternal('I_really_dont_exist', [], rffi.LONG,
compilation_info=eci)
py.test.raises(NotImplementedError, foobar)
assert not ALLOCATED # detects memory leaks in the test
@@ -399,10 +419,9 @@
b = rffi.cast(lltype.Ptr(B), a)
- checker = array.array('l')
+ expected = ''
for i in range(10):
- checker.append(i*i)
- expected = checker.tostring()
+ expected += get_long_pattern(i*i)
for i in range(len(expected)):
assert b[i] == expected[i]
@@ -418,7 +437,7 @@
assert e[i] == i*i
c = lltype.nullptr(rffi.VOIDP.TO)
- addr = rffi.cast(lltype.Signed, c)
+ addr = rffi.cast(rffi.LONG, c)
assert addr == 0
lltype.free(a, flavor='raw')
@@ -444,8 +463,13 @@
FUNCTYPE = lltype.FuncType([lltype.Signed], lltype.Signed)
cdummy = lltype2ctypes(llhelper(lltype.Ptr(FUNCTYPE), dummy))
- assert isinstance(cdummy,
- ctypes.CFUNCTYPE(ctypes.c_long, ctypes.c_long))
+ if not is_emulated_long:
+ assert isinstance(cdummy,
+ ctypes.CFUNCTYPE(ctypes.c_long, ctypes.c_long))
+ else:
+ # XXX maybe we skip this if it breaks on some platforms
+ assert isinstance(cdummy,
+ ctypes.CFUNCTYPE(ctypes.c_longlong, ctypes.c_longlong))
res = cdummy(41)
assert res == 42
lldummy = ctypes2lltype(lltype.Ptr(FUNCTYPE), cdummy)
@@ -455,7 +479,7 @@
assert not ALLOCATED # detects memory leaks in the test
def test_funcptr2(self):
- FUNCTYPE = lltype.FuncType([rffi.CCHARP], lltype.Signed)
+ FUNCTYPE = lltype.FuncType([rffi.CCHARP], rffi.LONG)
cstrlen = standard_c_lib.strlen
llstrlen = ctypes2lltype(lltype.Ptr(FUNCTYPE), cstrlen)
assert lltype.typeOf(llstrlen) == lltype.Ptr(FUNCTYPE)
@@ -545,8 +569,9 @@
checkval(uninitialized2ctypes(rffi.CHAR), 'B')
checkval(uninitialized2ctypes(rffi.SHORT), 'h')
- checkval(uninitialized2ctypes(rffi.INT), 'i')
- checkval(uninitialized2ctypes(rffi.UINT), 'I')
+ if not is_emulated_long:
+ checkval(uninitialized2ctypes(rffi.INT), 'i')
+ checkval(uninitialized2ctypes(rffi.UINT), 'I')
checkval(uninitialized2ctypes(rffi.LONGLONG), 'q')
checkval(uninitialized2ctypes(rffi.DOUBLE), 'd')
checkobj(uninitialized2ctypes(rffi.INTP),
@@ -554,7 +579,7 @@
checkobj(uninitialized2ctypes(rffi.CCHARP),
ctypes.sizeof(ctypes.c_void_p))
- S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+ S = lltype.Struct('S', ('x', rffi.LONG), ('y', rffi.LONG))
s = lltype.malloc(S, flavor='raw')
sc = lltype2ctypes(s)
checkval(sc.contents.x, 'l')
@@ -717,9 +742,13 @@
assert not ALLOCATED # detects memory leaks in the test
def test_get_errno(self):
+ # win64: works with python 2.6.7, but not with 2.7.2
+ # XXX check what is different with ctypes!
eci = ExternalCompilationInfo(includes=['string.h'])
if sys.platform.startswith('win'):
underscore_on_windows = '_'
+ if sys.version.startswith('2.7.2 '):
+ py.test.skip('ctypes is buggy. errno crashes with win64 and python 2.7.2')
else:
underscore_on_windows = ''
strlen = rffi.llexternal('strlen', [rffi.CCHARP], rffi.SIZE_T,
@@ -730,7 +759,7 @@
buffer = lltype.malloc(rffi.CCHARP.TO, 5, flavor='raw')
written = os_write(12312312, buffer, 5)
lltype.free(buffer, flavor='raw')
- assert rffi.cast(lltype.Signed, written) < 0
+ assert rffi.cast(rffi.LONG, written) < 0
# the next line is a random external function call,
# to check that it doesn't reset errno
strlen("hi!")
@@ -849,9 +878,9 @@
return one + get_x()
def fy():
- one = rffi.cast(lltype.Signed, get_y())
+ one = rffi.cast(rffi.LONG, get_y())
set_y(rffi.cast(rffi.INT, 13))
- return one + rffi.cast(lltype.Signed, get_y())
+ return one + rffi.cast(rffi.LONG, get_y())
def g():
l = rffi.liststr2charpp(["a", "b", "c"])
@@ -916,7 +945,7 @@
lltype.free(a, flavor='raw')
def test_array_type_bug(self):
- A = lltype.Array(lltype.Signed)
+ A = lltype.Array(rffi.LONG)
a1 = lltype.malloc(A, 0, flavor='raw')
a2 = lltype.malloc(A, 0, flavor='raw')
c1 = lltype2ctypes(a1)
@@ -1006,7 +1035,7 @@
def test_recursive_struct_more(self):
NODE = lltype.ForwardReference()
- NODE.become(lltype.Struct('NODE', ('value', lltype.Signed),
+ NODE.become(lltype.Struct('NODE', ('value', rffi.LONG),
('next', lltype.Ptr(NODE))))
CNODEPTR = get_ctypes_type(NODE)
pc = CNODEPTR()
@@ -1034,11 +1063,11 @@
assert p.pong.ping == p
def test_typedef(self):
- assert ctypes2lltype(lltype.Typedef(lltype.Signed, 'test'), 6) == 6
+ assert ctypes2lltype(lltype.Typedef(rffi.LONG, 'test'), 6) == 6
assert ctypes2lltype(lltype.Typedef(lltype.Float, 'test2'), 3.4) == 3.4
- assert get_ctypes_type(lltype.Signed) == get_ctypes_type(
- lltype.Typedef(lltype.Signed, 'test3'))
+ assert get_ctypes_type(rffi.LONG) == get_ctypes_type(
+ lltype.Typedef(rffi.LONG, 'test3'))
def test_cast_adr_to_int(self):
class someaddr(object):
@@ -1046,7 +1075,7 @@
return sys.maxint/2 * 3
res = cast_adr_to_int(someaddr())
- assert isinstance(res, int)
+ assert is_valid_int(res)
assert res == -sys.maxint/2 - 3
def test_cast_gcref_back_and_forth(self):
@@ -1299,7 +1328,7 @@
p = lltype.malloc(S, flavor='raw')
a = llmemory.cast_ptr_to_adr(p)
i = llmemory.cast_adr_to_int(a, "forced")
- assert type(i) is int
+ assert is_valid_int(i)
assert i == llmemory.cast_adr_to_int(a, "forced")
lltype.free(p, flavor='raw')
More information about the pypy-commit
mailing list