[pypy-svn] r74324 - in pypy/branch/py12: . lib-python/modified-2.5.2/distutils lib-python/modified-2.5.2/distutils/command pypy pypy/_interfaces pypy/annotation pypy/annotation/test pypy/config pypy/doc pypy/doc/config pypy/interpreter pypy/interpreter/test pypy/jit/backend/test pypy/jit/backend/x86/test pypy/jit/metainterp pypy/lib pypy/module/cpyext pypy/module/cpyext/include pypy/module/cpyext/src pypy/module/cpyext/test pypy/module/imp pypy/module/thread pypy/module/thread/test pypy/objspace/std pypy/objspace/std/test pypy/rlib pypy/rlib/test pypy/rpython pypy/rpython/lltypesystem pypy/rpython/lltypesystem/test pypy/rpython/test pypy/tool pypy/translator pypy/translator/c pypy/translator/c/gcc pypy/translator/c/gcc/test pypy/translator/c/src pypy/translator/c/test pypy/translator/goal pypy/translator/platform pypy/translator/test pypy/translator/tool pypy/translator/tool/test
hpk at codespeak.net
hpk at codespeak.net
Sun May 2 18:05:14 CEST 2010
Author: hpk
Date: Sun May 2 18:05:10 2010
New Revision: 74324
Added:
pypy/branch/py12/pypy/_interfaces/ (props changed)
- copied from r74323, pypy/trunk/pypy/_interfaces/
pypy/branch/py12/pypy/doc/config/objspace.usemodules.cpyext.txt
- copied unchanged from r74323, pypy/trunk/pypy/doc/config/objspace.usemodules.cpyext.txt
pypy/branch/py12/pypy/doc/config/translation.secondaryentrypoints.txt
- copied unchanged from r74323, pypy/trunk/pypy/doc/config/translation.secondaryentrypoints.txt
pypy/branch/py12/pypy/doc/config/translation.shared.txt
- copied unchanged from r74323, pypy/trunk/pypy/doc/config/translation.shared.txt
pypy/branch/py12/pypy/module/cpyext/ (props changed)
- copied from r74323, pypy/trunk/pypy/module/cpyext/
pypy/branch/py12/pypy/rlib/_rweakkeydict.py
- copied unchanged from r74323, pypy/trunk/pypy/rlib/_rweakkeydict.py
pypy/branch/py12/pypy/rlib/_rweakvaldict.py
- copied unchanged from r74323, pypy/trunk/pypy/rlib/_rweakvaldict.py
pypy/branch/py12/pypy/rlib/entrypoint.py
- copied unchanged from r74323, pypy/trunk/pypy/rlib/entrypoint.py
pypy/branch/py12/pypy/rlib/exports.py
- copied unchanged from r74323, pypy/trunk/pypy/rlib/exports.py
pypy/branch/py12/pypy/rlib/test/test_rweakkeydict.py
- copied unchanged from r74323, pypy/trunk/pypy/rlib/test/test_rweakkeydict.py
pypy/branch/py12/pypy/rlib/test/test_rweakvaldict.py
- copied unchanged from r74323, pypy/trunk/pypy/rlib/test/test_rweakvaldict.py
Removed:
pypy/branch/py12/pypy/doc/README.Debian
pypy/branch/py12/pypy/doc/README.compiling
pypy/branch/py12/pypy/rlib/rweakrefimpl.py
pypy/branch/py12/pypy/rlib/test/test_rweakref.py
Modified:
pypy/branch/py12/ (props changed)
pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py
pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py
pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py
pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py
pypy/branch/py12/pypy/annotation/annrpython.py
pypy/branch/py12/pypy/annotation/description.py
pypy/branch/py12/pypy/annotation/test/test_annrpython.py
pypy/branch/py12/pypy/config/pypyoption.py
pypy/branch/py12/pypy/config/translationoption.py
pypy/branch/py12/pypy/conftest.py
pypy/branch/py12/pypy/doc/project-ideas.txt
pypy/branch/py12/pypy/interpreter/argument.py
pypy/branch/py12/pypy/interpreter/baseobjspace.py
pypy/branch/py12/pypy/interpreter/executioncontext.py
pypy/branch/py12/pypy/interpreter/main.py
pypy/branch/py12/pypy/interpreter/pycompiler.py
pypy/branch/py12/pypy/interpreter/pyopcode.py
pypy/branch/py12/pypy/interpreter/test/test_argument.py
pypy/branch/py12/pypy/interpreter/test/test_typedef.py
pypy/branch/py12/pypy/interpreter/typedef.py
pypy/branch/py12/pypy/jit/backend/test/support.py
pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py
pypy/branch/py12/pypy/jit/metainterp/support.py
pypy/branch/py12/pypy/jit/metainterp/warmspot.py
pypy/branch/py12/pypy/lib/identity_dict.py
pypy/branch/py12/pypy/module/cpyext/include/ (props changed)
pypy/branch/py12/pypy/module/cpyext/src/ (props changed)
pypy/branch/py12/pypy/module/cpyext/test/ (props changed)
pypy/branch/py12/pypy/module/imp/importing.py
pypy/branch/py12/pypy/module/thread/ll_thread.py
pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py
pypy/branch/py12/pypy/objspace/std/fake.py
pypy/branch/py12/pypy/objspace/std/objspace.py
pypy/branch/py12/pypy/objspace/std/test/test_setobject.py
pypy/branch/py12/pypy/objspace/std/typeobject.py
pypy/branch/py12/pypy/rlib/rarithmetic.py
pypy/branch/py12/pypy/rlib/rstring.py
pypy/branch/py12/pypy/rlib/rweakref.py
pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py
pypy/branch/py12/pypy/rlib/test/test_rbigint.py
pypy/branch/py12/pypy/rlib/test/test_rstring.py
pypy/branch/py12/pypy/rpython/annlowlevel.py
pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py
pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py
pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py
pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py
pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py
pypy/branch/py12/pypy/rpython/test/test_llinterp.py
pypy/branch/py12/pypy/tool/fixeol
pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py
pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py
pypy/branch/py12/pypy/translator/c/genc.py
pypy/branch/py12/pypy/translator/c/node.py
pypy/branch/py12/pypy/translator/c/src/commondefs.h
pypy/branch/py12/pypy/translator/c/src/main.h
pypy/branch/py12/pypy/translator/c/src/obmalloc.c
pypy/branch/py12/pypy/translator/c/test/test_genc.py
pypy/branch/py12/pypy/translator/c/test/test_newgc.py
pypy/branch/py12/pypy/translator/c/test/test_standalone.py
pypy/branch/py12/pypy/translator/driver.py
pypy/branch/py12/pypy/translator/goal/ann_override.py
pypy/branch/py12/pypy/translator/platform/__init__.py
pypy/branch/py12/pypy/translator/platform/darwin.py
pypy/branch/py12/pypy/translator/platform/linux.py
pypy/branch/py12/pypy/translator/platform/posix.py
pypy/branch/py12/pypy/translator/platform/windows.py
pypy/branch/py12/pypy/translator/test/test_unsimplify.py
pypy/branch/py12/pypy/translator/tool/cbuild.py
pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py
pypy/branch/py12/pypy/translator/unsimplify.py
Log:
merge trunk
Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py (original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/command/build_ext.py Sun May 2 18:05:10 2010
@@ -167,7 +167,7 @@
# for Release and Debug builds.
# also Python's library directory must be appended to library_dirs
if os.name == 'nt':
- self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
+ self.library_dirs.append(os.path.join(sys.pypy_prefix, 'pypy', '_interfaces'))
if self.debug:
self.build_temp = os.path.join(self.build_temp, "Debug")
else:
@@ -175,8 +175,8 @@
# Append the source distribution include and library directories,
# this allows distutils on windows to work in the source tree
- self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
- self.library_dirs.append(os.path.join(sys.exec_prefix, 'PCBuild'))
+ #self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
+ #self.library_dirs.append(os.path.join(sys.exec_prefix, 'PCBuild'))
# OS/2 (EMX) doesn't support Debug vs Release builds, but has the
# import libraries in its "Config" subdirectory
@@ -645,24 +645,12 @@
shared extension. On most platforms, this is just 'ext.libraries';
on Windows and OS/2, we add the Python library (eg. python20.dll).
"""
- # The python library is always needed on Windows. For MSVC, this
- # is redundant, since the library is mentioned in a pragma in
- # pyconfig.h that MSVC groks. The other Windows compilers all seem
- # to need it mentioned explicitly, though, so that's what we do.
- # Append '_d' to the python import library on debug builds.
+ # The python library is always needed on Windows.
if sys.platform == "win32":
- from distutils.msvccompiler import MSVCCompiler
- if not isinstance(self.compiler, MSVCCompiler):
- template = "python%d%d"
- if self.debug:
- template = template + '_d'
- pythonlib = (template %
- (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
- # don't extend ext.libraries, it may be shared with other
- # extensions, it is a reference to the original list
- return ext.libraries + [pythonlib]
- else:
- return ext.libraries
+ pythonlib = 'libpypy-c.exe'
+ # don't extend ext.libraries, it may be shared with other
+ # extensions, it is a reference to the original list
+ return ext.libraries + [pythonlib]
elif sys.platform == "os2emx":
# EMX/GCC requires the python library explicitly, and I
# believe VACPP does as well (though not confirmed) - AIM Apr01
Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py (original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/msvccompiler.py Sun May 2 18:05:10 2010
@@ -1,154 +1,162 @@
-"""distutils.msvccompiler
+"""distutils.msvc9compiler
Contains MSVCCompiler, an implementation of the abstract CCompiler class
-for the Microsoft Visual Studio.
+for the Microsoft Visual Studio 2008.
+
+The module is compatible with VS 2005 and VS 2008. You can find legacy support
+for older versions of VS in distutils.msvccompiler.
"""
# Written by Perry Stoll
# hacked by Robin Becker and Thomas Heller to do a better job of
# finding DevStudio (through the registry)
+# ported to VS2005 and VS 2008 by Christian Heimes
-# This module should be kept compatible with Python 2.1.
-
-__revision__ = "$Id: msvccompiler.py 54645 2007-04-01 18:29:47Z neal.norwitz $"
+__revision__ = "$Id: msvc9compiler.py 78713 2010-03-06 02:17:28Z tarek.ziade $"
-import sys, os, string
-from distutils.errors import \
- DistutilsExecError, DistutilsPlatformError, \
- CompileError, LibError, LinkError
-from distutils.ccompiler import \
- CCompiler, gen_preprocess_options, gen_lib_options
+import os
+import subprocess
+import sys
+import re
+
+from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
+ CompileError, LibError, LinkError)
+from distutils.ccompiler import CCompiler, gen_lib_options
from distutils import log
+from distutils.util import get_platform
-_can_read_reg = 0
-try:
- import _winreg
-
- _can_read_reg = 1
- hkey_mod = _winreg
-
- RegOpenKeyEx = _winreg.OpenKeyEx
- RegEnumKey = _winreg.EnumKey
- RegEnumValue = _winreg.EnumValue
- RegError = _winreg.error
+import _winreg
-except ImportError:
- try:
- import win32api
- import win32con
- _can_read_reg = 1
- hkey_mod = win32con
-
- RegOpenKeyEx = win32api.RegOpenKeyEx
- RegEnumKey = win32api.RegEnumKey
- RegEnumValue = win32api.RegEnumValue
- RegError = win32api.error
-
- except ImportError:
- log.info("Warning: Can't read registry to find the "
- "necessary compiler setting\n"
- "Make sure that Python modules _winreg, "
- "win32api or win32con are installed.")
- pass
-
-if _can_read_reg:
- HKEYS = (hkey_mod.HKEY_USERS,
- hkey_mod.HKEY_CURRENT_USER,
- hkey_mod.HKEY_LOCAL_MACHINE,
- hkey_mod.HKEY_CLASSES_ROOT)
+RegOpenKeyEx = _winreg.OpenKeyEx
+RegEnumKey = _winreg.EnumKey
+RegEnumValue = _winreg.EnumValue
+RegError = _winreg.error
+
+HKEYS = (_winreg.HKEY_USERS,
+ _winreg.HKEY_CURRENT_USER,
+ _winreg.HKEY_LOCAL_MACHINE,
+ _winreg.HKEY_CLASSES_ROOT)
+
+VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
+VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"
+WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
+NET_BASE = r"Software\Microsoft\.NETFramework"
+
+# A map keyed by get_platform() return values to values accepted by
+# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
+# the param to cross-compile on x86 targetting amd64.)
+PLAT_TO_VCVARS = {
+ 'win32' : 'x86',
+ 'win-amd64' : 'amd64',
+ 'win-ia64' : 'ia64',
+}
-def read_keys(base, key):
- """Return list of registry keys."""
+class Reg:
+ """Helper class to read values from the registry
+ """
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- L = []
- i = 0
- while 1:
+ def get_value(cls, path, key):
+ for base in HKEYS:
+ d = cls.read_values(base, path)
+ if d and key in d:
+ return d[key]
+ raise KeyError(key)
+ get_value = classmethod(get_value)
+
+ def read_keys(cls, base, key):
+ """Return list of registry keys."""
try:
- k = RegEnumKey(handle, i)
+ handle = RegOpenKeyEx(base, key)
except RegError:
- break
- L.append(k)
- i = i + 1
- return L
+ return None
+ L = []
+ i = 0
+ while True:
+ try:
+ k = RegEnumKey(handle, i)
+ except RegError:
+ break
+ L.append(k)
+ i += 1
+ return L
+ read_keys = classmethod(read_keys)
-def read_values(base, key):
- """Return dict of registry keys and values.
+ def read_values(cls, base, key):
+ """Return dict of registry keys and values.
- All names are converted to lowercase.
- """
- try:
- handle = RegOpenKeyEx(base, key)
- except RegError:
- return None
- d = {}
- i = 0
- while 1:
+ All names are converted to lowercase.
+ """
try:
- name, value, type = RegEnumValue(handle, i)
+ handle = RegOpenKeyEx(base, key)
except RegError:
- break
- name = name.lower()
- d[convert_mbcs(name)] = convert_mbcs(value)
- i = i + 1
- return d
-
-def convert_mbcs(s):
- enc = getattr(s, "encode", None)
- if enc is not None:
- try:
- s = enc("mbcs")
- except UnicodeError:
- pass
- return s
+ return None
+ d = {}
+ i = 0
+ while True:
+ try:
+ name, value, type = RegEnumValue(handle, i)
+ except RegError:
+ break
+ name = name.lower()
+ d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
+ i += 1
+ return d
+ read_values = classmethod(read_values)
+
+ def convert_mbcs(s):
+ dec = getattr(s, "decode", None)
+ if dec is not None:
+ try:
+ s = dec("mbcs")
+ except UnicodeError:
+ pass
+ return s
+ convert_mbcs = staticmethod(convert_mbcs)
class MacroExpander:
def __init__(self, version):
self.macros = {}
+ self.vsbase = VS_BASE % version
self.load_macros(version)
def set_macro(self, macro, path, key):
- for base in HKEYS:
- d = read_values(base, path)
- if d:
- self.macros["$(%s)" % macro] = d[key]
- break
+ self.macros["$(%s)" % macro] = Reg.get_value(path, key)
def load_macros(self, version):
- vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
- self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
- self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
- net = r"Software\Microsoft\.NETFramework"
- self.set_macro("FrameworkDir", net, "installroot")
+ self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
+ self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
+ self.set_macro("FrameworkDir", NET_BASE, "installroot")
try:
- if version > 7.0:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
+ if version >= 8.0:
+ self.set_macro("FrameworkSDKDir", NET_BASE,
+ "sdkinstallrootv2.0")
else:
- self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
- except KeyError, exc: #
- raise DistutilsPlatformError, \
- ("""Python was built with Visual Studio 2003;
+ raise KeyError("sdkinstallrootv2.0")
+ except KeyError:
+ raise DistutilsPlatformError(
+ """Python was built with Visual Studio 2008;
extensions must be built with a compiler than can generate compatible binaries.
-Visual Studio 2003 was not found on this system. If you have Cygwin installed,
+Visual Studio 2008 was not found on this system. If you have Cygwin installed,
you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
- p = r"Software\Microsoft\NET Framework Setup\Product"
- for base in HKEYS:
- try:
- h = RegOpenKeyEx(base, p)
- except RegError:
- continue
- key = RegEnumKey(h, 0)
- d = read_values(base, r"%s\%s" % (p, key))
- self.macros["$(FrameworkVersion)"] = d["version"]
+ if version >= 9.0:
+ self.set_macro("FrameworkVersion", self.vsbase, "clr version")
+ self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
+ else:
+ p = r"Software\Microsoft\NET Framework Setup\Product"
+ for base in HKEYS:
+ try:
+ h = RegOpenKeyEx(base, p)
+ except RegError:
+ continue
+ key = RegEnumKey(h, 0)
+ d = Reg.get_value(base, r"%s\%s" % (p, key))
+ self.macros["$(FrameworkVersion)"] = d["version"]
def sub(self, s):
for k, v in self.macros.items():
- s = string.replace(s, k, v)
+ s = s.replace(k, v)
return s
def get_build_version():
@@ -157,35 +165,7 @@
For Python 2.3 and up, the version number is included in
sys.version. For earlier versions, assume the compiler is MSVC 6.
"""
-
- prefix = "MSC v."
- i = string.find(sys.version, prefix)
- if i == -1:
- return 6
- i = i + len(prefix)
- s, rest = sys.version[i:].split(" ", 1)
- majorVersion = int(s[:-2]) - 6
- minorVersion = int(s[2:3]) / 10.0
- # I don't think paths are affected by minor version in version 6
- if majorVersion == 6:
- minorVersion = 0
- if majorVersion >= 6:
- return majorVersion + minorVersion
- # else we don't know what version of the compiler this is
- return None
-
-def get_build_architecture():
- """Return the processor architecture.
-
- Possible results are "Intel", "Itanium", or "AMD64".
- """
-
- prefix = " bit ("
- i = string.find(sys.version, prefix)
- if i == -1:
- return "Intel"
- j = string.find(sys.version, ")", i)
- return sys.version[i+len(prefix):j]
+ return 8.0
def normalize_and_reduce_paths(paths):
"""Return a list of normalized paths with duplicates removed.
@@ -201,8 +181,104 @@
reduced_paths.append(np)
return reduced_paths
+def removeDuplicates(variable):
+ """Remove duplicate values of an environment variable.
+ """
+ oldList = variable.split(os.pathsep)
+ newList = []
+ for i in oldList:
+ if i not in newList:
+ newList.append(i)
+ newVariable = os.pathsep.join(newList)
+ return newVariable
+
+def find_vcvarsall(version):
+ """Find the vcvarsall.bat file
+
+ At first it tries to find the productdir of VS 2008 in the registry. If
+ that fails it falls back to the VS90COMNTOOLS env var.
+ """
+ vsbase = VS_BASE % version
+ try:
+ productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
+ "productdir")
+ except KeyError:
+ productdir = None
+
+ # trying Express edition
+ if productdir is None:
+ vsbase = VSEXPRESS_BASE % version
+ try:
+ productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
+ "productdir")
+ except KeyError:
+ productdir = None
+ log.debug("Unable to find productdir in registry")
+
+ if not productdir or not os.path.isdir(productdir):
+ toolskey = "VS%0.f0COMNTOOLS" % version
+ toolsdir = os.environ.get(toolskey, None)
+
+ if toolsdir and os.path.isdir(toolsdir):
+ productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
+ productdir = os.path.abspath(productdir)
+ if not os.path.isdir(productdir):
+ log.debug("%s is not a valid directory" % productdir)
+ return None
+ else:
+ log.debug("Env var %s is not set or invalid" % toolskey)
+ if not productdir:
+ log.debug("No productdir found")
+ return None
+ vcvarsall = os.path.join(productdir, "vcvarsall.bat")
+ if os.path.isfile(vcvarsall):
+ return vcvarsall
+ log.debug("Unable to find vcvarsall.bat")
+ return None
+
+def query_vcvarsall(version, arch="x86"):
+ """Launch vcvarsall.bat and read the settings from its environment
+ """
+ vcvarsall = find_vcvarsall(version)
+ interesting = set(("include", "lib", "libpath", "path"))
+ result = {}
+
+ if vcvarsall is None:
+ raise DistutilsPlatformError("Unable to find vcvarsall.bat")
+ log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
+ popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ stdout, stderr = popen.communicate()
+ if popen.wait() != 0:
+ raise DistutilsPlatformError(stderr.decode("mbcs"))
+
+ stdout = stdout.decode("mbcs")
+ for line in stdout.split("\n"):
+ line = Reg.convert_mbcs(line)
+ if '=' not in line:
+ continue
+ line = line.strip()
+ key, value = line.split('=', 1)
+ key = key.lower()
+ if key in interesting:
+ if value.endswith(os.pathsep):
+ value = value[:-1]
+ result[key] = removeDuplicates(value)
+
+ if len(result) != len(interesting):
+ raise ValueError(str(list(result.keys())))
+
+ return result
+
+# More globals
+VERSION = get_build_version()
+if VERSION < 8.0:
+ raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
+# MACROS = MacroExpander(VERSION)
-class MSVCCompiler (CCompiler) :
+class MSVCCompiler(CCompiler) :
"""Concrete class that implements an interface to Microsoft Visual C++,
as defined by the CCompiler abstract class."""
@@ -232,27 +308,29 @@
static_lib_format = shared_lib_format = '%s%s'
exe_extension = '.exe'
- def __init__ (self, verbose=0, dry_run=0, force=0):
+ def __init__(self, verbose=0, dry_run=0, force=0):
CCompiler.__init__ (self, verbose, dry_run, force)
- self.__version = get_build_version()
- self.__arch = get_build_architecture()
- if self.__arch == "Intel":
- # x86
- if self.__version >= 7:
- self.__root = r"Software\Microsoft\VisualStudio"
- self.__macros = MacroExpander(self.__version)
- else:
- self.__root = r"Software\Microsoft\Devstudio"
- self.__product = "Visual Studio version %s" % self.__version
- else:
- # Win64. Assume this was built with the platform SDK
- self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
-
+ self.__version = VERSION
+ self.__root = r"Software\Microsoft\VisualStudio"
+ # self.__macros = MACROS
+ self.__paths = []
+ # target platform (.plat_name is consistent with 'bdist')
+ self.plat_name = None
+ self.__arch = None # deprecated name
self.initialized = False
- def initialize(self):
- self.__paths = []
- if os.environ.has_key("DISTUTILS_USE_SDK") and os.environ.has_key("MSSdk") and self.find_exe("cl.exe"):
+ def initialize(self, plat_name=None):
+ # multi-init means we would need to check platform same each time...
+ assert not self.initialized, "don't init multiple times"
+ if plat_name is None:
+ plat_name = get_platform()
+ # sanity check for platforms to prevent obscure errors later.
+ ok_plats = 'win32', 'win-amd64', 'win-ia64'
+ if plat_name not in ok_plats:
+ raise DistutilsPlatformError("--plat-name must be one of %s" %
+ (ok_plats,))
+
+ if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
# Assume that the SDK set up everything alright; don't try to be
# smarter
self.cc = "cl.exe"
@@ -261,36 +339,54 @@
self.rc = "rc.exe"
self.mc = "mc.exe"
else:
- self.__paths = self.get_msvc_paths("path")
+ # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
+ # to cross compile, you use 'x86_amd64'.
+ # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
+ # compile use 'x86' (ie, it runs the x86 compiler directly)
+ # No idea how itanium handles this, if at all.
+ if plat_name == get_platform() or plat_name == 'win32':
+ # native build or cross-compile to win32
+ plat_spec = PLAT_TO_VCVARS[plat_name]
+ else:
+ # cross compile from win32 -> some 64bit
+ plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \
+ PLAT_TO_VCVARS[plat_name]
+
+ vc_env = query_vcvarsall(VERSION, plat_spec)
+
+ # take care to only use strings in the environment.
+ self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep)
+ os.environ['lib'] = vc_env['lib'].encode('mbcs')
+ os.environ['include'] = vc_env['include'].encode('mbcs')
- if len (self.__paths) == 0:
- raise DistutilsPlatformError, \
- ("Python was built with %s, "
+ if len(self.__paths) == 0:
+ raise DistutilsPlatformError("Python was built with %s, "
"and extensions need to be built with the same "
- "version of the compiler, but it isn't installed." % self.__product)
+ "version of the compiler, but it isn't installed."
+ % self.__product)
self.cc = self.find_exe("cl.exe")
self.linker = self.find_exe("link.exe")
self.lib = self.find_exe("lib.exe")
self.rc = self.find_exe("rc.exe") # resource compiler
self.mc = self.find_exe("mc.exe") # message compiler
- self.set_path_env_var('lib')
- self.set_path_env_var('include')
+ #self.set_path_env_var('lib')
+ #self.set_path_env_var('include')
# extend the MSVC path with the current path
try:
- for p in string.split(os.environ['path'], ';'):
+ for p in os.environ['path'].split(';'):
self.__paths.append(p)
except KeyError:
pass
self.__paths = normalize_and_reduce_paths(self.__paths)
- os.environ['path'] = string.join(self.__paths, ';')
+ os.environ['path'] = ";".join(self.__paths)
self.preprocess_options = None
- if self.__arch == "Intel":
- self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
+ if self.__arch == "x86":
+ self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3',
'/DNDEBUG']
- self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
+ self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3',
'/Z7', '/D_DEBUG']
else:
# Win64
@@ -304,20 +400,16 @@
self.ldflags_shared_debug = [
'/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
]
- else:
- self.ldflags_shared_debug = [
- '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
- ]
self.ldflags_static = [ '/nologo']
self.initialized = True
# -- Worker methods ------------------------------------------------
- def object_filenames (self,
- source_filenames,
- strip_dir=0,
- output_dir=''):
+ def object_filenames(self,
+ source_filenames,
+ strip_dir=0,
+ output_dir=''):
# Copied from ccompiler.py, extended to return .res as 'object'-file
# for .rc input file
if output_dir is None: output_dir = ''
@@ -344,17 +436,16 @@
base + self.obj_extension))
return obj_names
- # object_filenames ()
-
def compile(self, sources,
output_dir=None, macros=None, include_dirs=None, debug=0,
extra_preargs=None, extra_postargs=None, depends=None):
- if not self.initialized: self.initialize()
- macros, objects, extra_postargs, pp_opts, build = \
- self._setup_compile(output_dir, macros, include_dirs, sources,
- depends, extra_postargs)
+ if not self.initialized:
+ self.initialize()
+ compile_info = self._setup_compile(output_dir, macros, include_dirs,
+ sources, depends, extra_postargs)
+ macros, objects, extra_postargs, pp_opts, build = compile_info
compile_opts = extra_preargs or []
compile_opts.append ('/c')
@@ -383,13 +474,12 @@
input_opt = src
output_opt = "/fo" + obj
try:
- self.spawn ([self.rc] + pp_opts +
- [output_opt] + [input_opt])
+ self.spawn([self.rc] + pp_opts +
+ [output_opt] + [input_opt])
except DistutilsExecError, msg:
- raise CompileError, msg
+ raise CompileError(msg)
continue
elif ext in self._mc_extensions:
-
# Compile .MC to .RC file to .RES file.
# * '-h dir' specifies the directory for the
# generated include file
@@ -401,99 +491,95 @@
# we use the source-directory for the include file and
# the build directory for the RC file and message
# resources. This works at least for win32all.
-
- h_dir = os.path.dirname (src)
- rc_dir = os.path.dirname (obj)
+ h_dir = os.path.dirname(src)
+ rc_dir = os.path.dirname(obj)
try:
# first compile .MC to .RC and .H file
- self.spawn ([self.mc] +
- ['-h', h_dir, '-r', rc_dir] + [src])
+ self.spawn([self.mc] +
+ ['-h', h_dir, '-r', rc_dir] + [src])
base, _ = os.path.splitext (os.path.basename (src))
rc_file = os.path.join (rc_dir, base + '.rc')
# then compile .RC to .RES file
- self.spawn ([self.rc] +
- ["/fo" + obj] + [rc_file])
+ self.spawn([self.rc] +
+ ["/fo" + obj] + [rc_file])
except DistutilsExecError, msg:
- raise CompileError, msg
+ raise CompileError(msg)
continue
else:
# how to handle this file?
- raise CompileError (
- "Don't know how to compile %s to %s" % \
- (src, obj))
+ raise CompileError("Don't know how to compile %s to %s"
+ % (src, obj))
output_opt = "/Fo" + obj
try:
- self.spawn ([self.cc] + compile_opts + pp_opts +
- [input_opt, output_opt] +
- extra_postargs)
+ self.spawn([self.cc] + compile_opts + pp_opts +
+ [input_opt, output_opt] +
+ extra_postargs)
except DistutilsExecError, msg:
- raise CompileError, msg
+ raise CompileError(msg)
return objects
- # compile ()
-
- def create_static_lib (self,
- objects,
- output_libname,
- output_dir=None,
- debug=0,
- target_lang=None):
-
- if not self.initialized: self.initialize()
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- output_filename = \
- self.library_filename (output_libname, output_dir=output_dir)
+ def create_static_lib(self,
+ objects,
+ output_libname,
+ output_dir=None,
+ debug=0,
+ target_lang=None):
+
+ if not self.initialized:
+ self.initialize()
+ (objects, output_dir) = self._fix_object_args(objects, output_dir)
+ output_filename = self.library_filename(output_libname,
+ output_dir=output_dir)
- if self._need_link (objects, output_filename):
+ if self._need_link(objects, output_filename):
lib_args = objects + ['/OUT:' + output_filename]
if debug:
- pass # XXX what goes here?
+ pass # XXX what goes here?
try:
- self.spawn ([self.lib] + lib_args)
+ self.spawn([self.lib] + lib_args)
except DistutilsExecError, msg:
- raise LibError, msg
-
+ raise LibError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
- # create_static_lib ()
- def link (self,
- target_desc,
- objects,
- output_filename,
- output_dir=None,
- libraries=None,
- library_dirs=None,
- runtime_library_dirs=None,
- export_symbols=None,
- debug=0,
- extra_preargs=None,
- extra_postargs=None,
- build_temp=None,
- target_lang=None):
-
- if not self.initialized: self.initialize()
- (objects, output_dir) = self._fix_object_args (objects, output_dir)
- (libraries, library_dirs, runtime_library_dirs) = \
- self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
+ def link(self,
+ target_desc,
+ objects,
+ output_filename,
+ output_dir=None,
+ libraries=None,
+ library_dirs=None,
+ runtime_library_dirs=None,
+ export_symbols=None,
+ debug=0,
+ extra_preargs=None,
+ extra_postargs=None,
+ build_temp=None,
+ target_lang=None):
+
+ if not self.initialized:
+ self.initialize()
+ (objects, output_dir) = self._fix_object_args(objects, output_dir)
+ fixed_args = self._fix_lib_args(libraries, library_dirs,
+ runtime_library_dirs)
+ (libraries, library_dirs, runtime_library_dirs) = fixed_args
if runtime_library_dirs:
self.warn ("I don't know what to do with 'runtime_library_dirs': "
+ str (runtime_library_dirs))
- lib_opts = gen_lib_options (self,
- library_dirs, runtime_library_dirs,
- libraries)
+ lib_opts = gen_lib_options(self,
+ library_dirs, runtime_library_dirs,
+ libraries)
if output_dir is not None:
- output_filename = os.path.join (output_dir, output_filename)
-
- if self._need_link (objects, output_filename):
+ output_filename = os.path.join(output_dir, output_filename)
+ if self._need_link(objects, output_filename):
if target_desc == CCompiler.EXECUTABLE:
if debug:
ldflags = self.ldflags_shared_debug[1:]
@@ -517,47 +603,99 @@
# needed! Make sure they are generated in the temporary build
# directory. Since they have different names for debug and release
# builds, they can go into the same directory.
+ build_temp = os.path.dirname(objects[0])
if export_symbols is not None:
(dll_name, dll_ext) = os.path.splitext(
os.path.basename(output_filename))
implib_file = os.path.join(
- os.path.dirname(objects[0]),
+ build_temp,
self.library_filename(dll_name))
ld_args.append ('/IMPLIB:' + implib_file)
+ # Embedded manifests are recommended - see MSDN article titled
+ # "How to: Embed a Manifest Inside a C/C++ Application"
+ # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
+ # Ask the linker to generate the manifest in the temp dir, so
+ # we can embed it later.
+ temp_manifest = os.path.join(
+ build_temp,
+ os.path.basename(output_filename) + ".manifest")
+ ld_args.append('/MANIFESTFILE:' + temp_manifest)
+
if extra_preargs:
ld_args[:0] = extra_preargs
if extra_postargs:
ld_args.extend(extra_postargs)
- self.mkpath (os.path.dirname (output_filename))
+ self.mkpath(os.path.dirname(output_filename))
try:
- self.spawn ([self.linker] + ld_args)
+ self.spawn([self.linker] + ld_args)
except DistutilsExecError, msg:
- raise LinkError, msg
+ raise LinkError(msg)
+ # embed the manifest
+ # XXX - this is somewhat fragile - if mt.exe fails, distutils
+ # will still consider the DLL up-to-date, but it will not have a
+ # manifest. Maybe we should link to a temp file? OTOH, that
+ # implies a build environment error that shouldn't go undetected.
+ if target_desc == CCompiler.EXECUTABLE:
+ mfid = 1
+ else:
+ mfid = 2
+ self._remove_visual_c_ref(temp_manifest)
+ out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
+ try:
+ self.spawn(['mt.exe', '-nologo', '-manifest',
+ temp_manifest, out_arg])
+ except DistutilsExecError, msg:
+ raise LinkError(msg)
else:
log.debug("skipping %s (up-to-date)", output_filename)
- # link ()
-
+ def _remove_visual_c_ref(self, manifest_file):
+ try:
+ # Remove references to the Visual C runtime, so they will
+ # fall through to the Visual C dependency of Python.exe.
+ # This way, when installed for a restricted user (e.g.
+ # runtimes are not in WinSxS folder, but in Python's own
+ # folder), the runtimes do not need to be in every folder
+ # with .pyd's.
+ manifest_f = open(manifest_file)
+ try:
+ manifest_buf = manifest_f.read()
+ finally:
+ manifest_f.close()
+ pattern = re.compile(
+ r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
+ r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
+ re.DOTALL)
+ manifest_buf = re.sub(pattern, "", manifest_buf)
+ pattern = "<dependentAssembly>\s*</dependentAssembly>"
+ manifest_buf = re.sub(pattern, "", manifest_buf)
+ manifest_f = open(manifest_file, 'w')
+ try:
+ manifest_f.write(manifest_buf)
+ finally:
+ manifest_f.close()
+ except IOError:
+ pass
# -- Miscellaneous methods -----------------------------------------
# These are all used by the 'gen_lib_options() function, in
# ccompiler.py.
- def library_dir_option (self, dir):
+ def library_dir_option(self, dir):
return "/LIBPATH:" + dir
- def runtime_library_dir_option (self, dir):
- raise DistutilsPlatformError, \
- "don't know how to set runtime library search path for MSVC++"
+ def runtime_library_dir_option(self, dir):
+ raise DistutilsPlatformError(
+ "don't know how to set runtime library search path for MSVC++")
- def library_option (self, lib):
- return self.library_filename (lib)
+ def library_option(self, lib):
+ return self.library_filename(lib)
- def find_library_file (self, dirs, lib, debug=0):
+ def find_library_file(self, dirs, lib, debug=0):
# Prefer a debugging library if found (and requested), but deal
# with it if we don't have one.
if debug:
@@ -573,8 +711,6 @@
# Oops, didn't find it in *any* of 'dirs'
return None
- # find_library_file ()
-
# Helper methods for using the MSVC registry settings
def find_exe(self, exe):
@@ -586,67 +722,15 @@
absolute path that is known to exist. If none of them work, just
return the original program name, 'exe'.
"""
-
for p in self.__paths:
fn = os.path.join(os.path.abspath(p), exe)
if os.path.isfile(fn):
return fn
# didn't find it; try existing path
- for p in string.split(os.environ['Path'],';'):
+ for p in os.environ['Path'].split(';'):
fn = os.path.join(os.path.abspath(p),exe)
if os.path.isfile(fn):
return fn
return exe
-
- def get_msvc_paths(self, path, platform='x86'):
- """Get a list of devstudio directories (include, lib or path).
-
- Return a list of strings. The list will be empty if unable to
- access the registry or appropriate registry keys not found.
- """
-
- if not _can_read_reg:
- return []
-
- path = path + " dirs"
- if self.__version >= 7:
- key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
- % (self.__root, self.__version))
- else:
- key = (r"%s\6.0\Build System\Components\Platforms"
- r"\Win32 (%s)\Directories" % (self.__root, platform))
-
- for base in HKEYS:
- d = read_values(base, key)
- if d:
- if self.__version >= 7:
- return string.split(self.__macros.sub(d[path]), ";")
- else:
- return string.split(d[path], ";")
- # MSVC 6 seems to create the registry entries we need only when
- # the GUI is run.
- if self.__version == 6:
- for base in HKEYS:
- if read_values(base, r"%s\6.0" % self.__root) is not None:
- self.warn("It seems you have Visual Studio 6 installed, "
- "but the expected registry settings are not present.\n"
- "You must at least run the Visual Studio GUI once "
- "so that these entries are created.")
- break
- return []
-
- def set_path_env_var(self, name):
- """Set environment variable 'name' to an MSVC path type value.
-
- This is equivalent to a SET command prior to execution of spawned
- commands.
- """
-
- if name == "lib":
- p = self.get_msvc_paths("library")
- else:
- p = self.get_msvc_paths(name)
- if p:
- os.environ[name] = string.join(p, ';')
Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py (original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/spawn.py Sun May 2 18:05:10 2010
@@ -69,7 +69,6 @@
dry_run=0):
executable = cmd[0]
- cmd = _nt_quote_args(cmd)
if search_path:
# either we find one or it stays the same
executable = find_executable(executable) or executable
@@ -77,7 +76,8 @@
if not dry_run:
# spawn for NT requires a full path to the .exe
try:
- rc = os.spawnv(os.P_WAIT, executable, cmd)
+ import subprocess
+ rc = subprocess.call(cmd)
except OSError, exc:
# this seems to happen when the command isn't found
raise DistutilsExecError, \
Modified: pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py
==============================================================================
--- pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py (original)
+++ pypy/branch/py12/lib-python/modified-2.5.2/distutils/sysconfig_pypy.py Sun May 2 18:05:10 2010
@@ -11,6 +11,12 @@
python_build = False
+def get_python_inc(plat_specific=0, prefix=None):
+ from os.path import join as j
+ if plat_specific:
+ return j(sys.pypy_prefix, "pypy", "_interfaces")
+ return j(sys.pypy_prefix, 'pypy', 'module', 'cpyext', 'include')
+
def get_python_version():
"""Return a string containing the major and minor Python version,
leaving off the patchlevel. Sample return values could be '1.5'
@@ -47,6 +53,7 @@
"""Initialize the module as appropriate for POSIX systems."""
g = {}
g['EXE'] = ""
+ g['SO'] = ".so"
global _config_vars
_config_vars = g
@@ -56,6 +63,7 @@
"""Initialize the module as appropriate for NT"""
g = {}
g['EXE'] = ".exe"
+ g['SO'] = ".pyd"
global _config_vars
_config_vars = g
Modified: pypy/branch/py12/pypy/annotation/annrpython.py
==============================================================================
--- pypy/branch/py12/pypy/annotation/annrpython.py (original)
+++ pypy/branch/py12/pypy/annotation/annrpython.py Sun May 2 18:05:10 2010
@@ -83,20 +83,23 @@
#___ convenience high-level interface __________________
- def build_types(self, function, input_arg_types, complete_now=True):
+ def build_types(self, function, input_arg_types, complete_now=True,
+ main_entry_point=False):
"""Recursively build annotations about the specific entry point."""
assert isinstance(function, types.FunctionType), "fix that!"
+ from pypy.annotation.policy import AnnotatorPolicy
+ policy = AnnotatorPolicy()
# make input arguments and set their type
- inputcells = [self.typeannotation(t) for t in input_arg_types]
+ args_s = [self.typeannotation(t) for t in input_arg_types]
- desc = self.bookkeeper.getdesc(function)
- desc.getcallfamily() # record this implicit call (hint for back-ends)
- flowgraph = desc.specialize(inputcells)
+ flowgraph, inputcells = self.get_call_parameters(function, args_s, policy)
if not isinstance(flowgraph, FunctionGraph):
assert isinstance(flowgraph, annmodel.SomeObject)
return flowgraph
+ if main_entry_point:
+ self.translator.entry_point_graph = flowgraph
return self.build_graph_types(flowgraph, inputcells, complete_now=complete_now)
def get_call_parameters(self, function, args_s, policy):
Modified: pypy/branch/py12/pypy/annotation/description.py
==============================================================================
--- pypy/branch/py12/pypy/annotation/description.py (original)
+++ pypy/branch/py12/pypy/annotation/description.py Sun May 2 18:05:10 2010
@@ -209,8 +209,9 @@
if len(self._cache) != 1:
raise NoStandardGraph(self)
[graph] = self._cache.values()
+ relax_sig_check = getattr(self.pyobj, "relax_sig_check", False)
if (graph.signature != self.signature or
- graph.defaults != self.defaults):
+ graph.defaults != self.defaults) and not relax_sig_check:
raise NoStandardGraph(self)
return graph
Modified: pypy/branch/py12/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/py12/pypy/annotation/test/test_annrpython.py (original)
+++ pypy/branch/py12/pypy/annotation/test/test_annrpython.py Sun May 2 18:05:10 2010
@@ -3185,6 +3185,13 @@
assert isinstance(s, annmodel.SomeList)
assert s.listdef.listitem.resized
+ def test_varargs(self):
+ def f(*args):
+ return args[0] + 42
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [int, int])
+ assert isinstance(s, annmodel.SomeInteger)
+
def test_listitem_no_mutating(self):
from pypy.rlib.debug import check_annotation
called = []
@@ -3304,6 +3311,15 @@
s = a.build_types(f, [int])
assert s.knowntype is int
+ def test_relax(self):
+ def f(*args):
+ return args[0] + args[1]
+ f.relax_sig_check = True
+ def g(x):
+ return f(x, x - x)
+ a = self.RPythonAnnotator()
+ s = a.build_types(g, [int])
+ assert a.bookkeeper.getdesc(f).getuniquegraph()
def g(n):
return [0,1,2,n]
Modified: pypy/branch/py12/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/py12/pypy/config/pypyoption.py (original)
+++ pypy/branch/py12/pypy/config/pypyoption.py Sun May 2 18:05:10 2010
@@ -29,7 +29,8 @@
"rctime" , "select", "zipimport", "_lsprof",
"crypt", "signal", "_rawffi", "termios", "zlib",
"struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO",
- "thread", "itertools", "pyexpat", "_ssl"]
+ "thread", "itertools", "pyexpat", "_ssl"] # "cpyext"] commented out until
+ # it stops adding _pyolifeline on W_Root
))
working_oo_modules = default_modules.copy()
@@ -62,11 +63,14 @@
module_dependencies = {}
-module_suggests = { # the reason you want _rawffi is for ctypes, which
- # itself needs the interp-level struct module
- # because 'P' is missing from the app-level one
- '_rawffi': [("objspace.usemodules.struct", True)],
- }
+module_suggests = {
+ # the reason you want _rawffi is for ctypes, which
+ # itself needs the interp-level struct module
+ # because 'P' is missing from the app-level one
+ "_rawffi": [("objspace.usemodules.struct", True)],
+ "cpyext": [("translation.secondaryentrypoints", "cpyext"),
+ ("translation.shared", sys.platform == "win32")],
+ }
module_import_dependencies = {
# no _rawffi if importing pypy.rlib.libffi raises ImportError
Modified: pypy/branch/py12/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/py12/pypy/config/translationoption.py (original)
+++ pypy/branch/py12/pypy/config/translationoption.py Sun May 2 18:05:10 2010
@@ -42,6 +42,9 @@
},
cmdline="-b --backend"),
+ BoolOption("shared", "Build as a shared library",
+ default=False, cmdline="--shared"),
+
BoolOption("log", "Include debug prints in the translation (PYPYLOG=...)",
default=True, cmdline="--log"),
@@ -138,6 +141,9 @@
ArbitraryOption("instrumentctl", "internal",
default=None),
StrOption("output", "Output file name", cmdline="--output"),
+ StrOption("secondaryentrypoints",
+ "Comma separated list of keys choosing secondary entrypoints",
+ cmdline="--entrypoints", default=""),
BoolOption("dump_static_data_info", "Dump static data info",
cmdline="--dump_static_data_info",
Modified: pypy/branch/py12/pypy/conftest.py
==============================================================================
--- pypy/branch/py12/pypy/conftest.py (original)
+++ pypy/branch/py12/pypy/conftest.py Sun May 2 18:05:10 2010
@@ -59,7 +59,7 @@
try:
return _SPACECACHE[key]
except KeyError:
- if option.runappdirect:
+ if getattr(option, 'runappdirect', None):
if name not in (None, 'std'):
myname = getattr(sys, 'pypy_objspaceclass', '')
if not myname.lower().startswith(name):
Modified: pypy/branch/py12/pypy/doc/project-ideas.txt
==============================================================================
--- pypy/branch/py12/pypy/doc/project-ideas.txt (original)
+++ pypy/branch/py12/pypy/doc/project-ideas.txt Sun May 2 18:05:10 2010
@@ -21,22 +21,9 @@
--------------------------------
PyPy's Just-In-Time compiler relies on backends for actual code
-generation. We have so far a 32-bit Intel backend, and a CLI one. Open
-ideas are to write a backend for **Intel 64** (AMD64); or a backend for
-Java; or trying again to use LLVM-JIT (which I do not really recommend).
-
-CTypes
-------
-
-Support ctypes on more backends. Right now ctypes is supported only
-when compiling PyPy to C, and there is a bit of unfinished work to
-support it on **Intel 64.** A nice project would be to support it when
-compiling to .NET or the JVM. That's not too hard, the only thing needed
-is to port a small module that does the actual invocation of external
-libraries (a related project is to port this module to Jython or
-IronPython to get support for ctypes there, which is something that was
-tried but not finished as far as I know).
-
+generation. We have so far a 32-bit Intel backend, and a CLI one. There is
+Summer of Code project for 64bit (x86_64) backend, but other options
+(ARM, llvm) remain open.
.. _distribution:
.. _persistence:
Modified: pypy/branch/py12/pypy/interpreter/argument.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/argument.py (original)
+++ pypy/branch/py12/pypy/interpreter/argument.py Sun May 2 18:05:10 2010
@@ -128,19 +128,6 @@
kwds_w[self.keywords[i]] = self.keywords_w[i]
return self.arguments_w, kwds_w
- def unpack_cpy(self, starting_at=0):
- assert starting_at >= 0
- space = self.space
- args_w = self.arguments_w
- w_kw = space.newdict()
- if self.keywords:
- for i in range(len(self.keywords)):
- space.setitem(w_kw, space.wrap(self.keywords[i]), self.keywords_w[i])
- if starting_at != 0:
- args_w = args_w[starting_at:]
- args_tuple = space.newtuple([space.wrap(args_w), w_kw])
- return args_tuple
-
def replace_arguments(self, args_w):
"Return a new Arguments with a args_w as positional arguments."
return Arguments(self.space, args_w, self.keywords, self.keywords_w)
Modified: pypy/branch/py12/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/py12/pypy/interpreter/baseobjspace.py Sun May 2 18:05:10 2010
@@ -4,7 +4,6 @@
from pypy.interpreter.executioncontext import UserDelAction, FrameTraceAction
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.argument import Arguments
-from pypy.interpreter.pycompiler import PythonAstCompiler
from pypy.interpreter.miscutils import ThreadLocals
from pypy.tool.cache import Cache
from pypy.tool.uid import HUGEVAL_BYTES
@@ -579,6 +578,7 @@
try:
return self.default_compiler
except AttributeError:
+ from pypy.interpreter.pycompiler import PythonAstCompiler
compiler = PythonAstCompiler(self)
self.default_compiler = compiler
return compiler
Modified: pypy/branch/py12/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/executioncontext.py (original)
+++ pypy/branch/py12/pypy/interpreter/executioncontext.py Sun May 2 18:05:10 2010
@@ -50,8 +50,7 @@
def enter(self, frame):
if self.framestackdepth > self.space.sys.recursionlimit:
- raise OperationError(self.space.w_RuntimeError,
- self.space.wrap("maximum recursion depth exceeded"))
+ raise self.space.prebuilt_recursion_error
self.framestackdepth += 1
frame.f_backref = self.topframeref
self.topframeref = jit.virtual_ref(frame)
Modified: pypy/branch/py12/pypy/interpreter/main.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/main.py (original)
+++ pypy/branch/py12/pypy/interpreter/main.py Sun May 2 18:05:10 2010
@@ -1,7 +1,7 @@
-from pypy.interpreter import module, eval
+import sys
+from pypy.interpreter import eval, module
from pypy.interpreter.error import OperationError
-from pypy.interpreter.pycode import PyCode
-import sys, types
+
def ensure__main__(space):
w_main = space.wrap('__main__')
Modified: pypy/branch/py12/pypy/interpreter/pycompiler.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/pycompiler.py (original)
+++ pypy/branch/py12/pypy/interpreter/pycompiler.py Sun May 2 18:05:10 2010
@@ -3,10 +3,13 @@
Compiler instances are stored into 'space.getexecutioncontext().compiler'.
"""
-import sys
-from pypy.interpreter.astcompiler.consts import PyCF_DONT_IMPLY_DEDENT
+from pypy.interpreter import pycode
+from pypy.interpreter.pyparser import future, pyparse, error as parseerror
+from pypy.interpreter.astcompiler import (astbuilder, codegen, consts, misc,
+ optimize)
from pypy.interpreter.error import OperationError
+
class AbstractCompiler(object):
"""Abstract base class for a bytecode compiler."""
@@ -33,7 +36,7 @@
# Hackish default implementation based on the stdlib 'codeop' module.
# See comments over there.
space = self.space
- flags |= PyCF_DONT_IMPLY_DEDENT
+ flags |= consts.PyCF_DONT_IMPLY_DEDENT
# Check for source consisting of only blank lines and comments
if mode != "eval":
in_comment = False
@@ -82,8 +85,7 @@
def getcodeflags(self, code):
"""Return the __future__ compiler flags that were used to compile
the given code object."""
- from pypy.interpreter.pycode import PyCode
- if isinstance(code, PyCode):
+ if isinstance(code, pycode.PyCode):
return code.co_flags & self.compiler_flags
else:
return 0
@@ -98,62 +100,49 @@
the whole source after having only added a new '\n')
"""
def __init__(self, space, override_version=None):
-
- from pypy.interpreter.pyparser.pyparse import PythonParser
- from pypy.interpreter.pyparser import future
PyCodeCompiler.__init__(self, space)
- self.parser = PythonParser(space)
+ self.parser = pyparse.PythonParser(space)
self.additional_rules = {}
self.future_flags = future.futureFlags_2_5
self.compiler_flags = self.future_flags.allowed_flags
def compile_ast(self, node, filename, mode, flags):
- from pypy.interpreter.pyparser.pyparse import CompileInfo
- from pypy.interpreter.astcompiler.misc import parse_future
- info = CompileInfo(filename, mode, flags, parse_future(node))
+ future_pos = misc.parse_future(node)
+ info = pyparse.CompileInfo(filename, mode, flags, future_pos)
return self._compile_ast(node, info)
def _compile_ast(self, node, info):
- from pypy.interpreter.astcompiler import optimize
- from pypy.interpreter.astcompiler.codegen import compile_ast
- from pypy.interpreter.pyparser.error import SyntaxError
space = self.space
try:
mod = optimize.optimize_ast(space, node, info)
- code = compile_ast(space, mod, info)
- except SyntaxError, e:
+ code = codegen.compile_ast(space, mod, info)
+ except parseerror.SyntaxError, e:
raise OperationError(space.w_SyntaxError,
e.wrap_info(space))
return code
def compile_to_ast(self, source, filename, mode, flags):
- from pypy.interpreter.pyparser.pyparse import CompileInfo
- info = CompileInfo(filename, mode, flags)
+ info = pyparse.CompileInfo(filename, mode, flags)
return self._compile_to_ast(source, info)
def _compile_to_ast(self, source, info):
- from pypy.interpreter.pyparser.future import get_futures
- from pypy.interpreter.pyparser.error import (SyntaxError,
- IndentationError)
- from pypy.interpreter.astcompiler.astbuilder import ast_from_node
space = self.space
try:
- f_flags, future_info = get_futures(self.future_flags, source)
+ f_flags, future_info = future.get_futures(self.future_flags, source)
info.last_future_import = future_info
info.flags |= f_flags
parse_tree = self.parser.parse_source(source, info)
- mod = ast_from_node(space, parse_tree, info)
- except IndentationError, e:
+ mod = astbuilder.ast_from_node(space, parse_tree, info)
+ except parseerror.IndentationError, e:
raise OperationError(space.w_IndentationError,
e.wrap_info(space))
- except SyntaxError, e:
+ except parseerror.SyntaxError, e:
raise OperationError(space.w_SyntaxError,
e.wrap_info(space))
return mod
def compile(self, source, filename, mode, flags, hidden_applevel=False):
- from pypy.interpreter.pyparser.pyparse import CompileInfo
- info = CompileInfo(filename, mode, flags,
- hidden_applevel=hidden_applevel)
+ info = pyparse.CompileInfo(filename, mode, flags,
+ hidden_applevel=hidden_applevel)
mod = self._compile_to_ast(source, info)
return self._compile_ast(mod, info)
Modified: pypy/branch/py12/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/pyopcode.py (original)
+++ pypy/branch/py12/pypy/interpreter/pyopcode.py Sun May 2 18:05:10 2010
@@ -886,8 +886,6 @@
@jit.unroll_safe
def call_function(self, oparg, w_star=None, w_starstar=None):
- from pypy.interpreter.function import is_builtin_code
-
n_arguments = oparg & 0xff
n_keywords = (oparg>>8) & 0xff
if n_keywords:
@@ -909,7 +907,7 @@
args = self.argument_factory(arguments, keywords, keywords_w, w_star,
w_starstar)
w_function = self.popvalue()
- if self.is_being_profiled and is_builtin_code(w_function):
+ if self.is_being_profiled and function.is_builtin_code(w_function):
w_result = self.space.call_args_and_c_profile(self, w_function,
args)
else:
@@ -1014,7 +1012,7 @@
(ofs, ord(c), name) )
STOP_CODE = MISSING_OPCODE
-
+
def BUILD_MAP(self, itemcount, next_instr):
if itemcount != 0:
raise BytecodeCorruption
Modified: pypy/branch/py12/pypy/interpreter/test/test_argument.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/test/test_argument.py (original)
+++ pypy/branch/py12/pypy/interpreter/test/test_argument.py Sun May 2 18:05:10 2010
@@ -135,12 +135,6 @@
assert args1.keywords is args.keywords
assert args1.keywords_w is args.keywords_w
- def test_unpack_cpy(self):
- space = DummySpace()
- args = Arguments(space, ["0"])
- assert space.eq_w(args.unpack_cpy(), space.newtuple([space.newlist([space.wrap("0")]), space.newdict()]))
- assert space.eq_w(args.unpack_cpy(1), space.newtuple([space.newlist(), space.newdict()]))
-
def test_fixedunpacked(self):
space = DummySpace()
Modified: pypy/branch/py12/pypy/interpreter/test/test_typedef.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/test/test_typedef.py (original)
+++ pypy/branch/py12/pypy/interpreter/test/test_typedef.py Sun May 2 18:05:10 2010
@@ -1,5 +1,6 @@
from pypy.interpreter import typedef
from pypy.tool.udir import udir
+from pypy.interpreter.baseobjspace import Wrappable
# this test isn't so much to test that the objspace interface *works*
# -- it's more to test that it's *there*
@@ -132,6 +133,18 @@
assert len(set) <= 6, "%s has %d subclasses:\n%r" % (
cls, len(set), [subcls.__name__ for subcls in set])
+ def test_getsetproperty(self):
+ class W_SomeType(Wrappable):
+ pass
+ def fget(self, space, w_self):
+ assert self is prop
+ prop = typedef.GetSetProperty(fget, use_closure=True)
+ W_SomeType.typedef = typedef.TypeDef(
+ 'some_type',
+ x=prop)
+ w_obj = self.space.wrap(W_SomeType())
+ assert self.space.getattr(w_obj, self.space.wrap('x')) is self.space.w_None
+
class AppTestTypeDef:
Modified: pypy/branch/py12/pypy/interpreter/typedef.py
==============================================================================
--- pypy/branch/py12/pypy/interpreter/typedef.py (original)
+++ pypy/branch/py12/pypy/interpreter/typedef.py Sun May 2 18:05:10 2010
@@ -9,7 +9,7 @@
DescrMismatch
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.tool.sourcetools import compile2, func_with_new_name
-from pypy.rlib.objectmodel import instantiate, compute_identity_hash
+from pypy.rlib.objectmodel import instantiate, compute_identity_hash, specialize
from pypy.rlib.jit import hint
class TypeDef:
@@ -301,44 +301,63 @@
# ____________________________________________________________
-def make_descr_typecheck_wrapper(func, extraargs=(), cls=None):
+ at specialize.arg(0)
+def make_descr_typecheck_wrapper(tag, func, extraargs=(), cls=None,
+ use_closure=False):
if func is None:
return None
- if cls is None:
+ return _make_descr_typecheck_wrapper(tag, func, extraargs, cls, use_closure)
+
+ at specialize.memo()
+def _make_descr_typecheck_wrapper(tag, func, extraargs, cls, use_closure):
+ # - if cls is None, the wrapped object is passed to the function
+ # - if cls is a class, an unwrapped instance is passed
+ # - if cls is a string, XXX unused?
+ if cls is None and use_closure:
return func
if hasattr(func, 'im_func'):
assert func.im_class is cls
func = func.im_func
-
+
miniglobals = {
func.__name__: func,
'OperationError': OperationError
}
if isinstance(cls, str):
+ assert 0, "unused?"
#print "<CHECK", func.__module__ or '?', func.__name__
assert cls.startswith('<'),"pythontype typecheck should begin with <"
source = """
- def descr_typecheck_%(name)s(space, w_obj, %(extra)s):
+ def descr_typecheck_%(name)s(closure, space, w_obj, %(extra)s):
if not space.is_true(space.isinstance(w_obj, space.w_%(cls_name)s)):
# xxx improve msg
msg = "descriptor is for '%(expected)s'"
raise OperationError(space.w_TypeError, space.wrap(msg))
- return %(name)s(space, w_obj, %(extra)s)
+ return %(name)s(%(closure)s space, w_obj, %(extra)s)
"""
cls_name = cls[1:]
expected = repr(cls_name)
+ elif cls is None:
+ source = """
+ def descr_typecheck_%(name)s(closure, space, w_obj, %(extra)s):
+ return %(name)s(%(closure)s space, w_obj, %(extra)s)
+ """
else:
cls_name = cls.__name__
assert issubclass(cls, Wrappable)
source = """
- def descr_typecheck_%(name)s(space, w_obj, %(extra)s):
+ def descr_typecheck_%(name)s(closure, space, w_obj, %(extra)s):
obj = space.descr_self_interp_w(%(cls_name)s, w_obj)
- return %(name)s(space, obj, %(extra)s)
+ return %(name)s(%(closure)s space, obj, %(extra)s)
"""
miniglobals[cls_name] = cls
name = func.__name__
extra = ', '.join(extraargs)
+ if use_closure:
+ closure = "closure,"
+ else:
+ closure = ""
source = py.code.Source(source % locals())
exec source.compile() in miniglobals
return miniglobals['descr_typecheck_%s' % func.__name__]
@@ -348,16 +367,17 @@
raise OperationError(space.w_AttributeError,
space.wrap("generic property has no __objclass__"))
-def make_objclass_getter(func, cls, cache={}):
- if hasattr(func, 'im_func'):
+ at specialize.arg(0)
+def make_objclass_getter(tag, func, cls):
+ if func and hasattr(func, 'im_func'):
assert not cls or cls is func.im_class
cls = func.im_class
+ return _make_objclass_getter(cls)
+
+ at specialize.memo()
+def _make_objclass_getter(cls):
if not cls:
return unknown_objclass_getter, cls
- try:
- return cache[cls]
- except KeyError:
- pass
miniglobals = {}
if isinstance(cls, str):
assert cls.startswith('<'),"pythontype typecheck should begin with <"
@@ -372,16 +392,19 @@
\n""" % (typeexpr,)
exec compile2(source) in miniglobals
res = miniglobals['objclass_getter'], cls
- cache[cls] = res
return res
class GetSetProperty(Wrappable):
- def __init__(self, fget, fset=None, fdel=None, doc=None, cls=None):
- "NOT_RPYTHON: initialization-time only"
- objclass_getter, cls = make_objclass_getter(fget, cls)
- fget = make_descr_typecheck_wrapper(fget, cls=cls)
- fset = make_descr_typecheck_wrapper(fset, ('w_value',), cls=cls)
- fdel = make_descr_typecheck_wrapper(fdel, cls=cls)
+ @specialize.arg(7)
+ def __init__(self, fget, fset=None, fdel=None, doc=None,
+ cls=None, use_closure=False, tag=None):
+ objclass_getter, cls = make_objclass_getter(tag, fget, cls)
+ fget = make_descr_typecheck_wrapper((tag, 0), fget,
+ cls=cls, use_closure=use_closure)
+ fset = make_descr_typecheck_wrapper((tag, 1), fset, ('w_value',),
+ cls=cls, use_closure=use_closure)
+ fdel = make_descr_typecheck_wrapper((tag, 2), fdel,
+ cls=cls, use_closure=use_closure)
self.fget = fget
self.fset = fset
self.fdel = fdel
@@ -389,7 +412,8 @@
self.reqcls = cls
self.name = '<generic property>'
self.objclass_getter = objclass_getter
-
+ self.use_closure = use_closure
+
def descr_property_get(space, property, w_obj, w_cls=None):
"""property.__get__(obj[, type]) -> value
Read the value of the property of the given obj."""
@@ -400,7 +424,7 @@
return space.wrap(property)
else:
try:
- return property.fget(space, w_obj)
+ return property.fget(property, space, w_obj)
except DescrMismatch, e:
return w_obj.descr_call_mismatch(space, '__getattribute__',\
property.reqcls, Arguments(space, [w_obj,
@@ -414,7 +438,7 @@
raise OperationError(space.w_TypeError,
space.wrap("readonly attribute"))
try:
- fset(space, w_obj, w_value)
+ fset(property, space, w_obj, w_value)
except DescrMismatch, e:
w_obj.descr_call_mismatch(space, '__setattr__',\
property.reqcls, Arguments(space, [w_obj,
@@ -428,7 +452,7 @@
raise OperationError(space.w_AttributeError,
space.wrap("cannot delete attribute"))
try:
- fdel(space, w_obj)
+ fdel(property, space, w_obj)
except DescrMismatch, e:
w_obj.descr_call_mismatch(space, '__delattr__',\
property.reqcls, Arguments(space, [w_obj,
Modified: pypy/branch/py12/pypy/jit/backend/test/support.py
==============================================================================
--- pypy/branch/py12/pypy/jit/backend/test/support.py (original)
+++ pypy/branch/py12/pypy/jit/backend/test/support.py Sun May 2 18:05:10 2010
@@ -2,7 +2,7 @@
import sys
from pypy.rlib.debug import debug_print
from pypy.rlib.jit import OPTIMIZER_FULL
-from pypy.translator.translator import TranslationContext
+from pypy.translator.translator import TranslationContext, graphof
class BaseCompiledMixin(object):
@@ -56,7 +56,8 @@
""" % (arglist,))
exec src.compile() in locals()
- t.buildannotator().build_types(function, [int] * len(args))
+ t.buildannotator().build_types(function, [int] * len(args),
+ main_entry_point=True)
t.buildrtyper(type_system=self.type_system).specialize()
warmrunnerdesc = WarmRunnerDesc(t, translate_support_code=True,
CPUClass=self.CPUClass,
Modified: pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py (original)
+++ pypy/branch/py12/pypy/jit/backend/x86/test/test_zrpy_gc.py Sun May 2 18:05:10 2010
@@ -82,7 +82,7 @@
for name, value in kwds.items():
setattr(t.config.translation, name, value)
ann = t.buildannotator(policy=annpolicy.StrictAnnotatorPolicy())
- ann.build_types(f, [s_list_of_strings])
+ ann.build_types(f, [s_list_of_strings], main_entry_point=True)
t.buildrtyper().specialize()
if kwds['jit']:
apply_jit(t, optimizer=OPTIMIZER_SIMPLE)
Modified: pypy/branch/py12/pypy/jit/metainterp/support.py
==============================================================================
--- pypy/branch/py12/pypy/jit/metainterp/support.py (original)
+++ pypy/branch/py12/pypy/jit/metainterp/support.py Sun May 2 18:05:10 2010
@@ -41,7 +41,7 @@
annpolicy.allow_someobjects = False
a = t.buildannotator(policy=annpolicy)
argtypes = getargtypes(a, values)
- a.build_types(func, argtypes)
+ a.build_types(func, argtypes, main_entry_point=True)
rtyper = t.buildrtyper(type_system = type_system)
rtyper.specialize()
if inline:
Modified: pypy/branch/py12/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/py12/pypy/jit/metainterp/warmspot.py (original)
+++ pypy/branch/py12/pypy/jit/metainterp/warmspot.py Sun May 2 18:05:10 2010
@@ -231,7 +231,7 @@
def check_access_directly_sanity(self, graphs):
from pypy.translator.backendopt.inline import collect_called_graphs
jit_graphs = set(graphs)
- for graph in collect_called_graphs(self.translator.graphs[0],
+ for graph in collect_called_graphs(self.translator.entry_point_graph,
self.translator):
if graph in jit_graphs:
continue
Modified: pypy/branch/py12/pypy/lib/identity_dict.py
==============================================================================
--- pypy/branch/py12/pypy/lib/identity_dict.py (original)
+++ pypy/branch/py12/pypy/lib/identity_dict.py Sun May 2 18:05:10 2010
@@ -30,6 +30,12 @@
def __contains__(self, arg):
return id(arg) in self._dict
+ def copy(self):
+ d = type(self)()
+ d.update(self.iteritems())
+ assert len(d) == len(self)
+ return d
+
class IdentityDictPyPy(object, DictMixin):
__slots__ = ["_dict"]
@@ -52,6 +58,11 @@
def __contains__(self, arg):
return arg in self._dict
+ def copy(self):
+ d = type(self)()
+ d.update(self.iteritems())
+ assert len(d) == len(self)
+ return d
if idict is None:
identity_dict = IdentityDictPurePython
Modified: pypy/branch/py12/pypy/module/imp/importing.py
==============================================================================
--- pypy/branch/py12/pypy/module/imp/importing.py (original)
+++ pypy/branch/py12/pypy/module/imp/importing.py Sun May 2 18:05:10 2010
@@ -25,6 +25,11 @@
# PY_CODERESOURCE = 8
IMP_HOOK = 9
+if sys.platform.startswith('win'):
+ so_extension = ".pyd"
+else:
+ so_extension = ".so"
+
def find_modtype(space, filepart):
"""Check which kind of module to import for the given filepart,
which is a path without extension. Returns PY_SOURCE, PY_COMPILED or
@@ -40,16 +45,18 @@
# look for a lone .pyc file.
# The "imp" module does not respect this, and is allowed to find
# lone .pyc files.
- if not space.config.objspace.lonepycfiles:
- return SEARCH_ERROR, None, None
-
# check the .pyc file
- if space.config.objspace.usepycfiles:
+ if space.config.objspace.usepycfiles and space.config.objspace.lonepycfiles:
pycfile = filepart + ".pyc"
if os.path.exists(pycfile) and case_ok(pycfile):
# existing .pyc file
return PY_COMPILED, ".pyc", "rb"
+ if space.config.objspace.usemodules.cpyext:
+ pydfile = filepart + so_extension
+ if os.path.exists(pydfile) and case_ok(pydfile):
+ return C_EXTENSION, so_extension, "rb"
+
return SEARCH_ERROR, None, None
if sys.platform in ['linux2', 'freebsd']:
@@ -332,6 +339,9 @@
except:
stream.close()
raise
+ if modtype == C_EXTENSION:
+ filename = filepart + suffix
+ return FindInfo(modtype, filename, None, suffix, filemode)
except StreamErrors:
pass
@@ -356,7 +366,7 @@
if find_info.modtype == C_BUILTIN:
return space.getbuiltinmodule(find_info.filename, force_init=True)
- if find_info.modtype in (PY_SOURCE, PY_COMPILED, PKG_DIRECTORY):
+ if find_info.modtype in (PY_SOURCE, PY_COMPILED, C_EXTENSION, PKG_DIRECTORY):
w_mod = None
if reuse:
try:
@@ -397,6 +407,12 @@
# fetch the module again, in case of "substitution"
w_mod = check_sys_modules(space, w_modulename)
return w_mod
+ elif find_info.modtype == C_EXTENSION and space.config.objspace.usemodules.cpyext:
+ # the next line is mandantory to init cpyext
+ space.getbuiltinmodule("cpyext")
+ from pypy.module.cpyext.api import load_extension_module
+ load_extension_module(space, find_info.filename, space.str_w(w_modulename))
+ return check_sys_modules(space, w_modulename)
except OperationError:
w_mods = space.sys.get('modules')
space.call_method(w_mods, 'pop', w_modulename, space.w_None)
Modified: pypy/branch/py12/pypy/module/thread/ll_thread.py
==============================================================================
--- pypy/branch/py12/pypy/module/thread/ll_thread.py (original)
+++ pypy/branch/py12/pypy/module/thread/ll_thread.py Sun May 2 18:05:10 2010
@@ -35,15 +35,15 @@
ident = thread.start_new_thread(func, ())
except thread.error:
ident = -1
- return rffi.cast(rffi.INT, ident)
+ return rffi.cast(rffi.LONG, ident)
CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void))
-c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT,
+c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.LONG,
_callable=_emulated_start_new_thread,
threadsafe=True) # release the GIL, but most
# importantly, reacquire it
# around the callback
-c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT,
+c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.LONG,
_nowrapper=True) # always call directly
TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock',
Modified: pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py
==============================================================================
--- pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py (original)
+++ pypy/branch/py12/pypy/module/thread/test/test_ll_thread.py Sun May 2 18:05:10 2010
@@ -47,15 +47,16 @@
state.freed_counter += 1
def bootstrap():
- state.my_thread_ident = get_ident()
+ state.my_thread_ident = state.z.ident = get_ident()
assert state.my_thread_ident == get_ident()
+ assert get_ident() == state.z.ident
state.seen_value = state.z.value
state.z = None
state.done = 1
def g(i):
state.z = Z(i)
- start_new_thread(bootstrap, ())
+ return start_new_thread(bootstrap, ())
g._dont_inline_ = True
def f():
@@ -65,7 +66,7 @@
for i in range(50):
state.done = 0
state.seen_value = 0
- g(i)
+ ident = g(i)
gc.collect()
willing_to_wait_more = 1000
while not state.done:
@@ -74,6 +75,7 @@
raise Exception("thread didn't start?")
time.sleep(0.01)
assert state.my_thread_ident != main_ident
+ assert state.my_thread_ident == ident
assert state.seen_value == i
# try to force Boehm to do some freeing
for i in range(3):
Modified: pypy/branch/py12/pypy/objspace/std/fake.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/fake.py (original)
+++ pypy/branch/py12/pypy/objspace/std/fake.py Sun May 2 18:05:10 2010
@@ -114,6 +114,13 @@
cpy_type.__name__, base, **kw)
def __init__(w_self, space, val):
w_self.val = val
+ w_self.space = space
+ def getdict(w_self):
+ try:
+ d = w_self.val.__dict__
+ except AttributeError:
+ return W_Object.getdict(w_self)
+ return w_self.space.wrap(d)
def unwrap(w_self, space):
return w_self.val
W_Fake.__name__ = 'W_Fake%s'%(cpy_type.__name__.capitalize())
Modified: pypy/branch/py12/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/py12/pypy/objspace/std/objspace.py Sun May 2 18:05:10 2010
@@ -7,7 +7,7 @@
from pypy.objspace.std import (builtinshortcut, stdtypedef, frame, model,
transparent, callmethod, proxyobject)
from pypy.objspace.descroperation import DescrOperation, raiseattrerror
-from pypy.rlib.objectmodel import instantiate
+from pypy.rlib.objectmodel import instantiate, r_dict
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib.rarithmetic import base_int
from pypy.rlib.objectmodel import we_are_translated
@@ -206,8 +206,11 @@
return W_ComplexObject(x.real, x.imag)
if isinstance(x, set):
- wrappeditems = [self.wrap(item) for item in x]
- return W_SetObject(self, wrappeditems)
+ rdict_w = r_dict(self.eq_w, self.hash_w)
+ for item in x:
+ rdict_w[self.wrap(item)] = None
+ res = W_SetObject(self, rdict_w)
+ return res
if isinstance(x, frozenset):
wrappeditems = [self.wrap(item) for item in x]
@@ -450,21 +453,33 @@
raiseattrerror(self, w_obj, name)
def finditem_str(self, w_obj, key):
- # performance shortcut to avoid creating the OperationError(KeyError)
+ """ Perform a getitem on w_obj with key (string). Returns found
+ element or None on element not found.
+
+ performance shortcut to avoid creating the OperationError(KeyError)
+ and allocating W_StringObject
+ """
if (isinstance(w_obj, W_DictMultiObject) and
not w_obj.user_overridden_class):
return w_obj.getitem_str(key)
return ObjSpace.finditem_str(self, w_obj, key)
def finditem(self, w_obj, w_key):
- # performance shortcut to avoid creating the OperationError(KeyError)
+ """ Perform a getitem on w_obj with w_key (any object). Returns found
+ element or None on element not found.
+
+ performance shortcut to avoid creating the OperationError(KeyError).
+ """
if (isinstance(w_obj, W_DictMultiObject) and
not w_obj.user_overridden_class):
return w_obj.getitem(w_key)
return ObjSpace.finditem(self, w_obj, w_key)
def setitem_str(self, w_obj, key, w_value, shadows_type=True):
- # performance shortcut to avoid creating the OperationError(KeyError)
+ """ Same as setitem, but takes string instead of any wrapped object
+
+ XXX what shadows_type means???
+ """
if (isinstance(w_obj, W_DictMultiObject) and
not w_obj.user_overridden_class):
w_obj.setitem_str(key, w_value, shadows_type)
Modified: pypy/branch/py12/pypy/objspace/std/test/test_setobject.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/test/test_setobject.py (original)
+++ pypy/branch/py12/pypy/objspace/std/test/test_setobject.py Sun May 2 18:05:10 2010
@@ -46,6 +46,8 @@
t = W_SetObject(self.space, None)
_initialize_set(self.space, t, self.word)
assert self.space.eq_w(s,t)
+ u = self.space.wrap(set('simsalabim'))
+ assert self.space.eq_w(s,u)
class AppTestAppSetTest:
def test_subtype(self):
Modified: pypy/branch/py12/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/py12/pypy/objspace/std/typeobject.py (original)
+++ pypy/branch/py12/pypy/objspace/std/typeobject.py Sun May 2 18:05:10 2010
@@ -14,6 +14,7 @@
from pypy.rlib.rarithmetic import intmask, r_uint
from copy_reg import _HEAPTYPE
+_CPYTYPE = 1 # used for non-heap types defined in C
# from compiler/misc.py
@@ -96,7 +97,7 @@
w_self.needsdel = False
w_self.weakrefable = False
w_self.weak_subclasses = []
- w_self.__flags__ = 0 # or _HEAPTYPE
+ w_self.__flags__ = 0 # or _HEAPTYPE or _CPYTYPE
w_self.instancetypedef = overridetypedef
if overridetypedef is not None:
@@ -353,6 +354,9 @@
def is_heaptype(w_self):
return w_self.__flags__&_HEAPTYPE
+ def is_cpytype(w_self):
+ return w_self.__flags__ & _CPYTYPE
+
def get_module(w_self):
space = w_self.space
if w_self.is_heaptype() and '__module__' in w_self.dict_w:
Modified: pypy/branch/py12/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/rarithmetic.py (original)
+++ pypy/branch/py12/pypy/rlib/rarithmetic.py Sun May 2 18:05:10 2010
@@ -126,6 +126,10 @@
raise OverflowError
def compute_restype(self_type, other_type):
+ if self_type is other_type:
+ if self_type is bool:
+ return int
+ return self_type
if other_type in (bool, int, long):
if self_type is bool:
return int
Modified: pypy/branch/py12/pypy/rlib/rstring.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/rstring.py (original)
+++ pypy/branch/py12/pypy/rlib/rstring.py Sun May 2 18:05:10 2010
@@ -1,11 +1,49 @@
-
-""" String builder interface
+""" String builder interface and string functions
"""
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.annotation.model import SomeObject, SomeString, s_None,\
SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString
+
+# -------------- public API for string functions -----------------------
+def split(value, by, maxsplit=-1):
+ bylen = len(by)
+ if bylen == 0:
+ raise ValueError("empty separator")
+
+ res = []
+ start = 0
+ while maxsplit != 0:
+ next = value.find(by, start)
+ if next < 0:
+ break
+ res.append(value[start:next])
+ start = next + bylen
+ maxsplit -= 1 # NB. if it's already < 0, it stays < 0
+
+ res.append(value[start:len(value)])
+ return res
+
+def rsplit(value, by, maxsplit=-1):
+ res = []
+ end = len(value)
+ bylen = len(by)
+ if bylen == 0:
+ raise ValueError("empty separator")
+
+ while maxsplit != 0:
+ next = value.rfind(by, 0, end)
+ if next < 0:
+ break
+ res.append(value[next+bylen:end])
+ end = next
+ maxsplit -= 1 # NB. if it's already < 0, it stays < 0
+
+ res.append(value[:end])
+ res.reverse()
+ return res
+
# -------------- public API ---------------------------------
INIT_SIZE = 100 # XXX tweak
Modified: pypy/branch/py12/pypy/rlib/rweakref.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/rweakref.py (original)
+++ pypy/branch/py12/pypy/rlib/rweakref.py Sun May 2 18:05:10 2010
@@ -1,6 +1,7 @@
"""
Weakref support in RPython. Supports ref() without callbacks,
-and a limited version of WeakValueDictionary. LLType only for now!
+a form of WeakKeyDictionary, and a limited version of WeakValueDictionary.
+LLType only for now!
"""
import weakref
@@ -27,6 +28,36 @@
self._dict[key] = value
+class RWeakKeyDictionary(object):
+ """A dictionary containing weak keys.
+ Keys and values must be instances.
+ Prebuilt RWeakKeyDictionaries must be empty.
+ """
+
+ def __init__(self, keyclass, valueclass):
+ self._dict = weakref.WeakKeyDictionary()
+ self._keyclass = keyclass
+ self._valueclass = valueclass
+
+ def get(self, key):
+ """Get the value associated to 'key', or None by default."""
+ assert isinstance(key, self._keyclass)
+ return self._dict.get(key, None)
+
+ def set(self, key, value):
+ """Set the key/value pair (or delete it if value is None)."""
+ assert isinstance(key, self._keyclass)
+ if value is None:
+ self._dict.pop(key, None)
+ else:
+ assert isinstance(value, self._valueclass)
+ self._dict[key] = value
+
+ def length(self):
+ """Mostly for debugging. Slow, don't use in real code."""
+ return len(self._dict)
+
+
# ____________________________________________________________
from pypy.rpython import extregistry
@@ -41,8 +72,8 @@
self.valueclassdef = valueclassdef
def rtyper_makerepr(self, rtyper):
- from pypy.rlib import rweakrefimpl
- return rweakrefimpl.WeakValueDictRepr(rtyper)
+ from pypy.rlib import _rweakvaldict
+ return _rweakvaldict.WeakValueDictRepr(rtyper)
def rtyper_makekey_ex(self, rtyper):
return self.__class__,
@@ -65,14 +96,11 @@
_about_ = RWeakValueDictionary
def compute_result_annotation(self, s_valueclass):
- assert isinstance(s_valueclass, annmodel.SomePBC)
- assert s_valueclass.is_constant()
- [desc] = s_valueclass.descriptions
- return SomeWeakValueDict(desc.getuniqueclassdef())
+ return SomeWeakValueDict(_getclassdef(s_valueclass))
def specialize_call(self, hop):
- from pypy.rlib import rweakrefimpl
- return rweakrefimpl.specialize_make_weakdict(hop)
+ from pypy.rlib import _rweakvaldict
+ return _rweakvaldict.specialize_make_weakdict(hop)
class Entry(extregistry.ExtRegistryEntry):
_type_ = RWeakValueDictionary
@@ -81,3 +109,65 @@
bk = self.bookkeeper
x = self.instance
return SomeWeakValueDict(bk.getuniqueclassdef(x._valueclass))
+
+def _getclassdef(s_instance):
+ assert isinstance(s_instance, annmodel.SomePBC)
+ assert s_instance.is_constant()
+ [desc] = s_instance.descriptions
+ return desc.getuniqueclassdef()
+
+# ____________________________________________________________
+
+class SomeWeakKeyDict(annmodel.SomeObject):
+ knowntype = RWeakKeyDictionary
+
+ def __init__(self, keyclassdef, valueclassdef):
+ self.keyclassdef = keyclassdef
+ self.valueclassdef = valueclassdef
+
+ def rtyper_makerepr(self, rtyper):
+ from pypy.rlib import _rweakkeydict
+ return _rweakkeydict.WeakKeyDictRepr(rtyper)
+
+ def rtyper_makekey_ex(self, rtyper):
+ return self.__class__,
+
+ def method_get(self, s_key):
+ assert isinstance(s_key, annmodel.SomeInstance)
+ assert s_key.classdef.issubclass(self.keyclassdef)
+ return annmodel.SomeInstance(self.valueclassdef, can_be_None=True)
+
+ def method_set(self, s_key, s_value):
+ s_oldvalue = self.method_get(s_key)
+ assert s_oldvalue.contains(s_value)
+
+ def method_length(self):
+ return annmodel.SomeInteger(nonneg=True)
+
+class __extend__(pairtype(SomeWeakKeyDict, SomeWeakKeyDict)):
+ def union((s_wkd1, s_wkd2)):
+ if s_wkd1.keyclassdef is not s_wkd2.keyclassdef:
+ return SomeObject() # not the same key class! complain...
+ if s_wkd1.valueclassdef is not s_wkd2.valueclassdef:
+ return SomeObject() # not the same value class! complain...
+ return SomeWeakKeyDict(s_wkd1.keyclassdef, s_wkd1.valueclassdef)
+
+class Entry(extregistry.ExtRegistryEntry):
+ _about_ = RWeakKeyDictionary
+
+ def compute_result_annotation(self, s_keyclass, s_valueclass):
+ return SomeWeakKeyDict(_getclassdef(s_keyclass),
+ _getclassdef(s_valueclass))
+
+ def specialize_call(self, hop):
+ from pypy.rlib import _rweakkeydict
+ return _rweakkeydict.specialize_make_weakdict(hop)
+
+class Entry(extregistry.ExtRegistryEntry):
+ _type_ = RWeakKeyDictionary
+
+ def compute_annotation(self):
+ bk = self.bookkeeper
+ x = self.instance
+ return SomeWeakKeyDict(bk.getuniqueclassdef(x._keyclass),
+ bk.getuniqueclassdef(x._valueclass))
Modified: pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py (original)
+++ pypy/branch/py12/pypy/rlib/test/test_rarithmetic.py Sun May 2 18:05:10 2010
@@ -365,3 +365,7 @@
def test_isnan():
assert isnan(NAN)
+
+def test_int_real_union():
+ from pypy.rpython.lltypesystem.rffi import r_int_real
+ assert compute_restype(r_int_real, r_int_real) is r_int_real
Modified: pypy/branch/py12/pypy/rlib/test/test_rbigint.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/test/test_rbigint.py (original)
+++ pypy/branch/py12/pypy/rlib/test/test_rbigint.py Sun May 2 18:05:10 2010
@@ -474,10 +474,11 @@
def test_args_from_rarith_int(self):
from pypy.rpython.tool.rfficache import platform
from pypy.rlib.rarithmetic import r_int
+ from pypy.rpython.lltypesystem.rffi import r_int_real
classlist = platform.numbertype_to_rclass.values()
fnlist = []
for r in classlist:
- if r is r_int: # and also r_longlong on 64-bit
+ if r in (r_int, r_int_real): # and also r_longlong on 64-bit
continue
if r is int:
mask = sys.maxint*2+1
Modified: pypy/branch/py12/pypy/rlib/test/test_rstring.py
==============================================================================
--- pypy/branch/py12/pypy/rlib/test/test_rstring.py (original)
+++ pypy/branch/py12/pypy/rlib/test/test_rstring.py Sun May 2 18:05:10 2010
@@ -1,5 +1,26 @@
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit
+
+def test_split():
+ assert split("", 'x') == ['']
+ assert split("a", "a", 1) == ['', '']
+ assert split(" ", " ", 1) == ['', '']
+ assert split("aa", "a", 2) == ['', '', '']
+ assert split('a|b|c|d', '|') == ['a', 'b', 'c', 'd']
+ assert split('a|b|c|d', '|', 2) == ['a', 'b', 'c|d']
+ assert split('a//b//c//d', '//') == ['a', 'b', 'c', 'd']
+ assert split('endcase test', 'test') == ['endcase ', '']
+ raises(ValueError, split, 'abc', '')
+
+def test_rsplit():
+ assert rsplit("a", "a", 1) == ['', '']
+ assert rsplit(" ", " ", 1) == ['', '']
+ assert rsplit("aa", "a", 2) == ['', '', '']
+ assert rsplit('a|b|c|d', '|') == ['a', 'b', 'c', 'd']
+ assert rsplit('a|b|c|d', '|', 2) == ['a|b', 'c', 'd']
+ assert rsplit('a//b//c//d', '//') == ['a', 'b', 'c', 'd']
+ assert rsplit('endcase test', 'test') == ['endcase ', '']
+ raises(ValueError, rsplit, "abc", '')
def test_string_builder():
s = StringBuilder()
Modified: pypy/branch/py12/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/annlowlevel.py (original)
+++ pypy/branch/py12/pypy/rpython/annlowlevel.py Sun May 2 18:05:10 2010
@@ -34,6 +34,7 @@
else:
s = compact()
return s + 'Const'
+ __repr__ = __str__
class LowLevelAnnotatorPolicy(AnnotatorPolicy):
allow_someobjects = False
Modified: pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py (original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/ll2ctypes.py Sun May 2 18:05:10 2010
@@ -675,7 +675,8 @@
if T is lltype.Void:
return None
if isinstance(T, lltype.Ptr):
- if not cobj: # NULL pointer
+ if not cobj or not ctypes.cast(cobj, ctypes.c_void_p).value: # NULL pointer
+ # CFunctionType.__nonzero__ is broken before Python 2.6
return lltype.nullptr(T.TO)
if isinstance(T.TO, lltype.Struct):
REAL_TYPE = T.TO
@@ -963,7 +964,7 @@
def invoke_via_ctypes(*argvalues):
global _callback_exc_info
cargs = []
- for i in range(len(FUNCTYPE.ARGS)):
+ for i in range(len(argvalues)):
if i not in void_arguments:
cvalue = lltype2ctypes(argvalues[i])
if i in container_arguments:
@@ -1001,7 +1002,7 @@
elif isinstance(cvalue, (str, unicode)):
cvalue = ord(cvalue) # character -> integer
- if not isinstance(cvalue, (int, long)):
+ if not isinstance(cvalue, (int, long, float)):
raise NotImplementedError("casting %r to %r" % (TYPE1, RESTYPE))
if isinstance(RESTYPE, lltype.Ptr):
Modified: pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/lltype.py Sun May 2 18:05:10 2010
@@ -1,3 +1,8 @@
+import StringIO
+import traceback
+import sys
+
+import py
from pypy.rlib.rarithmetic import (r_int, r_uint, intmask, r_singlefloat,
r_ulonglong, r_longlong, base_int,
normalizedinttype)
@@ -12,6 +17,20 @@
TLS = tlsobject()
+# Track allocations to detect memory leaks
+# Don't track 'gc' and immortal mallocs
+TRACK_ALLOCATIONS = False
+ALLOCATED = identity_dict()
+
+def start_tracking_allocations():
+ global TRACK_ALLOCATIONS
+ TRACK_ALLOCATIONS = True
+ ALLOCATED.clear()
+
+def stop_tracking_allocations():
+ global TRACK_ALLOCATIONS
+ TRACK_ALLOCATIONS = False
+
class _uninitialized(object):
def __init__(self, TYPE):
self.TYPE = TYPE
@@ -1318,21 +1337,41 @@
__slots__ = ('_TYPE',
'_parent_type', '_parent_index', '_keepparent',
'_wrparent',
- '__weakref__',
- '_storage')
+ '__weakref__', '_traceback',
+ '__storage')
- def __init__(self, TYPE):
+ def __init__(self, TYPE, track_allocation=None):
self._wrparent = None
self._TYPE = TYPE
self._storage = True # means "use default storage", as opposed to:
# None - container was freed
# <ctypes object> - using ctypes
# (see ll2ctypes.py)
+ if track_allocation is not False and TRACK_ALLOCATIONS:
+ self._traceback = self._get_traceback()
+ ALLOCATED[self] = None
+ else:
+ self._traceback = None
+
+ def _get_traceback(self):
+ frame = sys._getframe().f_back.f_back.f_back.f_back
+ sio = StringIO.StringIO()
+ traceback.print_stack(frame, file=sio)
+ return sio.getvalue()
def _free(self):
self._check() # no double-frees
self._storage = None
+ def _storage_get(self):
+ return self.__storage
+
+ def _storage_set(self, value):
+ self.__storage = value
+ if value is not True and self in ALLOCATED:
+ del ALLOCATED[self]
+ _storage = property(_storage_get, _storage_set)
+
def _was_freed(self):
if self._storage is None:
return True
@@ -1409,14 +1448,14 @@
class _struct(_parentable):
_kind = "structure"
- __slots__ = ('_hash_cache_',)
+ __slots__ = ('_hash_cache_', '_compilation_info')
- def __new__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
+ def __new__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None, track_allocation=None):
my_variety = _struct_variety(TYPE._names)
return object.__new__(my_variety)
- def __init__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
- _parentable.__init__(self, TYPE)
+ def __init__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None, track_allocation=None):
+ _parentable.__init__(self, TYPE, track_allocation)
if n is not None and TYPE._arrayfld is None:
raise TypeError("%r is not variable-sized" % (TYPE,))
if n is None and TYPE._arrayfld is not None:
@@ -1424,7 +1463,8 @@
first, FIRSTTYPE = TYPE._first_struct()
for fld, typ in TYPE._flds.items():
if fld == TYPE._arrayfld:
- value = _array(typ, n, initialization=initialization, parent=self, parentindex=fld)
+ value = _array(typ, n, initialization=initialization, parent=self, parentindex=fld,
+ track_allocation=track_allocation)
else:
value = typ._allocate(initialization=initialization, parent=self, parentindex=fld)
setattr(self, fld, value)
@@ -1485,12 +1525,12 @@
__slots__ = ('items',)
- def __init__(self, TYPE, n, initialization=None, parent=None, parentindex=None):
+ def __init__(self, TYPE, n, initialization=None, parent=None, parentindex=None, track_allocation=None):
if not isinstance(n, int):
raise TypeError, "array length must be an int"
if n < 0:
raise ValueError, "negative array length"
- _parentable.__init__(self, TYPE)
+ _parentable.__init__(self, TYPE, track_allocation)
try:
myrange = range(n)
except OverflowError:
@@ -1557,7 +1597,7 @@
_cache = weakref.WeakKeyDictionary() # parentarray -> {subarrays}
def __init__(self, TYPE, parent, baseoffset_or_fieldname):
- _parentable.__init__(self, TYPE)
+ _parentable.__init__(self, TYPE, track_allocation=False)
self._setparentstructure(parent, baseoffset_or_fieldname)
# Keep the parent array alive, we share the same allocation.
# Don't do it if we are inside a GC object, though -- it's someone
@@ -1787,9 +1827,9 @@
else:
initialization = 'malloc'
if isinstance(T, Struct):
- o = _struct(T, n, initialization=initialization)
+ o = _struct(T, n, initialization=initialization, track_allocation=flavor == "raw" and not immortal)
elif isinstance(T, Array):
- o = _array(T, n, initialization=initialization)
+ o = _array(T, n, initialization=initialization, track_allocation=flavor == "raw" and not immortal)
elif isinstance(T, OpaqueType):
assert n is None
o = _opaque(T, initialization=initialization)
Modified: pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/rdict.py Sun May 2 18:05:10 2010
@@ -508,12 +508,14 @@
def ll_dict_lookup(d, key, hash):
entries = d.entries
+ ENTRIES = lltype.typeOf(entries).TO
+ direct_compare = not hasattr(ENTRIES, 'no_direct_compare')
mask = len(entries) - 1
i = hash & mask
# do the first try before any looping
if entries.valid(i):
checkingkey = entries[i].key
- if checkingkey == key:
+ if direct_compare and checkingkey == key:
return i # found the entry
if d.keyeq is not None and entries.hash(i) == hash:
# correct hash, maybe the key is e.g. a different pointer to
@@ -548,7 +550,7 @@
return freeslot
elif entries.valid(i):
checkingkey = entries[i].key
- if checkingkey == key:
+ if direct_compare and checkingkey == key:
return i
if d.keyeq is not None and entries.hash(i) == hash:
# correct hash, maybe the key is e.g. a different pointer to
Modified: pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py (original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/rffi.py Sun May 2 18:05:10 2010
@@ -48,6 +48,7 @@
result = isinstance(s_p, annmodel.SomePtr)
return self.bookkeeper.immutablevalue(result)
def specialize_call(self, hop):
+ hop.exception_cannot_occur()
return hop.inputconst(lltype.Bool, hop.s_result.const)
def llexternal(name, args, result, _callable=None,
@@ -388,6 +389,7 @@
r_int_real = rarithmetic.build_int("r_int_real", r_int.SIGN, r_int.BITS, True)
INT_real = lltype.build_number("INT", r_int_real)
platform.numbertype_to_rclass[INT_real] = r_int_real
+NUMBER_TYPES.append(INT_real)
# ^^^ this creates at least the following names:
# --------------------------------------------------------------------
Modified: pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sun May 2 18:05:10 2010
@@ -432,6 +432,29 @@
rffi.free_charp(p)
assert not ALLOCATED # detects memory leaks in the test
+ def test_funcptr_cast(self):
+ eci = ExternalCompilationInfo(
+ separate_module_sources=["""
+ long mul(long x, long y) { return x*y; }
+ long(*get_mul(long x)) () { return &mul; }
+ """],
+ export_symbols=['get_mul'])
+ get_mul = rffi.llexternal(
+ 'get_mul', [],
+ 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([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)
+ assert res == 41 * 42
+ raises(TypeError, cmul, 41)
+ raises(TypeError, cmul, 41, 42, 43)
+
def test_qsort(self):
CMPFUNC = lltype.FuncType([rffi.VOIDP, rffi.VOIDP], rffi.INT)
qsort = rffi.llexternal('qsort', [rffi.VOIDP,
Modified: pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py (original)
+++ pypy/branch/py12/pypy/rpython/lltypesystem/test/test_lltype.py Sun May 2 18:05:10 2010
@@ -1,5 +1,6 @@
import py
from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.lltypesystem import lltype, rffi
from pypy.lib.identity_dict import identity_dict
def isweak(p, T):
@@ -777,3 +778,42 @@
assert hash1 == identityhash(a)
p = cast_opaque_ptr(llmemory.GCREF, a)
assert hash1 == identityhash(p)
+
+class TestTrackAllocation:
+ def setup_method(self, func):
+ start_tracking_allocations()
+
+ def teardown_method(self, func):
+ assert not lltype.ALLOCATED, "Memory was not correctly freed"
+ stop_tracking_allocations()
+
+ def test_track_allocation(self):
+ """A malloc'd buffer fills the ALLOCATED dictionary"""
+ assert lltype.TRACK_ALLOCATIONS
+ assert not lltype.ALLOCATED
+ buf = malloc(Array(Signed), 1, flavor="raw")
+ assert len(lltype.ALLOCATED) == 1
+ assert lltype.ALLOCATED.keys() == [buf._obj]
+ free(buf, flavor="raw")
+ assert not lltype.ALLOCATED
+
+ def test_str_from_buffer(self):
+ """gc-managed memory does not need to be freed"""
+ size = 50
+ raw_buf, gc_buf = rffi.alloc_buffer(size)
+ for i in range(size): raw_buf[i] = 'a'
+ rstr = rffi.str_from_buffer(raw_buf, gc_buf, size, size)
+ rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+ assert not lltype.ALLOCATED
+
+ def test_leak_traceback(self):
+ """Test info stored for allocated items"""
+ buf = malloc(Array(Signed), 1, flavor="raw")
+ traceback = lltype.ALLOCATED.keys()[0]._traceback
+ lines = traceback.splitlines()
+ assert 'malloc(' in lines[-1] and 'flavor="raw")' in lines[-1]
+
+ # XXX The traceback should not be too long
+ print traceback
+
+ free(buf, flavor="raw")
Modified: pypy/branch/py12/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/branch/py12/pypy/rpython/test/test_llinterp.py (original)
+++ pypy/branch/py12/pypy/rpython/test/test_llinterp.py Sun May 2 18:05:10 2010
@@ -43,7 +43,7 @@
t = TranslationContext(config=config)
t.config.set(**extraconfigopts)
a = t.buildannotator(policy=policy)
- timelog("annotating", a.build_types, func, argtypes)
+ timelog("annotating", a.build_types, func, argtypes, main_entry_point=True)
if viewbefore == 'auto':
viewbefore = getattr(conftest.option, 'view', False)
if viewbefore:
Modified: pypy/branch/py12/pypy/tool/fixeol
==============================================================================
--- pypy/branch/py12/pypy/tool/fixeol (original)
+++ pypy/branch/py12/pypy/tool/fixeol Sun May 2 18:05:10 2010
@@ -48,7 +48,7 @@
return True
def checkeolfile(path):
- return path.ext in ('.txt', '.py', '.asc')
+ return path.ext in ('.txt', '.py', '.asc', '.h', '.c')
def fixdirectory(path):
print "+ checking directory", path,
Modified: pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py (original)
+++ pypy/branch/py12/pypy/translator/c/gcc/test/test_asmgcroot.py Sun May 2 18:05:10 2010
@@ -1,10 +1,14 @@
import py
-import sys, os
+import sys, os, gc
from pypy.translator.c.test import test_newgc
from pypy.translator.translator import TranslationContext
from pypy.translator.c.genc import CStandaloneBuilder
from pypy.annotation.listdef import s_list_of_strings
from pypy import conftest
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.entrypoint import entrypoint, secondary_entrypoints
+from pypy.rpython.lltypesystem.lloperation import llop
class AbstractTestAsmGCRoot:
# the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved
@@ -34,11 +38,15 @@
config = cls.make_config()
t = TranslationContext(config=config)
a = t.buildannotator()
+ sec_ep = getattr(cls, 'secondary_entrypoints', [])
+ for f, inputtypes in sec_ep:
+ a.build_types(f, inputtypes, False)
a.build_types(main, [s_list_of_strings])
t.buildrtyper().specialize()
t.checkgraphs()
- cbuilder = CStandaloneBuilder(t, main, config=config)
+ cbuilder = CStandaloneBuilder(t, main, config=config,
+ secondary_entrypoints=sec_ep)
c_source_filename = cbuilder.generate_source(
defines = cbuilder.DEBUG_DEFINES)
cls._patch_makefile(cbuilder.targetdir)
@@ -53,7 +61,12 @@
redirect = ' 2> NUL'
else:
redirect = ''
- g = os.popen('"%s" %s %d%s' % (exe_name, arg0, arg1, redirect), 'r')
+ if config.translation.shared and os.name == 'posix':
+ env = 'LD_LIBRARY_PATH="%s" ' % (exe_name.dirpath(),)
+ else:
+ env = ''
+ g = os.popen(
+ '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r')
for line in g:
print >> sys.stderr, 'RUN:', line.rstrip()
lines.append(line)
@@ -101,6 +114,7 @@
test_newgc.TestSemiSpaceGC):
# for the individual tests see
# ====> ../../test/test_newgc.py
+ secondary_entrypoints = []
def define_large_function(cls):
class A(object):
@@ -123,11 +137,6 @@
assert res == 1000
def define_callback_simple(cls):
- import gc
- from pypy.rpython.lltypesystem import lltype, rffi
- from pypy.rpython.annlowlevel import llhelper
- from pypy.translator.tool.cbuild import ExternalCompilationInfo
-
c_source = py.code.Source("""
int mystuff(int(*cb)(int, int))
{
@@ -153,11 +162,50 @@
return f
-
def test_callback_simple(self):
res = self.run('callback_simple')
assert res == 4900
+ def define_secondary_entrypoint_callback(cls):
+ # XXX this is baaaad, cleanup global state
+ try:
+ del secondary_entrypoints["x42"]
+ except KeyError:
+ pass
+
+ @entrypoint("x42", [lltype.Signed, lltype.Signed], c_name='callback')
+ def mycallback(a, b):
+ llop.gc_stack_bottom(lltype.Void)
+ rffi.stackcounter.stacks_counter += 1
+ gc.collect()
+ rffi.stackcounter.stacks_counter -= 1
+ return a + b
+
+ c_source = py.code.Source("""
+ int mystuff2()
+ {
+ return callback(40, 2) + callback(3, 4);
+ }
+ """)
+
+ eci = ExternalCompilationInfo(separate_module_sources=[c_source])
+ z = rffi.llexternal('mystuff2', [], lltype.Signed,
+ compilation_info=eci)
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ cls.secondary_entrypoints = secondary_entrypoints["x42"]
+
+ def f():
+ p = lltype.malloc(S)
+ p.x = 100
+ result = z()
+ return result * p.x
+
+ return f
+
+ def test_secondary_entrypoint_callback(self):
+ res = self.run('secondary_entrypoint_callback')
+ assert res == 4900
class TestAsmGCRootWithSemiSpaceGC_Mingw32(TestAsmGCRootWithSemiSpaceGC):
# for the individual tests see
@@ -186,6 +234,13 @@
def define_callback_with_collect(cls):
return lambda: 0
+class TestAsmGCRootWithSemiSpaceGC_Shared(TestAsmGCRootWithSemiSpaceGC):
+ @classmethod
+ def make_config(cls):
+ config = TestAsmGCRootWithSemiSpaceGC.make_config()
+ config.translation.shared = True
+ return config
+
class TestAsmGCRootWithHybridTagged(AbstractTestAsmGCRoot,
test_newgc.TestHybridTaggedPointers):
pass
Modified: pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py (original)
+++ pypy/branch/py12/pypy/translator/c/gcc/trackgcroot.py Sun May 2 18:05:10 2010
@@ -1640,6 +1640,7 @@
format = 'mingw32'
else:
format = 'elf'
+ entrypoint = 'main'
while len(sys.argv) > 1:
if sys.argv[1] == '-v':
del sys.argv[1]
@@ -1653,6 +1654,9 @@
elif sys.argv[1].startswith('-f'):
format = sys.argv[1][2:]
del sys.argv[1]
+ elif sys.argv[1].startswith('-m'):
+ entrypoint = sys.argv[1][2:]
+ del sys.argv[1]
else:
break
tracker = GcRootTracker(verbose=verbose, shuffle=shuffle, format=format)
@@ -1669,7 +1673,7 @@
lblfn = fn[:-2] + '.lbl.s'
g = open(lblfn, 'w')
try:
- tracker.process(f, g, filename=fn)
+ tracker.process(f, g, entrypoint=entrypoint, filename=fn)
except:
g.close()
os.unlink(lblfn)
Modified: pypy/branch/py12/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/genc.py (original)
+++ pypy/branch/py12/pypy/translator/c/genc.py Sun May 2 18:05:10 2010
@@ -13,6 +13,7 @@
from pypy.translator.c.support import log, c_string_constant
from pypy.rpython.typesystem import getfunctionptr
from pypy.translator.c import gc
+from pypy.rlib import exports
def import_module_from_directory(dir, modname):
file, pathname, description = imp.find_module(modname, [str(dir)])
@@ -77,14 +78,22 @@
self.outputfilename = outputfilename
self.profbased = profbased
- def _build(self, eci=ExternalCompilationInfo()):
+ def _build(self, eci=ExternalCompilationInfo(), shared=False):
+ outputfilename = self.outputfilename
+ if shared:
+ if outputfilename:
+ basename = outputfilename
+ else:
+ basename = self.cfiles[0].purebasename
+ outputfilename = 'lib' + basename
return self.platform.compile(self.cfiles, self.eci.merge(eci),
- outputfilename=self.outputfilename)
+ outputfilename=outputfilename,
+ standalone=not shared)
- def build(self):
+ def build(self, shared=False):
if self.profbased:
return self._do_profbased()
- return self._build()
+ return self._build(shared=shared)
def _do_profbased(self):
ProfDriver, args = self.profbased
@@ -103,7 +112,8 @@
modulename = None
split = False
- def __init__(self, translator, entrypoint, config, gcpolicy=None):
+ def __init__(self, translator, entrypoint, config, gcpolicy=None,
+ secondary_entrypoints=()):
self.translator = translator
self.entrypoint = entrypoint
self.entrypoint_name = getattr(self.entrypoint, 'func_name', None)
@@ -113,6 +123,7 @@
if gcpolicy is not None and gcpolicy.requires_stackless:
config.translation.stackless = True
self.eci = self.get_eci()
+ self.secondary_entrypoints = secondary_entrypoints
def get_eci(self):
pypy_include_dir = py.path.local(autopath.pypydir).join('translator', 'c')
@@ -159,7 +170,16 @@
self.c_entrypoint_name = None
else:
pfname = db.get(pf)
+
+ for func, _ in self.secondary_entrypoints:
+ bk = translator.annotator.bookkeeper
+ db.get(getfunctionptr(bk.getdesc(func).getuniquegraph()))
+
self.c_entrypoint_name = pfname
+
+ for obj in exports.EXPORTS_obj2name.keys():
+ db.getcontainernode(obj)
+ exports.clear()
db.complete()
self.collect_compilation_info(db)
@@ -240,6 +260,10 @@
if CBuilder.have___thread:
if not self.config.translation.no__thread:
defines['USE___THREAD'] = 1
+ if self.config.translation.shared:
+ defines['PYPY_MAIN_FUNCTION'] = "pypy_main_startup"
+ self.eci = self.eci.merge(ExternalCompilationInfo(
+ export_symbols=["pypy_main_startup"]))
self.eci, cfile, extra = gen_source_standalone(db, modulename,
targetdir,
self.eci,
@@ -404,12 +428,13 @@
if isinstance(self._module, isolate.Isolate):
isolate.close_isolate(self._module)
- def gen_makefile(self, targetdir):
+ def gen_makefile(self, targetdir, exe_name=None):
pass
class CStandaloneBuilder(CBuilder):
standalone = True
executable_name = None
+ shared_library_name = None
def getprofbased(self):
profbased = None
@@ -450,9 +475,40 @@
return res.out, res.err
return res.out
- def compile(self):
+ def build_main_for_shared(self, shared_library_name, entrypoint, exe_name):
+ import time
+ time.sleep(1)
+ self.shared_library_name = shared_library_name
+ # build main program
+ eci = self.get_eci()
+ kw = {}
+ if self.translator.platform.so_ext == 'so':
+ kw['libraries'] = [self.shared_library_name.purebasename[3:]]
+ kw['library_dirs'] = [self.targetdir]
+ else:
+ kw['libraries'] = [self.shared_library_name.new(ext='')]
+ eci = eci.merge(ExternalCompilationInfo(
+ separate_module_sources=['''
+ int %s(int argc, char* argv[]);
+
+ int main(int argc, char* argv[])
+ { return %s(argc, argv); }
+ ''' % (entrypoint, entrypoint)
+ ],
+ **kw
+ ))
+ eci = eci.convert_sources_to_files(
+ cache_dir=self.targetdir)
+ return self.translator.platform.compile(
+ [], eci,
+ outputfilename=exe_name)
+
+ def compile(self, exe_name=None):
assert self.c_source_filename
assert not self._compiled
+
+ shared = self.config.translation.shared
+
if (self.config.translation.gcrootfinder == "asmgcc" or
self.config.translation.force_make):
extra_opts = []
@@ -463,16 +519,23 @@
else:
compiler = CCompilerDriver(self.translator.platform,
[self.c_source_filename] + self.extrafiles,
- self.eci, profbased=self.getprofbased())
- self.executable_name = compiler.build()
+ self.eci, profbased=self.getprofbased(),
+ outputfilename=exe_name)
+ self.executable_name = compiler.build(shared=shared)
+ if shared:
+ self.executable_name = self.build_main_for_shared(
+ self.executable_name, "pypy_main_startup", exe_name)
assert self.executable_name
self._compiled = True
return self.executable_name
- def gen_makefile(self, targetdir):
+ def gen_makefile(self, targetdir, exe_name=None):
cfiles = [self.c_source_filename] + self.extrafiles
- mk = self.translator.platform.gen_makefile(cfiles, self.eci,
- path=targetdir)
+ mk = self.translator.platform.gen_makefile(
+ cfiles, self.eci,
+ path=targetdir, exe_name=exe_name,
+ shared=self.config.translation.shared)
+
if self.has_profopt():
profopt = self.config.translation.profopt
mk.definition('ABS_TARGET', '$(shell python -c "import sys,os; print os.path.abspath(sys.argv[1])" $(TARGET))')
@@ -516,6 +579,11 @@
mk.definition('GCMAPFILES', gcmapfiles)
mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g')
+ if self.config.translation.shared:
+ mk.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup")
+ else:
+ mk.definition('PYPY_MAIN_FUNCTION', "main")
+
if sys.platform == 'win32':
python = sys.executable.replace('\\', '/') + ' '
else:
@@ -541,7 +609,7 @@
'cmd /c $(MASM) /nologo /Cx /Cp /Zm /coff /Fo$@ /c $< $(INCLUDEDIRS)')
mk.rule('.c.gcmap', '',
['$(CC) /nologo $(ASM_CFLAGS) /c /FAs /Fa$*.s $< $(INCLUDEDIRS)',
- 'cmd /c ' + python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc -t $*.s > $@']
+ 'cmd /c ' + python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc -m$(PYPY_MAIN_FUNCTION) -t $*.s > $@']
)
mk.rule('gcmaptable.c', '$(GCMAPFILES)',
'cmd /c ' + python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc $(GCMAPFILES) > $@')
@@ -550,7 +618,7 @@
mk.definition('OBJECTS', '$(ASMLBLFILES) gcmaptable.s')
mk.rule('%.s', '%.c', '$(CC) $(CFLAGS) $(CFLAGSEXTRA) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)')
mk.rule('%.lbl.s %.gcmap', '%.s',
- python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -t $< > $*.gcmap')
+ python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py -m$(PYPY_MAIN_FUNCTION) -t $< > $*.gcmap')
mk.rule('gcmaptable.s', '$(GCMAPFILES)',
python + '$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@')
Modified: pypy/branch/py12/pypy/translator/c/node.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/node.py (original)
+++ pypy/branch/py12/pypy/translator/c/node.py Sun May 2 18:05:10 2010
@@ -10,6 +10,7 @@
from pypy.translator.c.support import cdecl, forward_cdecl, somelettersfrom
from pypy.translator.c.support import c_char_array_constant, barebonearray
from pypy.translator.c.primitive import PrimitiveType, name_signed
+from pypy.rlib import exports
from pypy.rlib.rarithmetic import isinf, isnan
from pypy.rlib.rstackovf import _StackOverflow
from pypy.translator.c import extfunc
@@ -468,7 +469,7 @@
if USESLOTS:
__slots__ = """db T obj
typename implementationtypename
- name ptrname
+ name ptrname compilation_info
globalcontainer""".split()
def __init__(self, db, T, obj):
@@ -479,7 +480,10 @@
self.typename = db.gettype(T) #, who_asks=self)
self.implementationtypename = db.gettype(T, varlength=self.getlength())
parent, parentindex = parentlink(obj)
- if parent is None:
+ if obj in exports.EXPORTS_obj2name:
+ self.name = exports.EXPORTS_obj2name[obj]
+ self.globalcontainer = True
+ elif parent is None:
self.name = db.namespace.uniquename('g_' + self.basename())
self.globalcontainer = True
else:
@@ -490,6 +494,7 @@
if self.typename != self.implementationtypename:
if db.gettypedefnode(T).extra_union_for_varlength:
self.name += '.b'
+ self.compilation_info = getattr(obj, '_compilation_info', None)
self.ptrname = '(&%s)' % self.name
def is_thread_local(self):
@@ -922,6 +927,8 @@
else:
assert fnobj.external == 'CPython'
return [CExternalFunctionCodeGenerator(fnobj, db)]
+ elif hasattr(fnobj._callable, "c_name"):
+ return []
else:
raise ValueError, "don't know how to generate code for %r" % (fnobj,)
Modified: pypy/branch/py12/pypy/translator/c/src/commondefs.h
==============================================================================
--- pypy/branch/py12/pypy/translator/c/src/commondefs.h (original)
+++ pypy/branch/py12/pypy/translator/c/src/commondefs.h Sun May 2 18:05:10 2010
@@ -15,6 +15,13 @@
#include <limits.h>
+#ifndef LLONG_MAX
+#define LLONG_MAX __LONG_LONG_MAX__
+#endif
+#ifndef LLONG_MIN
+#define LLONG_MIN (-LLONG_MAX - 1LL)
+#endif
+
#if INT_MAX != 2147483647
# error "unsupported value for INT_MAX"
#endif
@@ -62,9 +69,6 @@
/********************************************************/
-typedef long Py_intptr_t;
-typedef unsigned long Py_uintptr_t;
-
#if ((-1) >> 1) > 0
# define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) \
((I) < 0 ? -1-((-1-(I)) >> (J)) : (I) >> (J))
Modified: pypy/branch/py12/pypy/translator/c/src/main.h
==============================================================================
--- pypy/branch/py12/pypy/translator/c/src/main.h (original)
+++ pypy/branch/py12/pypy/translator/c/src/main.h Sun May 2 18:05:10 2010
@@ -15,11 +15,15 @@
#ifndef PYPY_NOT_MAIN_FILE
+#ifndef PYPY_MAIN_FUNCTION
+#define PYPY_MAIN_FUNCTION main
+#endif
+
#ifdef MS_WINDOWS
#include "src/winstuff.c"
#endif
-int main(int argc, char *argv[])
+int PYPY_MAIN_FUNCTION(int argc, char *argv[])
{
char *errmsg;
int i, exitcode;
Modified: pypy/branch/py12/pypy/translator/c/src/obmalloc.c
==============================================================================
--- pypy/branch/py12/pypy/translator/c/src/obmalloc.c (original)
+++ pypy/branch/py12/pypy/translator/c/src/obmalloc.c Sun May 2 18:05:10 2010
@@ -225,7 +225,7 @@
#define ulong unsigned long /* assuming >= 32 bits */
#undef uptr
-#define uptr Py_uintptr_t
+#define uptr unsigned long
/* When you say memory, my mind reasons in terms of (pointers to) blocks */
typedef uchar block;
@@ -439,7 +439,7 @@
arenabase = bp;
nfreepools = ARENA_SIZE / POOL_SIZE;
assert(POOL_SIZE * nfreepools == ARENA_SIZE);
- excess = (uint) ((Py_uintptr_t)bp & POOL_SIZE_MASK);
+ excess = (uint) ((uint)bp & POOL_SIZE_MASK);
if (excess != 0) {
--nfreepools;
arenabase += POOL_SIZE - excess;
Modified: pypy/branch/py12/pypy/translator/c/test/test_genc.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/test/test_genc.py (original)
+++ pypy/branch/py12/pypy/translator/c/test/test_genc.py Sun May 2 18:05:10 2010
@@ -12,6 +12,7 @@
from pypy.translator.gensupp import uniquemodulename
from pypy.translator.backendopt.all import backend_optimizations
from pypy.translator.interactive import Translation
+from pypy.rlib.entrypoint import entrypoint
def compile(fn, argtypes, view=False, gcpolicy="ref", backendopt=True,
annotatorpolicy=None):
@@ -396,3 +397,85 @@
if py.test.config.option.view:
t.view()
assert 'pypy_xyz_f' in t.driver.cbuilder.c_source_filename.read()
+
+def test_entrypoints():
+ def f():
+ return 3
+
+ key = "test_entrypoints42"
+ @entrypoint(key, [int], "foobar")
+ def g(x):
+ return x + 42
+
+ t = Translation(f, [], backend="c", secondaryentrypoints="test_entrypoints42")
+ t.annotate()
+ compiled_fn = t.compile_c()
+ if py.test.config.option.view:
+ t.view()
+ assert 'foobar' in t.driver.cbuilder.c_source_filename.read()
+
+def test_exportstruct():
+ from pypy.rlib.exports import export_struct
+ def f():
+ return 42
+ FOO = Struct("FOO", ("field1", Signed))
+ foo = malloc(FOO, flavor="raw")
+ foo.field1 = 43
+ export_struct("BarStruct", foo._obj)
+ t = Translation(f, [], backend="c")
+ t.annotate()
+ compiled_fn = t.compile_c()
+ if py.test.config.option.view:
+ t.view()
+ assert ' BarStruct ' in t.driver.cbuilder.c_source_filename.read()
+
+def test_recursive_llhelper():
+ from pypy.rpython.annlowlevel import llhelper
+ from pypy.rpython.lltypesystem import lltype
+ from pypy.rlib.objectmodel import specialize
+ from pypy.rlib.nonconst import NonConstant
+ FT = lltype.ForwardReference()
+ FTPTR = lltype.Ptr(FT)
+ STRUCT = lltype.Struct("foo", ("bar", FTPTR))
+ FT.become(lltype.FuncType([lltype.Ptr(STRUCT)], lltype.Signed))
+
+ class A:
+ def __init__(self, func, name):
+ self.func = func
+ self.name = name
+ def _freeze_(self):
+ return True
+ @specialize.memo()
+ def make_func(self):
+ f = getattr(self, "_f", None)
+ if f is not None:
+ return f
+ f = lambda *args: self.func(*args)
+ f.c_name = self.name
+ f.relax_sig_check = True
+ f.__name__ = "WRAP%s" % (self.name, )
+ self._f = f
+ return f
+ def get_llhelper(self):
+ return llhelper(FTPTR, self.make_func())
+ def f(s):
+ if s.bar == t.bar:
+ lltype.free(s, flavor="raw")
+ return 1
+ lltype.free(s, flavor="raw")
+ return 0
+ def g(x):
+ return 42
+ def chooser(x):
+ s = lltype.malloc(STRUCT, flavor="raw")
+ if x:
+ s.bar = llhelper(FTPTR, a_f.make_func())
+ else:
+ s.bar = llhelper(FTPTR, a_g.make_func())
+ return f(s)
+ a_f = A(f, "f")
+ a_g = A(g, "g")
+ t = lltype.malloc(STRUCT, flavor="raw")
+ t.bar = llhelper(FTPTR, a_f.make_func())
+ fn = compile(chooser, [bool])
+ assert fn(True)
Modified: pypy/branch/py12/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/py12/pypy/translator/c/test/test_newgc.py Sun May 2 18:05:10 2010
@@ -66,6 +66,12 @@
for fullname in dir(cls):
if not fullname.startswith('define'):
continue
+ keyword = conftest.option.keyword
+ if keyword:
+ if keyword.startswith('test_'):
+ keyword = keyword[len('test_'):]
+ if keyword not in fullname:
+ continue
prefix, name = fullname.split('_', 1)
definefunc = getattr(cls, fullname)
func = definefunc.im_func(cls)
Modified: pypy/branch/py12/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/py12/pypy/translator/c/test/test_standalone.py (original)
+++ pypy/branch/py12/pypy/translator/c/test/test_standalone.py Sun May 2 18:05:10 2010
@@ -16,11 +16,13 @@
class StandaloneTests(object):
config = None
- def compile(self, entry_point, debug=True):
+ def compile(self, entry_point, debug=True, shared=False):
t = TranslationContext(self.config)
t.buildannotator().build_types(entry_point, [s_list_of_strings])
t.buildrtyper().specialize()
+ t.config.translation.shared = shared
+
cbuilder = CStandaloneBuilder(t, entry_point, t.config)
if debug:
cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
@@ -587,6 +589,19 @@
# The traceback stops at f() because it's the first function that
# captures the AssertionError, which makes the program abort.
+ def test_shared(self, monkeypatch):
+ def f(argv):
+ print len(argv)
+ def entry_point(argv):
+ f(argv)
+ return 0
+ t, cbuilder = self.compile(entry_point, shared=True)
+ assert cbuilder.shared_library_name is not None
+ assert cbuilder.shared_library_name != cbuilder.executable_name
+ monkeypatch.setenv('LD_LIBRARY_PATH',
+ cbuilder.shared_library_name.dirpath())
+ out, err = cbuilder.cmdexec("a b")
+ assert out == "3"
class TestMaemo(TestStandalone):
def setup_class(cls):
Modified: pypy/branch/py12/pypy/translator/driver.py
==============================================================================
--- pypy/branch/py12/pypy/translator/driver.py (original)
+++ pypy/branch/py12/pypy/translator/driver.py Sun May 2 18:05:10 2010
@@ -12,6 +12,7 @@
import optparse
from pypy.tool.udir import udir
from pypy.rlib.jit import DEBUG_OFF, DEBUG_DETAILED, DEBUG_PROFILE, DEBUG_STEPS
+from pypy.rlib.entrypoint import secondary_entrypoints
import py
from pypy.tool.ansi_print import ansi_log
@@ -93,7 +94,7 @@
if setopts is not None:
self.config.set(**setopts)
-
+
self.exe_name = exe_name
self.extmod_name = extmod_name
@@ -210,12 +211,25 @@
self.entry_point = entry_point
self.translator = translator
self.libdef = None
+ self.secondary_entrypoints = []
+
+ if self.config.translation.secondaryentrypoints:
+ for key in self.config.translation.secondaryentrypoints.split(","):
+ try:
+ points = secondary_entrypoints[key]
+ except KeyError:
+ raise KeyError(
+ "Entrypoints not found. I only know the keys %r." %
+ (", ".join(secondary_entrypoints.keys()), ))
+ self.secondary_entrypoints.extend(points)
self.translator.driver_instrument_result = self.instrument_result
def setup_library(self, libdef, policy=None, extra={}, empty_translator=None):
+ """ Used by carbon python only. """
self.setup(None, None, policy, extra, empty_translator)
self.libdef = libdef
+ self.secondary_entrypoints = libdef.functions
def instrument_result(self, args):
backend, ts = self.get_backend_and_type_system()
@@ -304,23 +318,26 @@
annmodel.DEBUG = self.config.translation.debug
annotator = translator.buildannotator(policy=policy)
+ if self.secondary_entrypoints is not None:
+ for func, inputtypes in self.secondary_entrypoints:
+ if inputtypes == Ellipsis:
+ continue
+ rettype = annotator.build_types(func, inputtypes, False)
+
if self.entry_point:
s = annotator.build_types(self.entry_point, self.inputtypes)
-
- self.sanity_check_annotation()
- if self.standalone and s.knowntype != int:
- raise Exception("stand-alone program entry point must return an "
- "int (and not, e.g., None or always raise an "
- "exception).")
- annotator.simplify()
- return s
+ translator.entry_point_graph = annotator.bookkeeper.getdesc(self.entry_point).getuniquegraph()
else:
- assert self.libdef is not None
- for func, inputtypes in self.libdef.functions:
- annotator.build_types(func, inputtypes)
- func.c_name = func.func_name
- self.sanity_check_annotation()
- annotator.simplify()
+ s = None
+
+ self.sanity_check_annotation()
+ if self.entry_point and self.standalone and s.knowntype != int:
+ raise Exception("stand-alone program entry point must return an "
+ "int (and not, e.g., None or always raise an "
+ "exception).")
+ annotator.simplify()
+ return s
+
#
task_annotate = taskdef(task_annotate, [], "Annotating&simplifying")
@@ -471,7 +488,8 @@
else:
from pypy.translator.c.genc import CExtModuleBuilder as CBuilder
cbuilder = CBuilder(self.translator, self.entry_point,
- config=self.config)
+ config=self.config,
+ secondary_entrypoints=self.secondary_entrypoints)
cbuilder.stackless = self.config.translation.stackless
if not standalone: # xxx more messy
cbuilder.modulename = self.extmod_name
@@ -521,6 +539,10 @@
exename = mkexename(self.c_entryp)
newexename = self.compute_exe_name()
shutil.copy(str(exename), str(newexename))
+ if self.cbuilder.shared_library_name is not None:
+ soname = self.cbuilder.shared_library_name
+ newsoname = newexename.new(basename=soname.basename)
+ shutil.copy(str(soname), str(newsoname))
self.c_entryp = newexename
self.log.info("created: %s" % (self.c_entryp,))
@@ -529,7 +551,10 @@
translator/platform
"""
cbuilder = self.cbuilder
- cbuilder.compile()
+ kwds = {}
+ if self.standalone and self.exe_name is not None:
+ kwds['exe_name'] = self.compute_exe_name().basename
+ cbuilder.compile(**kwds)
if self.standalone:
self.c_entryp = cbuilder.executable_name
Modified: pypy/branch/py12/pypy/translator/goal/ann_override.py
==============================================================================
--- pypy/branch/py12/pypy/translator/goal/ann_override.py (original)
+++ pypy/branch/py12/pypy/translator/goal/ann_override.py Sun May 2 18:05:10 2010
@@ -81,7 +81,7 @@
def attach_lookup(pol, t, attr):
cached = "cached_%s" % attr
- if not t.is_heaptype():
+ if not t.is_heaptype() and not t.is_cpytype():
pol._remember_immutable(t, cached)
setattr(t, cached, t._lookup(attr))
return True
@@ -89,7 +89,7 @@
def attach_lookup_in_type_where(pol, t, attr):
cached = "cached_where_%s" % attr
- if not t.is_heaptype():
+ if not t.is_heaptype() and not t.is_cpytype():
pol._remember_immutable(t, cached)
setattr(t, cached, t._lookup_where(attr))
return True
@@ -177,14 +177,14 @@
CACHED_LOOKUP = """
def lookup_%(attr)s(space, w_obj, name):
w_type = space.type(w_obj)
- if not w_type.is_heaptype():
+ if not w_type.is_heaptype() and not w_type.is_cpytype():
return w_type.cached_%(attr)s
return w_type.lookup("%(attr)s")
"""
CACHED_LOOKUP_IN_TYPE_WHERE = """
def lookup_in_type_where_%(attr)s(space, w_type, name):
- if not w_type.is_heaptype():
+ if not w_type.is_heaptype() and not w_type.is_cpytype():
return w_type.cached_where_%(attr)s
return w_type.lookup_where("%(attr)s")
"""
Modified: pypy/branch/py12/pypy/translator/platform/__init__.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/__init__.py (original)
+++ pypy/branch/py12/pypy/translator/platform/__init__.py Sun May 2 18:05:10 2010
@@ -69,7 +69,8 @@
env)
return ExecutionResult(returncode, stdout, stderr)
- def gen_makefile(self, cfiles, eci, exe_name=None, path=None):
+ def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
+ shared=False):
raise NotImplementedError("Pure abstract baseclass")
def __repr__(self):
@@ -104,10 +105,8 @@
errorfile = outname.new(ext='errors')
errorfile.write(stderr, 'wb')
stderrlines = stderr.splitlines()
- for line in stderrlines[:50]:
+ for line in stderrlines:
log.ERROR(line)
- if len(stderrlines) > 50:
- log.ERROR('...')
raise CompilationError(stdout, stderr)
else:
for line in stderr.splitlines():
Modified: pypy/branch/py12/pypy/translator/platform/darwin.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/darwin.py (original)
+++ pypy/branch/py12/pypy/translator/platform/darwin.py Sun May 2 18:05:10 2010
@@ -18,7 +18,7 @@
self.cc = cc
def _args_for_shared(self, args):
- return (self.shared_only + ['-bundle', '-undefined', 'dynamic_lookup']
+ return (self.shared_only + ['-dynamiclib', '-undefined', 'dynamic_lookup']
+ args)
def include_dirs_for_libffi(self):
Modified: pypy/branch/py12/pypy/translator/platform/linux.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/linux.py (original)
+++ pypy/branch/py12/pypy/translator/platform/linux.py Sun May 2 18:05:10 2010
@@ -7,7 +7,7 @@
name = "linux"
link_flags = ['-pthread', '-lrt']
- cflags = ['-O3', '-pthread', '-fomit-frame-pointer', '-Wall']
+ cflags = ['-O3', '-pthread', '-fomit-frame-pointer', '-Wall', '-Wno-unused']
standalone_only = []
shared_only = ['-fPIC']
so_ext = 'so'
Modified: pypy/branch/py12/pypy/translator/platform/posix.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/posix.py (original)
+++ pypy/branch/py12/pypy/translator/platform/posix.py Sun May 2 18:05:10 2010
@@ -36,6 +36,10 @@
cwd=str(cfile.dirpath()))
return oname
+ def _link_args_from_eci(self, eci, standalone):
+ eci = eci.convert_exportsymbols_to_file()
+ return Platform._link_args_from_eci(self, eci, standalone)
+
def _link(self, cc, ofiles, link_args, standalone, exe_name):
args = [str(ofile) for ofile in ofiles] + link_args
args += ['-o', str(exe_name)]
@@ -55,7 +59,9 @@
# strip compiler flags
return [entry[2:] for entry in out.split()]
- def gen_makefile(self, cfiles, eci, exe_name=None, path=None):
+ def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
+ shared=False):
+ eci = eci.convert_exportsymbols_to_file()
cfiles = [py.path.local(f) for f in cfiles]
cfiles += [py.path.local(f) for f in eci.separate_module_files]
@@ -67,6 +73,16 @@
if exe_name is None:
exe_name = cfiles[0].new(ext=self.exe_ext)
+ linkflags = self.link_flags
+ if shared:
+ linkflags = self._args_for_shared(linkflags)
+
+ if shared:
+ libname = exe_name.new(ext='').basename
+ target_name = 'lib' + exe_name.new(ext=self.so_ext).basename
+ else:
+ target_name = exe_name.basename
+
m = GnuMakefile(path)
m.exe_name = exe_name
m.eci = eci
@@ -88,8 +104,8 @@
m.comment('automatically generated makefile')
definitions = [
('PYPYDIR', autopath.pypydir),
- ('TARGET', exe_name.basename),
- ('DEFAULT_TARGET', '$(TARGET)'),
+ ('TARGET', target_name),
+ ('DEFAULT_TARGET', exe_name.basename),
('SOURCES', rel_cfiles),
('OBJECTS', rel_ofiles),
('LIBS', self._libs(eci.libraries)),
@@ -97,7 +113,7 @@
('INCLUDEDIRS', self._includedirs(rel_includedirs)),
('CFLAGS', self.cflags),
('CFLAGSEXTRA', list(eci.compile_extra)),
- ('LDFLAGS', self.link_flags),
+ ('LDFLAGS', linkflags),
('LDFLAGSEXTRA', list(eci.link_extra)),
('CC', self.cc),
('CC_LINK', eci.use_cpp_linker and 'g++' or '$(CC)'),
@@ -115,6 +131,16 @@
for rule in rules:
m.rule(*rule)
+ if shared:
+ m.definition('SHARED_IMPORT_LIB', libname),
+ m.rule('main.c', '',
+ 'echo "'
+ 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); '
+ 'int main(int argc, char* argv[]) '
+ '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); }" > $@')
+ m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.o'],
+ '$(CC_LINK) main.o -L. -l$(SHARED_IMPORT_LIB) -o $@')
+
return m
def execute_makefile(self, path_to_makefile, extra_opts=[]):
Modified: pypy/branch/py12/pypy/translator/platform/windows.py
==============================================================================
--- pypy/branch/py12/pypy/translator/platform/windows.py (original)
+++ pypy/branch/py12/pypy/translator/platform/windows.py Sun May 2 18:05:10 2010
@@ -186,7 +186,8 @@
raise CompilationError(stdout, stderr)
- def gen_makefile(self, cfiles, eci, exe_name=None, path=None):
+ def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
+ shared=False):
cfiles = [py.path.local(f) for f in cfiles]
cfiles += [py.path.local(f) for f in eci.separate_module_files]
@@ -202,6 +203,17 @@
m.exe_name = exe_name
m.eci = eci
+ linkflags = self.link_flags
+ if shared:
+ linkflags = self._args_for_shared(linkflags) + [
+ '/EXPORT:$(PYPY_MAIN_FUNCTION)']
+
+ if shared:
+ so_name = exe_name.new(ext=self.so_ext)
+ target_name = so_name.basename
+ else:
+ target_name = exe_name.basename
+
def pypyrel(fpath):
rel = py.path.local(fpath).relto(pypypath)
if rel:
@@ -218,8 +230,8 @@
m.comment('automatically generated makefile')
definitions = [
('PYPYDIR', autopath.pypydir),
- ('TARGET', exe_name.basename),
- ('DEFAULT_TARGET', '$(TARGET)'),
+ ('TARGET', target_name),
+ ('DEFAULT_TARGET', exe_name.basename),
('SOURCES', rel_cfiles),
('OBJECTS', rel_ofiles),
('LIBS', self._libs(eci.libraries)),
@@ -227,12 +239,13 @@
('INCLUDEDIRS', self._includedirs(rel_includedirs)),
('CFLAGS', self.cflags),
('CFLAGSEXTRA', list(eci.compile_extra)),
- ('LDFLAGS', self.link_flags),
+ ('LDFLAGS', linkflags),
('LDFLAGSEXTRA', list(eci.link_extra)),
('CC', self.cc),
('CC_LINK', self.link),
('MASM', self.masm),
]
+
for args in definitions:
m.definition(*args)
@@ -253,6 +266,16 @@
'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1',
])
+ if shared:
+ m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename),
+ m.rule('main.c', '',
+ 'echo '
+ 'int $(PYPY_MAIN_FUNCTION)(int, char*[]); '
+ 'int main(int argc, char* argv[]) '
+ '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); } > $@')
+ m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.obj'],
+ '$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@')
+
return m
def execute_makefile(self, path_to_makefile, extra_opts=[]):
Modified: pypy/branch/py12/pypy/translator/test/test_unsimplify.py
==============================================================================
--- pypy/branch/py12/pypy/translator/test/test_unsimplify.py (original)
+++ pypy/branch/py12/pypy/translator/test/test_unsimplify.py Sun May 2 18:05:10 2010
@@ -9,6 +9,7 @@
def translate(func, argtypes, type_system="lltype"):
t = TranslationContext()
t.buildannotator().build_types(func, argtypes)
+ t.entry_point_graph = graphof(t, func)
t.buildrtyper(type_system=type_system).specialize()
return graphof(t, func), t
Modified: pypy/branch/py12/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/branch/py12/pypy/translator/tool/cbuild.py (original)
+++ pypy/branch/py12/pypy/translator/tool/cbuild.py Sun May 2 18:05:10 2010
@@ -260,24 +260,49 @@
d['separate_module_files'] += tuple(files)
return ExternalCompilationInfo(**d)
+ def convert_exportsymbols_to_file(self):
+ if not self.export_symbols:
+ return self
+ num = 0
+ while 1:
+ file_name = udir.join('dynamic-symbols-%i' % num)
+ num += 1
+ if not file_name.check():
+ break
+
+ f = file_name.open("w")
+ f.write("{\n")
+ for sym in self.export_symbols:
+ f.write("%s;\n" % (sym,))
+ f.write("};")
+ f.close()
+ d = self._copy_attributes()
+ d['link_extra'] += ("-Wl,--dynamic-list=" + str(file_name), )
+ d['export_symbols'] = ()
+ return ExternalCompilationInfo(**d)
+
+
def get_module_files(self):
d = self._copy_attributes()
files = d['separate_module_files']
d['separate_module_files'] = ()
return files, ExternalCompilationInfo(**d)
- def compile_shared_lib(self):
+ def compile_shared_lib(self, outputfilename=None):
self = self.convert_sources_to_files()
if not self.separate_module_files:
return self
- # find more or less unique name there
- basepath = py.path.local(self.separate_module_files[0]).dirpath()
- pth = basepath.join('externmod').new(ext=host.so_ext)
- num = 0
- while pth.check():
- pth = basepath.join('externmod_%d' % (num,)).new(ext=host.so_ext)
- num += 1
- lib = str(host.compile([], self, outputfilename=pth.purebasename,
+ if outputfilename is None:
+ # find more or less unique name there
+ basepath = py.path.local(self.separate_module_files[0]).dirpath()
+ pth = basepath.join('externmod').new(ext=host.so_ext)
+ num = 0
+ while pth.check():
+ pth = basepath.join(
+ 'externmod_%d' % (num,)).new(ext=host.so_ext)
+ num += 1
+ outputfilename=pth.purebasename
+ lib = str(host.compile([], self, outputfilename=outputfilename,
standalone=False))
d = self._copy_attributes()
d['libraries'] += (lib,)
Modified: pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py
==============================================================================
--- pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py (original)
+++ pypy/branch/py12/pypy/translator/tool/test/test_cbuild.py Sun May 2 18:05:10 2010
@@ -71,6 +71,17 @@
e = ExternalCompilationInfo()
assert e.convert_sources_to_files() is e
+ def test_convert_sources_to_c_files(self):
+ eci = ExternalCompilationInfo(
+ export_symbols=("foo", )
+ )
+ neweci = eci.convert_exportsymbols_to_file()
+ le = neweci.link_extra[-1]
+ assert "foo;" in file(le.rsplit("=", 1)[1]).read()
+ e = ExternalCompilationInfo()
+ assert e.convert_exportsymbols_to_file() is e
+
+
def test_make_shared_lib(self):
eci = ExternalCompilationInfo(
separate_module_sources = ['''
Modified: pypy/branch/py12/pypy/translator/unsimplify.py
==============================================================================
--- pypy/branch/py12/pypy/translator/unsimplify.py (original)
+++ pypy/branch/py12/pypy/translator/unsimplify.py Sun May 2 18:05:10 2010
@@ -168,7 +168,7 @@
if own_annhelper:
annhelper.finish()
- entry_point = translator.graphs[0]
+ entry_point = translator.entry_point_graph
v = copyvar(translator.annotator, entry_point.getreturnvar())
extrablock = Block([v])
v_none = varoftype(lltype.Void)
More information about the Pypy-commit
mailing list