Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r77702:544126f967ce
Date: 2015-05-30 13:29 +0200
http://bitbucket.org/pypy/pypy/changeset/544126f967ce/

Log:    import cffi/83a960dee7ad

diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -208,12 +208,10 @@
 #define _cffi_array_len(array)   (sizeof(array) / sizeof((array)[0]))
 
 #define _cffi_prim_int(size, sign)                                      \
-    ((size) == sizeof(int) ? ((sign) ? _CFFI_PRIM_INT   : _CFFI_PRIM_UINT)   : 
\
-     (size) == sizeof(long)? ((sign) ? _CFFI_PRIM_LONG  : _CFFI_PRIM_ULONG)  : 
\
-     (size) == 1           ? ((sign) ? _CFFI_PRIM_INT8  : _CFFI_PRIM_UINT8)  : 
\
-     (size) == 2           ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : 
\
-     (size) == 4           ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : 
\
-     (size) == 8           ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : 
\
+    ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8  : _CFFI_PRIM_UINT8)  :    \
+     (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) :    \
+     (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) :    \
+     (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) :    \
      0)
 
 #define _cffi_check_int(got, got_nonpos, expected)      \
diff --git a/lib_pypy/cffi/cffi_opcode.py b/lib_pypy/cffi/cffi_opcode.py
--- a/lib_pypy/cffi/cffi_opcode.py
+++ b/lib_pypy/cffi/cffi_opcode.py
@@ -9,7 +9,7 @@
             assert isinstance(self.arg, str)
             return '(_cffi_opcode_t)(%s)' % (self.arg,)
         classname = CLASS_NAME[self.op]
-        return '_CFFI_OP(_CFFI_OP_%s, %d)' % (classname, self.arg)
+        return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg)
 
     def as_python_bytes(self):
         if self.op is None:
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -189,8 +189,8 @@
                         raise api.CDefError("typedef does not declare any 
name",
                                             decl)
                     if (isinstance(decl.type.type, 
pycparser.c_ast.IdentifierType)
-                            and decl.type.type.names == ['__dotdotdot__']):
-                        realtype = model.unknown_type(decl.name)
+                            and decl.type.type.names[-1] == '__dotdotdot__'):
+                        realtype = self._get_unknown_type(decl)
                     elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
                           isinstance(decl.type.type, pycparser.c_ast.TypeDecl) 
and
                           isinstance(decl.type.type.type,
@@ -271,14 +271,12 @@
                 if tp.is_raw_function:
                     tp = self._get_type_pointer(tp)
                     self._declare('function ' + decl.name, tp)
-                elif (isinstance(tp, model.PrimitiveType) and
-                        tp.is_integer_type() and
+                elif (tp.is_integer_type() and
                         hasattr(decl, 'init') and
                         hasattr(decl.init, 'value') and
                         _r_int_literal.match(decl.init.value)):
                     self._add_integer_constant(decl.name, decl.init.value)
-                elif (isinstance(tp, model.PrimitiveType) and
-                        tp.is_integer_type() and
+                elif (tp.is_integer_type() and
                         isinstance(decl.init, pycparser.c_ast.UnaryOp) and
                         decl.init.op == '-' and
                         hasattr(decl.init.expr, 'value') and
@@ -338,7 +336,9 @@
             else:
                 length = self._parse_constant(
                     typenode.dim, partial_length_ok=partial_length_ok)
-            return model.ArrayType(self._get_type(typenode.type), length)
+            tp = self._get_type(typenode.type,
+                                partial_length_ok=(length == '...'))
+            return model.ArrayType(tp, length)
         #
         if isinstance(typenode, pycparser.c_ast.PtrDecl):
             # pointer type
@@ -639,3 +639,13 @@
                 self._declare(name, tp, included=True)
         for k, v in other._int_constants.items():
             self._add_constants(k, v)
+
+    def _get_unknown_type(self, decl):
+        typenames = decl.type.type.names
+        assert typenames[-1] == '__dotdotdot__'
+        if len(typenames) == 1:
+            return model.unknown_type(decl.name)
+        for t in typenames[:-1]:
+            if t not in ['int', 'short', 'long', 'signed', 'unsigned', 'char']:
+                raise api.FFIError(':%d: bad usage of "..."' % decl.coord.line)
+        return model.UnknownIntegerType(decl.name)
diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py
--- a/lib_pypy/cffi/model.py
+++ b/lib_pypy/cffi/model.py
@@ -31,7 +31,10 @@
 
     def has_c_name(self):
         return '$' not in self._get_c_name()
-    
+
+    def is_integer_type(self):
+        return False
+
     def sizeof_enabled(self):
         return False
 
@@ -76,7 +79,12 @@
 void_type = VoidType()
 
 
-class PrimitiveType(BaseType):
+class BasePrimitiveType(BaseType):
+    def sizeof_enabled(self):
+        return True
+
+
+class PrimitiveType(BasePrimitiveType):
     _attrs_ = ('name',)
 
     ALL_PRIMITIVE_TYPES = {
@@ -142,11 +150,23 @@
     def is_float_type(self):
         return self.ALL_PRIMITIVE_TYPES[self.name] == 'f'
 
-    def sizeof_enabled(self):
-        return True
+    def build_backend_type(self, ffi, finishlist):
+        return global_cache(self, ffi, 'new_primitive_type', self.name)
+
+
+class UnknownIntegerType(BasePrimitiveType):
+    _attrs_ = ('name',)
+
+    def __init__(self, name):
+        self.name = name
+        self.c_name_with_marker = name + '&'
+
+    def is_integer_type(self):
+        return True    # for now
 
     def build_backend_type(self, ffi, finishlist):
-        return global_cache(self, ffi, 'new_primitive_type', self.name)
+        raise NotImplementedError("integer type '%s' can only be used after "
+                                  "compilation" % self.name)
 
 
 class BaseFunctionType(BaseType):
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -144,7 +144,7 @@
                 self.cffi_types.append(tp)     # placeholder
                 for tp1 in tp.args:
                     assert isinstance(tp1, (model.VoidType,
-                                            model.PrimitiveType,
+                                            model.BasePrimitiveType,
                                             model.PointerType,
                                             model.StructOrUnionOrEnum,
                                             model.FunctionPtrType))
@@ -469,7 +469,7 @@
 
     def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
         extraarg = ''
-        if isinstance(tp, model.PrimitiveType):
+        if isinstance(tp, model.BasePrimitiveType):
             if tp.is_integer_type() and tp.name != '_Bool':
                 converter = '_cffi_to_c_int'
                 extraarg = ', %s' % tp.name
@@ -524,7 +524,7 @@
         self._prnt('  }')
 
     def _convert_expr_from_c(self, tp, var, context):
-        if isinstance(tp, model.PrimitiveType):
+        if isinstance(tp, model.BasePrimitiveType):
             if tp.is_integer_type():
                 return '_cffi_from_c_int(%s, %s)' % (var, tp.name)
             elif tp.name != 'long double':
@@ -753,7 +753,9 @@
             ptr_struct_name = tp_struct.get_c_name('*')
             actual_length = '_cffi_array_len(((%s)0)->%s)' % (
                 ptr_struct_name, field_name)
-            tp_field = tp_field.resolve_length(actual_length)
+            tp_item = self._field_type(tp_struct, '%s[0]' % field_name,
+                                       tp_field.item)
+            tp_field = model.ArrayType(tp_item, actual_length)
         return tp_field
 
     def _struct_collecttype(self, tp):
@@ -771,20 +773,19 @@
         prnt('  (void)p;')
         for fname, ftype, fbitsize in tp.enumfields():
             try:
-                if (isinstance(ftype, model.PrimitiveType)
-                    and ftype.is_integer_type()) or fbitsize >= 0:
+                if ftype.is_integer_type() or fbitsize >= 0:
                     # accept all integers, but complain on float or double
                     prnt('  (void)((p->%s) << 1);' % fname)
-                elif (isinstance(ftype, model.ArrayType)
-                      and (ftype.length is None or ftype.length == '...')):
-                    # for C++: "int(*)tmp[] = &p->a;" errors out if p->a is
-                    # declared as "int[5]".  Instead, write "int *tmp = p->a;".
-                    prnt('  { %s = p->%s; (void)tmp; }' % (
-                        ftype.item.get_c_name('*tmp', 'field %r'%fname), 
fname))
-                else:
-                    # only accept exactly the type declared.
-                    prnt('  { %s = &p->%s; (void)tmp; }' % (
-                        ftype.get_c_name('*tmp', 'field %r'%fname), fname))
+                    continue
+                # only accept exactly the type declared, except that '[]'
+                # is interpreted as a '*' and so will match any array length.
+                # (It would also match '*', but that's harder to detect...)
+                while (isinstance(ftype, model.ArrayType)
+                       and (ftype.length is None or ftype.length == '...')):
+                    ftype = ftype.item
+                    fname = fname + '[0]'
+                prnt('  { %s = &p->%s; (void)tmp; }' % (
+                    ftype.get_c_name('*tmp', 'field %r'%fname), fname))
             except ffiplatform.VerificationError as e:
                 prnt('  /* %s */' % str(e))   # cannot verify it, ignore
         prnt('}')
@@ -965,17 +966,16 @@
         prnt()
 
     def _generate_cpy_constant_collecttype(self, tp, name):
-        is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
+        is_int = tp.is_integer_type()
         if not is_int or self.target_is_python:
             self._do_collect_type(tp)
 
     def _generate_cpy_constant_decl(self, tp, name):
-        is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
+        is_int = tp.is_integer_type()
         self._generate_cpy_const(is_int, name, tp)
 
     def _generate_cpy_constant_ctx(self, tp, name):
-        if (not self.target_is_python and
-                isinstance(tp, model.PrimitiveType) and tp.is_integer_type()):
+        if not self.target_is_python and tp.is_integer_type():
             type_op = CffiOp(OP_CONSTANT_INT, -1)
         else:
             if not tp.sizeof_enabled():
@@ -1056,7 +1056,8 @@
     def _global_type(self, tp, global_name):
         if isinstance(tp, model.ArrayType) and tp.length == '...':
             actual_length = '_cffi_array_len(%s)' % (global_name,)
-            tp = tp.resolve_length(actual_length)
+            tp_item = self._global_type(tp.item, '%s[0]' % global_name)
+            tp = model.ArrayType(tp_item, actual_length)
         return tp
 
     def _generate_cpy_variable_collecttype(self, tp, name):
@@ -1086,6 +1087,10 @@
         prim_index = PRIMITIVE_TO_INDEX[tp.name]
         self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index)
 
+    def _emit_bytecode_UnknownIntegerType(self, tp, index):
+        s = '_cffi_prim_int(sizeof(%s), ((%s)-1) <= 0)' % (tp.name, tp.name)
+        self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s)
+
     def _emit_bytecode_RawFunctionType(self, tp, index):
         self.cffi_types[index] = CffiOp(OP_FUNCTION, 
self._typesdict[tp.result])
         index += 1
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py 
b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -883,3 +883,73 @@
         """)
         assert lib.getx(lib.myglob) == 42.5
         assert lib.getx(lib.increment(lib.myglob)) == 43.5
+
+    def test_struct_array_guess_length_2(self):
+        ffi, lib = self.prepare(
+            "struct foo_s { int a[...][...]; };",
+            'test_struct_array_guess_length_2',
+            "struct foo_s { int x; int a[5][8]; int y; };")
+        assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int')
+        s = ffi.new("struct foo_s *")
+        assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int')
+        assert s.a[4][7] == 0
+        raises(IndexError, 's.a[4][8]')
+        raises(IndexError, 's.a[5][0]')
+        assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
+        assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]")
+
+    def test_global_var_array_2(self):
+        ffi, lib = self.prepare(
+            "int a[...][...];",
+            'test_global_var_array_2',
+            'int a[10][8];')
+        lib.a[9][7] = 123456
+        assert lib.a[9][7] == 123456
+        raises(IndexError, 'lib.a[0][8]')
+        raises(IndexError, 'lib.a[10][0]')
+        assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
+        assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
+
+    def test_some_integer_type(self):
+        ffi, lib = self.prepare("""
+            typedef int... foo_t;
+            typedef unsigned long... bar_t;
+            typedef struct { foo_t a, b; } mystruct_t;
+            foo_t foobar(bar_t, mystruct_t);
+            static const bar_t mu = -20;
+            static const foo_t nu = 20;
+        """, 'test_some_integer_type', """
+            typedef unsigned long long foo_t;
+            typedef short bar_t;
+            typedef struct { foo_t a, b; } mystruct_t;
+            static foo_t foobar(bar_t x, mystruct_t s) {
+                return (foo_t)x + s.a + s.b;
+            }
+            static const bar_t mu = -20;
+            static const foo_t nu = 20;
+        """)
+        assert ffi.sizeof("foo_t") == ffi.sizeof("unsigned long long")
+        assert ffi.sizeof("bar_t") == ffi.sizeof("short")
+        maxulonglong = 2 ** 64 - 1
+        assert int(ffi.cast("foo_t", -1)) == maxulonglong
+        assert int(ffi.cast("bar_t", -1)) == -1
+        assert lib.foobar(-1, [0, 0]) == maxulonglong
+        assert lib.foobar(2 ** 15 - 1, [0, 0]) == 2 ** 15 - 1
+        assert lib.foobar(10, [20, 31]) == 61
+        assert lib.foobar(0, [0, maxulonglong]) == maxulonglong
+        raises(OverflowError, lib.foobar, 2 ** 15, [0, 0])
+        raises(OverflowError, lib.foobar, -(2 ** 15) - 1, [0, 0])
+        raises(OverflowError, ffi.new, "mystruct_t *", [0, -1])
+        assert lib.mu == -20
+        assert lib.nu == 20
+
+    def test_issue200(self):
+        ffi, lib = self.prepare("""
+            typedef void (function_t)(void*);
+            void function(void *);
+        """, 'test_issue200', """
+            static void function(void *p) { (void)p; }
+        """)
+        ffi.typeof('function_t*')
+        lib.function(ffi.NULL)
+        # assert did not crash
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
@@ -209,3 +209,18 @@
     _globals = (b'\x00\x00\x00\x21myglob',0,),
 )
 """
+
+def test_bitfield():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { int y:10; short x:5; };")
+    target = udir.join('test_bitfield.py')
+    make_py_source(ffi, 'test_bitfield', str(target))
+    assert target.read() == r"""# auto-generated file
+import _cffi_backend
+
+ffi = _cffi_backend.FFI('test_bitfield',
+    _version = 0x2601,
+    _types = b'\x00\x00\x07\x01\x00\x00\x05\x01\x00\x00\x00\x09',
+    _struct_unions = 
((b'\x00\x00\x00\x02\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x13\x00\x00\x00\x0Ay',b'\x00\x00\x01\x13\x00\x00\x00\x05x'),),
+)
+"""
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -1,6 +1,6 @@
 # Generated by pypy/tool/import_cffi.py
 import sys, os, py
-from cffi import FFI, VerificationError
+from cffi import FFI, FFIError, VerificationError
 from cffi import recompiler
 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
 from pypy.module.test_lib_pypy.cffi_tests.support import u
@@ -908,3 +908,90 @@
     """)
     assert lib.getx(lib.myglob) == 42.5
     assert lib.getx(lib.increment(lib.myglob)) == 43.5
+
+def test_struct_array_guess_length_2():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { int a[...][...]; };")
+    lib = verify(ffi, 'test_struct_array_guess_length_2',
+                 "struct foo_s { int x; int a[5][8]; int y; };")
+    assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int')
+    s = ffi.new("struct foo_s *")
+    assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int')
+    assert s.a[4][7] == 0
+    py.test.raises(IndexError, 's.a[4][8]')
+    py.test.raises(IndexError, 's.a[5][0]')
+    assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
+    assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]")
+
+def test_global_var_array_2():
+    ffi = FFI()
+    ffi.cdef("int a[...][...];")
+    lib = verify(ffi, 'test_global_var_array_2', 'int a[10][8];')
+    lib.a[9][7] = 123456
+    assert lib.a[9][7] == 123456
+    py.test.raises(IndexError, 'lib.a[0][8]')
+    py.test.raises(IndexError, 'lib.a[10][0]')
+    assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
+    assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
+
+def test_some_integer_type():
+    ffi = FFI()
+    ffi.cdef("""
+        typedef int... foo_t;
+        typedef unsigned long... bar_t;
+        typedef struct { foo_t a, b; } mystruct_t;
+        foo_t foobar(bar_t, mystruct_t);
+        static const bar_t mu = -20;
+        static const foo_t nu = 20;
+    """)
+    lib = verify(ffi, 'test_some_integer_type', """
+        typedef unsigned long long foo_t;
+        typedef short bar_t;
+        typedef struct { foo_t a, b; } mystruct_t;
+        static foo_t foobar(bar_t x, mystruct_t s) {
+            return (foo_t)x + s.a + s.b;
+        }
+        static const bar_t mu = -20;
+        static const foo_t nu = 20;
+    """)
+    assert ffi.sizeof("foo_t") == ffi.sizeof("unsigned long long")
+    assert ffi.sizeof("bar_t") == ffi.sizeof("short")
+    maxulonglong = 2 ** 64 - 1
+    assert int(ffi.cast("foo_t", -1)) == maxulonglong
+    assert int(ffi.cast("bar_t", -1)) == -1
+    assert lib.foobar(-1, [0, 0]) == maxulonglong
+    assert lib.foobar(2 ** 15 - 1, [0, 0]) == 2 ** 15 - 1
+    assert lib.foobar(10, [20, 31]) == 61
+    assert lib.foobar(0, [0, maxulonglong]) == maxulonglong
+    py.test.raises(OverflowError, lib.foobar, 2 ** 15, [0, 0])
+    py.test.raises(OverflowError, lib.foobar, -(2 ** 15) - 1, [0, 0])
+    py.test.raises(OverflowError, ffi.new, "mystruct_t *", [0, -1])
+    assert lib.mu == -20
+    assert lib.nu == 20
+
+def test_unsupported_some_void_type():
+    ffi = FFI()
+    py.test.raises(FFIError, ffi.cdef, """typedef void... foo_t;""")
+
+def test_some_float_type():
+    py.test.skip("later")
+    ffi = FFI()
+    ffi.cdef("typedef double... foo_t; foo_t sum(foo_t[]);")
+    lib = verify(ffi, 'test_some_float_type', """
+        typedef float foo_t;
+        static foo_t sum(foo_t x[]) { return x[0] + x[1]; }
+    """)
+    assert lib.sum([40.0, 2.25]) == 42.25
+
+def test_issue200():
+    ffi = FFI()
+    ffi.cdef("""
+        typedef void (function_t)(void*);
+        void function(void *);
+    """)
+    lib = verify(ffi, 'test_issue200', """
+        static void function(void *p) { (void)p; }
+    """)
+    ffi.typeof('function_t*')
+    lib.function(ffi.NULL)
+    # assert did not crash
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
@@ -2206,3 +2206,27 @@
     e = py.test.raises(ffi.error, "lib.FOO")
     assert str(e.value) == ("the C compiler says 'FOO' is equal to 124 (0x7c),"
                             " but the cdef disagrees")
+
+def test_some_integer_type_for_issue73():
+    ffi = FFI()
+    ffi.cdef("""
+        typedef int... AnIntegerWith32Bits;
+        typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
+        AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger);
+    """)
+    lib = ffi.verify("""
+        #ifdef __LP64__
+        typedef int AnIntegerWith32Bits;
+        #else
+        typedef long AnIntegerWith32Bits;
+        #endif
+        typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
+        AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger f) {
+            return f();
+        }
+    """)
+    @ffi.callback("AFunctionReturningInteger")
+    def add():
+        return 3 + 4
+    x = lib.InvokeFunction(add)
+    assert x == 7
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to