[pypy-svn] r14480 - in pypy/dist/pypy/translator/llvm2: . test

rxe at codespeak.net rxe at codespeak.net
Mon Jul 11 02:09:04 CEST 2005


Author: rxe
Date: Mon Jul 11 02:09:00 2005
New Revision: 14480

Modified:
   pypy/dist/pypy/translator/llvm2/arraynode.py
   pypy/dist/pypy/translator/llvm2/codewriter.py
   pypy/dist/pypy/translator/llvm2/database.py
   pypy/dist/pypy/translator/llvm2/funcnode.py
   pypy/dist/pypy/translator/llvm2/node.py
   pypy/dist/pypy/translator/llvm2/structnode.py
   pypy/dist/pypy/translator/llvm2/test/test_lltype.py
Log:

* Fleshed out test_lltype.py.
* Sanitised StructNode, StructVarNode and ArrayNode
* Added support for getarraysubstruct()
* Added repr_argwithtype which returns both arg and type
* Refactoring of database
* We now setup all the types before setup all the constants - as we need to
  know what the type names are to cast (if we need to cast to at all)
* Added repr_constant() to database which returns a representation for a
  in a generic way (credit hpk)

pbcs for llvm are nearly there.



Modified: pypy/dist/pypy/translator/llvm2/arraynode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/arraynode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/arraynode.py	Mon Jul 11 02:09:00 2005
@@ -15,14 +15,14 @@
 
         self.db = db
         self.array = array
-
+        self.arraytype = array.OF
         # ref is used to reference the arraytype in llvm source 
         # constructor_ref is used to reference the constructor 
         # for the array type in llvm source code 
         # constructor_decl is used to declare the constructor
         # for the array type (see writeimpl)
         c = nextnum()
-        self.ref = "%%array.%s.%s" % (c, array.OF)
+        self.ref = "%%array.%s.%s" % (c, self.arraytype)
         self.constructor_ref = "%%new.array.%s" % c 
         self.constructor_decl = "%s * %s(int %%len)" % \
                                 (self.ref, self.constructor_ref)
@@ -31,14 +31,14 @@
         return "<ArrayTypeNode %r>" % self.ref
         
     def setup(self):
-        self.db.prepare_repr_arg_type(self.array.OF)
+        self.db.prepare_repr_arg_type(self.arraytype)
         self._issetup = True
 
     # ______________________________________________________________________
     # entry points from genllvm
     #
     def writedatatypedecl(self, codewriter):
-        codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF))
+        codewriter.arraydef(self.ref, self.db.repr_arg_type(self.arraytype))
 
     def writedecl(self, codewriter): 
         # declaration for constructor
@@ -46,44 +46,66 @@
 
     def writeimpl(self, codewriter):
         log.writeimpl(self.ref)
-        fromtype = self.db.repr_arg_type(self.array.OF) 
+        fromtype = self.db.repr_arg_type(self.arraytype) 
         varsize.write_constructor(codewriter, self.ref, 
                                   self.constructor_decl,
                                   fromtype)
 
 class ArrayNode(LLVMNode):
+    """ An arraynode.  Elements can be
+    a primitive,
+    a struct,
+    pointer to struct/array
+    """
     _issetup = True 
     def __init__(self, db, value):
         assert isinstance(lltype.typeOf(value), lltype.Array)
         self.db = db
         self.value = value
         self.arraytype = lltype.typeOf(value).OF
-        self.ref = "%%arrayinstance.%s.%s" % (self.arraytype, nextnum())
+        self.ref = "%%arrayinstance.%s" % (nextnum(),)
+
+    def __str__(self):
+        return "<ArrayNode %r>" % (self.ref,)
+
+    def setup(self):
         if isinstance(self.arraytype, lltype.Ptr):
             for item in self.value.items:
                 self.db.addptrvalue(item)
 
-    def __str__(self):
-        return "<ArrayNode %r>" %(self.ref,)
-    
-    def typeandvalue(self):
-        """ Returns the type and value for this node. """
+        # set castref (note we must ensure that types are "setup" before we can
+        # get typeval)
+        typeval = self.db.repr_arg_type(lltype.typeOf(self.value))
+        self.castref = "cast (%s* %s to %s*)" % (self.get_typestr(),
+                                                 self.ref,
+                                                 typeval)
+        self._issetup = True
+
+    def get_typestr(self):
         items = self.value.items
         arraylen = len(items)
+        typeval = self.db.repr_arg_type(self.arraytype)
+        return "{ int, [%s x %s] }" % (arraylen, typeval)
 
+    def castfrom(self):
+        return "%s*" % self.get_typestr()
+    
+    def constantvalue(self):
+        """ Returns the constant representation for this node. """
+        items = self.value.items
+        arraylen = len(items)
         typeval = self.db.repr_arg_type(self.arraytype)
 
-        type_ = "{ int, [%s x %s] }" % (arraylen, typeval)        
-        arrayvalues = ["%s %s" % self.db.reprs_constant(v) for v in items]
+        arrayvalues = [self.db.reprs_constant(v) for v in items]
         value = "int %s, [%s x %s] [ %s ]" % (arraylen,
                                               arraylen,
                                               typeval,
                                               ", ".join(arrayvalues))
-        return type_, value
+
+        return "%s {%s}" % (self.get_typestr(), value)
     
     # ______________________________________________________________________
     # entry points from genllvm
 
     def writeglobalconstants(self, codewriter):
-        type_, values = self.typeandvalue()
-        codewriter.globalinstance(self.ref, type_, values)
+        codewriter.globalinstance(self.ref, self.constantvalue())

Modified: pypy/dist/pypy/translator/llvm2/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/codewriter.py	(original)
+++ pypy/dist/pypy/translator/llvm2/codewriter.py	Mon Jul 11 02:09:00 2005
@@ -3,7 +3,7 @@
 from pypy.translator.llvm2.log import log 
 
 log = log.codewriter 
-show_line_numbers = False # True
+show_line_numbers = True # False
 count = count().next
 
 class CodeWriter(object): 
@@ -16,8 +16,12 @@
         self._lines.append(line) 
         log(line) 
 
-    def comment(self, line):
-        self.append(";; " + line) 
+    def comment(self, line, indent=False):
+        line = ";; " + line
+        if indent:
+            self.indent(line)
+        else:
+            self.append(line)
 
     def newline(self):
         self.append("")
@@ -28,8 +32,8 @@
     def label(self, name):
         self.append("    %s:" % name)
 
-    def globalinstance(self, name, type, data):
-        self.append("%s = constant %s {%s}" % (name, type, data))
+    def globalinstance(self, name, typeandata):
+        self.append("%s = constant %s" % (name, typeandata))
 
     def structdef(self, name, typereprs):
         self.append("%s = type { %s }" %(name, ", ".join(typereprs)))

Modified: pypy/dist/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/database.py	(original)
+++ pypy/dist/pypy/translator/llvm2/database.py	Mon Jul 11 02:09:00 2005
@@ -52,40 +52,31 @@
     def items(self): 
         return self._dict.items()
 
+def primitive_to_str(type_, value):
+    if type_ is lltype.Bool:
+        repr = str(value).lower() #False --> false
+    elif type_ is lltype.Char:
+        repr = str(ord(value))
+    elif type_ is lltype.UniChar:
+        repr = "0" #XXX
+    else:
+        repr = str(value)
+    return repr
+
 class Database(object): 
     def __init__(self, translator): 
         self._translator = translator
         self.obj2node = NormalizingDict() 
         self.ptr2nodevalue = {} 
         self._pendingsetup = []
+        self._pendingconstants = []
         self._tmpcount = 1
 
     def addptrvalue(self, ptrvalue):
         value = ptrvalue._obj
-        node = self.create_constant_node(value)
-        self.ptr2nodevalue[value] = self.create_constant_node(value)        
-
-    def getptrnode(self, ptrvalue):
-        return self.ptr2nodevalue[ptrvalue._obj]
-
-    def getptrref(self, ptrvalue):
-        return self.ptr2nodevalue[ptrvalue._obj].ref
-
-    def reprs_constant(self, value):        
-        type_ = lltype.typeOf(value)
-        if isinstance(type_, lltype.Primitive):
-            if isinstance(value, str) and len(value) == 1:
-                res = ord(value)                    
-            res = str(value)
-        elif isinstance(type_, lltype.Ptr):
-            res = self.getptrref(value)
-        #elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct):
-        #XXX    res = self.value.typeandvalue()
-        else:
-            assert False, "not supported XXX"
-        return self.repr_arg_type(type_), res
+        self.ptr2nodevalue[value] = self.create_constant_node(value, setup=True)        
 
-    def create_constant_node(self, value):
+    def create_constant_node(self, value, setup=False):
         type_ = lltype.typeOf(value)
         node = None
         if isinstance(type_, lltype.FuncType):
@@ -104,14 +95,19 @@
         elif isinstance(type_, lltype.Array):
             node = ArrayNode(self, value)
         assert node is not None, "%s not supported" % lltype.typeOf(value)
+        if setup:
+            node.setup()
         return node
         
-    def addpending(self, key, node): 
+    def addpending(self, key, node):
         assert key not in self.obj2node, (
             "node with key %r already known!" %(key,))
         self.obj2node[key] = node 
         log("added to pending nodes:", node) 
-        self._pendingsetup.append(node) 
+        if isinstance(node, (StructNode, ArrayNode)):
+            self._pendingconstants.append(node)
+        else:
+            self._pendingsetup.append(node) 
 
     def prepare_repr_arg(self, const_or_var):
         """if const_or_var is not already in a dictionary self.obj2node,
@@ -126,7 +122,7 @@
                 log.prepare(const_or_var, "(is primitive)")
                 return
 
-            assert isinstance(ct, lltype.Ptr), "Preperation of non primitive and non pointer" 
+            assert isinstance(ct, lltype.Ptr), "Preparation of non primitive and non pointer" 
             value = const_or_var.value._obj            
                 
             self.addpending(const_or_var, self.create_constant_node(value))
@@ -156,8 +152,8 @@
         elif isinstance(type_, lltype.Array): 
             self.addpending(type_, ArrayTypeNode(self, type_))
 
-        else:     
-            log.XXX("need to prepare typerepr", type_)
+        else:
+            assert False, "need to prepare typerepr %s %s" % (type_, type(type_))
 
     def prepare_repr_arg_type_multi(self, types):
         for type_ in types:
@@ -171,9 +167,15 @@
     def setup_all(self):
         while self._pendingsetup: 
             x = self._pendingsetup.pop()
-            log.setup_all(x)
+            log.settingup(x)
+            x.setup()
+
+        while self._pendingconstants: 
+            x = self._pendingconstants.pop()
+            log.settingup_constant(x)
             x.setup()
 
+
     def getobjects(self, subset_types=None):
         res = []
         for v in self.obj2node.values() + self.ptr2nodevalue.values():
@@ -185,16 +187,18 @@
     # Representing variables and constants in LLVM source code 
     
     def repr_arg(self, arg):
-        if (isinstance(arg, Constant) and 
-            isinstance(arg.concretetype, lltype.Primitive)):
-           
-            # XXX generalize and test this 
-            if isinstance(arg.value, str) and len(arg.value) == 1: 
-                return str(ord(arg.value))
-            return str(arg.value).lower() #False --> false
-        elif isinstance(arg, Variable):
+        if isinstance(arg, Constant):
+            if isinstance(arg.concretetype, lltype.Primitive):
+                return primitive_to_str(arg.concretetype, arg.value)
+            else:
+                node = self.obj2node[arg]
+                if hasattr(node, "castref"):
+                    return node.castref
+                else:
+                    return node.ref
+        else:
+            assert isinstance(arg, Variable)
             return "%" + str(arg)
-        return self.obj2node[arg].ref
 
     def repr_arg_type(self, arg):
         if isinstance(arg, (Constant, Variable)): 
@@ -209,12 +213,38 @@
             else: 
                 raise TypeError("cannot represent %r" %(arg,))
 
+    def repr_argwithtype(self, arg):
+        return self.repr_arg(arg), self.repr_arg_type(arg)
+            
     def repr_arg_multi(self, args):
         return [self.repr_arg(arg) for arg in args]
 
     def repr_arg_type_multi(self, args):
         return [self.repr_arg_type(arg) for arg in args]
 
+    def reprs_constant(self, value):
+        type_ = lltype.typeOf(value)
+        if isinstance(type_, lltype.Primitive):
+            repr = primitive_to_str(type_, value)
+            return "%s %s" % (self.repr_arg_type(type_), repr)
+
+        elif isinstance(type_, lltype.Ptr):
+            node = self.ptr2nodevalue[value._obj]
+            ref = node.ref
+
+            fromptr = node.castfrom()
+            toptr = self.repr_arg_type(type_)
+            if fromptr:
+                refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref)
+                ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr)
+            return "%s %s" % (toptr, ref)
+
+        elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct):
+            node = self.create_constant_node(value, setup=True)
+            return node.constantvalue()
+
+        assert False, "%s not supported" % (type(value))
+
     def repr_tmpvar(self): 
         count = self._tmpcount 
         self._tmpcount += 1

Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py	Mon Jul 11 02:09:00 2005
@@ -140,7 +140,7 @@
     def write_block_operations(self, codewriter, block):
         opwriter = OpWriter(self.db, codewriter)
         for op in block.operations:
-            #codewriter.comment(str(op))
+            codewriter.comment(str(op), indent=True)
             opwriter.write_operation(op)
     def write_startblock(self, codewriter, block):
         self.write_block_operations(codewriter, block)
@@ -327,6 +327,7 @@
     cast_bool_to_int = cast_primitive
     cast_bool_to_uint = uint_is_true = cast_primitive
     cast_int_to_char = cast_char_to_int = cast_primitive
+    cast_int_to_uint = cast_primitive
 
     def int_is_true(self, op):
         self.codewriter.binaryop("setne",
@@ -382,54 +383,56 @@
 
     def getfield(self, op): 
         tmpvar = self.db.repr_tmpvar()
-        typ = self.db.repr_arg_type(op.args[0]) 
-        typevar = self.db.repr_arg(op.args[0])
+        struct, structtype = self.db.repr_argwithtype(op.args[0])
         fieldnames = list(op.args[0].concretetype.TO._names)
         index = fieldnames.index(op.args[1].value)
-        self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index))        
+        self.codewriter.getelementptr(tmpvar, structtype, struct, ("uint", index))        
         targetvar = self.db.repr_arg(op.result)
         targettype = self.db.repr_arg_type(op.result)
         assert targettype != "void"
         self.codewriter.load(targetvar, targettype, tmpvar)
 
     def getsubstruct(self, op): 
-        typ = self.db.repr_arg_type(op.args[0]) 
-        typevar = self.db.repr_arg(op.args[0])
+        struct, structtype = self.db.repr_argwithtype(op.args[0])
         fieldnames = list(op.args[0].concretetype.TO._names)
         index = fieldnames.index(op.args[1].value)
         targetvar = self.db.repr_arg(op.result)
-        self.codewriter.getelementptr(targetvar, typ, 
-                                      typevar, ("uint", index))        
+        self.codewriter.getelementptr(targetvar, structtype, 
+                                      struct, ("uint", index))        
         targettype = self.db.repr_arg_type(op.result)
         assert targettype != "void"
          
     def setfield(self, op): 
         tmpvar = self.db.repr_tmpvar()
-        type = self.db.repr_arg_type(op.args[0]) 
-        typevar = self.db.repr_arg(op.args[0]) 
+        struct, structtype = self.db.repr_argwithtype(op.args[0])
         fieldnames = list(op.args[0].concretetype.TO._names)
         index = fieldnames.index(op.args[1].value)
-        self.codewriter.getelementptr(tmpvar, type, typevar, ("uint", index))
-        valuevar = self.db.repr_arg(op.args[2]) 
-        valuetype = self.db.repr_arg_type(op.args[2])
+        self.codewriter.getelementptr(tmpvar, structtype, struct, ("uint", index))
+        valuevar, valuetype = self.db.repr_argwithtype(op.args[2])
         assert valuetype != "void"
         self.codewriter.store(valuetype, valuevar, tmpvar) 
 
-    def getarrayitem(self, op):
-        var = self.db.repr_arg(op.args[0])
-        vartype = self.db.repr_arg_type(op.args[0])
+    def getarrayitem(self, op):        
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
         index = self.db.repr_arg(op.args[1])
         indextype = self.db.repr_arg_type(op.args[1])
         tmpvar = self.db.repr_tmpvar()
-        self.codewriter.getelementptr(tmpvar, vartype, var,
+        self.codewriter.getelementptr(tmpvar, arraytype, array,
                                       ("uint", 1), (indextype, index))
         targetvar = self.db.repr_arg(op.result)
         targettype = self.db.repr_arg_type(op.result)
         self.codewriter.load(targetvar, targettype, tmpvar)
 
+    def getarraysubstruct(self, op):        
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
+        index = self.db.repr_arg(op.args[1])
+        indextype = self.db.repr_arg_type(op.args[1])
+        targetvar = self.db.repr_arg(op.result)
+        self.codewriter.getelementptr(targetvar, arraytype, array,
+                                      ("uint", 1), (indextype, index))
+
     def setarrayitem(self, op):
-        array = self.db.repr_arg(op.args[0])
-        arraytype = self.db.repr_arg_type(op.args[0])
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
         index = self.db.repr_arg(op.args[1])
         indextype = self.db.repr_arg_type(op.args[1])
 
@@ -439,14 +442,12 @@
 
         valuevar = self.db.repr_arg(op.args[2]) 
         valuetype = self.db.repr_arg_type(op.args[2])
-        assert valuevar.strip() != '-'
         self.codewriter.store(valuetype, valuevar, tmpvar) 
 
     def getarraysize(self, op):
-        var = self.db.repr_arg(op.args[0])
-        vartype = self.db.repr_arg_type(op.args[0])
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
         tmpvar = self.db.repr_tmpvar()
-        self.codewriter.getelementptr(tmpvar, vartype, var, ("uint", 0))
+        self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 0))
         targetvar = self.db.repr_arg(op.result)
         targettype = self.db.repr_arg_type(op.result)
         self.codewriter.load(targetvar, targettype, tmpvar)

Modified: pypy/dist/pypy/translator/llvm2/node.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/node.py	(original)
+++ pypy/dist/pypy/translator/llvm2/node.py	Mon Jul 11 02:09:00 2005
@@ -9,7 +9,7 @@
             if hasattr(self, "_ref"):
                 raise TypeError, ("can only set ref once! currently: %s" %
                                    (self._ref,))
-            if " " in ref: 
+            if " " in ref or "<" in ref: 
                 ref = '"%s"' % (ref,)
             self._ref = ref
         return property(_get_ref, _set_ref)

Modified: pypy/dist/pypy/translator/llvm2/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/structnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/structnode.py	Mon Jul 11 02:09:00 2005
@@ -16,15 +16,15 @@
         assert isinstance(struct, lltype.Struct)
         self.db = db
         self.struct = struct
-        self.name = "%s.%s" % (self.struct._name, nextnum())
-        self.ref = "%%st.%s" % self.name
+        self.name = "%s.%s" % (self.struct._name , nextnum())
+        self.ref = "%%st.%s" % (self.name)
         
     def __str__(self):
         return "<StructTypeNode %r>" %(self.ref,)
     
     def setup(self):
         # Recurse
-        for field in self.struct._flds:
+        for field in self.struct._flds.values():
             self.db.prepare_repr_arg_type(field)
         self._issetup = True
 
@@ -33,9 +33,10 @@
 
     def writedatatypedecl(self, codewriter):
         assert self._issetup 
-        fields = [getattr(self.struct, name) for name in self.struct._names_without_voids()] 
-        l = [self.db.repr_arg_type(field) for field in fields]
-        codewriter.structdef(self.ref, l)
+        fields = [getattr(self.struct, name)
+                  for name in self.struct._names_without_voids()] 
+        codewriter.structdef(self.ref,
+                             self.db.repr_arg_type_multi(fields))
 
 class StructVarsizeTypeNode(StructTypeNode):
 
@@ -48,6 +49,9 @@
     def __str__(self):
         return "<StructVarsizeTypeNode %r>" %(self.ref,)
         
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+
     def writedecl(self, codewriter): 
         # declaration for constructor
         codewriter.declare(self.constructor_decl)
@@ -73,92 +77,95 @@
             self.ref, self.constructor_decl, arraytype, 
             indices_to_array)
 
-
-#XXX Everything downwind of here is experimental code
-
-def cast_global(toptr, from_, name):
-    s = "cast(%s* getelementptr (%s* %s, int 0) to %s)" % (from_,
-                                                           from_,
-                                                           name,
-                                                           toptr)
-    return s
-
 class StructNode(LLVMNode):
+    """ A struct constant.  Can simply contain
+    a primitive,
+    a struct,
+    pointer to struct/array
+    """
     _issetup = False 
 
     def __init__(self, db, value):
         self.db = db
         self.value = value
-        self.ref = "%%stinstance.%s.%s" % (value._TYPE._name, nextnum())
-        for name in self.value._TYPE._names_without_voids():
-            T = self.value._TYPE._flds[name]
-            assert T is not lltype.Void
-            if isinstance(T, lltype.Ptr):
-                self.db.addptrvalue(getattr(self.value, name))
+        self.structtype = self.value._TYPE
+        self.ref = "%%stinstance.%s" % (nextnum(),)
 
     def __str__(self):
-        return "<StructNode %r>" %(self.ref,)
+        return "<StructNode %r>" % (self.ref,)
+
+    def _gettypes(self):
+        return [(name, self.structtype._flds[name])
+                for name in self.structtype._names_without_voids()]
 
     def setup(self):
+        for name, T in self._gettypes():
+            assert T is not lltype.Void
+            if isinstance(T, lltype.Ptr):
+                self.db.addptrvalue(getattr(self.value, name))
         self._issetup = True
 
-    def typeandvalue(self):
-        res = []
-        type_ = self.value._TYPE
-        for name in type_._names_without_voids():
-            T = type_._flds[name]
+    def castfrom(self):
+        return None
+
+    def get_typestr(self):
+        return self.db.repr_arg_type(self.structtype)
+    
+    def constantvalue(self):
+        """ Returns the constant representation for this node. """
+        values = []
+        for name, T in self._gettypes():
             value = getattr(self.value, name)
-            if isinstance(T, lltype.Ptr):
-                x = self.db.getptrnode(value)
-                value = self.db.getptrref(value)
-                t, v = x.typeandvalue()
-                value = cast_global(self.db.repr_arg_type(T), t, value)
+            values.append(self.db.reprs_constant(value))
                 
-            else:
-                value = str(value)
-            res.append((self.db.repr_arg_type(T), value))
-                
-        typestr = self.db.repr_arg_type(type_)
-        values = ", ".join(["%s %s" % (t, v) for t, v in res])
-        return typestr, values
+        return "%s {%s}" % (self.get_typestr(), ", ".join(values))
     
-    def writeglobalconstants(self, codewriter):
-        type_, values = self.typeandvalue()
-        codewriter.globalinstance(self.ref, type_, values)
+    # ______________________________________________________________________
+    # main entry points from genllvm 
 
-#XXX Everything downwind of here is very experimental code and no tests pass
+    def writeglobalconstants(self, codewriter):
+        codewriter.globalinstance(self.ref, self.constantvalue())
                 
 class StructVarsizeNode(StructNode):
+    """ A varsize struct constant.  Can simply contain
+    a primitive,
+    a struct,
+    pointer to struct/array
+
+    and the last element *must* be
+    an array
+    OR
+    a series of embedded structs, which has as its last element an array.
+    """
+
     def __str__(self):
-        return "<StructVarsizeNode %r>" %(self.ref,)
+        return "<StructVarsizeNode %r>" % (self.ref,)
 
-    def typeandvalue(self):
-        res = []
-        type_ = self.value._TYPE
-        for name in type_._names_without_voids()[:-1]:
-            T = type_._flds[name]
-            value = getattr(self.value, name)
-            if not isinstance(T, lltype.Primitive):
-                # Create a dummy constant hack XXX
-                value = self.db.repr_arg(Constant(value, T))
-            else:
-                value = str(value)
-            res.append((self.db.repr_arg_type(T), value))
-
-        # Special case for varsized arrays
-        name = type_._names_without_voids()[-1]
-        T = type_._flds[name]
-        assert not isinstance(T, lltype.Primitive)
-        value = getattr(self.value, name)
-        c = Constant(value, T)
-        x = self.db.obj2node[c]
-        t, v = x.typeandvalue()
-
-        #value = self.db.repr_arg(c)
-        value = cast_global(self.db.repr_arg_type(T), t, "{%s}" % v)
-        res.append((self.db.repr_arg_type(T), value))
-
-        typestr = self.db.repr_arg_type(type_)
-        values = ", ".join(["%s %s" % (t, v) for t, v in res])
-        return typestr, values
-    
+    def setup(self):
+        # set castref (note we must ensure that types are "setup" before we can
+        # get typeval)
+        typeval = self.db.repr_arg_type(lltype.typeOf(self.value))
+        self.castref = "cast (%s* %s to %s*)" % (self.get_typestr(),
+                                                 self.ref,
+                                                 typeval)
+        super(StructVarsizeNode, self).setup()
+        
+    def get_typestr(self):
+        lastname, LASTT = self._gettypes()[-1]
+        assert isinstance(LASTT, lltype.Array) or (
+            isinstance(LASTT, lltype.Struct) and LASTT._arrayfld)
+
+        #XXX very messy
+        node = self.db.create_constant_node(getattr(self.value, lastname), True)
+        lasttype = node.get_typestr()
+
+        types = []
+        for name, T in self._gettypes()[:-1]:
+            types.append(self.db.repr_arg_type(T))
+        types.append(lasttype)
+
+        return "{%s}" % ", ".join(types)
+        
+    def castfrom(self):
+        return "%s*" % self.get_typestr()
+ 

Modified: pypy/dist/pypy/translator/llvm2/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/test/test_lltype.py	(original)
+++ pypy/dist/pypy/translator/llvm2/test/test_lltype.py	Mon Jul 11 02:09:00 2005
@@ -1,60 +1,180 @@
+
 import py
 
 from pypy.rpython import lltype
 
 from pypy.translator.llvm2.genllvm import compile_function
 from pypy.translator.llvm2 import database, codewriter
+from pypy.rpython import rarithmetic 
 
 py.log.setconsumer("genllvm", py.log.STDOUT)
 py.log.setconsumer("genllvm database prepare", None)
 
-P = lltype.GcStruct("s",
-                    ('signed', lltype.Signed),
-                    ('unsigned', lltype.Unsigned),
-                    ('float', lltype.Float),
-                    ('char', lltype.Char),
-                    ('bool', lltype.Bool),
-                    ('unichar', lltype.UniChar)
-                    )
-
-def test_struct1():
-    # struct of primitives
-    def simple1():
-        s = lltype.malloc(P)
-        return s.signed# + s.unsigned + s.float + s.char + s.bool + s.unichar
-    fn = compile_function(simple1, [], embedexterns=False)
-    assert fn() == 0
-
-# def test_struct2():
-#     S = lltype.Struct("s", ('v', lltype.Signed))
-#     S2 = lltype.GcStruct("s2", ('a', S), ('b', S))
-#     def simple2():
-#         s = lltype.malloc(S2)
-#         s.a.v = 6
-#         s.b.v = 12
-#         return s.a.v + s.b.v
-#     fn = compile_function(simple2, [], embedexterns=False, view=True)
-#     assert fn() == 18
-
-# def test_simple_struct():
-#     S0 = lltype.GcStruct("s0", ('a', lltype.Signed), ('b', lltype.Signed))
-#     c0 = lltype.malloc(S0)
-#     c0.a, c0.b = 1, 2
-#     def simple_struct():
-#         return c0.a + c0.b
-#     f = compile_function(simple_struct, [], embedexterns=False, view=True)
-#     assert f() == 3
-
-# def test_simple_struct2():
-#     S0 = lltype.GcStruct("s0", ('a', lltype.Char), ('b', lltype.Signed))
-#     def build():
-#         s0 = lltype.malloc(S0)
-#         s0.a = "l"
-#         s0.b = 2
-#         return s0
-#     c0 = build()
-#     def simple_struct2():
-#         return c0.a + c0.b
-#     f = compile_function(simple_struct, [], embedexterns=False, view=True)
-#     assert f() == 3
+S = lltype.Struct("base", ('a', lltype.Signed), ('b', lltype.Signed))
+
+def test_struct_constant1():
+    P = lltype.GcStruct("s",
+                        ('signed', lltype.Signed),
+                        ('unsigned', lltype.Unsigned),
+                        ('float', lltype.Float),
+                        ('char', lltype.Char),
+                        ('bool', lltype.Bool),
+                        ('unichar', lltype.UniChar)
+                        )
+
+    s = lltype.malloc(P)
+    s.signed = 2
+    s.unsigned = rarithmetic.r_uint(1)
+    def struct_constant():
+        x1 = s.signed + s.unsigned
+        return x1
+    fn = compile_function(struct_constant, [], embedexterns=False)
+    assert fn() == 3
+
+def test_struct_constant2():
+    S2 = lltype.GcStruct("struct2", ('a', lltype.Signed), ('s1', S), ('s2', S))
+
+    s = lltype.malloc(S2)
+    s.a = 5
+    s.s1.a = 2
+    s.s1.b = 4
+    s.s2.b = 3
+    def struct_constant():
+        return s.a + s.s2.b + s.s1.a + s.s1.b
+    fn = compile_function(struct_constant, [], embedexterns=False)
+    assert fn() == 14
+
+def test_struct_constant3():
+    structs = []
+    cur = S
+    for n in range(20):
+        cur = lltype.Struct("struct%s" % n,  ("s", cur))
+        structs.append(cur)
+    TOP = lltype.GcStruct("top", ("s", cur))
+        
+    top = lltype.malloc(TOP)
+    cur = top.s
+    for ii in range(20):
+        cur = cur.s
+    cur.a = 10
+    cur.b = 5
+    def struct_constant():
+        return (top.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a -
+                top.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.b)
+    
+    fn = compile_function(struct_constant, [], embedexterns=False)
+    assert fn() == 5
+
+def test_struct_constant4():
+    SPTR = lltype.GcStruct('sptr', ('a', lltype.Signed))
+    STEST = lltype.GcStruct('test', ('sptr', lltype.Ptr(SPTR)))
+    s = lltype.malloc(STEST)
+    s.sptr = lltype.malloc(SPTR)
+    s.sptr.a = 21
+    def struct_constant():
+        return s.sptr.a * 2
+    fn = compile_function(struct_constant, [], embedexterns=False)
+    assert fn() == 42
+
+def test_struct_constant5():
+    SPTR = lltype.GcStruct('sptr', ('a', lltype.Signed), ('b', S))
+    STEST = lltype.GcStruct('test', ('sptr', lltype.Ptr(SPTR)))
+    s = lltype.malloc(STEST)
+    s.sptr = lltype.malloc(SPTR)
+    s.sptr.a = 21
+    s.sptr.b.a = 11
+    s.sptr.b.b = 10
+    def struct_constant():
+        return s.sptr.a + s.sptr.b.a + s.sptr.b.b
+    fn = compile_function(struct_constant, [], embedexterns=False)
+    assert fn() == 42
+
+def test_struct_constant6():
+    U = lltype.Struct('inlined', ('z', lltype.Signed))
+    T = lltype.GcStruct('subtest', ('y', lltype.Signed))
+    S = lltype.GcStruct('test', ('x', lltype.Ptr(T)), ('u', U), ('p', lltype.Ptr(U)))
+
+    s = lltype.malloc(S)
+    s.x = lltype.malloc(T)
+    s.x.y = 42
+    s.u.z = -100
+    s.p = s.u
+    def struct_constant():
+        return s.x.y + s.p.z
+    fn = compile_function(struct_constant, [], embedexterns=False)
+    assert fn() == -58
+
+def test_array_constant():
+    A = lltype.GcArray(lltype.Signed)
+    a = lltype.malloc(A, 3)
+    a[0] = 100
+    a[1] = 101
+    a[2] = 102
+    def array_constant():
+        return a[0] + a[1] + a[2]    
+    fn = compile_function(array_constant, [], embedexterns=False)
+    assert fn() == 303
+
+def test_array_constant2():
+    A = lltype.GcArray(lltype.Signed)
+    a = lltype.malloc(A, 3)
+    a[0] = 100
+    a[1] = 101
+    a[2] = 102
+    def array_constant():
+        a[0] = 0
+        return a[0] + a[1] + a[2]    
+    fn = compile_function(array_constant, [], embedexterns=False)
+    assert fn() == 203
+
+def test_array_constant3():
+    A = lltype.GcArray(('x', lltype.Signed))
+    a = lltype.malloc(A, 3)
+    a[0].x = 100
+    a[1].x = 101
+    a[2].x = 102
+    def array_constant():
+        return a[0].x + a[1].x + a[2].x    
+    fn = compile_function(array_constant, [], embedexterns=False)
+    assert fn() == 303
+
+def test_struct_array1():
+    A = lltype.GcArray(lltype.Signed)
+    STEST = lltype.GcStruct('test', ('aptr', lltype.Ptr(A)))
+    s = lltype.malloc(STEST)
+    s.aptr = a = lltype.malloc(A, 2)
+    a[0] = 100
+    a[1] = 101
+    def array_constant():
+        return s.aptr[1] - a[0]
+    fn = compile_function(array_constant, [], embedexterns=False)
+    assert fn() == 1
+
+def test_struct_array2():
+    A = lltype.Array(lltype.Signed)
+    STEST = lltype.GcStruct('test', ('a', lltype.Signed), ('b', A))
+    s = lltype.malloc(STEST, 2)
+    s.a = 41
+    s.b[0] = 100
+    s.b[1] = 101
+    def array_constant():
+        return s.b[1] - s.b[0] + s.a
+    fn = compile_function(array_constant, [], embedexterns=False)
+    assert fn() == 42
+
+def test_struct_array3():
+    A = lltype.Array(lltype.Signed)
+    STEST = lltype.GcStruct('test', ('a', lltype.Signed), ('b', A))
+    SBASE = lltype.GcStruct('base', ('p', lltype.Ptr(STEST)))
+    s = lltype.malloc(STEST, 2)
+    s.a = 41
+    s.b[0] = 100
+    s.b[1] = 101
+    b = lltype.malloc(SBASE)
+    b.p = s
+    def array_constant():
+        s = b.p
+        return s.b[1] - s.b[0] + s.a
+    fn = compile_function(array_constant, [], embedexterns=False)
+    assert fn() == 42
 



More information about the Pypy-commit mailing list