[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