[pypy-svn] r49424 - pypy/dist/pypy/translator/llvm

rxe at codespeak.net rxe at codespeak.net
Wed Dec 5 23:10:17 CET 2007


Author: rxe
Date: Wed Dec  5 23:10:16 2007
New Revision: 49424

Modified:
   pypy/dist/pypy/translator/llvm/arraynode.py
   pypy/dist/pypy/translator/llvm/codewriter.py
   pypy/dist/pypy/translator/llvm/database.py
   pypy/dist/pypy/translator/llvm/externs2ll.py
   pypy/dist/pypy/translator/llvm/genllvm.py
   pypy/dist/pypy/translator/llvm/modwrapper.py
   pypy/dist/pypy/translator/llvm/node.py
   pypy/dist/pypy/translator/llvm/opaquenode.py
   pypy/dist/pypy/translator/llvm/opwriter.py
   pypy/dist/pypy/translator/llvm/structnode.py
   pypy/dist/pypy/translator/llvm/typedefnode.py
Log:
rewrite of pbc code.   it is quite simple now.
the old code was written before knowledge of parentlink() and 
was somehow stitched up to work for the last 2.5 years - but i had no idea how it worked and i wrote
it.  so just threw it all away... :-)

the emitted code is now one getelementptr instead of a nested list of them that could  extend across about 100 lines

so

        store %structtype_object_vtable*
getelementptr(%structtype_pypy.translator.goal.richards.TaskState_vtable*
getelementptr(%structtype_pypy.translator.goal.richards.Task_vtable*
getelementptr(%structtype_pypy.translator.goal.richards.IdleTask_vtable*
@s_inst_pypy.translator.goal.richards.IdleTask_vtable, i32 0, i32 0),
i32 0, i32 0), i32 0, i32 0), %structtype_object_vtable** %tmp_17

now looks like
store %structtype_object_vtable* getelementptr(%structtype_IdleTaskRec_vtable* @s_inst_IdleTaskRec_vtable, i32 0, i32 0, i32 0), %structtype_object_
vtable** %tmp_99

also some random simplications.



Modified: pypy/dist/pypy/translator/llvm/arraynode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/arraynode.py	(original)
+++ pypy/dist/pypy/translator/llvm/arraynode.py	Wed Dec  5 23:10:16 2007
@@ -15,12 +15,6 @@
     
     def constantvalue(self):
         return '%s c"%s\\00"' % (self.get_typerepr(), self.value)
-
-    def get_childref(self, index):
-        return "getelementptr(%s* %s, i32 0, i32 %s)" % (
-            self.get_typerepr(),
-            self.name,
-            index)
     
     def writeglobalconstants(self, codewriter):
         codewriter.globalinstance(self.ref, self.constantvalue())
@@ -69,33 +63,6 @@
         typeval = self.db.repr_type(self.arraytype)
         return "{ %s, [%s x %s] }" % (self.db.get_machine_word(),
                                       arraylen, typeval)
-
-    def get_ref(self):
-        typeval = self.db.repr_type(lltype.typeOf(self.value))
-        p, c = lltype.parentlink(self.value)
-        if p is None:
-            ref = self.name
-        else:
-            ref = self.db.get_childref(p, c)
-
-        ref = "bitcast(%s* %s to %s*)" % (self.get_typerepr(),
-                                          ref,
-                                          typeval)
-        return ref
-
-    def get_pbcref(self, toptr):
-        p, c = lltype.parentlink(self.value)
-        assert p is None, "child PBC arrays are NOT needed by rtyper"
-
-        fromptr = "%s*" % self.get_typerepr()
-        ref = "bitcast(%s %s to %s)" % (fromptr, self.name, toptr)
-        return ref
-
-    def get_childref(self, index):
-        return "getelementptr(%s* %s, i32 0, i32 1, i32 %s)" % (
-            self.get_typerepr(),
-            self.name,
-            index)
     
     def constantvalue(self):
         physicallen, arrayrepr = self.get_arrayvalue()
@@ -108,20 +75,13 @@
                                             typeval,
                                             arrayrepr)
 
-        s = "%s {%s}" % (self.get_typerepr(), value)
-        return s
+        return "%s {%s}" % (self.get_typerepr(), value)
 
 class ArrayNoLengthNode(ArrayNode):
     def get_typerepr(self):
         arraylen = self.get_arrayvalue()[0]
         typeval = self.db.repr_type(self.arraytype)
         return "[%s x %s]" % (arraylen, typeval)
-    
-    def get_childref(self, index):
-        return "getelementptr(%s* %s, i32 0, i32 %s)" %(
-            self.get_typerepr(),
-            self.name,
-            index)
 
     def constantvalue(self):
         physicallen, arrayrepr = self.get_arrayvalue()
@@ -164,6 +124,9 @@
         name = '' #str(value).split()[1]
         self.make_name(name)
 
+    def get_typerepr(self):
+        return '[%s x i8]' % self.get_length()
+
     def constantvalue(self):
         return "{ %s } {%s %s}" % (self.db.get_machine_word(),
                                    self.db.get_machine_word(),

Modified: pypy/dist/pypy/translator/llvm/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/codewriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/codewriter.py	Wed Dec  5 23:10:16 2007
@@ -172,6 +172,7 @@
         self._indent("free %s %s" % (vartype, varref))
 
     def debug_print(self, s):
+        XXX # fixme
         var = self.db.repr_tmpvar()
         node = self.db.create_debug_string(s)
         self.call(var, "i32", "@write",

Modified: pypy/dist/pypy/translator/llvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/database.py	(original)
+++ pypy/dist/pypy/translator/llvm/database.py	Wed Dec  5 23:10:16 2007
@@ -1,4 +1,3 @@
-
 import sys
 
 from pypy.translator.llvm.log import log 
@@ -22,6 +21,17 @@
 
 log = log.database 
 
+def var_size_type(T):
+    " returns None if T not varsize "
+    if not T._is_varsize():
+        return None
+    elif isinstance(T, lltype.Array):
+        return T.OF
+    elif isinstance(T, lltype.Struct):
+        return T._arrayfld
+    else:
+        assert False, "unknown type"
+        
 class Database(object): 
     def __init__(self, genllvm, translator): 
         self.genllvm = genllvm
@@ -43,6 +53,7 @@
     #_______debuggging______________________________________
 
     def dump_pbcs(self):
+        XXX#FIXME
         r = ""
         for k, v in self.obj2node.iteritems():
 
@@ -58,13 +69,10 @@
             p, _ = lltype.parentlink(k)
             ref = v.get_ref()
             type_ = self.repr_type(lltype.Ptr(lltype.typeOf(k)))
-            pbc_ref = v.get_pbcref(type_)
-                
             r += "\ndump_pbcs %s (%s)\n" \
                  "parent %s\n" \
                  "type %s\n" \
-                 "getref -> %s \n" \
-                 "pbcref -> %s \n" % (v, k, p, type_, ref, pbc_ref)
+                 "getref -> %s \n" % (v, k, p, type_, ref)
         return r
     
     #_______setting up and preparation______________________________
@@ -113,7 +121,7 @@
 
         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 
@@ -242,6 +250,87 @@
     # __________________________________________________________
     # Representing variables and constants in LLVM source code 
 
+    def to_getelementptr(self, value):
+        # so we build the thing up instead
+        p = value
+        children = []
+        while True:
+            p, c = lltype.parentlink(p)
+            if p is None:
+                break
+            children.append((p, c))
+
+        children.reverse()
+        
+        TYPE = lltype.typeOf(children[0][0])
+        parentnode = self.obj2node[children[0][0]]
+
+        indices = [("i32", 0)]
+
+        for _, ii in children:
+            name = None
+
+            # this is because FixedSizeArray can sometimes be accessed like an
+            # Array and then sometimes a Struct
+            if isinstance(ii, str):
+                name = ii
+                assert name in list(TYPE._names)
+                fieldnames = TYPE._names_without_voids()
+                indexref = fieldnames.index(name)
+            else:
+                indexref = ii
+
+            if isinstance(TYPE, lltype.FixedSizeArray):
+                indices.append(("i32", indexref))
+                TYPE = TYPE.OF
+
+            elif isinstance(TYPE, lltype.Array):
+                if not TYPE._hints.get("nolength", False):
+                    indices.append(("i32", 1))
+                indices.append(("i32", indexref))
+                TYPE = TYPE.OF
+
+            elif isinstance(TYPE, lltype.Struct):
+                assert name is not None
+                TYPE = getattr(TYPE, name)
+                indices.append(("i32", indexref))
+
+            else:
+                raise Exception("unsupported type: %s" % TYPE)
+
+        indices_str = ', '.join ([('%s %s' % (x,y)) for x, y in indices])
+        ref = "getelementptr(%s* %s, %s)" % (
+            parentnode.get_typerepr(),
+            parentnode.ref,
+            indices_str)
+
+        return ref
+
+    def get_ref(self, value):
+        node = self.obj2node[value]
+        T = lltype.typeOf(value)
+        p, c = lltype.parentlink(value)
+        if p is None:
+            ref = node.ref
+            VT = var_size_type(T)
+            if VT and VT is not lltype.Void:
+                ref = "bitcast(%s* %s to %s*)" % (node.get_typerepr(),
+                                                  ref,
+                                                  self.repr_type(T))
+        else:
+            ref = self.to_getelementptr(value)
+            
+            if isinstance(node, FixedSizeArrayNode):
+                assert isinstance(value, lltype._subarray)
+
+                # XXX UGLY (but needs fixing outside of genllvm)
+                #  ptr -> array of len 1 (for now, since operations expect this)
+                ref = "bitcast(%s* %s to %s*)" % (self.repr_type(T.OF),
+                                                  ref,
+                                                  self.repr_type(T))
+
+        return ref
+
     def repr_arg(self, arg):
         if isinstance(arg, Constant):
             if isinstance(arg.concretetype, lltype.Primitive):
@@ -251,8 +340,7 @@
                 if not arg.value:
                     return 'null'
                 else:
-                    node = self.obj2node[arg.value._obj]
-                    return node.get_ref()
+                    return self.get_ref(arg.value._obj)
         else:
             assert isinstance(arg, Variable)
             return "%" + str(arg)
@@ -298,7 +386,7 @@
                 return None, "%s null" % toptr
 
             node = self.obj2node[value]
-            ref = node.get_pbcref(toptr)
+            ref = self.get_ref(value)
             return node, "%s %s" % (toptr, ref)
 
         elif isinstance(type_, (lltype.Array, lltype.Struct)):
@@ -331,10 +419,6 @@
                     return True
         return False
 
-    def get_childref(self, parent, child):
-        node = self.obj2node[parent]
-        return node.get_childref(child)
-
     def create_debug_string(self, s):
         r = DebugStrNode(s)
         self.debugstringnodes.append(r)

Modified: pypy/dist/pypy/translator/llvm/externs2ll.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/externs2ll.py	(original)
+++ pypy/dist/pypy/translator/llvm/externs2ll.py	Wed Dec  5 23:10:16 2007
@@ -65,7 +65,7 @@
     ccode = []
         
     if standalone:
-        ccode.append('#define __ENTRY_POINT__ %s' % entrynode.get_ref()[1:])
+        ccode.append('#define __ENTRY_POINT__ %s' % entrynode.ref[1:])
         ccode.append('#define ENTRY_POINT_DEFINED 1')
 
     sio = StringIO()

Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py	Wed Dec  5 23:10:16 2007
@@ -154,9 +154,9 @@
         return codewriter
    
     def setup_externs(self, c_db, db):
-        # XXX
+        # XXX this should be done via augmenting entrypoint
         exctransformer = c_db.exctransformer
-        for obj in [exctransformer._rpyexc_occured_ptr.value,
+        for obj in [exctransformer.rpyexc_occured_ptr.value,
                     exctransformer.rpyexc_fetch_type_ptr.value,
                     exctransformer.rpyexc_clear_ptr.value]:
             db.prepare_constant(lltype.typeOf(obj), obj)

Modified: pypy/dist/pypy/translator/llvm/modwrapper.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/modwrapper.py	(original)
+++ pypy/dist/pypy/translator/llvm/modwrapper.py	Wed Dec  5 23:10:16 2007
@@ -14,9 +14,9 @@
 
 _c = ctypes.CDLL(join(dirname(realpath(__file__)), "%s"))
 
-rpyexc_occured = _c.pypy__rpyexc_occured
+rpyexc_occured = _c.pypy_rpyexc_occured
 rpyexc_occured.argtypes = []
-rpyexc_occured.restype = ctypes.c_int
+rpyexc_occured.restype = ctypes.c_byte
 
 rpyexc_fetch_type = _c.pypy_rpyexc_fetch_type
 rpyexc_fetch_type.argtypes = []

Modified: pypy/dist/pypy/translator/llvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/node.py	(original)
+++ pypy/dist/pypy/translator/llvm/node.py	Wed Dec  5 23:10:16 2007
@@ -8,12 +8,13 @@
     nodename_count = {}
     def mangle(self, name):
         if name not in self.nodename_count:
-            result = name
             self.nodename_count[name] = 1
-            return result
+            return name
         else:
             result = '%s_%d' % (name, self.nodename_count[name])
             self.nodename_count[name] += 1
+            # this ensures (a) doesn exist yet, and (b) adds it to the
+            # dictionary just to prevent some function called xxx_42() and clashing
             return self.mangle(result)
 
     def make_name(self, name=''):
@@ -44,14 +45,6 @@
 
 class FuncNode(Node):
 
-    # XXX proof that the whole llvm is hanging on a bunch of loose stitches 
-    def get_ref(self):
-        return self.ref
-
-    # XXX proof that the whole llvm is hanging on a bunch of loose stitches 
-    def get_pbcref(self, _):
-        return self.ref
-
     def writedecl(self, codewriter):
         " write function forward declarations "
         pass
@@ -63,18 +56,6 @@
 class ConstantNode(Node):
     __slots__ = "".split()
 
-    def get_ref(self):
-        # XXX tmp 
-        return self.ref
-
-    def get_childref(self, index):
-        """ Returns a reference as used for operations in blocks for internals of a pbc. """
-        raise AttributeError("Must be implemented in subclass")
-
-    def get_pbcref(self, toptr):
-        """ Returns a reference as a pointer used per pbc. """        
-        return self.ref
-
     # ______________________________________________________________________
     # entry points from genllvm
 

Modified: pypy/dist/pypy/translator/llvm/opaquenode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opaquenode.py	(original)
+++ pypy/dist/pypy/translator/llvm/opaquenode.py	Wed Dec  5 23:10:16 2007
@@ -15,7 +15,6 @@
     def __init__(self, db, value):
         self.db = db
         self.value = value
-        self._get_ref_cache = None
 
         name = str(value).split()[1]
         self.make_name(name)
@@ -23,18 +22,6 @@
     # ______________________________________________________________________
     # main entry points from genllvm 
 
-    def get_ref(self):
-        """ Returns a reference as used for operations in blocks. """        
-        if self._get_ref_cache:
-            return self._get_ref_cache
-        p, c = lltype.parentlink(self.value)
-        if p is None:
-            ref = self.name
-        else:
-            ref = self.db.get_childref(p, c)
-        self._get_ref_cache = ref
-        return ref
-
     def writeglobalconstants(self, codewriter):
         pass
 

Modified: pypy/dist/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/opwriter.py	Wed Dec  5 23:10:16 2007
@@ -26,18 +26,6 @@
             self.rettype  = "%s (%s)*" % (self.rettype,
                                           ", ".join(self.argtypes[1:]))
 
-class OpReprInvoke(OpReprCall):
-    __slots__ = "db op retref rettype argrefs argtypes functionref".split()
-    def __init__(self, op, db):
-        super(OpReprInvoke, self).__init__(op, db)
-        
-        if op.opname in ('direct_call', 'indirect_call'):
-            self.functionref = self.argrefs[0]
-            self.argrefs = self.argrefs[1:]
-            self.argtypes = self.argtypes[1:]            
-        else:
-            self.functionref = '%pypyop_' + op.opname
-
 class OpWriter(object):            
   
     shift_operations = {
@@ -123,7 +111,6 @@
         return indices
 
     def write_operation(self, op):
-
         if self.db.genllvm.config.translation.llvm.debug:
             self.codewriter.comment(str(op))
             #self.codewriter.debug_print(str(op) + "\n")

Modified: pypy/dist/pypy/translator/llvm/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/structnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/structnode.py	Wed Dec  5 23:10:16 2007
@@ -12,12 +12,7 @@
     return index
         
 class StructNode(ConstantNode):
-    """ A struct constant.  Can simply contain
-    a primitive,
-    a struct,
-    pointer to struct/array
-    """
-    __slots__ = "db value structtype _get_ref_cache _get_types".split()
+    __slots__ = "db value structtype _get_types".split()
 
     prefix = '@s_inst_'
 
@@ -25,8 +20,8 @@
         self.db = db
         self.value = value
         self.structtype = self.value._TYPE
-        name = str(value).split()[1]
-        self._get_ref_cache = None
+        parts = str(value).split()[1]
+        name = parts.split('.')[-1]
         self._get_types = self._compute_types()
         self.make_name(name)
 
@@ -53,38 +48,6 @@
             
     def get_typerepr(self):
         return self.db.repr_type(self.structtype)
-
-    def get_childref(self, index):
-        pos = 0
-        found = False
-        for name in self.structtype._names_without_voids():
-            if name == index:
-                found = True
-                break
-            pos += 1
-
-        return "getelementptr(%s* %s, i32 0, i32 %s)" %(
-            self.get_typerepr(),
-            self.get_ref(),
-            pos)
-
-    def get_ref(self):
-        """ Returns a reference as used for operations in blocks. """        
-        # XXX cache here is **dangerous** considering it can return different values :-(
-        # XXX should write a test to prove this
-        #if self._get_ref_cache:
-        #    return self._get_ref_cache
-        p, c = lltype.parentlink(self.value)
-        if p is None:
-            ref = self.name
-        else:
-            ref = self.db.get_childref(p, c)
-        #XXXself._get_ref_cache = ref
-        return ref
-
-    def get_pbcref(self, toptr):
-        """ Returns a reference as used per pbc. """        
-        return self.get_ref()
     
     def constantvalue(self):
         """ Returns the constant representation for this node. """
@@ -95,7 +58,7 @@
         else:
             all_values = ",  ".join(values)
             return "%s { %s }" % (self.get_typerepr(), all_values)
-                
+
 class FixedSizeArrayNode(StructNode):
     prefix = '@fa_inst_'
 
@@ -110,40 +73,8 @@
         all_values = ",\n  ".join(values)
         return "%s [\n  %s\n  ]\n" % (self.get_typerepr(), all_values)
 
-    def get_ref(self):
-        p, c = lltype.parentlink(self.value)
-        if p is None:
-            ref = self.name
-        else:
-            ref = self.db.get_childref(p, c)
-            if isinstance(self.value, lltype._subarray):
-                # ptr -> array of len 1
-                ref = "bitcast(%s* %s to %s*)" % (self.db.repr_type(self.arraytype),
-                                               ref,
-                                               self.db.repr_type(lltype.typeOf(self.value)))
-        return ref
-
-    def get_childref(self, index):
-        if isinstance(index, str):
-            pos = 0
-            found = False
-            for name in self.structtype._names_without_voids():
-                if name == index:
-                    found = True
-                    break
-                pos += 1
-        else:
-            pos = index
-            
-        return "getelementptr(%s* %s, i32 0, i32 %s)" % (
-            self.get_typerepr(),
-            self.get_ref(),
-            pos) 
-
     def setup(self):
         if isinstance(self.value, lltype._subarray):
-            # XXX what is this?
-            # self.value._parentstructure()
             p, c = lltype.parentlink(self.value)
             if p is not None:
                 self.db.prepare_constant(lltype.typeOf(p), p)
@@ -151,17 +82,6 @@
             super(FixedSizeArrayNode, self).setup()
 
 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.
-    """
-
     prefix = '@sv_inst_'
 
     def _getvalues(self):
@@ -199,39 +119,3 @@
             result = "{%s}" % ", ".join(types_repr)
             self._get_typerepr_cache = result
             return result         
-
-    def get_childref(self, index):
-        pos = 0
-        found = False
-        for name in self.structtype._names_without_voids():
-            if name == index:
-                found = True
-                break
-            pos += 1
-        assert found
-
-        ref = "getelementptr(%s* %s, i32 0, i32 %s)" %(
-            self.get_typerepr(),
-            super(StructVarsizeNode, self).get_ref(),
-            pos)
-
-        return ref
-
-    def get_ref(self):
-        ref = super(StructVarsizeNode, self).get_ref()
-        typeval = self.db.repr_type(lltype.typeOf(self.value))
-        ref = "bitcast(%s* %s to %s*)" % (self.get_typerepr(),
-                                          ref,
-                                          typeval)
-        return ref
-    
-    def get_pbcref(self, toptr):
-        """ Returns a reference as used per pbc. """        
-        ref = self.name
-        p, c = lltype.parentlink(self.value)
-        assert p is None, "child varsize struct are NOT needed by rtyper"
-        fromptr = "%s*" % self.get_typerepr()
-        refptr = "getelementptr(%s %s, i32 0)" % (fromptr, ref)
-        ref = "bitcast(%s %s to %s)" % (fromptr, refptr, toptr)
-        return ref
-    

Modified: pypy/dist/pypy/translator/llvm/typedefnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/typedefnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/typedefnode.py	Wed Dec  5 23:10:16 2007
@@ -64,7 +64,9 @@
         assert isinstance(STRUCT, lltype.Struct)
         self.db = db
         self.STRUCT = STRUCT
-        self.make_name(self.STRUCT._name)
+        parts = self.STRUCT._name.split('.')
+        name = parts[-1]
+        self.make_name(name)
 
     def _fields(self):
         return [getattr(self.STRUCT, name) 



More information about the Pypy-commit mailing list