[pypy-svn] r65663 - in pypy/branch/pyjitpl5-experiments/pypy/jit/backend: llvm test

arigo at codespeak.net arigo at codespeak.net
Mon Jun 8 17:12:59 CEST 2009


Author: arigo
Date: Mon Jun  8 17:12:58 2009
New Revision: 65663

Modified:
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/compile.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/runner_test.py
Log:
Arrays.


Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/compile.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/compile.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/compile.py	Mon Jun  8 17:12:58 2009
@@ -7,7 +7,7 @@
 from pypy.jit.metainterp import resoperation
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.backend.x86 import symbolic     # xxx
-from pypy.jit.backend.llvm.runner import CallDescr, FieldDescr
+from pypy.jit.backend.llvm.runner import CallDescr, FieldDescr, ArrayDescr
 
 # ____________________________________________________________
 
@@ -473,18 +473,8 @@
                                           self.getptrarg(v_structure),
                                           indices, 1, "")
         lltype.free(indices, flavor='raw')
-        if fielddescr.size < 0:   # pointer field
-            ty_val = self.cpu.ty_char_ptr
-            ty = self.cpu.ty_char_ptr_ptr
-        elif fielddescr.size == symbolic.get_size(lltype.Signed,
-                                              self.cpu.translate_support_code):
-            ty_val = self.cpu.ty_int
-            ty = self.cpu.ty_int_ptr
-        elif fielddescr.size == 1:
-            ty_val = self.cpu.ty_char
-            ty = self.cpu.ty_char_ptr
-        else:
-            raise BadSizeError
+        ty_val = self.cpu.types_by_index[fielddescr.size_index]
+        ty = self.cpu.types_ptr_by_index[fielddescr.size_index]
         location = llvm_rffi.LLVMBuildBitCast(self.builder, location, ty, "")
         return location, ty_val
 
@@ -492,6 +482,8 @@
         loc, _ = self._generate_field_gep(op.args[0], op.descr)
         self.vars[op.result] = llvm_rffi.LLVMBuildLoad(self.builder, loc, "")
 
+    generate_GETFIELD_GC_PURE = generate_GETFIELD_GC
+
     def generate_SETFIELD_GC(self, op):
         loc, tyval = self._generate_field_gep(op.args[0], op.descr)
         if tyval == self.cpu.ty_char_ptr:
@@ -571,14 +563,56 @@
             self.getptrarg(op.args[0]),
             self.cpu.const_null_charptr, "")
 
+    def generate_ARRAYLEN_GC(self, op):
+        arraydescr = op.descr
+        assert isinstance(arraydescr, ArrayDescr)
+        array = llvm_rffi.LLVMBuildBitCast(self.builder,
+                                           self.getptrarg(op.args[0]),
+                                           arraydescr.ty_array_ptr, "")
+        indices = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), 2,
+                                flavor='raw')
+        indices[0] = self.cpu.const_zero
+        indices[1] = self.cpu.const_array_index_length
+        loc = llvm_rffi.LLVMBuildGEP(self.builder, array, indices, 2, "")
+        lltype.free(indices, flavor='raw')
+        self.vars[op.result] = llvm_rffi.LLVMBuildLoad(self.builder, loc, "")
+
+    def _generate_array_gep(self, v_array, v_index, arraydescr):
+        assert isinstance(arraydescr, ArrayDescr)
+        array = llvm_rffi.LLVMBuildBitCast(self.builder,
+                                           self.getptrarg(v_array),
+                                           arraydescr.ty_array_ptr, "")
+        indices = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), 3,
+                                flavor='raw')
+        indices[0] = self.cpu.const_zero
+        indices[1] = self.cpu.const_array_index_array
+        indices[2] = self.getintarg(v_index)
+        location = llvm_rffi.LLVMBuildGEP(self.builder, array, indices, 3, "")
+        lltype.free(indices, flavor='raw')
+        ty_val = self.cpu.types_by_index[arraydescr.itemsize_index]
+        return location, ty_val
+
+    def generate_GETARRAYITEM_GC(self, op):
+        loc, _ = self._generate_array_gep(op.args[0], op.args[1], op.descr)
+        self.vars[op.result] = llvm_rffi.LLVMBuildLoad(self.builder, loc, "")
+
+    generate_GETARRAYITEM_GC_PURE = generate_GETARRAYITEM_GC
+
+    def generate_SETARRAYITEM_GC(self, op):
+        loc, tyval = self._generate_array_gep(op.args[0], op.args[1], op.descr)
+        if tyval == self.cpu.ty_char_ptr:
+            value_ref = self.getptrarg(op.args[2])
+        elif tyval == self.cpu.ty_char:
+            value_ref = self.getchararg(op.args[2])
+        else:
+            value_ref = self.getintarg(op.args[2])
+        llvm_rffi.LLVMBuildStore(self.builder, value_ref, loc, "")
+
 # ____________________________________________________________
 
 class MissingOperation(Exception):
     pass
 
-class BadSizeError(Exception):
-    pass
-
 all_operations = {}
 for _key, _value in rop.__dict__.items():
     if 'A' <= _key <= 'Z':

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/llvm_rffi.py	Mon Jun  8 17:12:58 2009
@@ -123,6 +123,14 @@
                                rffi.UINT,                   # param count
                                rffi.INT],                   # flag: is_vararg
                               LLVMTypeRef)
+LLVMStructType = llexternal('LLVMStructType',
+                            [rffi.CArrayPtr(LLVMTypeRef),   # element types
+                             rffi.UINT,                     # element count
+                             rffi.INT],                     # flag: packed
+                            LLVMTypeRef)
+LLVMArrayType = llexternal('LLVMArrayType', [LLVMTypeRef,   # element type
+                                             rffi.UINT],    # element count
+                           LLVMTypeRef)
 LLVMPointerType = llexternal('LLVMPointerType', [LLVMTypeRef,  # element type
                                                  rffi.UINT],   # address space
                              LLVMTypeRef)

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py	Mon Jun  8 17:12:58 2009
@@ -18,6 +18,10 @@
     SIGNED_VALUE = rffi.CFixedArray(lltype.Signed, 1)
     POINTER_VALUE = rffi.CFixedArray(llmemory.GCREF, 1)
 
+    SIZE_GCPTR = 0
+    SIZE_INT   = 1
+    SIZE_CHAR  = 2
+
     def __init__(self, rtyper, stats=None, translate_support_code=False,
                  annmixlevel=None):
         self.rtyper = rtyper
@@ -25,12 +29,19 @@
         self.compiled_functions = []
         self.fail_ops = []
         self.in_out_args = []
-        self._descr_caches = {}
+        self._descr_caches = {
+            ('array', self.SIZE_GCPTR): ArrayDescr(self.SIZE_GCPTR),
+            ('array', self.SIZE_INT):   ArrayDescr(self.SIZE_INT),
+            ('array', self.SIZE_CHAR):  ArrayDescr(self.SIZE_CHAR),
+            }
         self.fielddescr_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr')
         if sys.maxint == 2147483647:
             self.size_of_int = 4
         else:
             self.size_of_int = 8
+        basesize, _, ofs_length = symbolic.get_array_token(
+            lltype.GcArray(lltype.Signed), self.translate_support_code)
+        self._fixed_array_shape = basesize, ofs_length
 
     def setup_once(self):
         if not we_are_translated():
@@ -53,6 +64,41 @@
         self.const_minint = self._make_const_int(-sys.maxint-1)
         self.const_null_charptr = self._make_const(0, self.ty_char_ptr)
         #
+        self.types_by_index = [self.ty_char_ptr,     # SIZE_GCPTR
+                               self.ty_int,          # SIZE_INT
+                               self.ty_char]         # SIZE_CHAR
+        self.types_ptr_by_index = [self.ty_char_ptr_ptr,   # SIZE_GCPTR
+                                   self.ty_int_ptr,        # SIZE_INT
+                                   self.ty_char_ptr]       # SIZE_CHAR
+        pad1 = self._fixed_array_shape[1]
+        pad2 = (self._fixed_array_shape[0] - self._fixed_array_shape[1]
+                - self.size_of_int)
+        self.const_array_index_length = self._make_const_int(pad1)
+        self.const_array_index_array = self._make_const_int(pad1 + 1 + pad2)
+        for i in range(len(self.types_by_index)):
+            # build the type "struct{pad1.., length, pad2.., array{type}}"
+            typeslist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMTypeRef),
+                                      pad1+pad2+2, flavor='raw')
+            # add the first padding
+            for n in range(pad1):
+                typeslist[n] = self.ty_char
+            # add the length field
+            typeslist[pad1] = self.ty_int
+            # add the second padding
+            for n in range(pad1+1, pad1+1+pad2):
+                typeslist[n] = self.ty_char
+            # add the array field
+            typeslist[pad1+1+pad2] = llvm_rffi.LLVMArrayType(
+                self.types_by_index[i], 0)
+            # done
+            ty_array = llvm_rffi.LLVMStructType(typeslist,
+                                                pad1+pad2+2,
+                                                1)
+            lltype.free(typeslist, flavor='raw')
+            ty_array_ptr = llvm_rffi.LLVMPointerType(ty_array, 0)
+            arraydescr = self._descr_caches['array', i]
+            arraydescr.ty_array_ptr = ty_array_ptr
+        #
         arglist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMTypeRef), 0,
                                 flavor='raw')
         self.ty_func = llvm_rffi.LLVMFunctionType(self.ty_int, arglist, 0,
@@ -230,20 +276,38 @@
             # indirect casting because the above doesn't work with ll2ctypes
             return llmemory.cast_ptr_to_adr(rffi.cast(llmemory.GCREF, x))
 
+    def _get_size_index(self, TYPE):
+        if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
+            return self.SIZE_GCPTR
+        else:
+            size = symbolic.get_size(TYPE, self.translate_support_code)
+            if size == symbolic.get_size(lltype.Signed,
+                                         self.translate_support_code):
+                return self.SIZE_INT
+            elif size == 1:
+                return self.SIZE_CHAR
+            else:
+                raise BadSizeError(S, fieldname, size)
+
     def fielddescrof(self, S, fieldname):
         try:
             return self._descr_caches['field', S, fieldname]
         except KeyError:
             pass
-        ofs, size = symbolic.get_field_token(S, fieldname,
-                                             self.translate_support_code)
-        if (isinstance(getattr(S, fieldname), lltype.Ptr) and
-            getattr(S, fieldname).TO._gckind == 'gc'):
-            size = -1
-        descr = FieldDescr(ofs, size)
+        ofs, _ = symbolic.get_field_token(S, fieldname,
+                                          self.translate_support_code)
+        size_index = self._get_size_index(getattr(S, fieldname))
+        descr = FieldDescr(ofs, size_index)
         self._descr_caches['field', S, fieldname] = descr
         return descr
 
+    def arraydescrof(self, A):
+        basesize, _, ofs_length = symbolic.get_array_token(A,
+                                               self.translate_support_code)
+        assert self._fixed_array_shape == (basesize, ofs_length)
+        itemsize_index = self._get_size_index(A.OF)
+        return self._descr_caches['array', itemsize_index]
+
     def calldescrof(self, FUNC, ARGS, RESULT):
         try:
             return self._descr_caches['call', ARGS, RESULT]
@@ -317,9 +381,15 @@
 
 
 class FieldDescr(AbstractDescr):
-    def __init__(self, offset, size):
+    def __init__(self, offset, size_index):
         self.offset = offset
-        self.size = size      # set to -1 to mark a pointer field
+        self.size_index = size_index    # index in cpu.types_by_index
+
+class ArrayDescr(AbstractDescr):
+    def __init__(self, itemsize_index):
+        self.itemsize_index = itemsize_index   # index in cpu.types_by_index
+        self.ty_array_ptr = lltype.nullptr(llvm_rffi.LLVMTypeRef.TO)
+        # ^^^ set by setup_once()
 
 class CallDescr(AbstractDescr):
     def __init__(self, ty_function_ptr, result_mask):
@@ -329,5 +399,8 @@
 
 # ____________________________________________________________
 
+class BadSizeError(Exception):
+    pass
+
 import pypy.jit.metainterp.executor
 pypy.jit.metainterp.executor.make_execute_list(LLVMCPU)

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/test/runner_test.py	Mon Jun  8 17:12:58 2009
@@ -1,5 +1,5 @@
 
-import sys, random
+import py, sys, random
 from pypy.jit.metainterp.history import (BoxInt, Box, BoxPtr, TreeLoop,
                                          ConstInt, ConstPtr, BoxObj,
                                          ConstObj)
@@ -384,6 +384,55 @@
         r = self.execute_operation(rop.OONONNULL, [null_box], 'int')
         assert r.value == 0
 
+    def test_array(self):
+        a_box, A = self.alloc_array_of(lltype.Signed, 342)
+        arraydescr = self.cpu.arraydescrof(A)
+        r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
+                                   'int', descr=arraydescr)
+        assert r.value == 342
+        r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
+                                                         BoxInt(7441)],
+                                   'void', descr=arraydescr)
+        assert r is None
+        r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
+                                   'int', descr=arraydescr)
+        assert r.value == 7441
+        #
+        a_box, A = self.alloc_array_of(lltype.Char, 11)
+        arraydescr = self.cpu.arraydescrof(A)
+        r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
+                                   'int', descr=arraydescr)
+        assert r.value == 11
+        r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(4),
+                                                         BoxInt(150)],
+                                   'void', descr=arraydescr)
+        assert r is None
+        r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(3),
+                                                         BoxInt(160)],
+                                   'void', descr=arraydescr)
+        assert r is None
+        r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(4)],
+                                   'int', descr=arraydescr)
+        assert r.value == 150
+        r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(3)],
+                                   'int', descr=arraydescr)
+        assert r.value == 160
+        #
+        if isinstance(A, lltype.GcArray):
+            A = lltype.Ptr(A)
+        b_box, B = self.alloc_array_of(A, 3)
+        arraydescr = self.cpu.arraydescrof(B)
+        r = self.execute_operation(rop.ARRAYLEN_GC, [b_box],
+                                   'int', descr=arraydescr)
+        assert r.value == 3
+        r = self.execute_operation(rop.SETARRAYITEM_GC, [b_box, BoxInt(1),
+                                                         a_box],
+                                   'void', descr=arraydescr)
+        assert r is None
+        r = self.execute_operation(rop.GETARRAYITEM_GC, [b_box, BoxInt(1)],
+                                   'ptr', descr=arraydescr)
+        assert r.value == a_box.value
+
 
 class LLtypeBackendTest(BaseBackendTest):
 
@@ -432,6 +481,13 @@
     def null_instance(self):
         return BoxPtr(lltype.nullptr(llmemory.GCREF.TO))
 
+    def alloc_array_of(self, ITEM, length):
+        cpu = self.cpu
+        A = lltype.GcArray(ITEM)
+        a = lltype.malloc(A, length)
+        a_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, a))
+        return a_box, A
+
 
     def test_casts(self):
         from pypy.rpython.lltypesystem import lltype, llmemory
@@ -486,3 +542,6 @@
 
     def null_instance(self):
         return BoxObj(ootype.NULL)
+
+    def alloc_array_of(self, ITEM, length):
+        py.test.skip("implement me")



More information about the Pypy-commit mailing list