[pypy-svn] r45299 - in pypy/dist/pypy/rpython/lltypesystem: . test
fijal at codespeak.net
fijal at codespeak.net
Tue Jul 24 13:42:16 CEST 2007
Author: fijal
Date: Tue Jul 24 13:42:16 2007
New Revision: 45299
Modified:
pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
pypy/dist/pypy/rpython/lltypesystem/rffi.py
pypy/dist/pypy/rpython/lltypesystem/rfficache.py
pypy/dist/pypy/rpython/lltypesystem/test/test_rfficache.py
Log:
Improve the rfficache to be a bit more general and also to store
#defines (simple ones)
Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Tue Jul 24 13:42:16 2007
@@ -355,7 +355,7 @@
elif T is not lltype.Signed:
from pypy.rpython.lltypesystem import rffi
try:
- inttype = rffi.numbertype_to_rclass[T]
+ inttype = rffi.platform.numbertype_to_rclass[T]
except KeyError:
llobj = cobj
else:
Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Tue Jul 24 13:42:16 2007
@@ -5,6 +5,7 @@
from pypy.annotation.model import lltype_to_annotation
from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic
from pypy.rlib import rarithmetic
+import os
class CConstant(Symbolic):
""" A C-level constant, maybe #define, rendered directly.
@@ -32,28 +33,35 @@
ll2ctypes.make_callable_via_ctypes(funcptr)
return funcptr
-numbertype_to_rclass = {} # {USHORT: r_ushort, ...}
+from pypy.rpython.lltypesystem.rfficache import platform
+
+TYPES = []
+for _name in 'short int long'.split():
+ for name in (_name, 'unsigned ' + _name):
+ TYPES.append(name)
+TYPES += ['signed char', 'unsigned char',
+ 'long long', 'unsigned long long', 'size_t']
+if os.name != 'nt':
+ TYPES.append('mode_t')
+ TYPES.append('pid_t')
def setup():
""" creates necessary c-level types
"""
- from pypy.rpython.lltypesystem.rfficache import platform
- for name, bits in platform.items():
+ for name in TYPES:
+ c_name = name
if name.startswith('unsigned'):
name = 'u' + name[9:]
signed = False
else:
signed = (name != 'size_t')
name = name.replace(' ', '')
- llname = name.upper()
- inttype = rarithmetic.build_int('r_' + name, signed, bits)
- NUMBERTYPE = lltype.build_number(llname, inttype)
- globals()['r_' + name] = inttype
- globals()[llname] = NUMBERTYPE
- numbertype_to_rclass[NUMBERTYPE] = inttype
+ tp = platform.inttype(name.upper(), c_name, signed)
+ globals()['r_' + name] = platform.numbertype_to_rclass[tp]
+ globals()[name.upper()] = tp
setup()
-numbertype_to_rclass[lltype.Signed] = int # avoid "r_long" for common cases
+platform.numbertype_to_rclass[lltype.Signed] = int # avoid "r_long" for common cases
# ^^^ this creates at least the following names:
# --------------------------------------------------------------------
# Type RPython integer class doing wrap-around
Modified: pypy/dist/pypy/rpython/lltypesystem/rfficache.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rfficache.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rfficache.py Tue Jul 24 13:42:16 2007
@@ -7,8 +7,10 @@
import os
from pypy.translator.tool.cbuild import build_executable
from pypy.tool.udir import udir
+from pypy.rlib import rarithmetic
+from pypy.rpython.lltypesystem import lltype
-def sizeof_c_type(c_typename, includes={}, compiler_exe=None):
+def ask_gcc(question, includes={}, add_source="", compiler_exe=None):
from py.compat.subprocess import PIPE, Popen
includes['stdio.h'] = True
includes['sys' + os.path.sep + 'types.h'] = True
@@ -17,57 +19,110 @@
// includes
%s
+ %s
+
// checking code
int main(void)
{
- printf("%%d\\n", sizeof(%s));
+ %s
return (0);
}
- ''' % (include_string, c_typename))
- c_file = udir.join("typetest.c")
+ ''' % (include_string, add_source, str(question)))
+ c_file = udir.join("gcctest.c")
c_file.write(c_source)
c_exec = build_executable([str(c_file)], compiler_exe=compiler_exe)
pipe = Popen(c_exec, stdout=PIPE)
pipe.wait()
- return int(pipe.stdout.read()) * 8
-
-# XXX add float types as well here
+ return pipe.stdout.read()
-TYPES = []
-for _name in 'short int long'.split():
- for name in (_name, 'unsigned ' + _name):
- TYPES.append(name)
-TYPES += ['signed char', 'unsigned char',
- 'long long', 'unsigned long long', 'size_t']
-if os.name != 'nt':
- TYPES.append('mode_t')
- TYPES.append('pid_t')
-
-def get_type_sizes(filename, compiler_exe=None):
- try:
- mod = {}
- exec py.path.local(filename).read() in mod
- types = mod['types']
- except (ImportError, py.error.ENOENT):
- types = {}
- try:
- if py.builtin.sorted(types.keys()) != py.builtin.sorted(TYPES):
- # invalidate file
- types = {}
- raise KeyError
- return types
- except KeyError:
- types = dict([(i, sizeof_c_type(i, compiler_exe=compiler_exe))
- for i in TYPES])
- py.path.local(filename).write('types = ' +
- repr(types) + "\n")
- return types
+def sizeof_c_type(c_typename, **kwds):
+ question = 'printf("%%d", sizeof(%s));' % (c_typename,);
+ return int(ask_gcc(question, **kwds)) * 8
+
+def c_ifdefined(c_def, **kwds):
+ question = py.code.Source("""
+ #ifdef %s
+ printf("0");
+ #endif
+ """ % (c_def,))
+ return ask_gcc(question, **kwds) == '0'
+
+def c_defined_int(c_def, **kwds):
+ question = 'printf("%%d", %s);' % (c_def,)
+ return int(ask_gcc(question, **kwds))
+
+class RffiCache(object):
+ """ Class holding all of the c-level caches, eventually loaded from
+ the file, like #ifdefs, typesizes, int-level #defines
+ """
+ def __init__(self, filename):
+ self.filename = filename
+ self.numbertype_to_rclass = {}
+ self.types = {}
+ try:
+ mod = {}
+ exec py.path.local(filename).read() in mod
+ self.cache = mod['cache']
+ self.type_names = mod['type_names']
+ self._build_types()
+ except (py.error.ENOENT, KeyError):
+ self.cache = {}
+ self.type_names = {}
+
+ def _build_types(self):
+ for name, (c_name, signed) in self.type_names.items():
+ bits = self.cache[c_name]
+ inttype = rarithmetic.build_int('r_' + name, signed, bits)
+ tp = lltype.build_number(name, inttype)
+ self.numbertype_to_rclass[tp] = inttype
+ self.types[name] = tp
+
+ def inttype(self, name, c_name, signed, **kwds):
+ # XXX sign should be inferred somehow automatically
+ try:
+ return self.types[name]
+ except KeyError:
+ bits = sizeof_c_type(c_name, **kwds)
+ inttype = rarithmetic.build_int('r_' + name, signed, bits)
+ self.cache[c_name] = bits
+ self.type_names[name] = (c_name, signed)
+ tp = lltype.build_number(name, inttype)
+ self.numbertype_to_rclass[tp] = inttype
+ self.types[name] = tp
+ self._store_cache()
+ return tp
+
+ def defined(self, name, **kwds):
+ try:
+ return self.cache[name]
+ except KeyError:
+ res = c_ifdefined(name, **kwds)
+ self.cache[name] = res
+ self._store_cache()
+ return res
+
+ def intdefined(self, name, **kwds):
+ try:
+ return self.cache[name]
+ except KeyError:
+ res = c_defined_int(name, **kwds)
+ self.cache[name] = res
+ self._store_cache()
+ return res
+
+ # optimal way of caching it, would be to store file on __del__,
+ # but since we cannot rely on __del__ having all modules, let's
+ # do it after each change :-(
+ def _store_cache(self):
+ types = 'type_names = ' + repr(self.type_names) + '\n'
+ py.path.local(self.filename).write('cache = ' + repr(self.cache)
+ + '\n' + types)
import pypy
import py
py.path.local(pypy.__file__).new(basename='_cache').ensure(dir=1)
from pypy.tool import autopath
CACHE = py.magic.autopath()/'..'/'..'/'..'/'_cache'/'stdtypes.py'
-platform = get_type_sizes(CACHE)
+platform = RffiCache(CACHE)
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rfficache.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rfficache.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rfficache.py Tue Jul 24 13:42:16 2007
@@ -7,18 +7,30 @@
sizeofchar = sizeof_c_type('char')
assert sizeofchar == 8
-def test_gettypesizes():
- tmpfile = udir.join("somecrappyfile.py")
- assert get_type_sizes(tmpfile)['signed char'] == 8
- # this should not invoke a compiler
- res = get_type_sizes(tmpfile, compiler_exe='xxx')
- assert res['unsigned char'] == 8
+def test_c_ifdefined():
+ assert c_ifdefined('X', add_source='#define X')
+ assert not c_ifdefined('X')
+
+def test_c_defined_int():
+ assert c_defined_int('X', add_source='#define X 3') == 3
+
+def test_rfficache():
+ cache = RffiCache(udir.join('cache.py'))
+ assert cache.inttype('uchar', 'unsigned char', False)._type.BITS == 8
+ assert cache.inttype('uchar', 'unsigned char', False, compiler_exe='xxx')._type.BITS == 8
+ assert cache.defined('STUFF', add_source='#define STUFF')
+ assert cache.defined('STUFF')
+ assert cache.intdefined('STUFFI', add_source='#define STUFFI 3') == 3
+ assert cache.intdefined('STUFFI') == 3
+ cache = RffiCache(udir.join('cache.py'))
+ assert cache.intdefined('STUFFI') == 3
+ assert cache.defined('STUFF')
+ assert cache.inttype('uchar', 'unsigned char', False, compiler_exe='xxx')._type.BITS == 8
def test_types_present():
- for name in TYPES:
+ for name in rffi.TYPES:
if name.startswith('unsigned'):
name = 'u' + name[9:]
name = name.replace(' ', '')
assert hasattr(rffi, 'r_' + name)
assert hasattr(rffi, name.upper())
-
More information about the Pypy-commit
mailing list