[pypy-commit] pypy win32-stdlib: merge from default

mattip noreply at buildbot.pypy.org
Sat May 19 21:48:37 CEST 2012


Author: Matti Picus <matti.picus at gmail.com>
Branch: win32-stdlib
Changeset: r55140:98154d21fea4
Date: 2012-05-17 21:44 +0300
http://bitbucket.org/pypy/pypy/changeset/98154d21fea4/

Log:	merge from default

diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py
--- a/pypy/annotation/builtin.py
+++ b/pypy/annotation/builtin.py
@@ -298,6 +298,9 @@
 def rarith_intmask(s_obj):
     return SomeInteger()
 
+def rarith_longlongmask(s_obj):
+    return SomeInteger(knowntype=pypy.rlib.rarithmetic.r_longlong)
+
 def robjmodel_instantiate(s_clspbc):
     assert isinstance(s_clspbc, SomePBC)
     clsdef = None
@@ -376,6 +379,7 @@
         BUILTIN_ANALYZERS[original] = value
 
 BUILTIN_ANALYZERS[pypy.rlib.rarithmetic.intmask] = rarith_intmask
+BUILTIN_ANALYZERS[pypy.rlib.rarithmetic.longlongmask] = rarith_longlongmask
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.instantiate] = robjmodel_instantiate
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.r_dict] = robjmodel_r_dict
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.hlinvoke] = robjmodel_hlinvoke
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -3756,6 +3756,18 @@
         s = a.build_types(main, [int])
         assert isinstance(s, annmodel.SomeInteger)
 
+    def test_join_none_and_nonnull(self):
+        from pypy.rlib.rstring import assert_str0
+        
+        def f(i):
+            a = str(i)
+            a = assert_str0(a)
+            return a.join([None])
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert isinstance(s, annmodel.SomeString)
+        assert not s.can_be_None
 
 def g(n):
     return [0,1,2,n]
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -493,7 +493,7 @@
             return SomeImpossibleValue()
         getbookkeeper().count("str_join", str)
         s_item = s_list.listdef.read_item()
-        if isinstance(s_item, SomeImpossibleValue):
+        if s_None.contains(s_item):
             if isinstance(str, SomeUnicodeString):
                 return immutablevalue(u"")
             return immutablevalue("")
diff --git a/pypy/doc/test/test_whatsnew.py b/pypy/doc/test/test_whatsnew.py
new file mode 100644
--- /dev/null
+++ b/pypy/doc/test/test_whatsnew.py
@@ -0,0 +1,80 @@
+import py
+import pypy
+from commands import getoutput
+ROOT = py.path.local(pypy.__file__).dirpath().dirpath()
+
+
+def parse_doc(s):
+    startrev = None
+    branches = set()
+    def parseline(line):
+        _, value = line.split(':', 1)
+        return value.strip()
+    #
+    for line in s.splitlines():
+        if line.startswith('.. startrev:'):
+            startrev = parseline(line)
+        elif line.startswith('.. branch:'):
+            branches.add(parseline(line))
+    return startrev, branches
+
+def get_merged_branches(path, startrev, endrev):
+    # X = take all the merges which are descendants of startrev and are on default
+    # revset = all the parents of X which are not on default
+    # ===>
+    # revset contains all the branches which have been merged to default since
+    # startrev
+    revset = 'parents(%s::%s and \
+                      merge() and \
+                      branch(default)) and \
+              not branch(default)' % (startrev, endrev)
+    cmd = r"hg log -R '%s' -r '%s' --template '{branches}\n'" % (path, revset)
+    out = getoutput(cmd)
+    branches = set(map(str.strip, out.splitlines()))
+    return branches
+
+
+def test_parse_doc():
+    s = """
+=====
+Title
+=====
+
+.. startrev: 12345
+
+bla bla bla bla
+
+.. branch: foobar
+
+xxx yyy zzz
+
+.. branch: hello
+
+qqq www ttt
+"""
+    startrev, branches = parse_doc(s)
+    assert startrev == '12345'
+    assert branches == set(['foobar', 'hello'])
+
+def test_get_merged_branches():
+    branches = get_merged_branches(ROOT, 'f34f0c11299f', '79770e0c2f93')
+    assert branches == set(['numpy-indexing-by-arrays-bool',
+                            'better-jit-hooks-2',
+                            'numpypy-ufuncs'])
+
+def test_whatsnew():
+    doc = ROOT.join('pypy', 'doc')
+    whatsnew_list = doc.listdir('whatsnew-*.rst')
+    whatsnew_list.sort()
+    last_whatsnew = whatsnew_list[-1].read()
+    startrev, documented = parse_doc(last_whatsnew)
+    merged = get_merged_branches(ROOT, startrev, '')
+    not_documented = merged.difference(documented)
+    not_merged = documented.difference(merged)
+    print 'Branches merged but not documented:'
+    print '\n'.join(not_documented)
+    print
+    print 'Branches documented but not merged:'
+    print '\n'.join(not_merged)
+    print
+    assert not not_documented and not not_merged
diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-1.9.rst
@@ -0,0 +1,78 @@
+======================
+What's new in PyPy 1.9
+======================
+
+.. this is the revision just after the creation of the release-1.8.x branch
+.. startrev: a4261375b359
+
+.. branch: array_equal
+.. branch: better-jit-hooks-2
+.. branch: faster-heapcache
+.. branch: faster-str-decode-escape
+.. branch: float-bytes
+Added some primitives for dealing with floats as raw bytes.
+.. branch: float-bytes-2
+Added more float byte primitives.
+.. branch: jit-frame-counter
+Put more debug info into resops.
+.. branch: kill-geninterp
+.. branch: kqueue
+Finished select.kqueue.
+.. branch: kwargsdict-strategy
+.. branch: matrixmath-dot
+numpypy can now handle matrix multiplication.
+.. branch: merge-2.7.2
+The stdlib was updated to version 2.7.2
+.. branch: ndmin
+.. branch: newindex
+.. branch: non-null-threadstate
+cpyext: Better support for PyEval_SaveThread and other PyTreadState_*
+functions.
+.. branch: numppy-flatitter
+.. branch: numpy-back-to-applevel
+.. branch: numpy-concatenate
+.. branch: numpy-indexing-by-arrays-bool
+.. branch: numpy-record-dtypes
+.. branch: numpy-single-jitdriver
+.. branch: numpy-ufuncs2
+.. branch: numpy-ufuncs3
+.. branch: numpypy-issue1137
+.. branch: numpypy-out
+The "out" argument was added to most of the numypypy functions.
+.. branch: numpypy-shape-bug
+.. branch: numpypy-ufuncs
+.. branch: pytest
+.. branch: safe-getargs-freelist
+.. branch: set-strategies
+.. branch: speedup-list-comprehension
+.. branch: stdlib-unification
+The directory "lib-python/modified-2.7" has been removed, and its
+content merged into "lib-python/2.7".
+.. branch: step-one-xrange
+The common case of a xrange iterator with no step argument specifed
+was somewhat optimized. The tightest loop involving it,
+sum(xrange(n)), is now 18% faster on average.
+.. branch: string-NUL
+PyPy refuses filenames with chr(0) characters. This is implemented in
+RPython which can enforce no-NUL correctness and propagation, similar
+to const-correctness in C++.
+.. branch: win32-cleanup
+.. branch: win32-cleanup2
+.. branch: win32-cleanup_2
+Many bugs were corrected for windows 32 bit. New functionality was added to
+test validity of file descriptors, leading to the removal of the  global 
+_invalid_parameter_handler
+.. branch: win64-stage1
+.. branch: zlib-mem-pressure
+
+.. branch: ffistruct
+The ``ffistruct`` branch adds a very low level way to express C structures
+with _ffi in a very JIT-friendly way
+
+
+
+.. "uninteresting" branches that we should just ignore for the whatsnew:
+.. branch: exception-cannot-occur
+.. branch: sanitize-finally-stack
+.. branch: revive-dlltool
+     (preliminary work for sepcomp)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1450,7 +1450,7 @@
                                  self.wrap("expected a 32-bit integer"))
         return value
 
-    def truncatedint(self, w_obj):
+    def truncatedint_w(self, w_obj):
         # Like space.gateway_int_w(), but return the integer truncated
         # instead of raising OverflowError.  For obscure cases only.
         try:
@@ -1461,6 +1461,17 @@
             from pypy.rlib.rarithmetic import intmask
             return intmask(self.bigint_w(w_obj).uintmask())
 
+    def truncatedlonglong_w(self, w_obj):
+        # Like space.gateway_r_longlong_w(), but return the integer truncated
+        # instead of raising OverflowError.
+        try:
+            return self.r_longlong_w(w_obj)
+        except OperationError, e:
+            if not e.match(self, self.w_OverflowError):
+                raise
+            from pypy.rlib.rarithmetic import longlongmask
+            return longlongmask(self.bigint_w(w_obj).ulonglongmask())
+
     def c_filedescriptor_w(self, w_fd):
         # This is only used sometimes in CPython, e.g. for os.fsync() but
         # not os.close().  It's likely designed for 'select'.  It's irregular
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -145,7 +145,7 @@
     def visit_c_nonnegint(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
-    def visit_truncatedint(self, el, app_sig):
+    def visit_truncatedint_w(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
     def visit__Wrappable(self, el, app_sig):
@@ -268,8 +268,8 @@
     def visit_c_nonnegint(self, typ):
         self.run_args.append("space.c_nonnegint_w(%s)" % (self.scopenext(),))
 
-    def visit_truncatedint(self, typ):
-        self.run_args.append("space.truncatedint(%s)" % (self.scopenext(),))
+    def visit_truncatedint_w(self, typ):
+        self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
 
     def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
         try:
@@ -404,8 +404,8 @@
     def visit_c_nonnegint(self, typ):
         self.unwrap.append("space.c_nonnegint_w(%s)" % (self.nextarg(),))
 
-    def visit_truncatedint(self, typ):
-        self.unwrap.append("space.truncatedint(%s)" % (self.nextarg(),))
+    def visit_truncatedint_w(self, typ):
+        self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
 
     def make_fastfunc(unwrap_spec, func):
         unwrap_info = UnwrapSpec_FastFunc_Unwrap()
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -241,6 +241,37 @@
         w_obj = space.wrap(-12)
         space.raises_w(space.w_ValueError, space.r_ulonglong_w, w_obj)
 
+    def test_truncatedint_w(self):
+        space = self.space
+        assert space.truncatedint_w(space.wrap(42)) == 42
+        assert space.truncatedint_w(space.wrap(sys.maxint)) == sys.maxint
+        assert space.truncatedint_w(space.wrap(sys.maxint+1)) == -sys.maxint-1
+        assert space.truncatedint_w(space.wrap(-1)) == -1
+        assert space.truncatedint_w(space.wrap(-sys.maxint-2)) == sys.maxint
+
+    def test_truncatedlonglong_w(self):
+        space = self.space
+        w_value = space.wrap(12)
+        res = space.truncatedlonglong_w(w_value)
+        assert res == 12
+        assert type(res) is r_longlong
+        #
+        w_value = space.wrap(r_ulonglong(9223372036854775808))
+        res = space.truncatedlonglong_w(w_value)
+        assert res == -9223372036854775808
+        assert type(res) is r_longlong
+        #
+        w_value = space.wrap(r_ulonglong(18446744073709551615))
+        res = space.truncatedlonglong_w(w_value)
+        assert res == -1
+        assert type(res) is r_longlong
+        #
+        w_value = space.wrap(r_ulonglong(18446744073709551616))
+        res = space.truncatedlonglong_w(w_value)
+        assert res == 0
+        assert type(res) is r_longlong
+
+
     def test_call_obj_args(self):
         from pypy.interpreter.argument import Arguments
         
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -823,7 +823,9 @@
     op_getfield_gc_pure = op_getfield_gc
 
     def op_getfield_raw(self, fielddescr, struct):
-        if fielddescr.typeinfo == REF:
+        if fielddescr.arg_types == 'dynamic': # abuse of .arg_types
+            return do_getfield_raw_dynamic(struct, fielddescr)
+        elif fielddescr.typeinfo == REF:
             return do_getfield_raw_ptr(struct, fielddescr.ofs)
         elif fielddescr.typeinfo == INT:
             return do_getfield_raw_int(struct, fielddescr.ofs)
@@ -919,7 +921,9 @@
             raise NotImplementedError
 
     def op_setfield_raw(self, fielddescr, struct, newvalue):
-        if fielddescr.typeinfo == REF:
+        if fielddescr.arg_types == 'dynamic': # abuse of .arg_types
+            do_setfield_raw_dynamic(struct, fielddescr, newvalue)
+        elif fielddescr.typeinfo == REF:
             do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue)
         elif fielddescr.typeinfo == INT:
             do_setfield_raw_int(struct, fielddescr.ofs, newvalue)
@@ -1500,6 +1504,17 @@
 def do_getfield_raw_ptr(struct, fieldnum):
     return cast_to_ptr(_getfield_raw(struct, fieldnum))
 
+def do_getfield_raw_dynamic(struct, fielddescr):
+    from pypy.rlib import libffi
+    addr = cast_from_int(rffi.VOIDP, struct)
+    ofs = fielddescr.ofs
+    if fielddescr.is_pointer_field():
+        assert False, 'fixme'
+    elif fielddescr.is_float_field():
+        assert False, 'fixme'
+    else:
+        return libffi._struct_getfield(lltype.Signed, addr, ofs)
+
 def do_new(size):
     TYPE = symbolic.Size2Type[size]
     x = lltype.malloc(TYPE, zero=True)
@@ -1597,6 +1612,17 @@
     newvalue = cast_from_ptr(FIELDTYPE, newvalue)
     setattr(ptr, fieldname, newvalue)
 
+def do_setfield_raw_dynamic(struct, fielddescr, newvalue):
+    from pypy.rlib import libffi
+    addr = cast_from_int(rffi.VOIDP, struct)
+    ofs = fielddescr.ofs
+    if fielddescr.is_pointer_field():
+        assert False, 'fixme'
+    elif fielddescr.is_float_field():
+        assert False, 'fixme'
+    else:
+        libffi._struct_setfield(lltype.Signed, addr, ofs, newvalue)
+
 def do_newstr(length):
     x = rstr.mallocstr(length)
     return cast_to_ptr(x)
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -334,6 +334,16 @@
         token = history.getkind(getattr(S, fieldname))
         return self.getdescr(ofs, token[0], name=fieldname)
 
+    def fielddescrof_dynamic(self, offset, fieldsize, is_pointer, is_float, is_signed):
+        if is_pointer:
+            typeinfo = REF
+        elif is_float:
+            typeinfo = FLOAT
+        else:
+            typeinfo = INT
+        # we abuse the arg_types field to distinguish dynamic and static descrs
+        return self.getdescr(offset, typeinfo, arg_types='dynamic', name='<dynamic field>')
+
     def interiorfielddescrof(self, A, fieldname):
         S = A.OF
         width = symbolic.get_size(A)
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -237,18 +237,25 @@
         cache[(ARRAY, name)] = descr
         return descr
 
+def compute_flag(is_pointer, is_float, is_signed):
+    if is_pointer:
+        assert not is_float
+        return FLAG_POINTER
+    elif is_float:
+        return FLAG_FLOAT
+    elif is_signed:
+        return FLAG_SIGNED
+    else:
+        return FLAG_UNSIGNED
+
+def get_dynamic_field_descr(offset, fieldsize, is_pointer, is_float, is_signed):
+    flag = compute_flag(is_pointer, is_float, is_signed)
+    return FieldDescr('dynamic', offset, fieldsize, flag)
+
 def get_dynamic_interiorfield_descr(gc_ll_descr, offset, width, fieldsize,
                                     is_pointer, is_float, is_signed):
     arraydescr = ArrayDescr(0, width, None, FLAG_STRUCT)
-    if is_pointer:
-        assert not is_float
-        flag = FLAG_POINTER
-    elif is_float:
-        flag = FLAG_FLOAT
-    elif is_signed:
-        flag = FLAG_SIGNED
-    else:
-        flag = FLAG_UNSIGNED
+    flag = compute_flag(is_pointer, is_float, is_signed)
     fielddescr = FieldDescr('dynamic', offset, fieldsize, flag)
     return InteriorFieldDescr(arraydescr, fielddescr)
 
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -11,7 +11,7 @@
 from pypy.jit.backend.llsupport.descr import (
     get_size_descr, get_field_descr, get_array_descr,
     get_call_descr, get_interiorfield_descr, get_dynamic_interiorfield_descr,
-    FieldDescr, ArrayDescr, CallDescr, InteriorFieldDescr)
+    FieldDescr, ArrayDescr, CallDescr, InteriorFieldDescr, get_dynamic_field_descr)
 from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
 
 
@@ -245,6 +245,9 @@
     def fielddescrof(self, STRUCT, fieldname):
         return get_field_descr(self.gc_ll_descr, STRUCT, fieldname)
 
+    def fielddescrof_dynamic(self, offset, fieldsize, is_pointer, is_float, is_signed):
+        return get_dynamic_field_descr(offset, fieldsize, is_pointer, is_float, is_signed)
+
     def unpack_fielddescr(self, fielddescr):
         assert isinstance(fielddescr, FieldDescr)
         return fielddescr.offset
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1660,20 +1660,37 @@
         assert s.x == chr(190)
         assert s.y == chr(150)
 
-    def test_field_raw_pure(self):
-        # This is really testing the same thing as test_field_basic but can't
-        # hurt...
-        S = lltype.Struct('S', ('x', lltype.Signed))
+    def test_fielddescrof_dynamic(self):
+        S = lltype.Struct('S',
+                          ('x', lltype.Signed),
+                          ('y', lltype.Signed),
+                          )
+        longsize = rffi.sizeof(lltype.Signed)
+        y_ofs = longsize
         s = lltype.malloc(S, flavor='raw')
         sa = llmemory.cast_ptr_to_adr(s)
         s_box = BoxInt(heaptracker.adr2int(sa))
+        #
+        field = self.cpu.fielddescrof(S, 'y')
+        field_dyn = self.cpu.fielddescrof_dynamic(offset=y_ofs,
+                                                  fieldsize=longsize,
+                                                  is_pointer=False,
+                                                  is_float=False,
+                                                  is_signed=True)
+        assert field.is_pointer_field() == field_dyn.is_pointer_field()
+        assert field.is_float_field()   == field_dyn.is_float_field()
+        if 'llgraph' not in str(self.cpu):
+            assert field.is_field_signed()  == field_dyn.is_field_signed()
+
+        #
         for get_op, set_op in ((rop.GETFIELD_RAW, rop.SETFIELD_RAW),
                                (rop.GETFIELD_RAW_PURE, rop.SETFIELD_RAW)):
-            fd = self.cpu.fielddescrof(S, 'x')
-            self.execute_operation(set_op, [s_box, BoxInt(32)], 'void',
-                                   descr=fd)
-            res = self.execute_operation(get_op, [s_box], 'int', descr=fd)
-            assert res.getint()  == 32
+            for descr in (field, field_dyn):
+                self.execute_operation(set_op, [s_box, BoxInt(32)], 'void',
+                                       descr=descr)
+                res = self.execute_operation(get_op, [s_box], 'int', descr=descr)
+                assert res.getint()  == 32
+
         lltype.free(s, flavor='raw')
 
     def test_new_with_vtable(self):
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -48,8 +48,10 @@
     OS_LIBFFI_PREPARE           = 60
     OS_LIBFFI_PUSH_ARG          = 61
     OS_LIBFFI_CALL              = 62
-    OS_LIBFFI_GETARRAYITEM      = 63
-    OS_LIBFFI_SETARRAYITEM      = 64
+    OS_LIBFFI_STRUCT_GETFIELD   = 63
+    OS_LIBFFI_STRUCT_SETFIELD   = 64
+    OS_LIBFFI_GETARRAYITEM      = 65
+    OS_LIBFFI_SETARRAYITEM      = 66
     #
     OS_LLONG_INVERT             = 69
     OS_LLONG_ADD                = 70
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -1675,6 +1675,12 @@
         elif oopspec_name.startswith('libffi_call_'):
             oopspecindex = EffectInfo.OS_LIBFFI_CALL
             extraeffect = EffectInfo.EF_RANDOM_EFFECTS
+        elif oopspec_name == 'libffi_struct_getfield':
+            oopspecindex = EffectInfo.OS_LIBFFI_STRUCT_GETFIELD
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
+        elif oopspec_name == 'libffi_struct_setfield':
+            oopspecindex = EffectInfo.OS_LIBFFI_STRUCT_SETFIELD
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
         elif oopspec_name == 'libffi_array_getitem':
             oopspecindex = EffectInfo.OS_LIBFFI_GETARRAYITEM
             extraeffect = EffectInfo.EF_CANNOT_RAISE
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -456,7 +456,6 @@
 def _ll_3_libffi_call_void(llfunc, funcsym, ll_args):
     return func(llfunc)._do_call(funcsym, ll_args, lltype.Void)
 
-
 # in the following calls to builtins, the JIT is allowed to look inside:
 inline_calls_to = [
     ('int_floordiv_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -7,7 +7,9 @@
 from pypy.rlib.libffi import Func
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rpython.lltypesystem import llmemory, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.rarithmetic import intmask
 
 
 class FuncInfo(object):
@@ -118,6 +120,9 @@
             ops = self.do_push_arg(op)
         elif oopspec == EffectInfo.OS_LIBFFI_CALL:
             ops = self.do_call(op)
+        elif (oopspec == EffectInfo.OS_LIBFFI_STRUCT_GETFIELD or
+              oopspec == EffectInfo.OS_LIBFFI_STRUCT_SETFIELD):
+            ops = self.do_struct_getsetfield(op, oopspec)
         elif (oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM or
             oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM):
             ops = self.do_getsetarrayitem(op, oopspec)
@@ -195,6 +200,46 @@
         ops.append(newop)
         return ops
 
+    def do_struct_getsetfield(self, op, oopspec):
+        ffitypeval = self.getvalue(op.getarg(1))
+        addrval = self.getvalue(op.getarg(2))
+        offsetval = self.getvalue(op.getarg(3))
+        if not ffitypeval.is_constant() or not offsetval.is_constant():
+            return [op]
+        #
+        ffitypeaddr = ffitypeval.box.getaddr()
+        ffitype = llmemory.cast_adr_to_ptr(ffitypeaddr, clibffi.FFI_TYPE_P)
+        offset = offsetval.box.getint()
+        descr = self._get_field_descr(ffitype, offset)
+        #
+        arglist = [addrval.force_box(self.optimizer)]
+        if oopspec == EffectInfo.OS_LIBFFI_STRUCT_GETFIELD:
+            opnum = rop.GETFIELD_RAW
+        else:
+            opnum = rop.SETFIELD_RAW
+            newval = self.getvalue(op.getarg(4))
+            arglist.append(newval.force_box(self.optimizer))
+        #
+        newop = ResOperation(opnum, arglist, op.result, descr=descr)
+        return [newop]
+
+    def _get_field_descr(self, ffitype, offset):
+        kind = libffi.types.getkind(ffitype)
+        is_pointer = is_float = is_signed = False
+        if ffitype is libffi.types.pointer:
+            is_pointer = True
+        elif kind == 'i':
+            is_signed = True
+        elif kind == 'f' or kind == 'I' or kind == 'U':
+            # longlongs are treated as floats, see e.g. llsupport/descr.py:getDescrClass
+            is_float = True
+        else:
+            assert False, "unsupported ffitype or kind"
+        #
+        fieldsize = intmask(ffitype.c_size)
+        return self.optimizer.cpu.fielddescrof_dynamic(offset, fieldsize,
+                                                       is_pointer, is_float, is_signed)
+    
     def do_getsetarrayitem(self, op, oopspec):
         ffitypeval = self.getvalue(op.getarg(1))
         widthval = self.getvalue(op.getarg(2))
@@ -245,6 +290,7 @@
             offset, width, fieldsize, is_pointer, is_float, is_signed
         )
 
+
     def propagate_forward(self, op):
         if self.logops is not None:
             debug_print(self.logops.repr_of_resop(op))
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
@@ -56,6 +56,13 @@
                              restype=types.sint,
                              flags=43)
         #
+        ffi_slong = types.slong
+        dyn_123_field = cpu.fielddescrof_dynamic(offset=123,
+                                                 fieldsize=types.slong.c_size,
+                                                 is_pointer=False,
+                                                 is_float=False,
+                                                 is_signed=True)
+        #
         def calldescr(cpu, FUNC, oopspecindex, extraeffect=None):
             if extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
                 f = None   # means "can force all" really
@@ -69,6 +76,8 @@
         libffi_push_arg = calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_PUSH_ARG)
         libffi_call =     calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_CALL,
                                     EffectInfo.EF_RANDOM_EFFECTS)
+        libffi_struct_getfield = calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_STRUCT_GETFIELD)
+        libffi_struct_setfield = calldescr(cpu, FUNC, EffectInfo.OS_LIBFFI_STRUCT_SETFIELD)
     
     namespace = namespace.__dict__
 
@@ -277,3 +286,30 @@
         jump(i3, f1, p2)
         """
         loop = self.optimize_loop(ops, expected)
+
+    def test_ffi_struct_fields(self):
+        ops = """
+        [i0]
+        i1 = call(0, ConstClass(ffi_slong), i0, 123, descr=libffi_struct_getfield)
+        i2 = int_add(i1, 1)
+        call(0, ConstClass(ffi_slong), i0, 123, i2, descr=libffi_struct_setfield)
+        jump(i1)
+        """
+        expected = """
+        [i0]
+        i1 = getfield_raw(i0, descr=dyn_123_field)
+        i2 = int_add(i1, 1)
+        setfield_raw(i0, i2, descr=dyn_123_field)
+        jump(i1)
+        """
+        loop = self.optimize_loop(ops, expected)
+
+    def test_ffi_struct_fields_nonconst(self):
+        ops = """
+        [i0, i1]
+        i2 = call(0, ConstClass(ffi_slong), i0, i1,  descr=libffi_struct_getfield)
+        i3 = call(0, i1                   , i0, 123, descr=libffi_struct_getfield)
+        jump(i1)
+        """
+        expected = ops
+        loop = self.optimize_loop(ops, expected)
diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py
--- a/pypy/jit/metainterp/test/test_fficall.py
+++ b/pypy/jit/metainterp/test/test_fficall.py
@@ -4,7 +4,7 @@
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.rlib.jit import JitDriver, promote, dont_look_inside
 from pypy.rlib.libffi import (ArgChain, IS_32_BIT, array_getitem, array_setitem,
-    types)
+    types, struct_setfield_int, struct_getfield_int)
 from pypy.rlib.objectmodel import specialize
 from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
 from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
@@ -187,5 +187,24 @@
 class TestFfiCallSupportAll(FfiCallTests, LLJitMixin):
     supports_all = True     # supports_{floats,longlong,singlefloats}
 
+    def test_struct_getfield(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'addr'])
+
+        def f(n):
+            i = 0
+            addr = lltype.malloc(rffi.VOIDP.TO, 10, flavor='raw')
+            while i < n:
+                myjitdriver.jit_merge_point(n=n, i=i, addr=addr)
+                struct_setfield_int(types.slong, addr, 0, 1)
+                i += struct_getfield_int(types.slong, addr, 0)
+            lltype.free(addr, flavor='raw')
+            return i
+        assert self.meta_interp(f, [20]) == f(20)
+        self.check_resops(
+            setfield_raw=2,
+            getfield_raw=2,
+            call=0)
+
+
 class TestFfiLookup(FfiLookupTests, LLJitMixin):
     pass
diff --git a/pypy/module/_ffi/__init__.py b/pypy/module/_ffi/__init__.py
--- a/pypy/module/_ffi/__init__.py
+++ b/pypy/module/_ffi/__init__.py
@@ -1,13 +1,16 @@
 from pypy.interpreter.mixedmodule import MixedModule
-from pypy.module._ffi import interp_ffi
 
 class Module(MixedModule):
 
     interpleveldefs = {
-        'CDLL':    'interp_ffi.W_CDLL',
-        'types':   'interp_ffi.W_types',
-        'FuncPtr': 'interp_ffi.W_FuncPtr',
-        'get_libc':'interp_ffi.get_libc',
+        'types':   'interp_ffitype.W_types',
+        'CDLL':    'interp_funcptr.W_CDLL',
+        'FuncPtr': 'interp_funcptr.W_FuncPtr',
+        'get_libc':'interp_funcptr.get_libc',
+        '_StructDescr': 'interp_struct.W__StructDescr',
+        'Field':     'interp_struct.W_Field',
     }
 
-    appleveldefs = {}
+    appleveldefs = {
+        'Structure': 'app_struct.Structure',
+        }
diff --git a/pypy/module/_ffi/app_struct.py b/pypy/module/_ffi/app_struct.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/app_struct.py
@@ -0,0 +1,21 @@
+import _ffi
+
+class MetaStructure(type):
+
+    def __new__(cls, name, bases, dic):
+        cls._compute_shape(name, dic)
+        return type.__new__(cls, name, bases, dic)
+
+    @classmethod
+    def _compute_shape(cls, name, dic):
+        fields = dic.get('_fields_')
+        if fields is None:
+            return
+        struct_descr = _ffi._StructDescr(name, fields)
+        for field in fields:
+            dic[field.name] = field
+        dic['_struct_'] = struct_descr
+
+
+class Structure(object):
+    __metaclass__ = MetaStructure
diff --git a/pypy/module/_ffi/interp_ffitype.py b/pypy/module/_ffi/interp_ffitype.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/interp_ffitype.py
@@ -0,0 +1,181 @@
+from pypy.rlib import libffi, clibffi
+from pypy.rlib.rarithmetic import intmask
+from pypy.rlib import jit
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.error import OperationError
+
+class W_FFIType(Wrappable):
+
+    _immutable_fields_ = ['name', 'w_structdescr', 'w_pointer_to']
+
+    def __init__(self, name, ffitype, w_structdescr=None, w_pointer_to=None):
+        self.name = name
+        self._ffitype = clibffi.FFI_TYPE_NULL
+        self.w_structdescr = w_structdescr
+        self.w_pointer_to = w_pointer_to
+        self.set_ffitype(ffitype)
+
+    @jit.elidable
+    def get_ffitype(self):
+        if not self._ffitype:
+            raise ValueError("Operation not permitted on an incomplete type")
+        return self._ffitype
+
+    def set_ffitype(self, ffitype):
+        if self._ffitype:
+            raise ValueError("The _ffitype is already set")
+        self._ffitype = ffitype
+        if ffitype and self.is_struct():
+            assert self.w_structdescr is not None
+
+    def descr_deref_pointer(self, space):
+        if self.w_pointer_to is None:
+            return space.w_None
+        return self.w_pointer_to
+
+    def descr_sizeof(self, space):
+        try:
+            return space.wrap(self.sizeof())
+        except ValueError:
+            msg = "Operation not permitted on an incomplete type"
+            raise OperationError(space.w_ValueError, space.wrap(msg))
+
+    def sizeof(self):
+        return intmask(self.get_ffitype().c_size)
+
+    def get_alignment(self):
+        return intmask(self.get_ffitype().c_alignment)
+
+    def repr(self, space):
+        return space.wrap(self.__repr__())
+
+    def __repr__(self):
+        name = self.name
+        if not self._ffitype:
+            name += ' (incomplete)'
+        return "<ffi type %s>" % name
+
+    def is_signed(self):
+        return (self is app_types.slong or
+                self is app_types.sint or
+                self is app_types.sshort or
+                self is app_types.sbyte or
+                self is app_types.slonglong)
+
+    def is_unsigned(self):
+        return (self is app_types.ulong or
+                self is app_types.uint or
+                self is app_types.ushort or
+                self is app_types.ubyte or
+                self is app_types.ulonglong)
+
+    def is_pointer(self):
+        return self.get_ffitype() is libffi.types.pointer
+
+    def is_char(self):
+        return self is app_types.char
+
+    def is_unichar(self):
+        return self is app_types.unichar
+
+    def is_longlong(self):
+        return libffi.IS_32_BIT and (self is app_types.slonglong or
+                                     self is app_types.ulonglong)
+
+    def is_double(self):
+        return self is app_types.double
+
+    def is_singlefloat(self):
+        return self is app_types.float
+
+    def is_void(self):
+        return self is app_types.void
+
+    def is_struct(self):
+        return libffi.types.is_struct(self.get_ffitype())
+
+    def is_char_p(self):
+        return self is app_types.char_p
+
+    def is_unichar_p(self):
+        return self is app_types.unichar_p
+
+
+W_FFIType.typedef = TypeDef(
+    'FFIType',
+    name = interp_attrproperty('name', W_FFIType),
+    __repr__ = interp2app(W_FFIType.repr),
+    deref_pointer = interp2app(W_FFIType.descr_deref_pointer),
+    sizeof = interp2app(W_FFIType.descr_sizeof),
+    )
+
+
+def build_ffi_types():
+    types = [
+        # note: most of the type name directly come from the C equivalent,
+        # with the exception of bytes: in C, ubyte and char are equivalent,
+        # but for _ffi the first expects a number while the second a 1-length
+        # string
+        W_FFIType('slong',     libffi.types.slong),
+        W_FFIType('sint',      libffi.types.sint),
+        W_FFIType('sshort',    libffi.types.sshort),
+        W_FFIType('sbyte',     libffi.types.schar),
+        W_FFIType('slonglong', libffi.types.slonglong),
+        #
+        W_FFIType('ulong',     libffi.types.ulong),
+        W_FFIType('uint',      libffi.types.uint),
+        W_FFIType('ushort',    libffi.types.ushort),
+        W_FFIType('ubyte',     libffi.types.uchar),
+        W_FFIType('ulonglong', libffi.types.ulonglong),
+        #
+        W_FFIType('char',      libffi.types.uchar),
+        W_FFIType('unichar',   libffi.types.wchar_t),
+        #
+        W_FFIType('double',    libffi.types.double),
+        W_FFIType('float',     libffi.types.float),
+        W_FFIType('void',      libffi.types.void),
+        W_FFIType('void_p',    libffi.types.pointer),
+        #
+        # missing types:
+
+        ## 's' : ffi_type_pointer,
+        ## 'z' : ffi_type_pointer,
+        ## 'O' : ffi_type_pointer,
+        ## 'Z' : ffi_type_pointer,
+
+        ]
+    d = dict([(t.name, t) for t in types])
+    w_char = d['char']
+    w_unichar = d['unichar']
+    d['char_p'] = W_FFIType('char_p', libffi.types.pointer, w_pointer_to = w_char)
+    d['unichar_p'] = W_FFIType('unichar_p', libffi.types.pointer, w_pointer_to = w_unichar)
+    return d
+
+class app_types:
+    pass
+app_types.__dict__ = build_ffi_types()
+
+def descr_new_pointer(space, w_cls, w_pointer_to):
+    try:
+        return descr_new_pointer.cache[w_pointer_to]
+    except KeyError:
+        if w_pointer_to is app_types.char:
+            w_result = app_types.char_p
+        elif w_pointer_to is app_types.unichar:
+            w_result = app_types.unichar_p
+        else:
+            w_pointer_to = space.interp_w(W_FFIType, w_pointer_to)
+            name = '(pointer to %s)' % w_pointer_to.name
+            w_result = W_FFIType(name, libffi.types.pointer, w_pointer_to = w_pointer_to)
+        descr_new_pointer.cache[w_pointer_to] = w_result
+        return w_result
+descr_new_pointer.cache = {}
+
+class W_types(Wrappable):
+    pass
+W_types.typedef = TypeDef(
+    'types',
+    Pointer = interp2app(descr_new_pointer, as_classmethod=True),
+    **app_types.__dict__)
diff --git a/pypy/module/_ffi/interp_ffi.py b/pypy/module/_ffi/interp_funcptr.py
rename from pypy/module/_ffi/interp_ffi.py
rename to pypy/module/_ffi/interp_funcptr.py
--- a/pypy/module/_ffi/interp_ffi.py
+++ b/pypy/module/_ffi/interp_funcptr.py
@@ -3,7 +3,7 @@
     operationerrfmt
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
-from pypy.module._rawffi.structure import W_StructureInstance, W_Structure
+from pypy.module._ffi.interp_ffitype import W_FFIType
 #
 from pypy.rpython.lltypesystem import lltype, rffi
 #
@@ -12,165 +12,16 @@
 from pypy.rlib.rdynload import DLOpenError
 from pypy.rlib.rarithmetic import intmask, r_uint
 from pypy.rlib.objectmodel import we_are_translated
-
-class W_FFIType(Wrappable):
-
-    _immutable_fields_ = ['name', 'ffitype', 'w_datashape', 'w_pointer_to']
-
-    def __init__(self, name, ffitype, w_datashape=None, w_pointer_to=None):
-        self.name = name
-        self.ffitype = ffitype
-        self.w_datashape = w_datashape
-        self.w_pointer_to = w_pointer_to
-        if self.is_struct():
-            assert w_datashape is not None
-
-    def descr_deref_pointer(self, space):
-        if self.w_pointer_to is None:
-            return space.w_None
-        return self.w_pointer_to
-
-    def repr(self, space):
-        return space.wrap(self.__repr__())
-
-    def __repr__(self):
-        return "<ffi type %s>" % self.name
-
-    def is_signed(self):
-        return (self is app_types.slong or
-                self is app_types.sint or
-                self is app_types.sshort or
-                self is app_types.sbyte or
-                self is app_types.slonglong)
-
-    def is_unsigned(self):
-        return (self is app_types.ulong or
-                self is app_types.uint or
-                self is app_types.ushort or
-                self is app_types.ubyte or
-                self is app_types.ulonglong)
-
-    def is_pointer(self):
-        return self.ffitype is libffi.types.pointer
-
-    def is_char(self):
-        return self is app_types.char
-
-    def is_unichar(self):
-        return self is app_types.unichar
-
-    def is_longlong(self):
-        return libffi.IS_32_BIT and (self is app_types.slonglong or
-                                     self is app_types.ulonglong)
-
-    def is_double(self):
-        return self is app_types.double
-
-    def is_singlefloat(self):
-        return self is app_types.float
-
-    def is_void(self):
-        return self is app_types.void
-
-    def is_struct(self):
-        return libffi.types.is_struct(self.ffitype)
-
-    def is_char_p(self):
-        return self is app_types.char_p
-
-    def is_unichar_p(self):
-        return self is app_types.unichar_p
-
-
-W_FFIType.typedef = TypeDef(
-    'FFIType',
-    __repr__ = interp2app(W_FFIType.repr),
-    deref_pointer = interp2app(W_FFIType.descr_deref_pointer),
-    )
-
-
-def build_ffi_types():
-    types = [
-        # note: most of the type name directly come from the C equivalent,
-        # with the exception of bytes: in C, ubyte and char are equivalent,
-        # but for _ffi the first expects a number while the second a 1-length
-        # string
-        W_FFIType('slong',     libffi.types.slong),
-        W_FFIType('sint',      libffi.types.sint),
-        W_FFIType('sshort',    libffi.types.sshort),
-        W_FFIType('sbyte',     libffi.types.schar),
-        W_FFIType('slonglong', libffi.types.slonglong),
-        #
-        W_FFIType('ulong',     libffi.types.ulong),
-        W_FFIType('uint',      libffi.types.uint),
-        W_FFIType('ushort',    libffi.types.ushort),
-        W_FFIType('ubyte',     libffi.types.uchar),
-        W_FFIType('ulonglong', libffi.types.ulonglong),
-        #
-        W_FFIType('char',      libffi.types.uchar),
-        W_FFIType('unichar',   libffi.types.wchar_t),
-        #
-        W_FFIType('double',    libffi.types.double),
-        W_FFIType('float',     libffi.types.float),
-        W_FFIType('void',      libffi.types.void),
-        W_FFIType('void_p',    libffi.types.pointer),
-        #
-        # missing types:
-
-        ## 's' : ffi_type_pointer,
-        ## 'z' : ffi_type_pointer,
-        ## 'O' : ffi_type_pointer,
-        ## 'Z' : ffi_type_pointer,
-
-        ]
-    d = dict([(t.name, t) for t in types])
-    w_char = d['char']
-    w_unichar = d['unichar']
-    d['char_p'] = W_FFIType('char_p', libffi.types.pointer, w_pointer_to = w_char)
-    d['unichar_p'] = W_FFIType('unichar_p', libffi.types.pointer, w_pointer_to = w_unichar)
-    return d
-
-class app_types:
-    pass
-app_types.__dict__ = build_ffi_types()
-
-def descr_new_pointer(space, w_cls, w_pointer_to):
-    try:
-        return descr_new_pointer.cache[w_pointer_to]
-    except KeyError:
-        if w_pointer_to is app_types.char:
-            w_result = app_types.char_p
-        elif w_pointer_to is app_types.unichar:
-            w_result = app_types.unichar_p
-        else:
-            w_pointer_to = space.interp_w(W_FFIType, w_pointer_to)
-            name = '(pointer to %s)' % w_pointer_to.name
-            w_result = W_FFIType(name, libffi.types.pointer, w_pointer_to = w_pointer_to)
-        descr_new_pointer.cache[w_pointer_to] = w_result
-        return w_result
-descr_new_pointer.cache = {}
-
-class W_types(Wrappable):
-    pass
-W_types.typedef = TypeDef(
-    'types',
-    Pointer = interp2app(descr_new_pointer, as_classmethod=True),
-    **app_types.__dict__)
+from pypy.module._ffi.type_converter import FromAppLevelConverter, ToAppLevelConverter
 
 
 def unwrap_ffitype(space, w_argtype, allow_void=False):
-    res = w_argtype.ffitype
+    res = w_argtype.get_ffitype()
     if res is libffi.types.void and not allow_void:
         msg = 'void is not a valid argument type'
         raise OperationError(space.w_TypeError, space.wrap(msg))
     return res
 
-def unwrap_truncate_int(TP, space, w_arg):
-    if space.is_true(space.isinstance(w_arg, space.w_int)):
-        return rffi.cast(TP, space.int_w(w_arg))
-    else:
-        return rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask())
-unwrap_truncate_int._annspecialcase_ = 'specialize:arg(0)'
 
 # ========================================================================
 
@@ -197,101 +48,19 @@
                                   self.func.name, expected, arg, given)
         #
         argchain = libffi.ArgChain()
+        argpusher = PushArgumentConverter(space, argchain, self)
         for i in range(expected):
             w_argtype = self.argtypes_w[i]
             w_arg = args_w[i]
-            if w_argtype.is_longlong():
-                # note that we must check for longlong first, because either
-                # is_signed or is_unsigned returns true anyway
-                assert libffi.IS_32_BIT
-                self.arg_longlong(space, argchain, w_arg)
-            elif w_argtype.is_signed():
-                argchain.arg(unwrap_truncate_int(rffi.LONG, space, w_arg))
-            elif self.add_char_p_maybe(space, argchain, w_arg, w_argtype):
-                # the argument is added to the argchain direcly by the method above
-                pass
-            elif w_argtype.is_pointer():
-                w_arg = self.convert_pointer_arg_maybe(space, w_arg, w_argtype)
-                argchain.arg(intmask(space.uint_w(w_arg)))
-            elif w_argtype.is_unsigned():
-                argchain.arg(unwrap_truncate_int(rffi.ULONG, space, w_arg))
-            elif w_argtype.is_char():
-                w_arg = space.ord(w_arg)
-                argchain.arg(space.int_w(w_arg))
-            elif w_argtype.is_unichar():
-                w_arg = space.ord(w_arg)
-                argchain.arg(space.int_w(w_arg))
-            elif w_argtype.is_double():
-                self.arg_float(space, argchain, w_arg)
-            elif w_argtype.is_singlefloat():
-                self.arg_singlefloat(space, argchain, w_arg)
-            elif w_argtype.is_struct():
-                # arg_raw directly takes value to put inside ll_args
-                w_arg = space.interp_w(W_StructureInstance, w_arg)
-                ptrval = w_arg.ll_buffer
-                argchain.arg_raw(ptrval)
-            else:
-                assert False, "Argument shape '%s' not supported" % w_argtype
+            argpusher.unwrap_and_do(w_argtype, w_arg)
         return argchain
 
-    def add_char_p_maybe(self, space, argchain, w_arg, w_argtype):
-        """
-        Automatic conversion from string to char_p. The allocated buffer will
-        be automatically freed after the call.
-        """
-        w_type = jit.promote(space.type(w_arg))
-        if w_argtype.is_char_p() and w_type is space.w_str:
-            strval = space.str_w(w_arg)
-            buf = rffi.str2charp(strval)
-            self.to_free.append(rffi.cast(rffi.VOIDP, buf))
-            addr = rffi.cast(rffi.ULONG, buf)
-            argchain.arg(addr)
-            return True
-        elif w_argtype.is_unichar_p() and (w_type is space.w_str or
-                                           w_type is space.w_unicode):
-            unicodeval = space.unicode_w(w_arg)
-            buf = rffi.unicode2wcharp(unicodeval)
-            self.to_free.append(rffi.cast(rffi.VOIDP, buf))
-            addr = rffi.cast(rffi.ULONG, buf)
-            argchain.arg(addr)
-            return True
-        return False
-
-    def convert_pointer_arg_maybe(self, space, w_arg, w_argtype):
-        """
-        Try to convert the argument by calling _as_ffi_pointer_()
-        """
-        meth = space.lookup(w_arg, '_as_ffi_pointer_') # this also promotes the type
-        if meth:
-            return space.call_function(meth, w_arg, w_argtype)
-        else:
-            return w_arg
-
-    def arg_float(self, space, argchain, w_arg):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether floats are supported
-        argchain.arg(space.float_w(w_arg))
-
-    def arg_longlong(self, space, argchain, w_arg):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether longlongs are supported
-        bigarg = space.bigint_w(w_arg)
-        ullval = bigarg.ulonglongmask()
-        llval = rffi.cast(rffi.LONGLONG, ullval)
-        argchain.arg(llval)
-
-    def arg_singlefloat(self, space, argchain, w_arg):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether singlefloats are supported
-        from pypy.rlib.rarithmetic import r_singlefloat
-        fval = space.float_w(w_arg)
-        sfval = r_singlefloat(fval)
-        argchain.arg(sfval)
-
     def call(self, space, args_w):
         self = jit.promote(self)
         argchain = self.build_argchain(space, args_w)
-        return self._do_call(space, argchain)
+        func_caller = CallFunctionConverter(space, self.func, argchain)
+        return func_caller.do_and_wrap(self.w_restype)
+        #return self._do_call(space, argchain)
 
     def free_temp_buffers(self, space):
         for buf in self.to_free:
@@ -301,40 +70,89 @@
             lltype.free(buf, flavor='raw')
         self.to_free = []
 
-    def _do_call(self, space, argchain):
-        w_restype = self.w_restype
-        if w_restype.is_longlong():
-            # note that we must check for longlong first, because either
-            # is_signed or is_unsigned returns true anyway
-            assert libffi.IS_32_BIT
-            return self._call_longlong(space, argchain)
-        elif w_restype.is_signed():
-            return self._call_int(space, argchain)
-        elif w_restype.is_unsigned() or w_restype.is_pointer():
-            return self._call_uint(space, argchain)
-        elif w_restype.is_char():
-            intres = self.func.call(argchain, rffi.UCHAR)
-            return space.wrap(chr(intres))
-        elif w_restype.is_unichar():
-            intres = self.func.call(argchain, rffi.WCHAR_T)
-            return space.wrap(unichr(intres))
-        elif w_restype.is_double():
-            return self._call_float(space, argchain)
-        elif w_restype.is_singlefloat():
-            return self._call_singlefloat(space, argchain)
-        elif w_restype.is_struct():
-            w_datashape = w_restype.w_datashape
-            assert isinstance(w_datashape, W_Structure)
-            ptrval = self.func.call(argchain, rffi.ULONG, is_struct=True)
-            return w_datashape.fromaddress(space, ptrval)
-        elif w_restype.is_void():
-            voidres = self.func.call(argchain, lltype.Void)
-            assert voidres is None
-            return space.w_None
-        else:
-            assert False, "Return value shape '%s' not supported" % w_restype
+    def getaddr(self, space):
+        """
+        Return the physical address in memory of the function
+        """
+        return space.wrap(rffi.cast(rffi.LONG, self.func.funcsym))
 
-    def _call_int(self, space, argchain):
+
+class PushArgumentConverter(FromAppLevelConverter):
+    """
+    A converter used by W_FuncPtr to unwrap the app-level objects into
+    low-level types and push them to the argchain.
+    """
+
+    def __init__(self, space, argchain, w_func):
+        FromAppLevelConverter.__init__(self, space)
+        self.argchain = argchain
+        self.w_func = w_func
+
+    def handle_signed(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_unsigned(self, w_ffitype, w_obj, uintval):
+        self.argchain.arg(uintval)
+
+    def handle_pointer(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_char(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_unichar(self, w_ffitype, w_obj, intval):
+        self.argchain.arg(intval)
+
+    def handle_longlong(self, w_ffitype, w_obj, longlongval):
+        self.argchain.arg(longlongval)
+
+    def handle_char_p(self, w_ffitype, w_obj, strval):
+        buf = rffi.str2charp(strval)
+        self.w_func.to_free.append(rffi.cast(rffi.VOIDP, buf))
+        addr = rffi.cast(rffi.ULONG, buf)
+        self.argchain.arg(addr)
+
+    def handle_unichar_p(self, w_ffitype, w_obj, unicodeval):
+        buf = rffi.unicode2wcharp(unicodeval)
+        self.w_func.to_free.append(rffi.cast(rffi.VOIDP, buf))
+        addr = rffi.cast(rffi.ULONG, buf)
+        self.argchain.arg(addr)
+
+    def handle_float(self, w_ffitype, w_obj, floatval):
+        self.argchain.arg(floatval)
+
+    def handle_singlefloat(self, w_ffitype, w_obj, singlefloatval):
+        self.argchain.arg(singlefloatval)
+
+    def handle_struct(self, w_ffitype, w_structinstance):
+        # arg_raw directly takes value to put inside ll_args
+        ptrval = w_structinstance.rawmem
+        self.argchain.arg_raw(ptrval)
+
+    def handle_struct_rawffi(self, w_ffitype, w_structinstance):
+        # arg_raw directly takes value to put inside ll_args
+        ptrval = w_structinstance.ll_buffer
+        self.argchain.arg_raw(ptrval)
+
+
+class CallFunctionConverter(ToAppLevelConverter):
+    """
+    A converter used by W_FuncPtr to call the function, expect the result of
+    a correct low-level type and wrap it to the corresponding app-level type
+    """
+
+    def __init__(self, space, func, argchain):
+        ToAppLevelConverter.__init__(self, space)
+        self.func = func
+        self.argchain = argchain
+
+    def get_longlong(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.LONGLONG)
+
+    def get_ulonglong(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.ULONGLONG)
+
+    def get_signed(self, w_ffitype):
         # if the declared return type of the function is smaller than LONG,
         # the result buffer may contains garbage in its higher bits.  To get
         # the correct value, and to be sure to handle the signed/unsigned case
@@ -342,88 +160,66 @@
         # that, we cast it back to LONG, because this is what we want to pass
         # to space.wrap in order to get a nice applevel <int>.
         #
-        restype = self.func.restype
+        restype = w_ffitype.get_ffitype()
         call = self.func.call
         if restype is libffi.types.slong:
-            intres = call(argchain, rffi.LONG)
+            return call(self.argchain, rffi.LONG)
         elif restype is libffi.types.sint:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.INT))
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.INT))
         elif restype is libffi.types.sshort:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.SHORT))
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.SHORT))
         elif restype is libffi.types.schar:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.SIGNEDCHAR))
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.SIGNEDCHAR))
         else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap('Unsupported restype'))
-        return space.wrap(intres)
+            self.error(w_ffitype)
+            
+    def get_unsigned(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.ULONG)
 
-    def _call_uint(self, space, argchain):
-        # the same comment as above apply. Moreover, we need to be careful
-        # when the return type is ULONG, because the value might not fit into
-        # a signed LONG: this is the only case in which we cast the result to
-        # something different than LONG; as a result, the applevel value will
-        # be a <long>.
-        #
-        # Note that we check for ULONG before UINT: this is needed on 32bit
-        # machines, where they are they same: if we checked for UINT before
-        # ULONG, we would cast to the wrong type.  Note that this also means
-        # that on 32bit the UINT case will never be entered (because it is
-        # handled by the ULONG case).
-        restype = self.func.restype
+    def get_unsigned_which_fits_into_a_signed(self, w_ffitype):
+        # the same comment as get_signed apply
+        restype = w_ffitype.get_ffitype()
         call = self.func.call
-        if restype is libffi.types.ulong:
-            # special case
-            uintres = call(argchain, rffi.ULONG)
-            return space.wrap(uintres)
-        elif restype is libffi.types.pointer:
-            ptrres = call(argchain, rffi.VOIDP)
-            uintres = rffi.cast(rffi.ULONG, ptrres)
-            return space.wrap(uintres)
-        elif restype is libffi.types.uint:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.UINT))
+        if restype is libffi.types.uint:
+            assert not libffi.IS_32_BIT
+            # on 32bit machines, we should never get here, because it's a case
+            # which has already been handled by get_unsigned above.
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.UINT))
         elif restype is libffi.types.ushort:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.USHORT))
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.USHORT))
         elif restype is libffi.types.uchar:
-            intres = rffi.cast(rffi.LONG, call(argchain, rffi.UCHAR))
+            return rffi.cast(rffi.LONG, call(self.argchain, rffi.UCHAR))
         else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap('Unsupported restype'))
-        return space.wrap(intres)
+            self.error(w_ffitype)
 
-    def _call_float(self, space, argchain):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether floats are supported
-        floatres = self.func.call(argchain, rffi.DOUBLE)
-        return space.wrap(floatres)
 
-    def _call_longlong(self, space, argchain):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether longlongs are supported
-        restype = self.func.restype
-        call = self.func.call
-        if restype is libffi.types.slonglong:
-            llres = call(argchain, rffi.LONGLONG)
-            return space.wrap(llres)
-        elif restype is libffi.types.ulonglong:
-            ullres = call(argchain, rffi.ULONGLONG)
-            return space.wrap(ullres)
-        else:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap('Unsupported longlong restype'))
+    def get_pointer(self, w_ffitype):
+        ptrres = self.func.call(self.argchain, rffi.VOIDP)
+        return rffi.cast(rffi.ULONG, ptrres)
 
-    def _call_singlefloat(self, space, argchain):
-        # a separate function, which can be seen by the jit or not,
-        # depending on whether singlefloats are supported
-        sfres = self.func.call(argchain, rffi.FLOAT)
-        return space.wrap(float(sfres))
+    def get_char(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.UCHAR)
 
-    def getaddr(self, space):
-        """
-        Return the physical address in memory of the function
-        """
-        return space.wrap(rffi.cast(rffi.LONG, self.func.funcsym))
+    def get_unichar(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.WCHAR_T)
 
+    def get_float(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.DOUBLE)
 
+    def get_singlefloat(self, w_ffitype):
+        return self.func.call(self.argchain, rffi.FLOAT)
+
+    def get_struct(self, w_ffitype, w_structdescr):
+        addr = self.func.call(self.argchain, rffi.LONG, is_struct=True)
+        return w_structdescr.fromaddress(self.space, addr)
+
+    def get_struct_rawffi(self, w_ffitype, w_structdescr):
+        uintval = self.func.call(self.argchain, rffi.ULONG, is_struct=True)
+        return w_structdescr.fromaddress(self.space, uintval)
+
+    def get_void(self, w_ffitype):
+        return self.func.call(self.argchain, lltype.Void)
+    
 
 def unpack_argtypes(space, w_argtypes, w_restype):
     argtypes_w = [space.interp_w(W_FFIType, w_argtype)
@@ -512,3 +308,4 @@
         return space.wrap(W_CDLL(space, get_libc_name(), -1))
     except OSError, e:
         raise wrap_oserror(space, e)
+
diff --git a/pypy/module/_ffi/interp_struct.py b/pypy/module/_ffi/interp_struct.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/interp_struct.py
@@ -0,0 +1,319 @@
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib import clibffi
+from pypy.rlib import libffi
+from pypy.rlib import jit
+from pypy.rlib.rgc import must_be_light_finalizer
+from pypy.rlib.rarithmetic import r_uint, r_ulonglong, r_singlefloat, intmask
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.error import operationerrfmt
+from pypy.objspace.std.typetype import type_typedef
+from pypy.module._ffi.interp_ffitype import W_FFIType, app_types
+from pypy.module._ffi.type_converter import FromAppLevelConverter, ToAppLevelConverter
+
+
+class W_Field(Wrappable):
+
+    def __init__(self, name, w_ffitype):
+        self.name = name
+        self.w_ffitype = w_ffitype
+        self.offset = -1
+
+    def __repr__(self):
+        return '<Field %s %s>' % (self.name, self.w_ffitype.name)
+
+ at unwrap_spec(name=str)
+def descr_new_field(space, w_type, name, w_ffitype):
+    w_ffitype = space.interp_w(W_FFIType, w_ffitype)
+    return W_Field(name, w_ffitype)
+
+W_Field.typedef = TypeDef(
+    'Field',
+    __new__ = interp2app(descr_new_field),
+    name = interp_attrproperty('name', W_Field),
+    ffitype = interp_attrproperty('w_ffitype', W_Field),
+    offset = interp_attrproperty('offset', W_Field),
+    )
+
+
+# ==============================================================================
+
+class FFIStructOwner(object):
+    """
+    The only job of this class is to stay outside of the reference cycle
+    W__StructDescr -> W_FFIType -> W__StructDescr and free the ffistruct
+    """
+
+    def __init__(self, ffistruct):
+        self.ffistruct = ffistruct
+
+    @must_be_light_finalizer
+    def __del__(self):
+        if self.ffistruct:
+            lltype.free(self.ffistruct, flavor='raw', track_allocation=True)
+        
+
+class W__StructDescr(Wrappable):
+
+    def __init__(self, space, name):
+        self.space = space
+        self.w_ffitype = W_FFIType('struct %s' % name, clibffi.FFI_TYPE_NULL,
+                                   w_structdescr=self)
+        self.fields_w = None
+        self.name2w_field = {}
+        self._ffistruct_owner = None
+
+    def define_fields(self, space, w_fields):
+        if self.fields_w is not None:
+            raise operationerrfmt(space.w_ValueError,
+                                  "%s's fields has already been defined",
+                                  self.w_ffitype.name)
+        space = self.space
+        fields_w = space.fixedview(w_fields)
+        # note that the fields_w returned by compute_size_and_alignement has a
+        # different annotation than the original: list(W_Root) vs list(W_Field)
+        size, alignment, fields_w = compute_size_and_alignement(space, fields_w)
+        self.fields_w = fields_w
+        field_types = [] # clibffi's types
+        for w_field in fields_w:
+            field_types.append(w_field.w_ffitype.get_ffitype())
+            self.name2w_field[w_field.name] = w_field
+        #
+        # on CPython, the FFIStructOwner might go into gc.garbage and thus the
+        # __del__ never be called. Thus, we don't track the allocation of the
+        # malloc done inside this function, else the leakfinder might complain
+        ffistruct = clibffi.make_struct_ffitype_e(size, alignment, field_types,
+                                                  track_allocation=False)
+        self.w_ffitype.set_ffitype(ffistruct.ffistruct)
+        self._ffistruct_owner = FFIStructOwner(ffistruct)
+
+    def check_complete(self, space):
+        if self.fields_w is None:
+            raise operationerrfmt(space.w_ValueError, "%s has an incomplete type",
+                                  self.w_ffitype.name)
+
+    def allocate(self, space):
+        self.check_complete(space)
+        return W__StructInstance(self)
+
+    @unwrap_spec(addr=int)
+    def fromaddress(self, space, addr):
+        self.check_complete(space)
+        rawmem = rffi.cast(rffi.VOIDP, addr)
+        return W__StructInstance(self, allocate=False, autofree=True, rawmem=rawmem)
+
+    @jit.elidable_promote('0')
+    def get_type_and_offset_for_field(self, name):
+        try:
+            w_field = self.name2w_field[name]
+        except KeyError:
+            raise operationerrfmt(self.space.w_AttributeError, '%s', name)
+
+        return w_field.w_ffitype, w_field.offset
+
+
+
+ at unwrap_spec(name=str)
+def descr_new_structdescr(space, w_type, name, w_fields=None):
+    descr = W__StructDescr(space, name)
+    if w_fields is not space.w_None:
+        descr.define_fields(space, w_fields)
+    return descr
+
+def round_up(size, alignment):
+    return (size + alignment - 1) & -alignment
+
+def compute_size_and_alignement(space, fields_w):
+    size = 0
+    alignment = 1
+    fields_w2 = []
+    for w_field in fields_w:
+        w_field = space.interp_w(W_Field, w_field)
+        fieldsize = w_field.w_ffitype.sizeof()
+        fieldalignment = w_field.w_ffitype.get_alignment()
+        alignment = max(alignment, fieldalignment)
+        size = round_up(size, fieldalignment)
+        w_field.offset = size
+        size += fieldsize
+        fields_w2.append(w_field)
+    #
+    size = round_up(size, alignment)
+    return size, alignment, fields_w2
+
+
+
+W__StructDescr.typedef = TypeDef(
+    '_StructDescr',
+    __new__ = interp2app(descr_new_structdescr),
+    ffitype = interp_attrproperty('w_ffitype', W__StructDescr),
+    define_fields = interp2app(W__StructDescr.define_fields),
+    allocate = interp2app(W__StructDescr.allocate),
+    fromaddress = interp2app(W__StructDescr.fromaddress),
+    )
+
+
+# ==============================================================================
+
+NULL = lltype.nullptr(rffi.VOIDP.TO)
+
+class W__StructInstance(Wrappable):
+
+    _immutable_fields_ = ['structdescr', 'rawmem']
+
+    def __init__(self, structdescr, allocate=True, autofree=True, rawmem=NULL):
+        self.structdescr = structdescr
+        self.autofree = autofree
+        if allocate:
+            assert not rawmem
+            assert autofree
+            size = structdescr.w_ffitype.sizeof()
+            self.rawmem = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
+                                        zero=True, add_memory_pressure=True)
+        else:
+            self.rawmem = rawmem
+
+    @must_be_light_finalizer
+    def __del__(self):
+        if self.autofree and self.rawmem:
+            lltype.free(self.rawmem, flavor='raw')
+            self.rawmem = lltype.nullptr(rffi.VOIDP.TO)
+
+    def getaddr(self, space):
+        addr = rffi.cast(rffi.ULONG, self.rawmem)
+        return space.wrap(addr)
+
+    @unwrap_spec(name=str)
+    def getfield(self, space, name):
+        w_ffitype, offset = self.structdescr.get_type_and_offset_for_field(name)
+        field_getter = GetFieldConverter(space, self.rawmem, offset)
+        return field_getter.do_and_wrap(w_ffitype)
+
+    @unwrap_spec(name=str)
+    def setfield(self, space, name, w_value):
+        w_ffitype, offset = self.structdescr.get_type_and_offset_for_field(name)
+        field_setter = SetFieldConverter(space, self.rawmem, offset)
+        field_setter.unwrap_and_do(w_ffitype, w_value)
+
+
+class GetFieldConverter(ToAppLevelConverter):
+    """
+    A converter used by W__StructInstance to get a field from the struct and
+    wrap it to the correct app-level type.
+    """
+
+    def __init__(self, space, rawmem, offset):
+        self.space = space
+        self.rawmem = rawmem
+        self.offset = offset
+
+    def get_longlong(self, w_ffitype): 
+        return libffi.struct_getfield_longlong(libffi.types.slonglong,
+                                               self.rawmem, self.offset)
+
+    def get_ulonglong(self, w_ffitype):
+        longlongval = libffi.struct_getfield_longlong(libffi.types.ulonglong,
+                                                      self.rawmem, self.offset)
+        return r_ulonglong(longlongval)
+
+
+    def get_signed(self, w_ffitype):
+        return libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                          self.rawmem, self.offset)
+
+    def get_unsigned(self, w_ffitype):
+        value = libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                           self.rawmem, self.offset)
+        return r_uint(value)
+
+    get_unsigned_which_fits_into_a_signed = get_signed
+    get_pointer = get_unsigned
+
+    def get_char(self, w_ffitype):
+        intval = libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                            self.rawmem, self.offset)
+        return rffi.cast(rffi.UCHAR, intval)
+
+    def get_unichar(self, w_ffitype):
+        intval = libffi.struct_getfield_int(w_ffitype.get_ffitype(),
+                                            self.rawmem, self.offset)
+        return rffi.cast(rffi.WCHAR_T, intval)
+
+    def get_float(self, w_ffitype):
+        return libffi.struct_getfield_float(w_ffitype.get_ffitype(),
+                                            self.rawmem, self.offset)
+
+    def get_singlefloat(self, w_ffitype):
+        return libffi.struct_getfield_singlefloat(w_ffitype.get_ffitype(),
+                                                  self.rawmem, self.offset)
+
+    def get_struct(self, w_ffitype, w_structdescr):
+        assert isinstance(w_structdescr, W__StructDescr)
+        rawmem = rffi.cast(rffi.CCHARP, self.rawmem)
+        innermem = rffi.cast(rffi.VOIDP, rffi.ptradd(rawmem, self.offset))
+        # we return a reference to the inner struct, not a copy
+        # autofree=False because it's still owned by the parent struct
+        return W__StructInstance(w_structdescr, allocate=False, autofree=False,
+                                 rawmem=innermem)
+
+    ## def get_void(self, w_ffitype):
+    ##     ...
+
+
+class SetFieldConverter(FromAppLevelConverter):
+    """
+    A converter used by W__StructInstance to convert an app-level object to
+    the corresponding low-level value and set the field of a structure.
+    """
+
+    def __init__(self, space, rawmem, offset):
+        self.space = space
+        self.rawmem = rawmem
+        self.offset = offset
+
+    def handle_signed(self, w_ffitype, w_obj, intval):
+        libffi.struct_setfield_int(w_ffitype.get_ffitype(), self.rawmem, self.offset,
+                                   intval)
+
+    def handle_unsigned(self, w_ffitype, w_obj, uintval):
+        libffi.struct_setfield_int(w_ffitype.get_ffitype(), self.rawmem, self.offset,
+                                   intmask(uintval))
+
+    handle_pointer = handle_signed
+    handle_char = handle_signed
+    handle_unichar = handle_signed
+
+    def handle_longlong(self, w_ffitype, w_obj, longlongval):
+        libffi.struct_setfield_longlong(w_ffitype.get_ffitype(),
+                                        self.rawmem, self.offset, longlongval)
+
+    def handle_float(self, w_ffitype, w_obj, floatval):
+        libffi.struct_setfield_float(w_ffitype.get_ffitype(),
+                                     self.rawmem, self.offset, floatval)
+
+    def handle_singlefloat(self, w_ffitype, w_obj, singlefloatval):
+        libffi.struct_setfield_singlefloat(w_ffitype.get_ffitype(),
+                                           self.rawmem, self.offset, singlefloatval)
+
+    def handle_struct(self, w_ffitype, w_structinstance):
+        rawmem = rffi.cast(rffi.CCHARP, self.rawmem)
+        dst = rffi.cast(rffi.VOIDP, rffi.ptradd(rawmem, self.offset))
+        src = w_structinstance.rawmem
+        length = w_ffitype.sizeof()
+        rffi.c_memcpy(dst, src, length)
+
+    ## def handle_char_p(self, w_ffitype, w_obj, strval):
+    ##     ...
+
+    ## def handle_unichar_p(self, w_ffitype, w_obj, unicodeval):
+    ##     ...
+
+
+
+
+W__StructInstance.typedef = TypeDef(
+    '_StructInstance',
+    getaddr  = interp2app(W__StructInstance.getaddr),
+    getfield = interp2app(W__StructInstance.getfield),
+    setfield = interp2app(W__StructInstance.setfield),
+    )
diff --git a/pypy/module/_ffi/test/test_ffitype.py b/pypy/module/_ffi/test/test_ffitype.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/test/test_ffitype.py
@@ -0,0 +1,39 @@
+from pypy.module._ffi.test.test_funcptr import BaseAppTestFFI
+
+class AppTestFFIType(BaseAppTestFFI):
+
+    def test_simple_types(self):
+        from _ffi import types
+        assert str(types.sint) == "<ffi type sint>"
+        assert str(types.uint) == "<ffi type uint>"
+        assert types.sint.name == 'sint'
+        assert types.uint.name == 'uint'
+        
+    def test_sizeof(self):
+        from _ffi import types
+        assert types.sbyte.sizeof() == 1
+        assert types.sint.sizeof() == 4
+
+    def test_typed_pointer(self):
+        from _ffi import types
+        intptr = types.Pointer(types.sint) # create a typed pointer to sint
+        assert intptr.deref_pointer() is types.sint
+        assert str(intptr) == '<ffi type (pointer to sint)>'
+        assert types.sint.deref_pointer() is None
+        raises(TypeError, "types.Pointer(42)")
+
+    def test_pointer_identity(self):
+        from _ffi import types
+        x = types.Pointer(types.slong)
+        y = types.Pointer(types.slong)
+        z = types.Pointer(types.char)
+        assert x is y
+        assert x is not z
+
+    def test_char_p_cached(self):
+        from _ffi import types
+        x = types.Pointer(types.char)
+        assert x is types.char_p
+        x = types.Pointer(types.unichar)
+        assert x is types.unichar_p
+
diff --git a/pypy/module/_ffi/test/test__ffi.py b/pypy/module/_ffi/test/test_funcptr.py
rename from pypy/module/_ffi/test/test__ffi.py
rename to pypy/module/_ffi/test/test_funcptr.py
--- a/pypy/module/_ffi/test/test__ffi.py
+++ b/pypy/module/_ffi/test/test_funcptr.py
@@ -7,7 +7,7 @@
 
 import os, sys, py
 
-class AppTestFfi:
+class BaseAppTestFFI(object):
 
     @classmethod
     def prepare_c_example(cls):
@@ -36,7 +36,6 @@
         eci = ExternalCompilationInfo(export_symbols=[])
         return str(platform.compile([c_file], eci, 'x', standalone=False))
 
-    
     def setup_class(cls):
         from pypy.rpython.lltypesystem import rffi
         from pypy.rlib.libffi import get_libc_name, CDLL, types
@@ -52,7 +51,12 @@
         pow = libm.getpointer('pow', [], types.void)
         pow_addr = rffi.cast(rffi.LONG, pow.funcsym)
         cls.w_pow_addr = space.wrap(pow_addr)
-        #
+
+class AppTestFFI(BaseAppTestFFI):
+
+    def setup_class(cls):
+        BaseAppTestFFI.setup_class.im_func(cls)
+        space = cls.space
         # these are needed for test_single_float_args
         from ctypes import c_float
         f_12_34 = c_float(12.34).value
@@ -78,11 +82,6 @@
         res = dll.getfunc('Py_IsInitialized', [], types.slong)()
         assert res == 1
 
-    def test_simple_types(self):
-        from _ffi import types
-        assert str(types.sint) == "<ffi type sint>"
-        assert str(types.uint) == "<ffi type uint>"
-        
     def test_callfunc(self):
         from _ffi import CDLL, types
         libm = CDLL(self.libm_name)
@@ -263,29 +262,6 @@
         assert list(array) == list('foobar\00')
         do_nothing.free_temp_buffers()
 
-    def test_typed_pointer(self):
-        from _ffi import types
-        intptr = types.Pointer(types.sint) # create a typed pointer to sint
-        assert intptr.deref_pointer() is types.sint
-        assert str(intptr) == '<ffi type (pointer to sint)>'
-        assert types.sint.deref_pointer() is None
-        raises(TypeError, "types.Pointer(42)")
-
-    def test_pointer_identity(self):
-        from _ffi import types
-        x = types.Pointer(types.slong)
-        y = types.Pointer(types.slong)
-        z = types.Pointer(types.char)
-        assert x is y
-        assert x is not z
-
-    def test_char_p_cached(self):
-        from _ffi import types
-        x = types.Pointer(types.char)
-        assert x is types.char_p
-        x = types.Pointer(types.unichar)
-        assert x is types.unichar_p
-
     def test_typed_pointer_args(self):
         """
             extern int dummy; // defined in test_void_result 
@@ -476,6 +452,51 @@
                 return p.x + p.y;
             }
         """
+        from _ffi import CDLL, types, _StructDescr, Field
+        Point = _StructDescr('Point', [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ])
+        libfoo = CDLL(self.libfoo_name)
+        sum_point = libfoo.getfunc('sum_point', [Point.ffitype], types.slong)
+        #
+        p = Point.allocate()
+        p.setfield('x', 30)
+        p.setfield('y', 12)
+        res = sum_point(p)
+        assert res == 42
+
+    def test_byval_result(self):
+        """
+            DLLEXPORT struct Point make_point(long x, long y) {
+                struct Point p;
+                p.x = x;
+                p.y = y;
+                return p;
+            }
+        """
+        from _ffi import CDLL, types, _StructDescr, Field
+        Point = _StructDescr('Point', [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ])
+        libfoo = CDLL(self.libfoo_name)
+        make_point = libfoo.getfunc('make_point', [types.slong, types.slong],
+                                    Point.ffitype)
+        #
+        p = make_point(12, 34)
+        assert p.getfield('x') == 12
+        assert p.getfield('y') == 34
+
+    # XXX: support for _rawffi structures should be killed as soon as we
+    # implement ctypes.Structure on top of _ffi. In the meantime, we support
+    # both
+    def test_byval_argument__rawffi(self):
+        """
+            // defined above
+            struct Point;
+            DLLEXPORT long sum_point(struct Point p);
+        """
         import _rawffi
         from _ffi import CDLL, types
         POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
@@ -490,14 +511,10 @@
         assert res == 42
         p.free()
 
-    def test_byval_result(self):
+    def test_byval_result__rawffi(self):
         """
-            DLLEXPORT struct Point make_point(long x, long y) {
-                struct Point p;
-                p.x = x;
-                p.y = y;
-                return p;
-            }
+            // defined above
+            DLLEXPORT struct Point make_point(long x, long y);
         """
         import _rawffi
         from _ffi import CDLL, types
@@ -511,6 +528,7 @@
         assert p.y == 34
         p.free()
 
+
     def test_TypeError_numargs(self):
         from _ffi import CDLL, types
         libfoo = CDLL(self.libfoo_name)
diff --git a/pypy/module/_ffi/test/test_struct.py b/pypy/module/_ffi/test/test_struct.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/test/test_struct.py
@@ -0,0 +1,320 @@
+import sys
+from pypy.conftest import gettestobjspace
+from pypy.module._ffi.test.test_funcptr import BaseAppTestFFI
+from pypy.module._ffi.interp_struct import compute_size_and_alignement, W_Field
+from pypy.module._ffi.interp_ffitype import app_types, W_FFIType
+
+
+class TestStruct(object):
+
+    class FakeSpace(object):
+        def interp_w(self, cls, obj):
+            return obj
+
+    def compute(self, ffitypes_w):
+        fields_w = [W_Field('<dummy>', w_ffitype) for
+                    w_ffitype in ffitypes_w]
+        return compute_size_and_alignement(self.FakeSpace(), fields_w)
+
+    def sizeof(self, ffitypes_w):
+        size, aligned, fields_w = self.compute(ffitypes_w)
+        return size
+
+    def test_compute_size(self):
+        T = app_types
+        byte_size = app_types.sbyte.sizeof()
+        long_size = app_types.slong.sizeof()
+        llong_size = app_types.slonglong.sizeof()
+        llong_align = app_types.slonglong.get_alignment()
+        #
+        assert llong_align >= 4
+        assert self.sizeof([T.sbyte, T.slong]) == 2*long_size
+        assert self.sizeof([T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.sbyte, T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.sbyte, T.sbyte, T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.sbyte, T.sbyte, T.sbyte, T.sbyte, T.slonglong]) == llong_align + llong_size
+        assert self.sizeof([T.slonglong, T.sbyte]) == llong_size + llong_align
+        assert self.sizeof([T.slonglong, T.sbyte, T.sbyte]) == llong_size + llong_align
+        assert self.sizeof([T.slonglong, T.sbyte, T.sbyte, T.sbyte]) == llong_size + llong_align
+        assert self.sizeof([T.slonglong, T.sbyte, T.sbyte, T.sbyte, T.sbyte]) == llong_size + llong_align
+
+class AppTestStruct(BaseAppTestFFI):
+
+    def setup_class(cls):
+        BaseAppTestFFI.setup_class.im_func(cls)
+        #
+        def read_raw_mem(self, addr, typename, length):
+            import ctypes
+            addr = ctypes.cast(addr, ctypes.c_void_p)
+            c_type = getattr(ctypes, typename)
+            array_type = ctypes.POINTER(c_type * length)
+            ptr_array = ctypes.cast(addr, array_type)
+            array = ptr_array[0]
+            lst = [array[i] for i in range(length)]
+            return lst
+        cls.w_read_raw_mem = cls.space.wrap(read_raw_mem)
+        #
+        from pypy.rlib import clibffi
+        from pypy.rlib.rarithmetic import r_uint
+        from pypy.rpython.lltypesystem import lltype, rffi
+        dummy_type = lltype.malloc(clibffi.FFI_TYPE_P.TO, flavor='raw')
+        dummy_type.c_size = r_uint(123)
+        dummy_type.c_alignment = rffi.cast(rffi.USHORT, 0)
+        dummy_type.c_type = rffi.cast(rffi.USHORT, 0)
+        cls.w_dummy_type = W_FFIType('dummy', dummy_type)
+        
+    def test__StructDescr(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        assert descr.ffitype.sizeof() == longsize*2
+        assert descr.ffitype.name == 'struct foo'
+
+    def test_alignment(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.sbyte),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        assert descr.ffitype.sizeof() == longsize*2
+        assert fields[0].offset == 0
+        assert fields[1].offset == longsize # aligned to WORD
+
+    def test_missing_field(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        raises(AttributeError, "struct.getfield('missing')")
+        raises(AttributeError, "struct.setfield('missing', 42)")
+
+    def test_unknown_type(self):
+        from _ffi import _StructDescr, Field
+        fields = [
+            Field('x', self.dummy_type),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        raises(TypeError, "struct.getfield('x')")
+        raises(TypeError, "struct.setfield('x', 42)")
+
+    def test_getfield_setfield(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('x', 42)
+        struct.setfield('y', 43)
+        assert struct.getfield('x') == 42
+        assert struct.getfield('y') == 43
+        mem = self.read_raw_mem(struct.getaddr(), 'c_long', 2)
+        assert mem == [42, 43]
+
+    def test_getfield_setfield_signed_types(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('sbyte', types.sbyte),
+            Field('sshort', types.sshort),
+            Field('sint', types.sint),
+            Field('slong', types.slong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('sbyte', 128)
+        assert struct.getfield('sbyte') == -128
+        struct.setfield('sshort', 32768)
+        assert struct.getfield('sshort') == -32768
+        struct.setfield('sint', 43)
+        assert struct.getfield('sint') == 43
+        struct.setfield('slong', sys.maxint+1)
+        assert struct.getfield('slong') == -sys.maxint-1
+        struct.setfield('slong', sys.maxint*3)
+        assert struct.getfield('slong') == sys.maxint-2
+
+    def test_getfield_setfield_unsigned_types(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('ubyte', types.ubyte),
+            Field('ushort', types.ushort),
+            Field('uint', types.uint),
+            Field('ulong', types.ulong),
+            Field('char', types.char),
+            Field('unichar', types.unichar),
+            Field('ptr', types.void_p),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('ubyte', -1)
+        assert struct.getfield('ubyte') == 255
+        struct.setfield('ushort', -1)
+        assert struct.getfield('ushort') == 65535
+        struct.setfield('uint', 43)
+        assert struct.getfield('uint') == 43
+        struct.setfield('ulong', -1)
+        assert struct.getfield('ulong') == sys.maxint*2 + 1
+        struct.setfield('ulong', sys.maxint*2 + 2)
+        assert struct.getfield('ulong') == 0
+        struct.setfield('char', 'a')
+        assert struct.getfield('char') == 'a'
+        struct.setfield('unichar', u'\u1234')
+        assert struct.getfield('unichar') == u'\u1234'
+        struct.setfield('ptr', -1)
+        assert struct.getfield('ptr') == sys.maxint*2 + 1
+    
+    def test_getfield_setfield_longlong(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('slonglong', types.slonglong),
+            Field('ulonglong', types.ulonglong),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('slonglong', 9223372036854775808)
+        assert struct.getfield('slonglong') == -9223372036854775808
+        struct.setfield('ulonglong', -1)
+        assert struct.getfield('ulonglong') == 18446744073709551615        
+        mem = self.read_raw_mem(struct.getaddr(), 'c_longlong', 2)
+        assert mem == [-9223372036854775808, -1]
+
+    def test_getfield_setfield_float(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.double),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('x', 123.4)
+        assert struct.getfield('x') == 123.4
+        mem = self.read_raw_mem(struct.getaddr(), 'c_double', 1)
+        assert mem == [123.4]
+
+    def test_getfield_setfield_singlefloat(self):
+        import sys
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.float),
+            ]
+        descr = _StructDescr('foo', fields)
+        struct = descr.allocate()
+        struct.setfield('x', 123.4) # this is a value which DOES loose
+                                    # precision in a single float
+        assert 0 < abs(struct.getfield('x') - 123.4) < 0.0001
+        #
+        struct.setfield('x', 123.5) # this is a value which does not loose
+                                    # precision in a single float
+        assert struct.getfield('x') == 123.5
+        mem = self.read_raw_mem(struct.getaddr(), 'c_float', 1)
+        assert mem == [123.5]
+
+    def test_define_fields(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo')
+        assert descr.ffitype.name == 'struct foo'
+        assert repr(descr.ffitype) == '<ffi type struct foo (incomplete)>'
+        raises(ValueError, "descr.ffitype.sizeof()")
+        raises(ValueError, "descr.allocate()")
+        #
+        descr.define_fields(fields)
+        assert repr(descr.ffitype) == '<ffi type struct foo>'
+        assert descr.ffitype.sizeof() == longsize*2
+        raises(ValueError, "descr.define_fields(fields)")
+
+    def test_pointer_to_incomplete_struct(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        descr = _StructDescr('foo')
+        foo_ffitype = descr.ffitype
+        foo_p = types.Pointer(descr.ffitype)
+        assert foo_p.deref_pointer() is foo_ffitype
+        descr.define_fields(fields)
+        assert descr.ffitype is foo_ffitype
+        assert foo_p.deref_pointer() is foo_ffitype
+        assert types.Pointer(descr.ffitype) is foo_p
+
+    def test_nested_structure(self):
+        from _ffi import _StructDescr, Field, types
+        longsize = types.slong.sizeof()
+        foo_fields = [
+            Field('x', types.slong),
+            Field('y', types.slong),
+            ]
+        foo_descr = _StructDescr('foo', foo_fields)
+        #
+        bar_fields = [
+            Field('x', types.slong),
+            Field('foo', foo_descr.ffitype),
+            ]
+        bar_descr = _StructDescr('bar', bar_fields)
+        assert bar_descr.ffitype.sizeof() == longsize*3
+        #
+        struct = bar_descr.allocate()
+        struct.setfield('x', 40)
+        # reading a nested structure yields a reference to it
+        struct_foo = struct.getfield('foo')
+        struct_foo.setfield('x', 41)
+        struct_foo.setfield('y', 42)
+        mem = self.read_raw_mem(struct.getaddr(), 'c_long', 3)
+        assert mem == [40, 41, 42]
+        #
+        struct_foo2 = foo_descr.allocate()
+        struct_foo2.setfield('x', 141)
+        struct_foo2.setfield('y', 142)
+        # writing a nested structure copies its memory into the target
+        struct.setfield('foo', struct_foo2)
+        struct_foo2.setfield('x', 241)
+        struct_foo2.setfield('y', 242)
+        mem = self.read_raw_mem(struct.getaddr(), 'c_long', 3)
+        assert mem == [40, 141, 142]
+        mem = self.read_raw_mem(struct_foo2.getaddr(), 'c_long', 2)
+        assert mem == [241, 242]
+
+
+
+    def test_compute_shape(self):
+        from _ffi import Structure, Field, types
+        class Point(Structure):
+            _fields_ = [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ]
+
+        longsize = types.slong.sizeof()
+        assert isinstance(Point.x, Field)
+        assert isinstance(Point.y, Field)
+        assert Point.x.offset == 0
+        assert Point.y.offset == longsize
+        assert Point._struct_.ffitype.sizeof() == longsize*2
+        assert Point._struct_.ffitype.name == 'struct Point'
+
diff --git a/pypy/module/_ffi/test/test_type_converter.py b/pypy/module/_ffi/test/test_type_converter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/test/test_type_converter.py
@@ -0,0 +1,128 @@
+import sys
+from pypy.conftest import gettestobjspace
+from pypy.rlib.rarithmetic import r_uint, r_singlefloat, r_longlong, r_ulonglong
+from pypy.rlib.libffi import IS_32_BIT
+from pypy.module._ffi.interp_ffitype import app_types, descr_new_pointer
+from pypy.module._ffi.type_converter import FromAppLevelConverter, ToAppLevelConverter
+
+class DummyFromAppLevelConverter(FromAppLevelConverter):
+
+    def handle_all(self, w_ffitype, w_obj, val):
+        self.lastval = val
+
+    handle_signed = handle_all
+    handle_unsigned = handle_all
+    handle_pointer = handle_all
+    handle_char = handle_all        
+    handle_unichar = handle_all
+    handle_longlong = handle_all
+    handle_char_p = handle_all
+    handle_unichar_p = handle_all
+    handle_float = handle_all
+    handle_singlefloat = handle_all
+    
+    def handle_struct(self, w_ffitype, w_structinstance):
+        self.lastval = w_structinstance
+
+    def convert(self, w_ffitype, w_obj):
+        self.unwrap_and_do(w_ffitype, w_obj)
+        return self.lastval
+
+
+class TestFromAppLevel(object):
+
+    def setup_class(cls):
+        cls.space = gettestobjspace(usemodules=('_ffi',))
+        converter = DummyFromAppLevelConverter(cls.space)
+        cls.from_app_level = staticmethod(converter.convert)
+
+    def check(self, w_ffitype, w_obj, expected):
+        v = self.from_app_level(w_ffitype, w_obj)
+        assert v == expected
+        assert type(v) is type(expected)
+
+    def test_int(self):
+        self.check(app_types.sint, self.space.wrap(42), 42)
+        self.check(app_types.sint, self.space.wrap(sys.maxint+1), -sys.maxint-1)
+        self.check(app_types.sint, self.space.wrap(sys.maxint*2), -2)
+
+    def test_unsigned(self):
+        space = self.space
+        self.check(app_types.uint, space.wrap(42), r_uint(42))
+        self.check(app_types.uint, space.wrap(-1), r_uint(sys.maxint*2 +1))
+        self.check(app_types.uint, space.wrap(sys.maxint*3),
+                   r_uint(sys.maxint - 2))
+        self.check(app_types.ulong, space.wrap(sys.maxint+12),
+                   r_uint(sys.maxint+12))
+        self.check(app_types.ulong, space.wrap(sys.maxint*2+3), r_uint(1))
+
+    def test_char(self):
+        space = self.space
+        self.check(app_types.char, space.wrap('a'), ord('a'))
+        self.check(app_types.unichar, space.wrap(u'\u1234'), 0x1234)
+
+    def test_signed_longlong(self):
+        space = self.space
+        maxint32 = 2147483647 # we cannot really go above maxint on 64 bits
+                              # (and we would not test anything, as there long
+                              # is the same as long long)
+        expected = maxint32+1
+        if IS_32_BIT:
+            expected = r_longlong(expected)
+        self.check(app_types.slonglong, space.wrap(maxint32+1), expected)
+
+    def test_unsigned_longlong(self):
+        space = self.space
+        maxint64 = 9223372036854775807 # maxint64+1 does not fit into a
+                                       # longlong, but it does into a
+                                       # ulonglong
+        if IS_32_BIT:
+            # internally, the type converter always casts to signed longlongs
+            expected = r_longlong(-maxint64-1)
+        else:
+            # on 64 bit, ulonglong == uint (i.e., unsigned long in C terms)
+            expected = r_uint(maxint64+1)
+        self.check(app_types.ulonglong, space.wrap(maxint64+1), expected)
+
+    def test_float_and_double(self):
+        space = self.space
+        self.check(app_types.float, space.wrap(12.34), r_singlefloat(12.34))
+        self.check(app_types.double, space.wrap(12.34), 12.34)
+
+    def test_pointer(self):
+        # pointers are "unsigned" at applevel, but signed at interp-level (for
+        # no good reason, at interp-level Signed or Unsigned makes no
+        # difference for passing bits around)
+        space = self.space
+        self.check(app_types.void_p, space.wrap(42), 42)
+        self.check(app_types.void_p, space.wrap(sys.maxint+1), -sys.maxint-1)
+        #
+        # typed pointers
+        w_ptr_sint = descr_new_pointer(space, None, app_types.sint)
+        self.check(w_ptr_sint, space.wrap(sys.maxint+1), -sys.maxint-1)
+
+
+    def test__as_ffi_pointer_(self):
+        space = self.space
+        w_MyPointerWrapper = space.appexec([], """():
+            import _ffi
+            class MyPointerWrapper(object):
+                def __init__(self, value):
+                    self.value = value
+                def _as_ffi_pointer_(self, ffitype):
+                    assert ffitype is _ffi.types.void_p
+                    return self.value
+
+            return MyPointerWrapper
+        """)
+        w_obj = space.call_function(w_MyPointerWrapper, space.wrap(42))
+        self.check(app_types.void_p, w_obj, 42)
+
+    def test_strings(self):
+        # first, try automatic conversion from applevel
+        self.check(app_types.char_p, self.space.wrap('foo'), 'foo')
+        self.check(app_types.unichar_p, self.space.wrap(u'foo\u1234'), u'foo\u1234')    
+        self.check(app_types.unichar_p, self.space.wrap('foo'), u'foo')    
+        # then, try to pass explicit pointers
+        self.check(app_types.char_p, self.space.wrap(42), 42)
+        self.check(app_types.unichar_p, self.space.wrap(42), 42)        
diff --git a/pypy/module/_ffi/type_converter.py b/pypy/module/_ffi/type_converter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi/type_converter.py
@@ -0,0 +1,364 @@
+from pypy.rlib import libffi
+from pypy.rlib import jit
+from pypy.rlib.rarithmetic import intmask, r_uint
+from pypy.rpython.lltypesystem import rffi
+from pypy.interpreter.error import operationerrfmt, OperationError
+from pypy.module._rawffi.structure import W_StructureInstance, W_Structure
+from pypy.module._ffi.interp_ffitype import app_types
+
+class FromAppLevelConverter(object):
+    """
+    Unwrap an app-level object to the corresponding low-level type, following
+    the conversion rules which apply to the specified w_ffitype.  Once
+    unwrapped, the value is passed to the corresponding handle_* method.
+    Subclasses should override the desired ones.
+    """
+
+    def __init__(self, space):
+        self.space = space
+
+    def unwrap_and_do(self, w_ffitype, w_obj):
+        from pypy.module._ffi.interp_struct import W__StructInstance
+        space = self.space
+        if w_ffitype.is_longlong():
+            # note that we must check for longlong first, because either
+            # is_signed or is_unsigned returns true anyway
+            assert libffi.IS_32_BIT
+            self._longlong(w_ffitype, w_obj)
+        elif w_ffitype.is_signed():
+            intval = space.truncatedint_w(w_obj)
+            self.handle_signed(w_ffitype, w_obj, intval)
+        elif self.maybe_handle_char_or_unichar_p(w_ffitype, w_obj):
+            # the object was already handled from within
+            # maybe_handle_char_or_unichar_p
+            pass
+        elif w_ffitype.is_pointer():
+            w_obj = self.convert_pointer_arg_maybe(w_obj, w_ffitype)
+            intval = space.truncatedint_w(w_obj)
+            self.handle_pointer(w_ffitype, w_obj, intval)
+        elif w_ffitype.is_unsigned():
+            uintval = r_uint(space.truncatedint_w(w_obj))
+            self.handle_unsigned(w_ffitype, w_obj, uintval)
+        elif w_ffitype.is_char():
+            intval = space.int_w(space.ord(w_obj))
+            self.handle_char(w_ffitype, w_obj, intval)
+        elif w_ffitype.is_unichar():
+            intval = space.int_w(space.ord(w_obj))
+            self.handle_unichar(w_ffitype, w_obj, intval)
+        elif w_ffitype.is_double():
+            self._float(w_ffitype, w_obj)
+        elif w_ffitype.is_singlefloat():
+            self._singlefloat(w_ffitype, w_obj)
+        elif w_ffitype.is_struct():
+            if isinstance(w_obj, W_StructureInstance):
+                self.handle_struct_rawffi(w_ffitype, w_obj)
+            else:
+                w_obj = space.interp_w(W__StructInstance, w_obj)
+                self.handle_struct(w_ffitype, w_obj)
+        else:
+            self.error(w_ffitype, w_obj)
+
+    def _longlong(self, w_ffitype, w_obj):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether longlongs are supported
+        longlongval = self.space.truncatedlonglong_w(w_obj)
+        self.handle_longlong(w_ffitype, w_obj, longlongval)
+
+    def _float(self, w_ffitype, w_obj):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether floats are supported
+        floatval = self.space.float_w(w_obj)
+        self.handle_float(w_ffitype, w_obj, floatval)
+
+    def _singlefloat(self, w_ffitype, w_obj):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether singlefloats are supported
+        from pypy.rlib.rarithmetic import r_singlefloat
+        floatval = self.space.float_w(w_obj)
+        singlefloatval = r_singlefloat(floatval)
+        self.handle_singlefloat(w_ffitype, w_obj, singlefloatval)
+
+    def maybe_handle_char_or_unichar_p(self, w_ffitype, w_obj):
+        w_type = jit.promote(self.space.type(w_obj))
+        if w_ffitype.is_char_p() and w_type is self.space.w_str:
+            strval = self.space.str_w(w_obj)
+            self.handle_char_p(w_ffitype, w_obj, strval)
+            return True
+        elif w_ffitype.is_unichar_p() and (w_type is self.space.w_str or
+                                           w_type is self.space.w_unicode):
+            unicodeval = self.space.unicode_w(w_obj)
+            self.handle_unichar_p(w_ffitype, w_obj, unicodeval)
+            return True
+        return False
+
+    def convert_pointer_arg_maybe(self, w_arg, w_argtype):
+        """
+        Try to convert the argument by calling _as_ffi_pointer_()
+        """
+        space = self.space
+        meth = space.lookup(w_arg, '_as_ffi_pointer_') # this also promotes the type
+        if meth:
+            return space.call_function(meth, w_arg, w_argtype)
+        else:
+            return w_arg
+
+    def error(self, w_ffitype, w_obj):
+        raise operationerrfmt(self.space.w_TypeError,
+                              'Unsupported ffi type to convert: %s',
+                              w_ffitype.name)
+
+    def handle_signed(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_unsigned(self, w_ffitype, w_obj, uintval):
+        """
+        uintval: lltype.Unsigned
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_pointer(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_char(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+        
+    def handle_unichar(self, w_ffitype, w_obj, intval):
+        """
+        intval: lltype.Signed
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_longlong(self, w_ffitype, w_obj, longlongval):
+        """
+        longlongval: lltype.SignedLongLong
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_char_p(self, w_ffitype, w_obj, strval):
+        """
+        strval: interp-level str
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_unichar_p(self, w_ffitype, w_obj, unicodeval):
+        """
+        unicodeval: interp-level unicode
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_float(self, w_ffitype, w_obj, floatval):
+        """
+        floatval: lltype.Float
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_singlefloat(self, w_ffitype, w_obj, singlefloatval):
+        """
+        singlefloatval: lltype.SingleFloat
+        """
+        self.error(w_ffitype, w_obj)
+
+    def handle_struct(self, w_ffitype, w_structinstance):
+        """
+        w_structinstance: W_StructureInstance
+        """
+        self.error(w_ffitype, w_structinstance)
+
+    def handle_struct_rawffi(self, w_ffitype, w_structinstance):
+        """
+        This method should be killed as soon as we remove support for _rawffi structures
+        
+        w_structinstance: W_StructureInstance
+        """
+        self.error(w_ffitype, w_structinstance)
+
+
+
+class ToAppLevelConverter(object):
+    """
+    Wrap a low-level value to an app-level object, following the conversion
+    rules which apply to the specified w_ffitype.  The value is got by calling
+    the get_* method corresponding to the w_ffitype. Subclasses should
+    override the desired ones.
+    """
+
+    def __init__(self, space):
+        self.space = space
+
+    def do_and_wrap(self, w_ffitype):
+        from pypy.module._ffi.interp_struct import W__StructDescr
+        space = self.space
+        if w_ffitype.is_longlong():
+            # note that we must check for longlong first, because either
+            # is_signed or is_unsigned returns true anyway
+            assert libffi.IS_32_BIT
+            return self._longlong(w_ffitype)
+        elif w_ffitype.is_signed():
+            intval = self.get_signed(w_ffitype)
+            return space.wrap(intval)
+        elif w_ffitype is app_types.ulong or w_ffitype is app_types.ulonglong:
+            # Note that we the second check (for ulonglong) is meaningful only
+            # on 64 bit, because on 32 bit the ulonglong case would have been
+            # handled by the is_longlong() branch above. On 64 bit, ulonglong
+            # is essentially the same as ulong.
+            #
+            # We need to be careful when the return type is ULONG, because the
+            # value might not fit into a signed LONG, and thus might require
+            # and app-evel <long>.  This is why we need to treat it separately
+            # than the other unsigned types.
+            uintval = self.get_unsigned(w_ffitype)
+            return space.wrap(uintval)
+        elif w_ffitype.is_unsigned(): # note that ulong is handled just before
+            intval = self.get_unsigned_which_fits_into_a_signed(w_ffitype)
+            return space.wrap(intval)
+        elif w_ffitype.is_pointer():
+            uintval = self.get_pointer(w_ffitype)
+            return space.wrap(uintval)
+        elif w_ffitype.is_char():
+            ucharval = self.get_char(w_ffitype)
+            return space.wrap(chr(ucharval))
+        elif w_ffitype.is_unichar():
+            wcharval = self.get_unichar(w_ffitype)
+            return space.wrap(unichr(wcharval))
+        elif w_ffitype.is_double():
+            return self._float(w_ffitype)
+        elif w_ffitype.is_singlefloat():
+            return self._singlefloat(w_ffitype)
+        elif w_ffitype.is_struct():
+            w_structdescr = w_ffitype.w_structdescr
+            if isinstance(w_structdescr, W__StructDescr):
+                return self.get_struct(w_ffitype, w_structdescr)
+            elif isinstance(w_structdescr, W_Structure):
+                return self.get_struct_rawffi(w_ffitype, w_structdescr)
+            else:
+                raise OperationError(self.space.w_TypeError,
+                                     self.space.wrap("Unsupported struct shape"))
+        elif w_ffitype.is_void():
+            voidval = self.get_void(w_ffitype)
+            assert voidval is None
+            return space.w_None
+        else:
+            self.error(w_ffitype)
+
+    def _longlong(self, w_ffitype):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether longlongs are supported
+        if w_ffitype is app_types.slonglong:
+            longlongval = self.get_longlong(w_ffitype)
+            return self.space.wrap(longlongval)
+        elif w_ffitype is app_types.ulonglong:
+            ulonglongval = self.get_ulonglong(w_ffitype)
+            return self.space.wrap(ulonglongval)
+        else:
+            self.error(w_ffitype)
+
+    def _float(self, w_ffitype):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether floats are supported
+        floatval = self.get_float(w_ffitype)
+        return self.space.wrap(floatval)
+
+    def _singlefloat(self, w_ffitype):
+        # a separate function, which can be seen by the jit or not,
+        # depending on whether singlefloats are supported
+        singlefloatval = self.get_singlefloat(w_ffitype)
+        return self.space.wrap(float(singlefloatval))
+
+    def error(self, w_ffitype):
+        raise operationerrfmt(self.space.w_TypeError,
+                              'Unsupported ffi type to convert: %s',
+                              w_ffitype.name)
+
+    def get_longlong(self, w_ffitype):
+        """
+        Return type: lltype.SignedLongLong
+        """
+        self.error(w_ffitype)
+
+    def get_ulonglong(self, w_ffitype):
+        """
+        Return type: lltype.UnsignedLongLong
+        """
+        self.error(w_ffitype)
+
+    def get_signed(self, w_ffitype):
+        """
+        Return type: lltype.Signed
+        """
+        self.error(w_ffitype)
+
+    def get_unsigned(self, w_ffitype):
+        """
+        Return type: lltype.Unsigned
+        """
+        self.error(w_ffitype)
+
+    def get_unsigned_which_fits_into_a_signed(self, w_ffitype):
+        """
+        Return type: lltype.Signed.
+        
+        We return Signed even if the input type is unsigned, because this way
+        we get an app-level <int> instead of a <long>.
+        """
+        self.error(w_ffitype)
+
+    def get_pointer(self, w_ffitype):
+        """
+        Return type: lltype.Unsigned
+        """
+        self.error(w_ffitype)
+
+    def get_char(self, w_ffitype):
+        """
+        Return type: rffi.UCHAR
+        """
+        self.error(w_ffitype)
+
+    def get_unichar(self, w_ffitype):
+        """
+        Return type: rffi.WCHAR_T
+        """
+        self.error(w_ffitype)
+
+    def get_float(self, w_ffitype):
+        """
+        Return type: lltype.Float
+        """
+        self.error(w_ffitype)
+
+    def get_singlefloat(self, w_ffitype):
+        """
+        Return type: lltype.SingleFloat
+        """
+        self.error(w_ffitype)
+
+    def get_struct(self, w_ffitype, w_structdescr):
+        """
+        Return type: lltype.Signed
+        (the address of the structure)
+        """
+        self.error(w_ffitype)
+
+    def get_struct_rawffi(self, w_ffitype, w_structdescr):
+        """
+        This should be killed as soon as we kill support for _rawffi structures
+        
+        Return type: lltype.Unsigned
+        (the address of the structure)
+        """
+        self.error(w_ffitype)
+
+    def get_void(self, w_ffitype):
+        """
+        Return type: None
+        """
+        self.error(w_ffitype)
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -253,7 +253,7 @@
         # XXX: this assumes that you have the _ffi module enabled. In the long
         # term, probably we will move the code for build structures and arrays
         # from _rawffi to _ffi
-        from pypy.module._ffi.interp_ffi import W_FFIType
+        from pypy.module._ffi.interp_ffitype import W_FFIType
         return W_FFIType('<unknown>', self.get_basic_ffi_type(), self)
 
     @unwrap_spec(n=int)
diff --git a/pypy/module/binascii/interp_crc32.py b/pypy/module/binascii/interp_crc32.py
--- a/pypy/module/binascii/interp_crc32.py
+++ b/pypy/module/binascii/interp_crc32.py
@@ -61,7 +61,7 @@
 crc_32_tab = map(r_uint, crc_32_tab)
 
 
- at unwrap_spec(data='bufferstr', oldcrc='truncatedint')
+ at unwrap_spec(data='bufferstr', oldcrc='truncatedint_w')
 def crc32(space, data, oldcrc=0):
     "Compute the CRC-32 incrementally."
 
diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
@@ -134,3 +134,31 @@
         call = ops[idx]
         assert (call.args[0] == 'ConstClass(fabs)' or    # e.g. OS/X
                 int(call.args[0]) == fabs_addr)
+
+
+    def test__ffi_struct(self):
+        def main():
+            from _ffi import _StructDescr, Field, types
+            fields = [
+                Field('x', types.slong),
+                ]
+            descr = _StructDescr('foo', fields)
+            struct = descr.allocate()
+            i = 0
+            while i < 300:
+                x = struct.getfield('x')   # ID: getfield
+                x = x+1
+                struct.setfield('x', x)    # ID: setfield
+                i += 1
+            return struct.getfield('x')
+        #
+        log = self.run(main, [])
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match_by_id('getfield', """
+            guard_not_invalidated(descr=...)
+            i57 = getfield_raw(i46, descr=<FieldS dynamic 0>)
+        """)
+        assert loop.match_by_id('setfield', """
+            setfield_raw(i44, i57, descr=<FieldS dynamic 0>)
+        """)
+
diff --git a/pypy/module/select/interp_kqueue.py b/pypy/module/select/interp_kqueue.py
--- a/pypy/module/select/interp_kqueue.py
+++ b/pypy/module/select/interp_kqueue.py
@@ -3,6 +3,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, generic_new_descr, GetSetProperty
 from pypy.rlib._rsocket_rffi import socketclose
+from pypy.rlib.rarithmetic import r_uint
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -226,9 +227,12 @@
         if self.event:
             lltype.free(self.event, flavor="raw")
 
-    @unwrap_spec(filter=int, flags='c_uint', fflags='c_uint', data=int, udata='c_uint')
-    def descr__init__(self, space, w_ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0):
-        ident = space.c_filedescriptor_w(w_ident)
+    @unwrap_spec(filter=int, flags='c_uint', fflags='c_uint', data=int, udata=r_uint)
+    def descr__init__(self, space, w_ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=r_uint(0)):
+        if space.isinstance_w(w_ident, space.w_long):
+            ident = space.uint_w(w_ident)
+        else:
+            ident = r_uint(space.c_filedescriptor_w(w_ident))
 
         self.event = lltype.malloc(kevent, flavor="raw")
         rffi.setintfield(self.event, "c_ident", ident)
@@ -320,7 +324,7 @@
         return space.wrap(self.event.c_data)
 
     def descr_get_udata(self, space):
-        return space.wrap(rffi.cast(rffi.SIZE_T, self.event.c_udata))
+        return space.wrap(rffi.cast(rffi.UINTPTR_T, self.event.c_udata))
 
 
 W_Kevent.typedef = TypeDef("select.kevent",
diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -74,6 +74,32 @@
     pollmethods[methodname] = interp2app(getattr(Poll, methodname))
 Poll.typedef = TypeDef('select.poll', **pollmethods)
 
+# ____________________________________________________________
+
+
+from pypy.rlib import _rsocket_rffi as _c
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+def _build_fd_set(space, list_w, ll_list, nfds):
+    _c.FD_ZERO(ll_list)
+    fdlist = []
+    for w_f in list_w:
+        fd = space.c_filedescriptor_w(w_f)
+        if fd > nfds:
+            nfds = fd
+        _c.FD_SET(fd, ll_list)
+        fdlist.append(fd)
+    return fdlist, nfds
+_build_fd_set._always_inline_ = True    # get rid of the tuple result
+
+def _unbuild_fd_set(space, list_w, fdlist, ll_list, reslist_w):
+    for i in range(len(fdlist)):
+        fd = fdlist[i]
+        if _c.FD_ISSET(fd, ll_list):
+            reslist_w.append(list_w[i])
+
+
 def select(space, w_iwtd, w_owtd, w_ewtd, w_timeout=None):
     """Wait until one or more file descriptors are ready for some kind of I/O.
 The first three arguments are sequences of file descriptors to be waited for:
@@ -99,29 +125,62 @@
     iwtd_w = space.listview(w_iwtd)
     owtd_w = space.listview(w_owtd)
     ewtd_w = space.listview(w_ewtd)
-    iwtd = [space.c_filedescriptor_w(w_f) for w_f in iwtd_w]
-    owtd = [space.c_filedescriptor_w(w_f) for w_f in owtd_w]
-    ewtd = [space.c_filedescriptor_w(w_f) for w_f in ewtd_w]
-    iwtd_d = {}
-    owtd_d = {}
-    ewtd_d = {}
-    for i in range(len(iwtd)):
-        iwtd_d[iwtd[i]] = iwtd_w[i]
-    for i in range(len(owtd)):
-        owtd_d[owtd[i]] = owtd_w[i]
-    for i in range(len(ewtd)):
-        ewtd_d[ewtd[i]] = ewtd_w[i]
+
+    ll_inl  = lltype.nullptr(_c.fd_set.TO)
+    ll_outl = lltype.nullptr(_c.fd_set.TO)
+    ll_errl = lltype.nullptr(_c.fd_set.TO)
+    ll_timeval = lltype.nullptr(_c.timeval)
+    
     try:
+        fdlistin  = None
+        fdlistout = None
+        fdlisterr = None
+        nfds = -1
+        if len(iwtd_w) > 0:
+            ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw')
+            fdlistin, nfds = _build_fd_set(space, iwtd_w, ll_inl, nfds)
+        if len(owtd_w) > 0:
+            ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw')
+            fdlistout, nfds = _build_fd_set(space, owtd_w, ll_outl, nfds)
+        if len(ewtd_w) > 0:
+            ll_errl = lltype.malloc(_c.fd_set.TO, flavor='raw')
+            fdlisterr, nfds = _build_fd_set(space, ewtd_w, ll_errl, nfds)
+
         if space.is_w(w_timeout, space.w_None):
-            iwtd, owtd, ewtd = rpoll.select(iwtd, owtd, ewtd)
+            timeout = -1.0
         else:
-            iwtd, owtd, ewtd = rpoll.select(iwtd, owtd, ewtd, space.float_w(w_timeout))
-    except rpoll.SelectError, s:
-        w_errortype = space.fromcache(Cache).w_error
-        raise OperationError(w_errortype, space.newtuple([
-            space.wrap(s.errno), space.wrap(s.get_msg())]))
+            timeout = space.float_w(w_timeout)
+        if timeout >= 0.0:
+            ll_timeval = rffi.make(_c.timeval)
+            i = int(timeout)
+            rffi.setintfield(ll_timeval, 'c_tv_sec', i)
+            rffi.setintfield(ll_timeval, 'c_tv_usec', int((timeout-i)*1000000))
 
-    return space.newtuple([
-        space.newlist([iwtd_d[i] for i in iwtd]),
-        space.newlist([owtd_d[i] for i in owtd]),
-        space.newlist([ewtd_d[i] for i in ewtd])])
+        res = _c.select(nfds + 1, ll_inl, ll_outl, ll_errl, ll_timeval)
+
+        if res < 0:
+            errno = _c.geterrno()
+            msg = _c.socket_strerror_str(errno)
+            w_errortype = space.fromcache(Cache).w_error
+            raise OperationError(w_errortype, space.newtuple([
+                space.wrap(errno), space.wrap(msg)]))
+
+        resin_w = []
+        resout_w = []
+        reserr_w = []
+        if res > 0:
+            if fdlistin is not None:
+                _unbuild_fd_set(space, iwtd_w, fdlistin,  ll_inl,  resin_w)
+            if fdlistout is not None:
+                _unbuild_fd_set(space, owtd_w, fdlistout, ll_outl, resout_w)
+            if fdlisterr is not None:
+                _unbuild_fd_set(space, ewtd_w, fdlisterr, ll_errl, reserr_w)
+    finally:
+        if ll_timeval: lltype.free(ll_timeval, flavor='raw')
+        if ll_errl:    lltype.free(ll_errl, flavor='raw')
+        if ll_outl:    lltype.free(ll_outl, flavor='raw')
+        if ll_inl:     lltype.free(ll_inl, flavor='raw')
+
+    return space.newtuple([space.newlist(resin_w),
+                           space.newlist(resout_w),
+                           space.newlist(reserr_w)])
diff --git a/pypy/module/select/test/test_kqueue.py b/pypy/module/select/test/test_kqueue.py
--- a/pypy/module/select/test/test_kqueue.py
+++ b/pypy/module/select/test/test_kqueue.py
@@ -100,7 +100,7 @@
         client.setblocking(False)
         try:
             client.connect(("127.0.0.1", server_socket.getsockname()[1]))
-        except socket.error as e:
+        except socket.error, e:
             if 'bsd' in sys.platform:
                 assert e.args[0] == errno.ENOENT
             else:
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -16,7 +16,8 @@
 def setup():
     for key, value in cpy_signal.__dict__.items():
         if (key.startswith('SIG') or key.startswith('CTRL_')) and \
-                is_valid_int(value):
+                is_valid_int(value) and \
+                key != 'SIG_DFL' and key != 'SIG_IGN':
             globals()[key] = value
             yield key
 
@@ -24,11 +25,18 @@
 SIG_DFL = cpy_signal.SIG_DFL
 SIG_IGN = cpy_signal.SIG_IGN
 signal_names = list(setup())
-signal_values = [globals()[key] for key in signal_names]
 signal_values = {}
 for key in signal_names:
     signal_values[globals()[key]] = None
-
+if sys.platform == 'win32' and not hasattr(cpy_signal,'CTRL_C_EVENT'):
+    # XXX Hack to revive values that went missing,
+    #     Remove this once we are sure the host cpy module has them.
+    signal_values[0] = None
+    signal_values[1] = None
+    signal_names.append('CTRL_C_EVENT')
+    signal_names.append('CTRL_BREAK_EVENT')
+    CTRL_C_EVENT = 0
+    CTRL_BREAK_EVENT = 1
 includes = ['stdlib.h', 'src/signals.h']
 if sys.platform != 'win32':
     includes.append('sys/time.h')
diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -43,7 +43,11 @@
         cls.w_signal = space.appexec([], "(): import signal; return signal")
 
     def test_exported_names(self):
+        import os
         self.signal.__dict__   # crashes if the interpleveldefs are invalid
+        if os.name == 'nt':
+            assert self.signal.CTRL_BREAK_EVENT == 1
+            assert self.signal.CTRL_C_EVENT == 0
 
     def test_basics(self):
         import types, os
@@ -61,8 +65,6 @@
             received.append(signum)
         signal.signal(signum, myhandler)
 
-        print dir(os)
-
         os.kill(os.getpid(), signum)
         # the signal should be delivered to the handler immediately
         assert received == [signum]
diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py
--- a/pypy/module/zlib/interp_zlib.py
+++ b/pypy/module/zlib/interp_zlib.py
@@ -20,7 +20,7 @@
         return intmask((x ^ SIGN_EXTEND2) - SIGN_EXTEND2)
 
 
- at unwrap_spec(string='bufferstr', start='truncatedint')
+ at unwrap_spec(string='bufferstr', start='truncatedint_w')
 def crc32(space, string, start = rzlib.CRC32_DEFAULT_START):
     """
     crc32(string[, start]) -- Compute a CRC-32 checksum of string.
@@ -41,7 +41,7 @@
     return space.wrap(checksum)
 
 
- at unwrap_spec(string='bufferstr', start='truncatedint')
+ at unwrap_spec(string='bufferstr', start='truncatedint_w')
 def adler32(space, string, start=rzlib.ADLER32_DEFAULT_START):
     """
     adler32(string[, start]) -- Compute an Adler-32 checksum of string.
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -55,6 +55,9 @@
         from pypy.rlib.rbigint import rbigint
         return rbigint.fromint(NonConstant(42))
 
+class W_MyType(W_MyObject):
+    def __init__(self):
+        self.mro_w = [w_some_obj(), w_some_obj()]
 
 def w_some_obj():
     if NonConstant(False):
@@ -66,6 +69,9 @@
         return None
     return w_some_obj()
 
+def w_some_type():
+    return W_MyType()
+
 def is_root(w_obj):
     assert isinstance(w_obj, W_Root)
 is_root.expecting = W_Root
@@ -220,6 +226,9 @@
         assert typedef is not None
         return self.fromcache(TypeCache).getorbuild(typedef)
 
+    def type(self, w_obj):
+        return w_some_type()
+
     def unpackiterable(self, w_iterable, expected_length=-1):
         is_root(w_iterable)
         if expected_length < 0:
@@ -287,10 +296,13 @@
                  ObjSpace.ExceptionTable +
                  ['int', 'str', 'float', 'long', 'tuple', 'list',
                   'dict', 'unicode', 'complex', 'slice', 'bool',
-                  'type', 'basestring', 'object']):
+                  'basestring', 'object']):
         setattr(FakeObjSpace, 'w_' + name, w_some_obj())
+    FakeObjSpace.w_type = w_some_type()
     #
     for (name, _, arity, _) in ObjSpace.MethodTable:
+        if name == 'type':
+            continue
         args = ['w_%d' % i for i in range(arity)]
         params = args[:]
         d = {'is_root': is_root,
diff --git a/pypy/objspace/fake/test/test_checkmodule.py b/pypy/objspace/fake/test/test_checkmodule.py
--- a/pypy/objspace/fake/test/test_checkmodule.py
+++ b/pypy/objspace/fake/test/test_checkmodule.py
@@ -1,9 +1,9 @@
-import py
+
 from pypy.objspace.fake.objspace import FakeObjSpace, is_root
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app, W_Root, ObjSpace
-
+from pypy.rpython.test.test_llinterp import interpret
 
 def make_checker():
     check = []
@@ -61,3 +61,18 @@
     assert not check
     space.translates()
     assert check
+
+def test_gettype_mro_untranslated():
+    space = FakeObjSpace()
+    w_type = space.type(space.wrap(1))
+    assert len(w_type.mro_w) == 2
+
+def test_gettype_mro():
+    space = FakeObjSpace()
+
+    def f(i):
+        w_x = space.wrap(i)
+        w_type = space.type(w_x)
+        return len(w_type.mro_w)
+
+    assert interpret(f, [1]) == 2
diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py
--- a/pypy/objspace/std/test/test_stdobjspace.py
+++ b/pypy/objspace/std/test/test_stdobjspace.py
@@ -74,3 +74,20 @@
         space = gettestobjspace(withstrbuf=True)
         cls = space._get_interplevel_cls(space.w_str)
         assert cls is W_AbstractStringObject
+
+    def test_wrap_various_unsigned_types(self):
+        import sys
+        from pypy.rpython.lltypesystem import lltype, rffi
+        space = self.space
+        value = sys.maxint * 2
+        x = rffi.cast(lltype.Unsigned, value)
+        assert space.eq_w(space.wrap(value), space.wrap(x))
+        x = rffi.cast(rffi.UINTPTR_T, value)
+        assert x > 0
+        assert space.eq_w(space.wrap(value), space.wrap(x))
+        value = 60000
+        x = rffi.cast(rffi.USHORT, value)
+        assert space.eq_w(space.wrap(value), space.wrap(x))
+        value = 200
+        x = rffi.cast(rffi.UCHAR, value)
+        assert space.eq_w(space.wrap(value), space.wrap(x))
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -11,6 +11,7 @@
 from pypy.rlib.rdynload import dlopen, dlclose, dlsym, dlsym_byordinal
 from pypy.rlib.rdynload import DLOpenError, DLLHANDLE
 from pypy.rlib import jit
+from pypy.rlib.objectmodel import specialize
 from pypy.tool.autopath import pypydir
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import platform
@@ -141,6 +142,7 @@
 
 FFI_TYPE_P = lltype.Ptr(lltype.ForwardReference())
 FFI_TYPE_PP = rffi.CArrayPtr(FFI_TYPE_P)
+FFI_TYPE_NULL = lltype.nullptr(FFI_TYPE_P.TO)
 
 class CConfig:
     _compilation_info_ = eci
@@ -346,11 +348,13 @@
                                         ('ffistruct', FFI_TYPE_P.TO),
                                         ('members', lltype.Array(FFI_TYPE_P))))
 
-def make_struct_ffitype_e(size, aligment, field_types):
+ at specialize.arg(3)
+def make_struct_ffitype_e(size, aligment, field_types, track_allocation=True):
     """Compute the type of a structure.  Returns a FFI_STRUCT_P out of
        which the 'ffistruct' member is a regular FFI_TYPE.
     """
-    tpe = lltype.malloc(FFI_STRUCT_P.TO, len(field_types)+1, flavor='raw')
+    tpe = lltype.malloc(FFI_STRUCT_P.TO, len(field_types)+1, flavor='raw',
+                        track_allocation=track_allocation)
     tpe.ffistruct.c_type = rffi.cast(rffi.USHORT, FFI_TYPE_STRUCT)
     tpe.ffistruct.c_size = rffi.cast(rffi.SIZE_T, size)
     tpe.ffistruct.c_alignment = rffi.cast(rffi.USHORT, aligment)
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -210,7 +210,7 @@
 
     _immutable_fields_ = ['funcsym']
     argtypes = []
-    restype = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+    restype = clibffi.FFI_TYPE_NULL
     flags = 0
     funcsym = lltype.nullptr(rffi.VOIDP.TO)
 
@@ -416,6 +416,96 @@
     def getaddressindll(self, name):
         return dlsym(self.lib, name)
 
+# ======================================================================
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_int(ffitype, addr, offset):
+    """
+    Return the field of type ``ffitype`` at ``addr+offset``, widened to
+    lltype.Signed.
+    """
+    for TYPE, ffitype2 in clibffi.ffitype_map_int_or_ptr:
+        if ffitype is ffitype2:
+            value = _struct_getfield(TYPE, addr, offset)
+            return rffi.cast(lltype.Signed, value)
+    assert False, "cannot find the given ffitype"
+
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_int(ffitype, addr, offset, value):
+    """
+    Set the field of type ``ffitype`` at ``addr+offset``.  ``value`` is of
+    type lltype.Signed, and it's automatically converted to the right type.
+    """
+    for TYPE, ffitype2 in clibffi.ffitype_map_int_or_ptr:
+        if ffitype is ffitype2:
+            value = rffi.cast(TYPE, value)
+            _struct_setfield(TYPE, addr, offset, value)
+            return
+    assert False, "cannot find the given ffitype"
+
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_longlong(ffitype, addr, offset):
+    """
+    Return the field of type ``ffitype`` at ``addr+offset``, casted to
+    lltype.LongLong.
+    """
+    value = _struct_getfield(lltype.SignedLongLong, addr, offset)
+    return value
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_longlong(ffitype, addr, offset, value):
+    """
+    Set the field of type ``ffitype`` at ``addr+offset``.  ``value`` is of
+    type lltype.LongLong
+    """
+    _struct_setfield(lltype.SignedLongLong, addr, offset, value)
+
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_float(ffitype, addr, offset):
+    value = _struct_getfield(lltype.Float, addr, offset)
+    return value
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_float(ffitype, addr, offset, value):
+    _struct_setfield(lltype.Float, addr, offset, value)
+
+
+ at jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
+def struct_getfield_singlefloat(ffitype, addr, offset):
+    value = _struct_getfield(lltype.SingleFloat, addr, offset)
+    return value
+
+ at jit.oopspec('libffi_struct_setfield(ffitype, addr, offset, value)')
+def struct_setfield_singlefloat(ffitype, addr, offset, value):
+    _struct_setfield(lltype.SingleFloat, addr, offset, value)
+
+
+ at specialize.arg(0)
+def _struct_getfield(TYPE, addr, offset):
+    """
+    Read the field of type TYPE at addr+offset.
+    addr is of type rffi.VOIDP, offset is an int.
+    """
+    addr = rffi.ptradd(addr, offset)
+    PTR_FIELD = lltype.Ptr(rffi.CArray(TYPE))
+    return rffi.cast(PTR_FIELD, addr)[0]
+
+
+ at specialize.arg(0)
+def _struct_setfield(TYPE, addr, offset, value):
+    """
+    Write the field of type TYPE at addr+offset.
+    addr is of type rffi.VOIDP, offset is an int.
+    """
+    addr = rffi.ptradd(addr, offset)
+    PTR_FIELD = lltype.Ptr(rffi.CArray(TYPE))
+    rffi.cast(PTR_FIELD, addr)[0] = value
+
+# ======================================================================
+
 # These specialize.call_location's should really be specialize.arg(0), however
 # you can't hash a pointer obj, which the specialize machinery wants to do.
 # Given the present usage of these functions, it's good enough.
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -97,6 +97,9 @@
 # XXX TODO: replace all int(n) by long(n) and fix everything that breaks.
 # XXX       Then relax it and replace int(n) by n.
 def intmask(n):
+    """
+    NOT_RPYTHON
+    """
     if isinstance(n, objectmodel.Symbolic):
         return n        # assume Symbolics don't overflow
     assert not isinstance(n, float)
@@ -109,6 +112,9 @@
     return int(n)
 
 def longlongmask(n):
+    """
+    NOT_RPYTHON
+    """
     assert isinstance(n, (int, long))
     n = long(n)
     n &= LONGLONG_MASK
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -2,12 +2,16 @@
 
 import py
 
-from pypy.rlib.libffi import (CDLL, Func, get_libc_name, ArgChain, types,
-    IS_32_BIT, array_getitem, array_setitem)
 from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
 from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
+from pypy.rlib.libffi import (CDLL, Func, get_libc_name, ArgChain, types,
+                              IS_32_BIT, array_getitem, array_setitem)
+from pypy.rlib.libffi import (struct_getfield_int, struct_setfield_int,
+                              struct_getfield_longlong, struct_setfield_longlong,
+                              struct_getfield_float, struct_setfield_float,
+                              struct_getfield_singlefloat, struct_setfield_singlefloat)
 
 class TestLibffiMisc(BaseFfiTest):
 
@@ -54,6 +58,33 @@
         del lib
         assert not ALLOCATED
 
+    def test_struct_fields(self):
+        longsize = 4 if IS_32_BIT else 8
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.LONG),
+                              ('y', rffi.SHORT),
+                              ('z', rffi.VOIDP),
+                              )
+        y_ofs = longsize
+        z_ofs = longsize*2
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = 42
+        p.y = rffi.cast(rffi.SHORT, -1)
+        p.z = rffi.cast(rffi.VOIDP, 0x1234)
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_int(types.slong, addr, 0) == 42
+        assert struct_getfield_int(types.sshort, addr, y_ofs) == -1
+        assert struct_getfield_int(types.pointer, addr, z_ofs) == 0x1234
+        #
+        struct_setfield_int(types.slong, addr, 0, 43)
+        struct_setfield_int(types.sshort, addr, y_ofs, 0x1234FFFE) # 0x1234 is masked out
+        struct_setfield_int(types.pointer, addr, z_ofs, 0x4321)
+        assert p.x == 43
+        assert p.y == -2
+        assert rffi.cast(rffi.LONG, p.z) == 0x4321
+        #
+        lltype.free(p, flavor='raw')
+
     def test_array_fields(self):
         POINT = lltype.Struct("POINT",
             ("x", lltype.Float),
@@ -69,18 +100,81 @@
         assert array_getitem(types.double, 16, points, 0, 8) == 2.0
         assert array_getitem(types.double, 16, points, 1, 0) == 3.0
         assert array_getitem(types.double, 16, points, 1, 8) == 4.0
-
+        #
         array_setitem(types.double, 16, points, 0, 0, 10.0)
         array_setitem(types.double, 16, points, 0, 8, 20.0)
         array_setitem(types.double, 16, points, 1, 0, 30.0)
         array_setitem(types.double, 16, points, 1, 8, 40.0)
-
+        #
         assert array_getitem(types.double, 16, points, 0, 0) == 10.0
         assert array_getitem(types.double, 16, points, 0, 8) == 20.0
         assert array_getitem(types.double, 16, points, 1, 0) == 30.0
         assert array_getitem(types.double, 16, points, 1, 8) == 40.0
+        #
+        lltype.free(points, flavor="raw")
 
-        lltype.free(points, flavor="raw")
+
+    def test_struct_fields_longlong(self):
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.LONGLONG),
+                              ('y', rffi.ULONGLONG)
+                              )
+        y_ofs = 8
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = r_longlong(123)
+        p.y = r_ulonglong(456)
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_longlong(types.slonglong, addr, 0) == 123
+        assert struct_getfield_longlong(types.ulonglong, addr, y_ofs) == 456
+        #
+        v = rffi.cast(lltype.SignedLongLong, r_ulonglong(9223372036854775808))
+        struct_setfield_longlong(types.slonglong, addr, 0, v)
+        struct_setfield_longlong(types.ulonglong, addr, y_ofs, r_longlong(-1))
+        assert p.x == -9223372036854775808
+        assert rffi.cast(lltype.UnsignedLongLong, p.y) == 18446744073709551615
+        #
+        lltype.free(p, flavor='raw')
+
+    def test_struct_fields_float(self):
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.DOUBLE),
+                              ('y', rffi.DOUBLE)
+                              )
+        y_ofs = 8
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = 123.4
+        p.y = 567.8
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_float(types.double, addr, 0) == 123.4
+        assert struct_getfield_float(types.double, addr, y_ofs) == 567.8
+        #
+        struct_setfield_float(types.double, addr, 0, 321.0)
+        struct_setfield_float(types.double, addr, y_ofs, 876.5)
+        assert p.x == 321.0
+        assert p.y == 876.5
+        #
+        lltype.free(p, flavor='raw')
+
+    def test_struct_fields_singlefloat(self):
+        POINT = lltype.Struct('POINT',
+                              ('x', rffi.FLOAT),
+                              ('y', rffi.FLOAT)
+                              )
+        y_ofs = 4
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = r_singlefloat(123.4)
+        p.y = r_singlefloat(567.8)
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield_singlefloat(types.double, addr, 0) == r_singlefloat(123.4)
+        assert struct_getfield_singlefloat(types.double, addr, y_ofs) == r_singlefloat(567.8)
+        #
+        struct_setfield_singlefloat(types.double, addr, 0, r_singlefloat(321.0))
+        struct_setfield_singlefloat(types.double, addr, y_ofs, r_singlefloat(876.5))
+        assert p.x == r_singlefloat(321.0)
+        assert p.y == r_singlefloat(876.5)
+        #
+        lltype.free(p, flavor='raw')
+
 
 class TestLibffiCall(BaseFfiTest):
     """
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -436,6 +436,7 @@
           'long long', 'unsigned long long',
           'size_t', 'time_t', 'wchar_t',
           'uintptr_t', 'intptr_t']
+_TYPES_ARE_UNSIGNED = set(['size_t', 'uintptr_t'])   # plus "unsigned *"
 if os.name != 'nt':
     TYPES.append('mode_t')
     TYPES.append('pid_t')
@@ -454,7 +455,7 @@
             name = 'u' + name[9:]
             signed = False
         else:
-            signed = (name != 'size_t')
+            signed = (name not in _TYPES_ARE_UNSIGNED)
         name = name.replace(' ', '')
         names.append(name)
         populatelist.append((name.upper(), c_name, signed))
diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -1544,9 +1544,8 @@
     def register_os_umask(self):
         os_umask = self.llexternal(underscore_on_windows+'umask', [rffi.MODE_T], rffi.MODE_T)
 
-        def umask_llimpl(fd):
-            rposix.validate_fd(fd)
-            res = os_umask(rffi.cast(rffi.MODE_T, fd))
+        def umask_llimpl(newmask):
+            res = os_umask(rffi.cast(rffi.MODE_T, newmask))
             return rffi.cast(lltype.Signed, res)
 
         return extdef([int], int, llimpl=umask_llimpl,
diff --git a/pypy/rpython/rbuiltin.py b/pypy/rpython/rbuiltin.py
--- a/pypy/rpython/rbuiltin.py
+++ b/pypy/rpython/rbuiltin.py
@@ -247,6 +247,11 @@
     vlist = hop.inputargs(lltype.Signed)
     return vlist[0]
 
+def rtype_longlongmask(hop):
+    hop.exception_cannot_occur()
+    vlist = hop.inputargs(lltype.SignedLongLong)
+    return vlist[0]
+
 def rtype_builtin_min(hop):
     v1, v2 = hop.inputargs(hop.r_result, hop.r_result)
     hop.exception_cannot_occur()
@@ -564,6 +569,7 @@
 BUILTIN_TYPER[lltype.Ptr] = rtype_const_result
 BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info
 BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask
+BUILTIN_TYPER[rarithmetic.longlongmask] = rtype_longlongmask
 
 BUILTIN_TYPER[objectmodel.hlinvoke] = rtype_hlinvoke
 
diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -5,7 +5,7 @@
 from pypy.rlib.debug import llinterpcall
 from pypy.rpython.lltypesystem import lltype
 from pypy.tool import udir
-from pypy.rlib.rarithmetic import intmask, is_valid_int
+from pypy.rlib.rarithmetic import intmask, longlongmask, r_int64, is_valid_int
 from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
 from pypy.annotation.builtin import *
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
@@ -79,6 +79,16 @@
         res = self.interpret(f, [r_uint(5)])
         assert type(res) is int and res == 5
 
+    def test_longlongmask(self):
+        def f(x=r_ulonglong):
+            try:
+                return longlongmask(x)
+            except ValueError:
+                return 0
+
+        res = self.interpret(f, [r_ulonglong(5)])
+        assert type(res) is r_int64 and res == 5
+
     def test_rbuiltin_list(self):
         def f(): 
             l=list((1,2,3))
diff --git a/pypy/translator/backendopt/test/test_finalizer.py b/pypy/translator/backendopt/test/test_finalizer.py
--- a/pypy/translator/backendopt/test/test_finalizer.py
+++ b/pypy/translator/backendopt/test/test_finalizer.py
@@ -84,8 +84,8 @@
 
             def __del__(self):
                 if self.x:
+                    lltype.free(self.x, flavor='raw')
                     self.x = lltype.nullptr(S)
-                    lltype.free(self.x, flavor='raw')
 
         def f():
             return A()
diff --git a/pypy/translator/c/test/test_typed.py b/pypy/translator/c/test/test_typed.py
--- a/pypy/translator/c/test/test_typed.py
+++ b/pypy/translator/c/test/test_typed.py
@@ -885,3 +885,13 @@
         assert res == 'acquire, hello, raised, release'
         res = f(2)
         assert res == 'acquire, hello, raised, release'
+
+    def test_longlongmask(self):
+        from pypy.rlib.rarithmetic import longlongmask, r_ulonglong
+        def func(n):
+            m = r_ulonglong(n)
+            m *= 100000
+            return longlongmask(m)
+        f = self.getcompiled(func, [int])
+        res = f(-2000000000)
+        assert res == -200000000000000
diff --git a/pypy/translator/cli/test/test_builtin.py b/pypy/translator/cli/test/test_builtin.py
--- a/pypy/translator/cli/test/test_builtin.py
+++ b/pypy/translator/cli/test/test_builtin.py
@@ -16,7 +16,10 @@
     test_os_isdir = skip_os
     test_os_dup_oo = skip_os
     test_os_access = skip_os
-        
+
+    def test_longlongmask(self):
+        py.test.skip("fix me")
+    
     def test_builtin_math_frexp(self):
         self._skip_powerpc("Mono math floating point problem")
         BaseTestBuiltin.test_builtin_math_frexp(self)
diff --git a/pypy/translator/jvm/test/test_builtin.py b/pypy/translator/jvm/test/test_builtin.py
--- a/pypy/translator/jvm/test/test_builtin.py
+++ b/pypy/translator/jvm/test/test_builtin.py
@@ -47,6 +47,9 @@
         res = self.interpret(fn, [])
         assert stat.S_ISREG(res)
 
+    def test_longlongmask(self):
+        py.test.skip("fix me")
+
 class TestJvmTime(JvmTest, BaseTestTime):
 
     pass


More information about the pypy-commit mailing list