[pypy-commit] pypy ffi-backend: Pom pom pom
arigo
noreply at buildbot.pypy.org
Sat Jun 23 15:46:58 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r55780:e73d843759a7
Date: 2012-06-23 15:46 +0200
http://bitbucket.org/pypy/pypy/changeset/e73d843759a7/
Log: Pom pom pom
diff --git a/pypy/module/_ffi_backend/__init__.py b/pypy/module/_ffi_backend/__init__.py
--- a/pypy/module/_ffi_backend/__init__.py
+++ b/pypy/module/_ffi_backend/__init__.py
@@ -12,9 +12,12 @@
'new_primitive_type': 'newtype.new_primitive_type',
'new_pointer_type': 'newtype.new_pointer_type',
'new_array_type': 'newtype.new_array_type',
+ 'new_struct_type': 'newtype.new_struct_type',
+ 'complete_struct_or_union': 'newtype.complete_struct_or_union',
'newp': 'func.newp',
'cast': 'func.cast',
'sizeof': 'func.sizeof',
'alignof': 'func.alignof',
+ '_getfields': 'func._getfields',
}
diff --git a/pypy/module/_ffi_backend/ctypeobj.py b/pypy/module/_ffi_backend/ctypeobj.py
--- a/pypy/module/_ffi_backend/ctypeobj.py
+++ b/pypy/module/_ffi_backend/ctypeobj.py
@@ -1,16 +1,16 @@
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.rarithmetic import intmask, ovfcheck
-from pypy.rlib.objectmodel import keepalive_until_here
+from pypy.rlib.objectmodel import keepalive_until_here, we_are_translated
from pypy.module._ffi_backend import cdataobj, misc
class W_CType(Wrappable):
- _immutable_ = True
+ #_immutable_ = True XXX newtype.complete_struct_or_union()?
def __init__(self, space, size, name, name_position):
self.space = space
@@ -72,8 +72,20 @@
return name, name_position
def alignof(self):
+ align = self._alignof()
+ if not we_are_translated():
+ # obscure hack when untranslated, maybe, approximate, don't use
+ from pypy.rpython.lltypesystem import llmemory
+ if isinstance(align, llmemory.FieldOffset):
+ align = rffi.sizeof(align.TYPE.y)
+ return align
+
+ def _alignof(self):
xxx
+ def _getfields(self):
+ return None
+
class W_CTypePtrOrArray(W_CType):
@@ -135,7 +147,7 @@
p = rffi.ptradd(cdata, i * self.ctitem.size)
return cdataobj.W_CData(self.space, p, self)
- def alignof(self):
+ def _alignof(self):
from pypy.module._ffi_backend import newtype
return newtype.alignment_of_pointer
@@ -148,7 +160,7 @@
self.length = length
self.ctptr = ctptr
- def alignof(self):
+ def _alignof(self):
return self.ctitem.alignof()
def newp(self, w_init):
@@ -223,7 +235,7 @@
W_CType.__init__(self, space, size, name, name_position)
self.align = align
- def alignof(self):
+ def _alignof(self):
return self.align
def cast_single_char(self, w_ob):
@@ -370,8 +382,61 @@
misc.write_raw_float_data(cdata, value, self.size)
+class W_CTypeStructOrUnion(W_CType):
+ # fields added by complete_struct_or_union():
+ alignment = -1
+ fields_list = None
+ fields_dict = None
+
+ def __init__(self, space, name):
+ name = '%s %s' % (self.kind, name)
+ W_CType.__init__(self, space, -1, name, len(name))
+
+ def _alignof(self):
+ space = self.space
+ if self.size < 0:
+ raise operationerrfmt(space.w_TypeError,
+ "'%s' is not completed yet", self.name)
+ return self.alignment
+
+ def _getfields(self):
+ if self.size < 0:
+ return None
+ space = self.space
+ result = [None] * len(self.fields_list)
+ for fname, field in self.fields_dict.iteritems():
+ i = self.fields_list.index(field)
+ result[i] = space.newtuple([space.wrap(fname),
+ space.wrap(field)])
+ return space.newlist(result)
+
+
+class W_CTypeStruct(W_CTypeStructOrUnion):
+ kind = "struct"
+
+class W_CTypeUnion(W_CTypeStructOrUnion):
+ kind = "union"
+
+class W_CField(Wrappable):
+ _immutable_ = True
+ def __init__(self, ctype, offset, bitshift, bitsize):
+ self.ctype = ctype
+ self.offset = offset
+ self.bitshift = bitshift
+ self.bitsize = bitsize
+
+
W_CType.typedef = TypeDef(
'_ffi_backend.CTypeDescr',
__repr__ = interp2app(W_CType.repr),
)
W_CType.typedef.acceptable_as_base_class = False
+
+W_CField.typedef = TypeDef(
+ '_ffi_backend.CField',
+ type = interp_attrproperty('ctype', W_CField),
+ offset = interp_attrproperty('offset', W_CField),
+ bitshift = interp_attrproperty('bitshift', W_CField),
+ bitsize = interp_attrproperty('bitsize', W_CField),
+ )
+W_CField.typedef.acceptable_as_base_class = False
diff --git a/pypy/module/_ffi_backend/func.py b/pypy/module/_ffi_backend/func.py
--- a/pypy/module/_ffi_backend/func.py
+++ b/pypy/module/_ffi_backend/func.py
@@ -1,8 +1,7 @@
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-from pypy.rlib.objectmodel import we_are_translated
+from pypy.rpython.lltypesystem import lltype, rffi
from pypy.module._ffi_backend import ctypeobj, cdataobj
@@ -40,8 +39,8 @@
@unwrap_spec(ctype=ctypeobj.W_CType)
def alignof(space, ctype):
align = ctype.alignof()
- if not we_are_translated():
- # obscure hack when untranslated, maybe, approximate, don't use
- assert isinstance(align, llmemory.FieldOffset)
- align = rffi.sizeof(align.TYPE.y)
return space.wrap(align)
+
+ at unwrap_spec(ctype=ctypeobj.W_CType)
+def _getfields(space, ctype):
+ return ctype._getfields()
diff --git a/pypy/module/_ffi_backend/newtype.py b/pypy/module/_ffi_backend/newtype.py
--- a/pypy/module/_ffi_backend/newtype.py
+++ b/pypy/module/_ffi_backend/newtype.py
@@ -80,3 +80,98 @@
#
ctypeptr = ctypeobj.W_CTypeArray(space, ctptr, length, arraysize, extra)
return ctypeptr
+
+# ____________________________________________________________
+
+ at unwrap_spec(name=str)
+def new_struct_type(space, name):
+ return ctypeobj.W_CTypeStruct(space, name)
+
+ at unwrap_spec(ctype=ctypeobj.W_CType, totalsize=int, totalalignment=int)
+def complete_struct_or_union(space, ctype, w_fields, w_ignored=None,
+ totalsize=-1, totalalignment=-1):
+ if (not isinstance(ctype, ctypeobj.W_CTypeStructOrUnion)
+ or ctype.size >= 0):
+ raise OperationError(space.w_TypeError,
+ space.wrap("first arg must be a non-initialized"
+ " struct or union ctype"))
+
+ is_union = isinstance(ctype, ctypeobj.W_CTypeUnion)
+ maxsize = 1
+ alignment = 1
+ offset = 0
+ fields_w = space.listview(w_fields)
+ fields_list = []
+ fields_dict = {}
+ prev_bit_position = 0
+ prev_field = None
+
+ for w_field in fields_w:
+ field_w = space.fixedview(w_field)
+ if not (2 <= len(field_w) <= 4):
+ raise OperationError(space.w_TypeError,
+ space.wrap("bad field descr"))
+ fname = space.str_w(field_w[0])
+ ftype = space.interp_w(ctypeobj.W_CType, field_w[1])
+ fbitsize = -1
+ foffset = -1
+ if len(field_w) > 2: fbitsize = space.int_w(field_w[2])
+ if len(field_w) > 3: foffset = space.int_w(field_w[3])
+ #
+ if fname in fields_dict:
+ raise operationerrfmt(space.w_KeyError,
+ "duplicate field name '%s'", fname)
+ #
+ if ftype.size < 0:
+ raise operationerrfmt(space.w_TypeError,
+ "field '%s.%s' has ctype '%s' of unknown size",
+ ctype.name, fname, ftype.name)
+ #
+ falign = ftype.alignof()
+ if alignment < falign:
+ alignment = falign
+ #
+ if foffset < 0:
+ # align this field to its own 'falign' by inserting padding
+ offset = (offset + falign - 1) & ~(falign-1)
+ else:
+ offset = foffset
+ #
+ if fbitsize < 0 or (fbitsize == 8 * ftype.size and
+ not isinstance(ftype, W_CTypePrimitiveChar)):
+ fbitsize = -1
+ bitshift = -1
+ prev_bit_position = 0
+ else:
+ xxx
+ #
+ fld = ctypeobj.W_CField(ftype, offset, bitshift, fbitsize)
+ fields_list.append(fld)
+ fields_dict[fname] = fld
+ #
+ if maxsize < ftype.size:
+ maxsize = ftype.size
+ if not is_union:
+ offset += ftype.size
+
+ if is_union:
+ assert offset == 0
+ offset = maxsize
+ else:
+ if offset == 0:
+ offset = 1
+ offset = (offset + alignment - 1) & ~(alignment-1)
+
+ if totalsize < 0:
+ totalsize = offset
+ elif totalsize < offset:
+ raise operationerrfmt(space.w_TypeError,
+ "%s cannot be of size %d: there are fields at least "
+ "up to %d", ctype.name, totalsize, offset)
+ if totalalignment < 0:
+ totalalignment = alignment
+
+ ctype.size = totalsize
+ ctype.alignment = totalalignment
+ ctype.fields_list = fields_list
+ ctype.fields_dict = fields_dict
diff --git a/pypy/module/_ffi_backend/test/_backend_test_c.py b/pypy/module/_ffi_backend/test/_backend_test_c.py
--- a/pypy/module/_ffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_ffi_backend/test/_backend_test_c.py
@@ -440,6 +440,7 @@
assert repr(BStruct) == "<ctype 'struct foo'>"
BPtr = new_pointer_type(BStruct)
assert repr(BPtr) == "<ctype 'struct foo *'>"
+ py.test.raises(TypeError, alignof, BStruct)
def test_new_union_type():
BUnion = new_union_type("foo")
More information about the pypy-commit
mailing list