Author: Christian Tismer <tis...@stackless.com> Branch: win64 test Changeset: r45358:f412af2f88c1 Date: 2011-07-05 18:53 +0200 http://bitbucket.org/pypy/pypy/changeset/f412af2f88c1/
Log: Making much progress with win64 and test_ll2ctypes. Compiler configuration works with Visual Studio 8. Checking in since there might be a problem in PyPy that is dependant of the test selection both on 32 and 64 bit. test_arrayofstruct seems to fail at assert a1[2].x == 102 result is always array[0] which is 100. I will check the trunk first before reporting an error. diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py --- a/pypy/rlib/rarithmetic.py +++ b/pypy/rlib/rarithmetic.py @@ -33,24 +33,53 @@ """ -import sys +import sys, struct from pypy.rpython import extregistry from pypy.rlib import objectmodel -# set up of machine internals, using sys.maxint only. -# if sys.maxsize exists and is greater, it is used instead. -_maxnumber = sys.maxint -if hasattr(sys, "maxsize"): - _maxnumber = max(sys.maxint, sys.maxsize) -_bits = 1 -_test = _maxnumber -while _test: - _bits += 1 - _test >>= 1 +""" +Long-term target: +We want to make pypy very flexible concerning its data type layout. +This is a larger task for later. + +Short-term target: +We want to run PyPy on windows 64 bit. + +Problem: +On windows 64 bit, integers are only 32 bit. This is a problem for PyPy +right now, since it assumes that a c long can hold a pointer. +We therefore set up the target machine constants to obey this rule. +Right now this affects 64 bit Python only on windows. + +Note: We use the struct module, because the array module doesn's support +all typecodes. +""" + +def _get_bitsize(typecode): + return len(struct.pack(typecode, 1)) * 8 + +_long_typecode = 'l' +if _get_bitsize('P') > _get_bitsize('l'): + _long_typecode = 'P' + +def _get_long_bit(): + # whatever size a long has, make it big enough for a pointer. + return _get_bitsize(_long_typecode) + +# exported for now for testing array values. +# might go into its own module. +def get_long_pattern(x): + """get the bit pattern for a long, adjusted to pointer size""" + return struct.pack(_long_typecode, x) + +# used in tests for ctypes: +is_emulated_long = _long_typecode <> 'l' -LONG_BIT = _bits +LONG_BIT = _get_long_bit() LONG_MASK = (2**LONG_BIT)-1 LONG_TEST = 2**(LONG_BIT-1) + +# XXX this is a good guess, but what if a long long is 128 bit? LONGLONG_BIT = 64 LONGLONG_MASK = (2**LONGLONG_BIT)-1 LONGLONG_TEST = 2**(LONGLONG_BIT-1) @@ -107,8 +136,6 @@ r_class.BITS == LONG_BIT and r_class.SIGNED) _should_widen_type._annspecialcase_ = 'specialize:memo' -del _bits, _test, _maxnumber - def is_valid_int(r): return -sys.maxint - 1 <= r <= sys.maxint diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py --- a/pypy/rpython/lltypesystem/rffi.py +++ b/pypy/rpython/lltypesystem/rffi.py @@ -17,6 +17,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.rstring import StringBuilder, UnicodeBuilder from pypy.rpython.lltypesystem import llmemory +from pypy.rlib.rarithmetic import LONG_BIT import os, sys class CConstant(Symbolic): @@ -884,7 +885,7 @@ return 4 assert isinstance(tp, lltype.Number) if tp is lltype.Signed: - return ULONG._type.BITS/8 + return LONG_BIT/8 return tp._type.BITS/8 sizeof._annspecialcase_ = 'specialize:memo' 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 @@ -15,7 +15,7 @@ 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 +from pypy.rlib.rarithmetic import r_uint, get_long_pattern, is_emulated_long if False: # for now, please keep it False by default from pypy.rpython.lltypesystem import ll2ctypes @@ -154,11 +154,6 @@ assert not ALLOCATED def test_array_nolength(self): - # XXX cannot fix this test when lltype.Signed is faked for win64. - # Replacement with rffi.LONG does not work because then I cannot - # index an array. So I have to use lltype.Signed . But the rffi.sizeof - # at the end has a hard-coded mapping to LONG and ignores the faked - # maxint. So what should I do? A = lltype.Array(lltype.Signed, hints={'nolength': True}) a = lltype.malloc(A, 10, flavor='raw') a[0] = 100 @@ -399,10 +394,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] @@ -442,10 +436,15 @@ def dummy(n): return n+1 - FUNCTYPE = lltype.FuncType([rffi.LONG], rffi.LONG) + 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) @@ -479,13 +478,13 @@ export_symbols=['get_mul']) get_mul = rffi.llexternal( 'get_mul', [], - lltype.Ptr(lltype.FuncType([rffi.LONG], rffi.LONG)), + lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)), compilation_info=eci) # This call returns a pointer to a function taking one argument funcptr = get_mul() # cast it to the "real" function type - FUNCTYPE2 = lltype.FuncType([rffi.LONG, rffi.LONG], - rffi.LONG) + FUNCTYPE2 = lltype.FuncType([lltype.Signed, lltype.Signed], + lltype.Signed) cmul = rffi.cast(lltype.Ptr(FUNCTYPE2), funcptr) # and it can be called with the expected number of arguments res = cmul(41, 42) @@ -502,12 +501,12 @@ lltype.Void) lst = [23, 43, 24, 324, 242, 34, 78, 5, 3, 10] - A = lltype.Array(rffi.LONG, hints={'nolength': True}) + A = lltype.Array(lltype.Signed, hints={'nolength': True}) a = lltype.malloc(A, 10, flavor='raw') for i in range(10): a[i] = lst[i] - SIGNEDPTR = lltype.Ptr(lltype.FixedSizeArray(rffi.LONG, 1)) + SIGNEDPTR = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1)) def my_compar(p1, p2): p1 = rffi.cast(SIGNEDPTR, p1) @@ -517,7 +516,7 @@ qsort(rffi.cast(rffi.VOIDP, a), rffi.cast(rffi.SIZE_T, 10), - rffi.cast(rffi.SIZE_T, llmemory.sizeof(rffi.LONG)), + rffi.cast(rffi.SIZE_T, llmemory.sizeof(lltype.Signed)), llhelper(lltype.Ptr(CMPFUNC), my_compar)) for i in range(10): @@ -545,8 +544,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), @@ -563,7 +563,7 @@ assert not ALLOCATED # detects memory leaks in the test def test_substructures(self): - S1 = lltype.Struct('S1', ('x', rffi.LONG)) + S1 = lltype.Struct('S1', ('x', lltype.Signed)) BIG = lltype.Struct('BIG', ('s1a', S1), ('s1b', S1)) s = lltype.malloc(BIG, flavor='raw') s.s1a.x = 123 @@ -613,7 +613,7 @@ def test_recursive_struct(self): SX = lltype.ForwardReference() - S1 = lltype.Struct('S1', ('p', lltype.Ptr(SX)), ('x', rffi.LONG)) + S1 = lltype.Struct('S1', ('p', lltype.Ptr(SX)), ('x', lltype.Signed)) SX.become(S1) # a chained list s1 = lltype.malloc(S1, flavor='raw') @@ -691,7 +691,7 @@ assert not ALLOCATED # detects memory leaks in the test def test_arrayofstruct(self): - S1 = lltype.Struct('S1', ('x', rffi.LONG)) + S1 = lltype.Struct('S1', ('x', lltype.Signed)) A = lltype.Array(S1, hints={'nolength': True}) a = lltype.malloc(A, 5, flavor='raw') a[0].x = 100 diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py --- a/pypy/translator/platform/__init__.py +++ b/pypy/translator/platform/__init__.py @@ -253,8 +253,12 @@ else: host_factory = Freebsd_64 elif os.name == 'nt': - from pypy.translator.platform.windows import Windows - host_factory = Windows + from pypy.translator.platform.windows import Windows, Windows_x64 + import platform + if platform.architecture()[0] == '32bit': + host_factory = Windows + else: + host_factory = Windows_x64 else: # pray from pypy.translator.platform.distutils_platform import DistutilsPlatform diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py --- a/pypy/translator/platform/windows.py +++ b/pypy/translator/platform/windows.py @@ -12,14 +12,23 @@ return MingwPlatform(cc) else: return MsvcPlatform(cc) + +def Windows_x64(cc=None): + return MsvcPlatform(cc, True) -def _get_msvc_env(vsver): +def _get_msvc_env(vsver, x64flag): try: toolsdir = os.environ['VS%sCOMNTOOLS' % vsver] except KeyError: return None - vcvars = os.path.join(toolsdir, 'vsvars32.bat') + if x64flag: + vsinstalldir = os.path.abspath(os.path.join(toolsdir, '..', '..')) + vcinstalldir = os.path.join(vsinstalldir, 'VC') + vcbindir = os.path.join(vcinstalldir, 'BIN') + vcvars = os.path.join(vcbindir, 'amd64', 'vcvarsamd64.bat') + else: + vcvars = os.path.join(toolsdir, 'vsvars32.bat') import subprocess popen = subprocess.Popen('"%s" & set' % (vcvars,), @@ -42,21 +51,21 @@ ## log.msg("Updated environment with %s" % (vcvars,)) return env -def find_msvc_env(): +def find_msvc_env(x64flag=False): # First, try to get the compiler which served to compile python msc_pos = sys.version.find('MSC v.') if msc_pos != -1: msc_ver = int(sys.version[msc_pos+6:msc_pos+10]) # 1300 -> 70, 1310 -> 71, 1400 -> 80, 1500 -> 90 vsver = (msc_ver / 10) - 60 - env = _get_msvc_env(vsver) + env = _get_msvc_env(vsver, x64flag) if env is not None: return env # Then, try any other version for vsver in (100, 90, 80, 71, 70): # All the versions I know - env = _get_msvc_env(vsver) + env = _get_msvc_env(vsver, x64flag) if env is not None: return env @@ -64,7 +73,8 @@ log.error("Could not find a Microsoft Compiler") # Assume that the compiler is already part of the environment -msvc_compiler_environ = find_msvc_env() +msvc_compiler_environ32 = find_msvc_env(False) +msvc_compiler_environ64 = find_msvc_env(True) class MsvcPlatform(Platform): name = "msvc" @@ -80,7 +90,11 @@ shared_only = () environ = None - def __init__(self, cc=None): + def __init__(self, cc=None, x64=False): + if x64: + msvc_compiler_environ = msvc_compiler_environ64 + else: + msvc_compiler_environ = msvc_compiler_environ32 Platform.__init__(self, 'cl.exe') if msvc_compiler_environ: self.c_environ = os.environ.copy() _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit