[pypy-svn] r15993 - pypy/dist/pypy/translator/llvm2

rxe at codespeak.net rxe at codespeak.net
Fri Aug 12 01:31:57 CEST 2005


Author: rxe
Date: Fri Aug 12 01:31:53 2005
New Revision: 15993

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/node.py
   pypy/dist/pypy/translator/llvm2/opwriter.py
   pypy/dist/pypy/translator/llvm2/pyxwrapper.py
   pypy/dist/pypy/translator/llvm2/structnode.py
   pypy/dist/pypy/translator/llvm2/varsize.py
Log:
A first attempt at getting genllvm2 to work on 64 bit machines.

Not everything is working... yet.  Mostly externals and some exceptions (ones
that involve external code); this is another reason why we should at least aim
to generate the code instead of hand-coding it - I guess.  But we know that!

Also in this checkin:
 * Annotated some commented out code with XXX and reasons
 * Got rid of some horrendously long and unreabable names of generated ArrayTypeNodes



Modified: pypy/dist/pypy/translator/llvm2/arraynode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/arraynode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/arraynode.py	Fri Aug 12 01:31:53 2005
@@ -14,17 +14,28 @@
 
         self.db = db
         self.array = array
-        self.arraytype = array.OF
+        arraytype = 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 = "%%arraytype.%s.%s" % (c, self.arraytype)
-        self.constructor_ref = "%%new.array.%s" % c
-        self.constructor_decl = "%s * %s(int %%len)" % \
-                                (self.ref, self.constructor_ref)
+        name = ""        
+        if isinstance(arraytype, lltype.Ptr):
+            name += "ptr_"
+            arraytype = arraytype.TO
+        if hasattr(arraytype, "_name"):            
+            name += arraytype._name
+        else:
+            name += str(arraytype)
+
+        self.ref = self.make_ref('%arraytype.', name)
+        self.constructor_ref = self.make_ref('%new.array.', name)
+        self.constructor_decl = "%s * %s(%s %%len)" % \
+                                (self.ref,
+                                 self.constructor_ref,
+                                 self.db.get_machine_word())
 
     def __str__(self):
         return "<ArrayTypeNode %r>" % self.ref
@@ -45,7 +56,9 @@
     # entry points from genllvm
     #
     def writedatatypedecl(self, codewriter):
-        codewriter.arraydef(self.ref, self.db.repr_arg_type(self.arraytype))
+        codewriter.arraydef(self.ref,
+                            self.db.get_machine_word(),
+                            self.db.repr_arg_type(self.arraytype))
 
     def writedecl(self, codewriter): 
         # declaration for constructor
@@ -54,7 +67,7 @@
     def writeimpl(self, codewriter):
         log.writeimpl(self.ref)
         fromtype = self.db.repr_arg_type(self.arraytype) 
-        varsize.write_constructor(codewriter, self.ref, 
+        varsize.write_constructor(self.db, codewriter, self.ref, 
                                   self.constructor_decl,
                                   fromtype,
                                   atomicmalloc=self.is_atomic())
@@ -63,10 +76,11 @@
 
     def __init__(self, db, array):
         assert isinstance(array, lltype.Array)
+        self.db = db
         self.ref = "%arraytype.Void"
 
     def writedatatypedecl(self, codewriter):
-        td = "%s = type { int }" % self.ref
+        td = "%s = type { %s }" % (self.ref, self.db.get_machine_word())
         codewriter.append(td)
         
 class ArrayNode(ConstantLLVMNode):
@@ -108,7 +122,8 @@
     def get_typerepr(self):
         arraylen = self.get_arrayvalue()[0]
         typeval = self.db.repr_arg_type(self.arraytype)
-        return "{ int, [%s x %s] }" % (arraylen, typeval)
+        return "{ %s, [%s x %s] }" % (self.db.get_machine_word(),
+                                      arraylen, typeval)
 
     def get_ref(self):
         typeval = self.db.repr_arg_type(lltype.typeOf(self.value))
@@ -145,10 +160,11 @@
         typeval = self.db.repr_arg_type(self.arraytype)
 
         # first length is logical, second is physical
-        value = "int %s, [%s x %s] %s" % (self.get_length(),
-                                              physicallen,
-                                              typeval,
-                                              arrayrepr)
+        value = "%s %s, [%s x %s] %s" % (self.db.get_machine_word(),
+                                         self.get_length(),
+                                         physicallen,
+                                         typeval,
+                                         arrayrepr)
 
         s = "%s {%s}" % (self.get_typerepr(), value)
         return s
@@ -164,15 +180,6 @@
         item_length = len(items)
         if item_length == 0 or items[-1] != chr(0):
             items = items + [chr(0)]
-        l = item_length + 1
-        r = "".join([self.db.repr_constant(v)[1] for v in items])
-        return l, r 
-
-    def get_arrayvalue(self):
-        items = self.value.items
-        item_length = len(items)
-        if item_length == 0 or items[-1] != chr(0):
-            items = items + [chr(0)]
             item_length += 1
         s = []
         for c in items:
@@ -188,9 +195,12 @@
 
     def __init__(self, db, value):
         assert isinstance(lltype.typeOf(value), lltype.Array)
+        self.db = db
         self.ref = self.make_ref('%arrayinstance', '')
         self.value = value
 
     def constantvalue(self):
-        return "{ int } {int %s}" % len(self.value.items)
+        return "{ %s } {%s %s}" % (self.db.get_machine_word(),
+                                   self.db.get_machine_word(),
+                                   len(self.value.items))
 

Modified: pypy/dist/pypy/translator/llvm2/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/codewriter.py	(original)
+++ pypy/dist/pypy/translator/llvm2/codewriter.py	Fri Aug 12 01:31:53 2005
@@ -41,8 +41,8 @@
     def structdef(self, name, typereprs):
         self.append("%s = type { %s }" %(name, ", ".join(typereprs)))
 
-    def arraydef(self, name, typerepr):
-        self.append("%s = type { int, [0 x %s] }" % (name, typerepr))
+    def arraydef(self, name, lentype, typerepr):
+        self.append("%s = type { %s, [0 x %s] }" % (name, lentype, typerepr))
 
     def funcdef(self, name, rettyperepr, argtypereprs):
         self.append("%s = type %s (%s)" % (name, rettyperepr,

Modified: pypy/dist/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/database.py	(original)
+++ pypy/dist/pypy/translator/llvm2/database.py	Fri Aug 12 01:31:53 2005
@@ -1,3 +1,4 @@
+import sys
 from pypy.translator.llvm2.log import log 
 from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode
 from pypy.translator.llvm2.extfuncnode import ExternalFuncNode
@@ -13,14 +14,6 @@
             
 log = log.database 
 
-PRIMITIVES_TO_LLVM = {lltype.Signed: "int",
-                      lltype.Char: "sbyte",
-                      lltype.Unsigned: "uint",
-                      lltype.Bool: "bool",
-                      lltype.Float: "double",
-                      lltype.UniChar: "uint",
-                      lltype.Void: "void"}
-
 class NormalizingDict(object): 
     """ this is a helper dict for obj2node in order 
         to allow saner key-unification for Ptrs to functions 
@@ -60,17 +53,6 @@
     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 = str(ord(value))
-    else:
-        repr = str(value)
-    return repr
-
 class Database(object): 
     def __init__(self, translator): 
         self._translator = translator
@@ -81,6 +63,33 @@
         # debug operation comments
         self._opcomments = {}
 
+        self.primitives_init()
+
+    def primitives_init(self):
+        primitives = {
+            lltype.Char: "sbyte",
+            lltype.Bool: "bool",
+            lltype.Float: "double",
+            lltype.UniChar: "uint",
+            lltype.Void: "void"}
+
+        # 32 bit platform
+        if sys.maxint == 2**31-1:
+            primitives.update({
+                lltype.Signed: "int",
+                lltype.Unsigned: "uint" })
+            
+        # 64 bit platform
+        elif sys.maxint == 2**63-1:        
+            primitives.update({
+                lltype.Signed: "long",
+                lltype.Unsigned: "ulong" })
+            
+        else:
+            assert False, "Unsupported platform"        
+
+        self.primitives = primitives
+        
     #_______for debugging llvm code_________________________
 
     def add_op2comment(self, lenofopstr, op):
@@ -270,11 +279,11 @@
         
     # __________________________________________________________
     # Representing variables and constants in LLVM source code 
-    
+
     def repr_arg(self, arg):
         if isinstance(arg, Constant):
             if isinstance(arg.concretetype, lltype.Primitive):
-                return primitive_to_str(arg.concretetype, arg.value)
+                return self.primitive_to_str(arg.concretetype, arg.value)
             else:
                 node = self.obj2node.get(arg)
                 if node is None:
@@ -292,7 +301,7 @@
             return self.obj2node[arg].ref 
         except KeyError: 
             if isinstance(arg, lltype.Primitive):
-                return PRIMITIVES_TO_LLVM[arg]
+                return self.primitives[arg]
             elif isinstance(arg, lltype.Ptr):
                 return self.repr_arg_type(arg.TO) + '*'
             else: 
@@ -311,7 +320,7 @@
         " returns node and repr as tuple "
         type_ = lltype.typeOf(value)
         if isinstance(type_, lltype.Primitive):
-            repr = primitive_to_str(type_, value)
+            repr = self.primitive_to_str(type_, value)
             return None, "%s %s" % (self.repr_arg_type(type_), repr)
 
         elif isinstance(type_, lltype.Ptr):
@@ -336,3 +345,24 @@
         count = self._tmpcount 
         self._tmpcount += 1
         return "%tmp." + str(count) 
+
+    # __________________________________________________________
+    # Primitive stuff
+
+    def primitive_to_str(self, type_, value):
+        #XXX Need to watch for special float values (inf, 2E200)
+        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 = str(ord(value))
+        else:
+            repr = str(value)
+        return repr
+
+    def get_machine_word(self):
+        return self.primitives[lltype.Signed]
+
+    def get_machine_uword(self):
+        return self.primitives[lltype.Unsigned]

Modified: pypy/dist/pypy/translator/llvm2/node.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/node.py	(original)
+++ pypy/dist/pypy/translator/llvm2/node.py	Fri Aug 12 01:31:53 2005
@@ -35,7 +35,7 @@
             if hasattr(self, "_constructor_ref"):
                 raise TypeError, ("can only set constructor_ref once!"
                                   " currently: %s" % (self._constructor_ref,))
-            if " " in ref: 
+            if " " in ref or "<" in ref: 
                 ref = '"%s"' % (ref,)
             self._constructor_ref = ref
         return property(_get_ref, _set_ref)

Modified: pypy/dist/pypy/translator/llvm2/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm2/opwriter.py	Fri Aug 12 01:31:53 2005
@@ -96,6 +96,7 @@
                 if not meth:
                     msg = "operation %s not found" %(op.opname,)
                     self.codewriter.comment('XXX: Error: ' + msg)
+                    # XXX commented out for testing
                     #assert meth is not None, msg
                     return
                 meth(op)    
@@ -105,9 +106,12 @@
         mult_val = self.db.repr_arg(op.args[0])
         last_val = mult_val
         try:
-            operand = int(op.args[1].value)
-        except:
-            msg = 'XXX: Error: _generic_pow: Variable has no value'
+            value = "NO VALUE"
+            value = op.args[1].value
+            operand = int(value)
+        except Exception, exc:
+            msg = 'XXX: Error: _generic_pow: Variable '\
+                  '%s - failed to convert to int %s' % (value, str(exc))
             self.codewriter.comment(msg)
             return
         if operand < 1:
@@ -150,8 +154,11 @@
                                  self.db.repr_arg(op.args[0]),
                                  )
     def int_neg(self, op):
-        self._generic_neg(op, "0") 
-    uint_neg = int_neg  #this is really generates, don't know why
+        self._generic_neg(op, "0")
+
+    #this is really generated, don't know why
+    # XXX rxe: Surely that cant be right?
+    uint_neg = int_neg  
 
     def float_neg(self, op):
         self._generic_neg(op, "0.0") 
@@ -200,7 +207,8 @@
                                 self.db.repr_arg(op.args[0]),
                                 tmpvar)
 
-    def cast_primitive(self, op): #works for all primitives
+    def cast_primitive(self, op):
+        " works for all casts "
         assert len(op.args) == 1
         targetvar = self.db.repr_arg(op.result)
         targettype = self.db.repr_arg_type(op.result)
@@ -256,7 +264,6 @@
             self.codewriter.call_void(functionref, argrefs, argtypes)
 
     def invoke(self, op):
-        # XXX hack as per remove_voids()
         op_args = [arg for arg in op.args
                    if arg.concretetype is not lltype.Void]
 
@@ -271,6 +278,7 @@
             else:
                 msg = "exception raising operation %s not found" %(op.opname,)
                 self.codewriter.comment('XXX: Error: ' + msg)
+                # XXX commented out for testing
                 #assert functionref in extfunctions, msg
         
         assert len(op_args) >= 1
@@ -416,7 +424,9 @@
                                           ("uint", index))        
             self.codewriter.load(targetvar, targettype, tmpvar)
         else:
-            self.codewriter.comment("***Skipping operation getfield()***")  #XXX what if this the last operation of the exception block?
+            #XXX what if this the last operation of the exception block?
+            # XXX rxe: would a getfield() ever raise anyway???
+            self.codewriter.comment("***Skipping operation getfield()***")
  
     def getsubstruct(self, op): 
         struct, structtype = self.db.repr_argwithtype(op.args[0])
@@ -470,7 +480,6 @@
 
         valuevar = self.db.repr_arg(op.args[2]) 
         valuetype = self.db.repr_arg_type(op.args[2])
-        #XXX These should skip too if the case comes up
         if valuetype != "void":
             self.codewriter.getelementptr(tmpvar, arraytype, array,
                                       ("uint", 1), (indextype, index))
@@ -478,7 +487,6 @@
         else:
             self.codewriter.comment("***Skipping operation setarrayitem()***")
 
-
     def getarraysize(self, op):
         array, arraytype = self.db.repr_argwithtype(op.args[0])
         tmpvar = self.db.repr_tmpvar()

Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/pyxwrapper.py	(original)
+++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py	Fri Aug 12 01:31:53 2005
@@ -1,15 +1,29 @@
+import sys
 from pypy.translator.llvm2.log import log 
 from pypy.rpython import lltype 
 from pypy.translator.llvm2.genllvm import use_boehm_gc
 log = log.pyrex 
 
-PRIMITIVES_TO_C = {lltype.Signed: "int",
-                   lltype.Unsigned: "unsigned int",
-                   lltype.Bool: "char",
+PRIMITIVES_TO_C = {lltype.Bool: "char",
                    lltype.Float: "double",
                    lltype.Char: "char",
                    }
 
+# 32 bit platform
+if sys.maxint == 2**31-1:
+    PRIMITIVES_TO_C.update({
+        lltype.Signed: "int",
+        lltype.Unsigned: "unsigned int" })
+    
+# 64 bit platform
+elif sys.maxint == 2**63-1:        
+    PRIMITIVES_TO_C.update({
+        lltype.Signed: "long",
+        lltype.Unsigned: "unsigned long" })
+
+else:
+    assert False, "Unsupported platform"        
+
 def write_pyx_wrapper(funcgen, targetpath): 
     def c_declaration():
         returntype = PRIMITIVES_TO_C[

Modified: pypy/dist/pypy/translator/llvm2/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/structnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/structnode.py	Fri Aug 12 01:31:53 2005
@@ -51,8 +51,10 @@
     def __init__(self, db, struct): 
         super(StructVarsizeTypeNode, self).__init__(db, struct)
         self.constructor_ref = "%%new.varsizestruct.%s" % (self.name)
-        self.constructor_decl = "%s * %s(int %%len)" % \
-                                (self.ref, self.constructor_ref)
+        self.constructor_decl = "%s * %s(%s %%len)" % \
+                                (self.ref,
+                                 self.constructor_ref,
+                                 self.db.get_machine_word())
 
     def __str__(self):
         return "<StructVarsizeTypeNode %r>" %(self.ref,)
@@ -79,7 +81,7 @@
         assert isinstance(current, lltype.Array)
         arraytype = self.db.repr_arg_type(current.OF)
         # XXX write type info as a comment 
-        varsize.write_constructor(codewriter, 
+        varsize.write_constructor(self.db, codewriter, 
             self.ref, self.constructor_decl, arraytype, 
             indices_to_array,
             atomicmalloc=self.is_atomic())

Modified: pypy/dist/pypy/translator/llvm2/varsize.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/varsize.py	(original)
+++ pypy/dist/pypy/translator/llvm2/varsize.py	Fri Aug 12 01:31:53 2005
@@ -15,14 +15,15 @@
    ret %array* %result
 }"""
 
-def write_constructor(codewriter, ref, constructor_decl, elemtype, 
+def write_constructor(db, codewriter, ref, constructor_decl, elemtype, 
                       indices_to_array=(), atomicmalloc=False): 
     #varsized arrays and structs look like this: 
     #Array: {int length , elemtype*}
     #Struct: {...., Array}
 
-    # the following indices access the last element in the array 
-    elemindices = list(indices_to_array) + [("uint", 1), ("int", "%len")]
+    # the following indices access the last element in the array
+    lentype = db.get_machine_word()
+    elemindices = list(indices_to_array) + [("uint", 1), (lentype, "%len")]
    
     codewriter.openfunc(constructor_decl)
     codewriter.getelementptr("%size", ref + "*", "null", *elemindices) 
@@ -35,7 +36,7 @@
     codewriter.getelementptr("%arraylength", ref + "*", 
                              "%result", 
                              *indices_to_array)
-    codewriter.store("int", "%len", "%arraylength")
+    codewriter.store(lentype, "%len", "%arraylength")
     codewriter.ret(ref + "*", "%result")
     codewriter.closefunc()
 



More information about the Pypy-commit mailing list