[pypy-commit] pypy default: merge

fijal noreply at buildbot.pypy.org
Wed Apr 17 18:20:06 CEST 2013


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: 
Changeset: r63456:2207377f4cc9
Date: 2013-04-17 18:19 +0200
http://bitbucket.org/pypy/pypy/changeset/2207377f4cc9/

Log:	merge

diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -13,7 +13,7 @@
     operations as regalloc_operations,
     operations_with_guard as regalloc_operations_with_guard)
 from rpython.jit.backend.llsupport import jitframe
-from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge
+from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler
 from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
 from rpython.jit.backend.model import CompiledLoopToken
 from rpython.jit.codewriter.effectinfo import EffectInfo
@@ -25,7 +25,7 @@
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref
 from rpython.rtyper.lltypesystem import lltype, rffi
-
+from rpython.jit.backend.arm.detect import detect_hardfloat
 
 class AssemblerARM(ResOpAssembler):
 
@@ -49,6 +49,10 @@
         self.loop_run_counters = []
         self.gcrootmap_retaddr_forced = 0
 
+    def setup_once(self):
+        BaseAssembler.setup_once(self)
+        self.hf_abi = detect_hardfloat()
+
     def setup(self, looptoken):
         assert self.memcpy_addr != 0, 'setup_once() not called?'
         if we_are_translated():
@@ -274,7 +278,7 @@
         mc.CMP_ri(r.r0.value, 0)
         mc.B(self.propagate_exception_path, c=c.EQ)
         #
-        self._reload_frame_if_necessary(mc, align_stack=True)
+        self._reload_frame_if_necessary(mc)
         self._pop_all_regs_from_jitframe(mc, [r.r0, r.r1], self.cpu.supports_floats)
         #
         nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr()
@@ -289,7 +293,7 @@
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
         self.malloc_slowpath = rawstart
 
-    def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0):
+    def _reload_frame_if_necessary(self, mc):
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap and gcrootmap.is_shadow_stack:
             rst = gcrootmap.get_root_stack_top_addr()
@@ -301,7 +305,7 @@
             # frame never uses card marking, so we enforce this is not
             # an array
             self._write_barrier_fastpath(mc, wbdescr, [r.fp], array=False,
-                                         is_frame=True)#, align_stack=align_stack)
+                                         is_frame=True)
 
     def propagate_memoryerror_if_r0_is_null(self):
         # see ../x86/assembler.py:propagate_memoryerror_if_eax_is_null
diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py
--- a/rpython/jit/backend/arm/detect.py
+++ b/rpython/jit/backend/arm/detect.py
@@ -1,5 +1,5 @@
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.clibffi import FFI_DEFAULT_ABI, FFI_SYSV, FFI_VFP
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.platform import CompilationError
 
@@ -14,10 +14,7 @@
     """])
 
 def detect_hardfloat():
-    # http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02419.html
-    if rffi_platform.getdefined('__ARM_PCS_VFP', ''):
-       return rffi_platform.getconstantinteger('__ARM_PCS_VFP', '')
-    return False
+    return FFI_DEFAULT_ABI == FFI_VFP
 
 def detect_float():
     """Check for hardware float support
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -3,7 +3,6 @@
 from rpython.jit.backend.arm import registers as r
 from rpython.jit.backend.arm import shift
 from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE
-
 from rpython.jit.backend.arm.helper.assembler import (gen_emit_op_by_helper_call,
                                                 gen_emit_op_unary_cmp,
                                                 gen_emit_guard_unary_cmp,
@@ -351,10 +350,11 @@
         return cond
 
     def _emit_call(self, adr, arglocs, fcond=c.AL, resloc=None,
-                                            result_info=(-1, -1),
-                                            can_collect=1,
-                                            reload_frame=False):
-        if self.cpu.hf_abi:
+                    result_info=(-1, -1),
+                    # whether to worry about a CALL that can collect; this
+                    # is always true except in call_release_gil
+                    can_collect=True):
+        if self.hf_abi:
             stack_args, adr = self._setup_call_hf(adr, arglocs, fcond,
                                             resloc, result_info)
         else:
@@ -362,6 +362,9 @@
                                             resloc, result_info)
 
         if can_collect:
+            # we push *now* the gcmap, describing the status of GC registers
+            # after the rearrangements done just above, ignoring the return
+            # value eax, if necessary
             noregs = self.cpu.gc_ll_descr.is_shadow_stack()
             gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs)
             self.push_gcmap(self.mc, gcmap, store=True)
@@ -379,17 +382,15 @@
 
         # ensure the result is wellformed and stored in the correct location
         if resloc is not None:
-            if resloc.is_vfp_reg() and not self.cpu.hf_abi:
+            if resloc.is_vfp_reg() and not self.hf_abi:
                 # move result to the allocated register
                 self.mov_to_vfp_loc(r.r0, r.r1, resloc)
             elif resloc.is_reg() and result_info != (-1, -1):
                 self._ensure_result_bit_extension(resloc, result_info[0],
                                                           result_info[1])
         if can_collect:
-            self._reload_frame_if_necessary(self.mc, can_collect=can_collect)
+            self._reload_frame_if_necessary(self.mc)
             self.pop_gcmap(self.mc)
-        elif reload_frame:
-            self._reload_frame_if_necessary(self.mc)
         return fcond
 
     def _restore_sp(self, stack_args, fcond):
@@ -1260,6 +1261,7 @@
     def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc,
                                                                     fcond):
 
+        self._store_force_index(guard_op)
         # first, close the stack in the sense of the asmgcc GC root tracker
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         numargs = op.numargs()
@@ -1268,24 +1270,27 @@
         resloc = arglocs[0]
 
         if gcrootmap:
-            noregs = self.cpu.gc_ll_descr.is_shadow_stack()
-            assert noregs
-            gcmap = self._regalloc.get_gcmap([r.r0], noregs=noregs)
+            # we put the gcmap now into the frame before releasing the GIL,
+            # and pop it below after reacquiring the GIL.  The assumption
+            # is that this gcmap describes correctly the situation at any
+            # point in-between: all values containing GC pointers should
+            # be safely saved out of registers by now, and will not be
+            # manipulated by any of the following CALLs.
+            gcmap = self._regalloc.get_gcmap(noregs=True)
             self.push_gcmap(self.mc, gcmap, store=True)
             self.call_release_gil(gcrootmap, arglocs, regalloc, fcond)
         # do the call
-        self._store_force_index(guard_op)
-        #
         descr = op.getdescr()
         size = descr.get_result_size()
         signed = descr.is_result_signed()
         #
         self._emit_call(adr, callargs, fcond,
                                     resloc, (size, signed),
-                                    can_collect=0)
+                                    can_collect=False)
         # then reopen the stack
         if gcrootmap:
             self.call_reacquire_gil(gcrootmap, resloc, regalloc, fcond)
+            self.pop_gcmap(self.mc)     # remove the gcmap saved above
 
         self._emit_guard_may_force(guard_op, arglocs[numargs+1:], numargs)
         return fcond
@@ -1314,7 +1319,7 @@
         # call the reopenstack() function (also reacquiring the GIL)
         with saved_registers(self.mc, regs_to_save, vfp_regs_to_save):
             self._emit_call(imm(self.reacqgil_addr), [], fcond,
-                    can_collect=False, reload_frame=True)
+                    can_collect=False)
 
     def _store_force_index(self, guard_op):
         faildescr = guard_op.getdescr()
diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py
--- a/rpython/jit/backend/arm/runner.py
+++ b/rpython/jit/backend/arm/runner.py
@@ -6,6 +6,7 @@
 from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
 from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER
 from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.jit.backend.arm.detect import detect_hardfloat
 
 jitframe.STATICSIZE = JITFRAME_FIXED_SIZE
 
@@ -16,7 +17,7 @@
     supports_floats = True
     supports_longlong = False # XXX requires an implementation of
                               # read_timestamp that works in user mode
-    supports_singlefloats = True
+    supports_singlefloats = not detect_hardfloat()
 
     from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE
     all_reg_indexes = range(len(all_regs))
@@ -112,22 +113,10 @@
 
 
 class CPU_ARM(AbstractARMCPU):
-    """ARM v7 uses softfp ABI, requires vfp"""
+    """ARM v7"""
     backend_name = "armv7"
 
-
-class CPU_ARMHF(AbstractARMCPU):
-    """ARM v7 uses hardfp ABI, requires vfp"""
-    hf_abi = True
-    backend_name = "armv7hf"
-    supports_floats = True
-    supports_singlefloats = False
-
-
-class CPU_ARMv6HF(AbstractARMCPU):
+class CPU_ARMv6(AbstractARMCPU):
     """ ARM v6, uses hardfp ABI, requires vfp"""
-    hf_abi = True
     arch_version = 6
-    backend_name = "armv6hf"
-    supports_floats = True
-    supports_singlefloats = False
+    backend_name = "armv6"
diff --git a/rpython/jit/backend/arm/test/conftest.py b/rpython/jit/backend/arm/test/conftest.py
--- a/rpython/jit/backend/arm/test/conftest.py
+++ b/rpython/jit/backend/arm/test/conftest.py
@@ -16,6 +16,7 @@
                     dest="run_translation_tests",
                     help="run tests that translate code")
 
-def pytest_runtest_setup(item):
+def pytest_collect_directory(path, parent):
     if not cpu.startswith('arm'):
         py.test.skip("ARM(v7) tests skipped: cpu is %r" % (cpu,))
+pytest_collect_file = pytest_collect_directory
diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py
--- a/rpython/jit/backend/detect_cpu.py
+++ b/rpython/jit/backend/detect_cpu.py
@@ -61,8 +61,6 @@
                 model = 'x86-without-sse2'
     if model.startswith('arm'):
         from rpython.jit.backend.arm.detect import detect_hardfloat, detect_float
-        if detect_hardfloat():
-            model += 'hf'
         assert detect_float(), 'the JIT-compiler requires a vfp unit'
     return model
 
@@ -77,12 +75,10 @@
         return "rpython.jit.backend.x86.runner", "CPU_X86_64"
     elif backend_name == 'cli':
         return "rpython.jit.backend.cli.runner", "CliCPU"
-    elif backend_name == 'armv6hf':
-        return "rpython.jit.backend.arm.runner", "CPU_ARMv6HF"
-    elif backend_name == 'armv7':
+    elif backend_name.startswith('armv6'):
+        return "rpython.jit.backend.arm.runner", "CPU_ARMv6"
+    elif backend_name.startswith('armv7'):
         return "rpython.jit.backend.arm.runner", "CPU_ARM"
-    elif backend_name == 'armv7hf':
-        return "rpython.jit.backend.arm.runner", "CPU_ARMHF"
     else:
         raise ProcessorAutodetectError, (
             "we have no JIT backend for this cpu: '%s'" % backend_name)
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -34,7 +34,7 @@
                                  ('t', lltype.Signed))
         tdescr = get_size_descr(self.gc_ll_descr, T)
         tdescr.tid = 5678
-        get_field_descr(self.gc_ll_descr, T, 'z')
+        tzdescr = get_field_descr(self.gc_ll_descr, T, 'z')
         #
         A = lltype.GcArray(lltype.Signed)
         adescr = get_array_descr(self.gc_ll_descr, A)
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -129,8 +129,6 @@
 
     def __init__(self, translator):
         from rpython.memory.gc.base import choose_gc_from_config
-        from rpython.memory.gc.base import ARRAY_TYPEID_MAP
-        from rpython.memory.gc import inspector
 
         super(BaseFrameworkGCTransformer, self).__init__(translator,
                                                          inline=True)
@@ -232,7 +230,51 @@
 
         classdef = bk.getuniqueclassdef(GCClass)
         s_gc = annmodel.SomeInstance(classdef)
+
+        self._declare_functions(GCClass, getfn, s_gc, s_typeid16)
+
+        # thread support
+        if translator.config.translation.continuation:
+            root_walker.stacklet_support = True
+            root_walker.need_stacklet_support(self, getfn)
+        if translator.config.translation.thread:
+            root_walker.need_thread_support(self, getfn)
+
+        self.layoutbuilder.encode_type_shapes_now()
+
+        annhelper.finish()   # at this point, annotate all mix-level helpers
+        annhelper.backend_optimize()
+
+        self.collect_analyzer = CollectAnalyzer(self.translator)
+        self.collect_analyzer.analyze_all()
+
+        s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
+        r_gc = self.translator.rtyper.getrepr(s_gc)
+        self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
+        s_gc_data = self.translator.annotator.bookkeeper.valueoftype(
+            gctypelayout.GCData)
+        r_gc_data = self.translator.rtyper.getrepr(s_gc_data)
+        self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata)
+        self.malloc_zero_filled = GCClass.malloc_zero_filled
+
+        HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR
+
+        size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header
+        vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field)
+        self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo)
+        tig = self.layoutbuilder.type_info_group._as_ptr()
+        self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig)
+        sko = llmemory.sizeof(gcdata.TYPE_INFO)
+        self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko)
+
+
+    def _declare_functions(self, GCClass, getfn, s_gc, s_typeid16):
+        from rpython.memory.gc.base import ARRAY_TYPEID_MAP
+        from rpython.memory.gc import inspector
+
         s_gcref = annmodel.SomePtr(llmemory.GCREF)
+        gcdata = self.gcdata
+        translator = self.translator
 
         malloc_fixedsize_clear_meth = GCClass.malloc_fixedsize_clear.im_func
         self.malloc_fixedsize_clear_ptr = getfn(
@@ -466,39 +508,6 @@
                                                    [annmodel.SomeAddress()],
                                                    annmodel.s_None)
 
-        # thread support
-        if translator.config.translation.continuation:
-            root_walker.stacklet_support = True
-            root_walker.need_stacklet_support(self, getfn)
-        if translator.config.translation.thread:
-            root_walker.need_thread_support(self, getfn)
-
-        self.layoutbuilder.encode_type_shapes_now()
-
-        annhelper.finish()   # at this point, annotate all mix-level helpers
-        annhelper.backend_optimize()
-
-        self.collect_analyzer = CollectAnalyzer(self.translator)
-        self.collect_analyzer.analyze_all()
-
-        s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
-        r_gc = self.translator.rtyper.getrepr(s_gc)
-        self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
-        s_gc_data = self.translator.annotator.bookkeeper.valueoftype(
-            gctypelayout.GCData)
-        r_gc_data = self.translator.rtyper.getrepr(s_gc_data)
-        self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata)
-        self.malloc_zero_filled = GCClass.malloc_zero_filled
-
-        HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR
-
-        size_gc_header = self.gcdata.gc.gcheaderbuilder.size_gc_header
-        vtableinfo = (HDR, size_gc_header, self.gcdata.gc.typeid_is_in_field)
-        self.c_vtableinfo = rmodel.inputconst(lltype.Void, vtableinfo)
-        tig = self.layoutbuilder.type_info_group._as_ptr()
-        self.c_type_info_group = rmodel.inputconst(lltype.typeOf(tig), tig)
-        sko = llmemory.sizeof(gcdata.TYPE_INFO)
-        self.c_vtinfo_skip_offset = rmodel.inputconst(lltype.typeOf(sko), sko)
 
     def consider_constant(self, TYPE, value):
         self.layoutbuilder.consider_constant(TYPE, value, self.gcdata.gc)
diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py
--- a/rpython/rlib/clibffi.py
+++ b/rpython/rlib/clibffi.py
@@ -4,6 +4,7 @@
 
 from rpython.rtyper.tool import rffi_platform
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.tool import rffi_platform
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.rarithmetic import intmask, is_emulated_long
 from rpython.rlib.objectmodel import we_are_translated
@@ -15,6 +16,7 @@
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.translator.platform import platform
 from rpython.conftest import cdir
+from platform import machine
 import py
 import os
 import sys
@@ -35,6 +37,8 @@
 _LITTLE_ENDIAN = sys.byteorder == 'little'
 _BIG_ENDIAN = sys.byteorder == 'big'
 
+_ARM = rffi_platform.getdefined('__arm__', '')
+
 if _WIN32:
     from rpython.rlib import rwin32
 
@@ -154,6 +158,10 @@
     if _WIN32 and not _WIN64:
         FFI_STDCALL = rffi_platform.ConstantInteger('FFI_STDCALL')
 
+    if _ARM:
+        FFI_SYSV = rffi_platform.ConstantInteger('FFI_SYSV')
+        FFI_VFP = rffi_platform.ConstantInteger('FFI_VFP')
+
     FFI_TYPE_STRUCT = rffi_platform.ConstantInteger('FFI_TYPE_STRUCT')
 
     size_t = rffi_platform.SimpleType("size_t", rffi.ULONG)
@@ -327,6 +335,9 @@
 FFI_DEFAULT_ABI = cConfig.FFI_DEFAULT_ABI
 if _WIN32 and not _WIN64:
     FFI_STDCALL = cConfig.FFI_STDCALL
+if _ARM:
+    FFI_SYSV = cConfig.FFI_SYSV
+    FFI_VFP = cConfig.FFI_VFP
 FFI_TYPE_STRUCT = cConfig.FFI_TYPE_STRUCT
 FFI_CIFP = lltype.Ptr(cConfig.ffi_cif)
 
diff --git a/rpython/translator/c/database.py b/rpython/translator/c/database.py
--- a/rpython/translator/c/database.py
+++ b/rpython/translator/c/database.py
@@ -64,9 +64,8 @@
 
         self.instrument_ncounter = 0
 
-    def gettypedefnode(self, T, varlength=1):
-        if varlength <= 1:
-            varlength = 1   # it's C after all
+    def gettypedefnode(self, T, varlength=None):
+        if varlength is None:
             key = T
         else:
             key = T, varlength
@@ -94,7 +93,7 @@
             self.pendingsetupnodes.append(node)
         return node
 
-    def gettype(self, T, varlength=1, who_asks=None, argnames=[]):
+    def gettype(self, T, varlength=None, who_asks=None, argnames=[]):
         if isinstance(T, Primitive) or T == GCREF:
             return PrimitiveType[T]
         elif isinstance(T, Typedef):
diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py
--- a/rpython/translator/c/node.py
+++ b/rpython/translator/c/node.py
@@ -47,12 +47,12 @@
     typetag = 'struct'
     extra_union_for_varlength = True
 
-    def __init__(self, db, STRUCT, varlength=1):
+    def __init__(self, db, STRUCT, varlength=None):
         NodeWithDependencies.__init__(self, db)
         self.STRUCT = STRUCT
         self.LLTYPE = STRUCT
         self.varlength = varlength
-        if varlength == 1:
+        if varlength is None:
             basename = STRUCT._name
             with_number = True
         else:
@@ -93,7 +93,7 @@
         self.fields = []
         db = self.db
         STRUCT = self.STRUCT
-        if self.varlength != 1:
+        if self.varlength is not None:
             self.normalizedtypename = db.gettype(STRUCT, who_asks=self)
         if needs_gcheader(self.STRUCT):
             HDR = db.gcpolicy.struct_gcheader_definition(self)
@@ -120,7 +120,7 @@
                 rtti = getRuntimeTypeInfo(STRUCT)
             except ValueError:
                 pass
-        if self.varlength == 1:
+        if self.varlength is None:
             self.db.gcpolicy.struct_setup(self, rtti)
         return self.gcinfo
     gcinfo = defaultproperty(computegcinfo)
@@ -160,12 +160,14 @@
             if typename == PrimitiveType[Void]:
                 line = '/* %s */' % line
             else:
+                if is_empty and typename.endswith('[RPY_VARLENGTH]'):
+                    yield '\tRPY_DUMMY_VARLENGTH'
                 is_empty = False
             yield '\t' + line
         if is_empty:
             yield '\t' + 'char _dummy; /* this struct is empty */'
         yield '};'
-        if self.varlength != 1:
+        if self.varlength is not None:
             assert self.typetag == 'struct'
             yield 'union %su {' % self.name
             yield '  struct %s a;' % self.name
@@ -182,7 +184,7 @@
 
     def debug_offsets(self):
         # generate number exprs giving the offset of the elements in the struct
-        assert self.varlength == 1
+        assert self.varlength is None
         for name in self.fieldnames:
             FIELD_T = self.c_struct_field_type(name)
             if FIELD_T is Void:
@@ -196,18 +198,25 @@
                     yield 'offsetof(%s %s, %s)' % (self.typetag,
                                                    self.name, cname)
 
+def deflength(varlength):
+    if varlength is None:
+        return 'RPY_VARLENGTH'
+    elif varlength == 0:
+        return 'RPY_LENGTH0'
+    else:
+        return varlength
 
 class ArrayDefNode(NodeWithDependencies):
     typetag = 'struct'
     extra_union_for_varlength = True
 
-    def __init__(self, db, ARRAY, varlength=1):
+    def __init__(self, db, ARRAY, varlength=None):
         NodeWithDependencies.__init__(self, db)
         self.ARRAY = ARRAY
         self.LLTYPE = ARRAY
         self.gcfields = []
         self.varlength = varlength
-        if varlength == 1:
+        if varlength is None:
             basename = 'array'
             with_number = True
         else:
@@ -226,7 +235,7 @@
         db = self.db
         ARRAY = self.ARRAY
         self.gcinfo    # force it to be computed
-        if self.varlength != 1:
+        if self.varlength is not None:
             self.normalizedtypename = db.gettype(ARRAY, who_asks=self)
         if needs_gcheader(ARRAY):
             HDR = db.gcpolicy.array_gcheader_definition(self)
@@ -238,7 +247,7 @@
     def computegcinfo(self):
         # let the gcpolicy do its own setup
         self.gcinfo = None   # unless overwritten below
-        if self.varlength == 1:
+        if self.varlength is None:
             self.db.gcpolicy.array_setup(self)
         return self.gcinfo
     gcinfo = defaultproperty(computegcinfo)
@@ -269,21 +278,22 @@
             yield '\t' + cdecl(typename, fname) + ';'
         if not self.ARRAY._hints.get('nolength', False):
             yield '\tlong length;'
-        line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength)
+        line = '%s;' % cdecl(self.itemtypename,
+                             'items[%s]' % deflength(self.varlength))
         if self.ARRAY.OF is Void:    # strange
             line = '/* array of void */'
             if self.ARRAY._hints.get('nolength', False):
                 line = 'char _dummy; ' + line
         yield '\t' + line
         yield '};'
-        if self.varlength != 1:
+        if self.varlength is not None:
             yield 'union %su {' % self.name
             yield '  struct %s a;' % self.name
             yield '  %s;' % cdecl(self.normalizedtypename, 'b')
             yield '};'
 
     def visitor_lines(self, prefix, on_item):
-        assert self.varlength == 1
+        assert self.varlength is None
         ARRAY = self.ARRAY
         # we need a unique name for this C variable, or at least one that does
         # not collide with the expression in 'prefix'
@@ -310,7 +320,7 @@
 
     def debug_offsets(self):
         # generate three offsets for debugging inspection
-        assert self.varlength == 1
+        assert self.varlength is None
         if not self.ARRAY._hints.get('nolength', False):
             yield 'offsetof(struct %s, length)' % (self.name,)
         else:
@@ -333,7 +343,7 @@
     forward_decl = None
     extra_union_for_varlength = False
 
-    def __init__(self, db, ARRAY, varlength=1):
+    def __init__(self, db, ARRAY, varlength=None):
         NodeWithDependencies.__init__(self, db)
         self.ARRAY = ARRAY
         self.LLTYPE = ARRAY
@@ -342,8 +352,8 @@
         # There is no such thing as an array of voids:
         # we use a an array of chars instead; only the pointer can be void*.
         self.itemtypename = db.gettype(contained_type, who_asks=self)
-        self.fulltypename = self.itemtypename.replace('@', '(@)[%d]' %
-                                                      (self.varlength,))
+        self.fulltypename = self.itemtypename.replace('@', '(@)[%s]' %
+                                                      deflength(varlength))
         if ARRAY._hints.get("render_as_void"):
             self.fullptrtypename = 'void *@'
         else:
@@ -493,7 +503,8 @@
         Node.__init__(self, db)
         self.obj = obj
         self.typename = db.gettype(T)  #, who_asks=self)
-        self.implementationtypename = db.gettype(T, varlength=self.getlength())
+        self.implementationtypename = db.gettype(
+            T, varlength=self.getvarlength())
         parent, parentindex = parentlink(obj)
         if obj in exports.EXPORTS_obj2name:
             self.name = exports.EXPORTS_obj2name[obj]
@@ -559,8 +570,8 @@
     def startupcode(self):
         return []
 
-    def getlength(self):
-        return 1
+    def getvarlength(self):
+        return None
 
 assert not USESLOTS or '__dict__' not in dir(ContainerNode)
 
@@ -578,10 +589,10 @@
         for name in T._names:
             yield getattr(self.obj, name)
 
-    def getlength(self):
+    def getvarlength(self):
         T = self.getTYPE()
         if T._arrayfld is None:
-            return 1
+            return None
         else:
             array = getattr(self.obj, T._arrayfld)
             return len(array.items)
@@ -696,7 +707,7 @@
     def enum_dependencies(self):
         return self.obj.items
 
-    def getlength(self):
+    def getvarlength(self):
         return len(self.obj.items)
 
     def initializationexpr(self, decoration=''):
@@ -765,8 +776,8 @@
         for i in range(self.obj.getlength()):
             yield self.obj.getitem(i)
 
-    def getlength(self):
-        return 1    # not variable-sized!
+    def getvarlength(self):
+        return None    # not variable-sized!
 
     def initializationexpr(self, decoration=''):
         T = self.getTYPE()
diff --git a/rpython/translator/c/src/g_prerequisite.h b/rpython/translator/c/src/g_prerequisite.h
--- a/rpython/translator/c/src/g_prerequisite.h
+++ b/rpython/translator/c/src/g_prerequisite.h
@@ -14,8 +14,14 @@
 
 #ifdef __GNUC__       /* other platforms too, probably */
 typedef _Bool bool_t;
+# define RPY_VARLENGTH   /* nothing: [RPY_VARLENGTH] => [] */
+# define RPY_LENGTH0     0       /* array decl [0] are ok  */
+# define RPY_DUMMY_VARLENGTH     char _dummy[0];
 #else
 typedef unsigned char bool_t;
+# define RPY_VARLENGTH   1       /* [RPY_VARLENGTH] => [1] */
+# define RPY_LENGTH0     1       /* array decl [0] are bad */
+# define RPY_DUMMY_VARLENGTH     /* nothing */
 #endif
 
 
diff --git a/rpython/translator/c/src/support.h b/rpython/translator/c/src/support.h
--- a/rpython/translator/c/src/support.h
+++ b/rpython/translator/c/src/support.h
@@ -2,16 +2,6 @@
 /************************************************************/
  /***  C header subsection: support functions              ***/
 
-/* a temporary(?) workaround for GCC 4.8.  See:
-    http://stackoverflow.com/questions/16016627/
-*/
-#ifdef __GNUC__
-# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
-#  pragma GCC optimize("no-aggressive-loop-optimizations")
-# endif
-#endif
-
-
 #define RUNNING_ON_LLINTERP	0
 #define OP_JIT_RECORD_KNOWN_CLASS(i, c, r)  /* nothing */
 
diff --git a/rpython/translator/c/test/test_lltyped.py b/rpython/translator/c/test/test_lltyped.py
--- a/rpython/translator/c/test/test_lltyped.py
+++ b/rpython/translator/c/test/test_lltyped.py
@@ -919,3 +919,25 @@
             return x
         fn = self.getcompiled(llf, [int])
         assert fn(5) == 42
+
+    def test_raw_array_field_prebuilt(self):
+        from rpython.rtyper.lltypesystem import rffi
+        S = Struct('S', ('array', rffi.CArray(Signed)))
+        s0 = malloc(S, 0, flavor='raw', immortal=True)
+        s1 = malloc(S, 1, flavor='raw', immortal=True)
+        s1.array[0] = 521
+        s2 = malloc(S, 2, flavor='raw', immortal=True)
+        s2.array[0] = 12
+        s2.array[1] = 34
+        def llf(i):
+            if   i == 0: s = s0
+            elif i == 1: s = s1
+            else:        s = s2
+            x = 10
+            if i > 0:
+                x += s.array[i-1]
+            return x
+        fn = self.getcompiled(llf, [int])
+        assert fn(0) == 10
+        assert fn(1) == 10 + 521
+        assert fn(2) == 10 + 34


More information about the pypy-commit mailing list