[pypy-svn] r72828 - in pypy/branch/fix-64/pypy/rpython/tool: . test

arigo at codespeak.net arigo at codespeak.net
Thu Mar 25 17:36:27 CET 2010


Author: arigo
Date: Thu Mar 25 17:36:26 2010
New Revision: 72828

Modified:
   pypy/branch/fix-64/pypy/rpython/tool/rffi_platform.py
   pypy/branch/fix-64/pypy/rpython/tool/test/test_rffi_platform.py
Log:
Whack whack whack until the test passes.


Modified: pypy/branch/fix-64/pypy/rpython/tool/rffi_platform.py
==============================================================================
--- pypy/branch/fix-64/pypy/rpython/tool/rffi_platform.py	(original)
+++ pypy/branch/fix-64/pypy/rpython/tool/rffi_platform.py	Thu Mar 25 17:36:26 2010
@@ -299,11 +299,16 @@
             fieldoffsets.append(offset)
             seen[cell] = True
 
+        allfields = tuple(['c_' + name for name, _ in fields])
+        padfields = tuple(padfields)
         name = self.name
+        padding_drop = PaddingDrop(name, allfields, padfields,
+                                   config_result.CConfig._compilation_info_)
         hints = {'align': info['align'],
                  'size': info['size'],
                  'fieldoffsets': tuple(fieldoffsets),
-                 'padding': tuple(padfields)}
+                 'padding': padfields,
+                 'get_padding_drop': padding_drop}
         if name.startswith('struct '):
             name = name[7:]
         else:
@@ -477,6 +482,85 @@
         return info['size']
 
 # ____________________________________________________________
+
+class PaddingDrop(object):
+    # Compute (lazily) the padding_drop for a structure.
+    # See test_generate_padding for more information.
+    cache = None
+
+    def __init__(self, name, allfields, padfields, eci):
+        self.name = name
+        self.allfields = allfields
+        self.padfields = padfields
+        self.eci = eci
+
+    def __call__(self, types):
+        if self.cache is None:
+            self.compute_now(types)
+        return self.cache
+
+    def compute_now(self, types):
+        # Some simplifying assumptions there.  We assume that all fields
+        # are either integers or pointers, so can be written in C as '0'.
+        # We also assume that the C backend gives us in 'types' a dictionary
+        # mapping non-padding field names to their C type (without '@').
+        drops = []
+        staticfields = []
+        consecutive_pads = []
+        for fieldname in self.allfields:
+            if fieldname in self.padfields:
+                consecutive_pads.append(fieldname)
+                continue
+            staticfields.append(types[fieldname])
+            if consecutive_pads:
+                # In that case we have to ask: how many of these pads are
+                # really needed?  The correct answer might be between none
+                # and all of the pads listed in 'consecutive_pads'.
+                for i in range(len(consecutive_pads)+1):
+                    class CConfig:
+                        _compilation_info_ = self.eci
+                        FIELDLOOKUP = _PaddingDropFieldLookup(self.name,
+                                                              staticfields,
+                                                              fieldname)
+                    got = configure(CConfig)['FIELDLOOKUP']
+                    if got == 1:
+                        break     # found
+                    staticfields.insert(-1, None)
+                else:
+                    raise Exception("could not determine the detailed field"
+                                    " layout of %r" % (self.name,))
+                # succeeded with 'i' pads.  Drop all pads beyond that.
+                drops += consecutive_pads[i:]
+            consecutive_pads = []
+        self.cache = drops
+
+class _PaddingDropFieldLookup(CConfigEntry):
+    def __init__(self, name, staticfields, fieldname):
+        self.name = name
+        self.staticfields = staticfields
+        self.fieldname = fieldname
+
+    def prepare_code(self):
+        yield 'typedef %s platcheck_t;' % (self.name,)
+        yield 'static platcheck_t s = {'
+        for i, type in enumerate(self.staticfields):
+            if i == len(self.staticfields)-1:
+                value = -1
+            else:
+                value = 0
+            if type:
+                yield '\t(%s)%s,' % (type, value)
+            else:
+                yield '\t%s,' % (value,)
+        yield '};'
+        fieldname = self.fieldname
+        assert fieldname.startswith('c_')
+        yield 'dump("fieldlookup", s.%s != 0);' % (fieldname[2:],)
+
+    def build_result(self, info, config_result):
+        return info['fieldlookup']
+
+# ____________________________________________________________
 #
 # internal helpers
 

Modified: pypy/branch/fix-64/pypy/rpython/tool/test/test_rffi_platform.py
==============================================================================
--- pypy/branch/fix-64/pypy/rpython/tool/test/test_rffi_platform.py	(original)
+++ pypy/branch/fix-64/pypy/rpython/tool/test/test_rffi_platform.py	Thu Mar 25 17:36:26 2010
@@ -275,7 +275,8 @@
            """, [("c1", lltype.Signed),
                  ("s1", lltype.Signed)])
     assert S._hints['padding'] == ('c__pad0',)
-    assert S._hints['padding_drop'] == ('c__pad0',)
+    d = {'c_c1': 'char', 'c_s1': 'short'}
+    assert S._hints['get_padding_drop'](d) == ['c__pad0']
     #
     S = rffi_platform.getstruct("foobar_t", """
            typedef struct {
@@ -286,7 +287,8 @@
            """, [("c1", lltype.Signed),
                  ("s1", lltype.Signed)])
     assert S._hints['padding'] == ('c__pad0',)
-    assert S._hints['padding_drop'] == ()
+    d = {'c_c1': 'char', 'c_s1': 'short'}
+    assert S._hints['get_padding_drop'](d) == []
     #
     S = rffi_platform.getstruct("foobar_t", """
            typedef struct {
@@ -298,7 +300,8 @@
            """, [("c1", lltype.Signed),
                  ("i1", lltype.Signed)])
     assert S._hints['padding'] == ('c__pad0', 'c__pad1', 'c__pad2')
-    assert S._hints['padding_drop'] == ('c__pad1', 'c__pad2')
+    d = {'c_c1': 'char', 'c_i1': 'int'}
+    assert S._hints['get_padding_drop'](d) == ['c__pad1', 'c__pad2']
     #
     S = rffi_platform.getstruct("foobar_t", """
            typedef struct {
@@ -311,7 +314,8 @@
            """, [("c1", lltype.Signed),
                  ("i1", lltype.Signed)])
     assert S._hints['padding'] == ('c__pad0', 'c__pad1', 'c__pad2')
-    assert S._hints['padding_drop'] == ('c__pad2',)
+    d = {'c_c1': 'char', 'c_i1': 'int'}
+    assert S._hints['get_padding_drop'](d) == ['c__pad2']
     #
     S = rffi_platform.getstruct("foobar_t", """
            typedef struct {
@@ -323,7 +327,8 @@
            """, [("c1", lltype.Signed),
                  ("i1", lltype.Signed)])
     assert S._hints['padding'] == ('c__pad0', 'c__pad1', 'c__pad2')
-    assert S._hints['padding_drop'] == ('c__pad1', 'c__pad2')
+    d = {'c_c1': 'char', 'c_i1': 'int'}
+    assert S._hints['get_padding_drop'](d) == ['c__pad1', 'c__pad2']
     #
     S = rffi_platform.getstruct("foobar_t", """
            typedef struct {
@@ -340,4 +345,5 @@
                  ("s1", lltype.Signed)])
     assert S._hints['padding'] == ('c__pad0', 'c__pad1', 'c__pad2',
                                    'c__pad3', 'c__pad4')
-    assert S._hints['padding_drop'] == ('c__pad1', 'c__pad2', 'c__pad4')
+    d = {'c_c1': 'char', 'c_i1': 'int', 'c_s1': 'short'}
+    assert S._hints['get_padding_drop'](d) == ['c__pad1', 'c__pad2', 'c__pad4']



More information about the Pypy-commit mailing list