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