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

rxe at codespeak.net rxe at codespeak.net
Fri Jul 15 17:01:13 CEST 2005


Author: rxe
Date: Fri Jul 15 17:01:09 2005
New Revision: 14702

Added:
   pypy/dist/pypy/translator/llvm2/opaquenode.py
Modified:
   pypy/dist/pypy/translator/llvm2/arraynode.py
   pypy/dist/pypy/translator/llvm2/database.py
   pypy/dist/pypy/translator/llvm2/funcnode.py
   pypy/dist/pypy/translator/llvm2/genllvm.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:
* add dummy opaque nodes.

* get rid of hack in StructVarsizeNode where we were creating multiple nodes
  for the last entry in the struct.

* refactored out database to just use obj2node and _pendingsetup attributes
  again.

Will write to pypy-dev with status update later today.



Modified: pypy/dist/pypy/translator/llvm2/arraynode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/arraynode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/arraynode.py	Fri Jul 15 17:01:09 2005
@@ -1,7 +1,7 @@
 import py
 from pypy.rpython import lltype
 from pypy.translator.llvm2.log import log
-from pypy.translator.llvm2.node import LLVMNode
+from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode
 from pypy.translator.llvm2 import varsize 
 import itertools  
 log = log.structnode
@@ -51,7 +51,7 @@
                                   self.constructor_decl,
                                   fromtype)
 
-class ArrayNode(LLVMNode):
+class ArrayNode(ConstantLLVMNode):
     """ An arraynode.  Elements can be
     a primitive,
     a struct,
@@ -71,24 +71,24 @@
     def setup(self):
         if isinstance(self.arraytype, lltype.Ptr):
             for item in self.value.items:
-                self.db.addptrvalue(item)
+                self.db.prepare_ptr(item)
 
         # 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.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(),
                                                  self.ref,
                                                  typeval)
         self._issetup = True
 
-    def get_typestr(self):
+    def get_typerepr(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()
+        return "%s*" % self.get_typerepr()
     
     def constantvalue(self):
         """ Returns the constant representation for this node. """
@@ -96,13 +96,13 @@
         arraylen = len(items)
         typeval = self.db.repr_arg_type(self.arraytype)
 
-        arrayvalues = [self.db.reprs_constant(v) for v in items]
+        arrayvalues = [self.db.repr_constant(v)[1] for v in items]
         value = "int %s, [%s x %s] [ %s ]" % (arraylen,
                                               arraylen,
                                               typeval,
                                               ", ".join(arrayvalues))
 
-        return "%s {%s}" % (self.get_typestr(), value)
+        return "%s {%s}" % (self.get_typerepr(), value)
     
     # ______________________________________________________________________
     # entry points from genllvm

Modified: pypy/dist/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/database.py	(original)
+++ pypy/dist/pypy/translator/llvm2/database.py	Fri Jul 15 17:01:09 2005
@@ -3,6 +3,8 @@
 from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \
      StructTypeNode, StructVarsizeTypeNode
 from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode
+from pypy.translator.llvm2.opaquenode import OpaqueNode, OpaqueTypeNode
+from pypy.translator.llvm2.node import ConstantLLVMNode
 from pypy.rpython import lltype
 from pypy.objspace.flow.model import Block, Constant, Variable
 
@@ -30,10 +32,10 @@
     def dump(self): 
         for x,y in self._dict.items():
             print x, y
-    def _get(self, key): 
+    def _get(self, key):
         if isinstance(key, Constant): 
-            if isinstance(key.value, lltype._ptr): 
-                key = key.value._obj 
+            if isinstance(key.value, lltype._ptr):                
+                key = key.value._obj
         return key 
     def __getitem__(self, key): 
         key = self._get(key)
@@ -58,7 +60,7 @@
     elif type_ is lltype.Char:
         repr = str(ord(value))
     elif type_ is lltype.UniChar:
-        repr = "0" #XXX
+        repr = "0" # XXX Dont know what to do here at all?
     else:
         repr = str(value)
     return repr
@@ -67,17 +69,10 @@
     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
-        self.ptr2nodevalue[value] = self.create_constant_node(value, setup=True)        
-
-    def create_constant_node(self, value, setup=False):
-        type_ = lltype.typeOf(value)
+    def create_constant_node(self, type_, value, setup=False):
         node = None
         if isinstance(type_, lltype.FuncType):
             if value._callable and (not hasattr(value, "graph") or value.graph is None 
@@ -94,21 +89,28 @@
                     
         elif isinstance(type_, lltype.Array):
             node = ArrayNode(self, value)
-        assert node is not None, "%s not supported" % lltype.typeOf(value)
+
+        elif isinstance(type_, lltype.OpaqueType):
+            node = OpaqueNode(self, value)
+
+        assert node is not None, "%s not supported %s" % (type_, lltype.typeOf(value))
         if setup:
             node.setup()
         return node
-        
+
     def addpending(self, key, node):
+        # santity check we at least have a key of the right type
+        assert (isinstance(key, lltype.LowLevelType) or
+                isinstance(key, Constant) or
+                isinstance(lltype.typeOf(key), lltype.ContainerType))
+
         assert key not in self.obj2node, (
             "node with key %r already known!" %(key,))
+        
+        log("added to pending nodes:", type(key), node)        
         self.obj2node[key] = node 
-        log("added to pending nodes:", node) 
-        if isinstance(node, (StructNode, ArrayNode)):
-            self._pendingconstants.append(node)
-        else:
-            self._pendingsetup.append(node) 
-
+        self._pendingsetup.append(node)
+        
     def prepare_repr_arg(self, const_or_var):
         """if const_or_var is not already in a dictionary self.obj2node,
         the appropriate node gets constructed and gets added to
@@ -123,9 +125,9 @@
                 return
 
             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))
+            value = const_or_var.value._obj
+
+            self.addpending(const_or_var, self.create_constant_node(ct.TO, value))
         else:
             log.prepare(const_or_var, type(const_or_var))
 
@@ -152,6 +154,9 @@
         elif isinstance(type_, lltype.Array): 
             self.addpending(type_, ArrayTypeNode(self, type_))
 
+        elif isinstance(type_, lltype.OpaqueType):
+            self.addpending(type_, OpaqueTypeNode(self, type_))            
+
         else:
             assert False, "need to prepare typerepr %s %s" % (type_, type(type_))
 
@@ -164,24 +169,35 @@
         self.prepare_repr_arg_type(const_or_var.concretetype)
         self.prepare_repr_arg(const_or_var)
             
+    def prepare_ptr(self, ptrvalue):        
+        assert isinstance(lltype.typeOf(ptrvalue), lltype.Ptr)
+        value = ptrvalue._obj
+        type_ = lltype.typeOf(ptrvalue).TO
+        if value in self.obj2node or value is None:
+            return
+        self.addpending(value,
+                        self.create_constant_node(type_, value))
+
     def setup_all(self):
+        # Constants setup need to be done after the rest
+        pendingconstants = []
         while self._pendingsetup: 
-            x = self._pendingsetup.pop()
-            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():
-            if subset_types is None or isinstance(v, subset_types):
-                res.append(v)
-        return res
+            node = self._pendingsetup.pop()
+            if isinstance(node, (StructNode, ArrayNode)):
+                pendingconstants.append(node)
+                continue
+            log.settingup(node)
+            node.setup()
+
+        self._pendingsetup = pendingconstants
+        while self._pendingsetup:
+            node = self._pendingsetup.pop()
+            assert isinstance(node, ConstantLLVMNode)
+            log.settingup_constant(node)
+            node.setup()
+
+    def getnodes(self):
+        return self.obj2node.values()
         
     # __________________________________________________________
     # Representing variables and constants in LLVM source code 
@@ -222,26 +238,32 @@
     def repr_arg_type_multi(self, args):
         return [self.repr_arg_type(arg) for arg in args]
 
-    def reprs_constant(self, value):
+    def repr_constant(self, value):
+        " returns node and repr as tuple "
         type_ = lltype.typeOf(value)
         if isinstance(type_, lltype.Primitive):
             repr = primitive_to_str(type_, value)
-            return "%s %s" % (self.repr_arg_type(type_), repr)
+            return None, "%s %s" % (self.repr_arg_type(type_), repr)
 
         elif isinstance(type_, lltype.Ptr):
-            node = self.ptr2nodevalue[value._obj]
+            toptr = self.repr_arg_type(type_)
+
+            # special case, null pointer
+            if value._obj is None:
+                return None, "%s null" % (toptr,)
+
+            node = self.obj2node[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)
+            return node, "%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()
+            node = self.create_constant_node(type_, value, setup=True)
+            return node, node.constantvalue()
 
         assert False, "%s not supported" % (type(value))
 

Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py	Fri Jul 15 17:01:09 2005
@@ -4,7 +4,7 @@
 from pypy.rpython import lltype
 from pypy.translator.backendoptimization import remove_same_as 
 from pypy.translator.unsimplify import remove_double_links                     
-from pypy.translator.llvm2.node import LLVMNode
+from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode
 from pypy.translator.llvm2.atomic import is_atomic
 from pypy.translator.llvm2.log import log 
 from pypy.rpython.extfunctable import table as extfunctable
@@ -17,7 +17,9 @@
         self.db = db
         assert isinstance(type_, lltype.FuncType)
         self.type_ = type_
-        self.ref = 'ft.%s.%s' % (type_, nextnum())
+        # XXX Make simplier for now, it is far too hard to read otherwise
+        #self.ref = 'ft.%s.%s' % (type_, nextnum())
+        self.ref = '%%ft.%s' % (nextnum(),)
         
     def __str__(self):
         return "<FuncTypeNode %r>" % self.ref
@@ -29,11 +31,9 @@
     def writedatatypedecl(self, codewriter):
         returntype = self.db.repr_arg_type(self.type_.RESULT)
         inputargtypes = self.db.repr_arg_type_multi(self.type_._trueargs())
-        decl = "%s type %s (%s)*" % (self.ref, returntype,
-                                     ", ".join(inputargtypes))
         codewriter.funcdef(self.ref, returntype, inputargtypes)
                 
-class FuncNode(LLVMNode):
+class FuncNode(ConstantLLVMNode):
     _issetup = False 
 
     def __init__(self, db, value):

Modified: pypy/dist/pypy/translator/llvm2/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm2/genllvm.py	Fri Jul 15 17:01:09 2005
@@ -49,18 +49,18 @@
         nl = codewriter.newline
 
         nl(); comment("Type Declarations"); nl()
-        for typ_decl in self.db.getobjects():
+        for typ_decl in self.db.getnodes():
             typ_decl.writedatatypedecl(codewriter)
 
         nl(); comment("Global Data") ; nl()
-        for typ_decl in self.db.getobjects():
+        for typ_decl in self.db.getnodes():
             typ_decl.writeglobalconstants(codewriter)
 
         nl(); comment("Function Prototypes") ; nl()
         if self.embedexterns:
             for extdecl in extdeclarations.split('\n'):
                 codewriter.append(extdecl)
-        for typ_decl in self.db.getobjects():
+        for typ_decl in self.db.getnodes():
             typ_decl.writedecl(codewriter)
 
         #import pdb ; pdb.set_trace()
@@ -73,7 +73,7 @@
         for extfunc in gc_funcs.split('\n'):
             codewriter.append(extfunc)
 
-        for typ_decl in self.db.getobjects():
+        for typ_decl in self.db.getnodes():
             typ_decl.writeimpl(codewriter)
 
         depdone = {}

Modified: pypy/dist/pypy/translator/llvm2/node.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/node.py	(original)
+++ pypy/dist/pypy/translator/llvm2/node.py	Fri Jul 15 17:01:09 2005
@@ -47,3 +47,8 @@
     # __________________ after "implementation" ____________________
     def writeimpl(self, codewriter):
         """ write function implementations. """ 
+
+class ConstantLLVMNode(LLVMNode):
+
+    def castfrom(self):
+        return None

Added: pypy/dist/pypy/translator/llvm2/opaquenode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm2/opaquenode.py	Fri Jul 15 17:01:09 2005
@@ -0,0 +1,27 @@
+from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode
+from pypy.rpython import lltype
+
+class OpaqueTypeNode(LLVMNode):
+
+    def __init__(self, db, opaquetype): 
+        assert isinstance(opaquetype, lltype.OpaqueType)
+        self.db = db
+        self.opaquetype = opaquetype
+        self.ref = "%%opaque.%s" % (opaquetype.tag)
+        
+    def __str__(self):
+        return "<OpaqueNode %r>" %(self.ref,)
+
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+
+    def writedatatypedecl(self, codewriter):
+        # XXX Dummy - not sure what what we want
+        codewriter.funcdef(self.ref, 'sbyte*', ['sbyte *'])
+
+
+class OpaqueNode(ConstantLLVMNode):
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        self.ref = "null"

Modified: pypy/dist/pypy/translator/llvm2/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/structnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/structnode.py	Fri Jul 15 17:01:09 2005
@@ -1,6 +1,6 @@
 import py
 from pypy.translator.llvm2.log import log
-from pypy.translator.llvm2.node import LLVMNode
+from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode
 from pypy.translator.llvm2 import varsize
 from pypy.rpython import lltype
 
@@ -77,7 +77,7 @@
             self.ref, self.constructor_decl, arraytype, 
             indices_to_array)
 
-class StructNode(LLVMNode):
+class StructNode(ConstantLLVMNode):
     """ A struct constant.  Can simply contain
     a primitive,
     a struct,
@@ -90,7 +90,7 @@
         self.value = value
         self.structtype = self.value._TYPE
         self.ref = "%%stinstance.%s" % (nextnum(),)
-
+        
     def __str__(self):
         return "<StructNode %r>" % (self.ref,)
 
@@ -98,27 +98,27 @@
         return [(name, self.structtype._flds[name])
                 for name in self.structtype._names_without_voids()]
 
+    def _getvalues(self):
+        values = []
+        for name, T in self._gettypes():
+            value = getattr(self.value, name)
+            values.append(self.db.repr_constant(value)[1])
+        return values
+    
     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.db.prepare_ptr(getattr(self.value, name))
         self._issetup = True
 
-    def castfrom(self):
-        return None
-
-    def get_typestr(self):
+    def get_typerepr(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)
-            values.append(self.db.reprs_constant(value))
-                
-        return "%s {%s}" % (self.get_typestr(), ", ".join(values))
+        values = self._getvalues()
+        return "%s {%s}" % (self.get_typerepr(), ", ".join(values))
     
     # ______________________________________________________________________
     # main entry points from genllvm 
@@ -141,31 +141,44 @@
     def __str__(self):
         return "<StructVarsizeNode %r>" % (self.ref,)
 
+    def _getvalues(self):
+        values = []
+        for name, T in self._gettypes()[:-1]:
+            value = getattr(self.value, name)
+            values.append(self.db.repr_constant(value)[1])
+        values.append(self._get_lastnoderepr())
+        return values
+    
+    def _get_lastnode(self):
+        if not hasattr(self, "lastnode"):
+            lastname, LASTT = self._gettypes()[-1]
+            assert isinstance(LASTT, lltype.Array) or (
+                isinstance(LASTT, lltype.Struct) and LASTT._arrayfld)
+            value = getattr(self.value, lastname)
+            self.lastnode, self.lastnode_repr = self.db.repr_constant(value)
+        return self.lastnode
+
+    def _get_lastnoderepr(self):
+        self._get_lastnode()
+        return self.lastnode_repr
+
     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.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(),
                                                  self.ref,
                                                  typeval)
         super(StructVarsizeNode, self).setup()
+    
+    def get_typerepr(self):
+        # last type is a special case and need to be worked out recursively
+        types = self._gettypes()[:-1]
+        types_repr = [self.db.repr_arg_type(T) for name, T in types]
+        types_repr.append(self._get_lastnode().get_typerepr())
         
-    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)
+        return "{%s}" % ", ".join(types_repr)
         
     def castfrom(self):
-        return "%s*" % self.get_typestr()
+        return "%s*" % self.get_typerepr()
  

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	Fri Jul 15 17:01:09 2005
@@ -178,3 +178,13 @@
     fn = compile_function(array_constant, [], embedexterns=False)
     assert fn() == 42
 
+def test_struct_opaque():
+    PRTTI = lltype.Ptr(lltype.RuntimeTypeInfo)
+    S = lltype.GcStruct('s', ('a', lltype.Signed), ('r', PRTTI))
+    s = lltype.malloc(S)
+    s.a = 42
+    def array_constant():
+        return s.a
+    fn = compile_function(array_constant, [], embedexterns=False)
+    assert fn() == 42
+    



More information about the Pypy-commit mailing list