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

ericvrp at codespeak.net ericvrp at codespeak.net
Thu Jul 21 00:42:23 CEST 2005


Author: ericvrp
Date: Thu Jul 21 00:42:22 2005
New Revision: 14837

Added:
   pypy/dist/pypy/translator/llvm2/extfuncnode.py
   pypy/dist/pypy/translator/llvm2/opwriter.py
Modified:
   pypy/dist/pypy/translator/llvm2/database.py
   pypy/dist/pypy/translator/llvm2/extfunction.py
   pypy/dist/pypy/translator/llvm2/funcnode.py
   pypy/dist/pypy/translator/llvm2/genllvm.py
   pypy/dist/pypy/translator/llvm2/node.py
Log:
- moved parts of funcnode.py into extfuncnode.py and opwriter.py
- simplified extfuncnode.py by not special-casing functions that have
  a one-to-one c-equivalent
- moved (optimization) code for tracking which externl functions are actually used
  from LLVMNode to external node.
- simplified external function node detection in database.py
- added ll_os_dup and ll_os_close to extfunction.py because they are no longer special-case
- use the new suggested_primitive methology



Modified: pypy/dist/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/database.py	(original)
+++ pypy/dist/pypy/translator/llvm2/database.py	Thu Jul 21 00:42:22 2005
@@ -1,5 +1,6 @@
 from pypy.translator.llvm2.log import log 
-from pypy.translator.llvm2.funcnode import ExternalFuncNode, FuncNode, FuncTypeNode
+from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode
+from pypy.translator.llvm2.extfuncnode import ExternalFuncNode
 from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \
      StructTypeNode, StructVarsizeTypeNode
 from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode
@@ -75,8 +76,7 @@
     def create_constant_node(self, type_, value):
         node = None
         if isinstance(type_, lltype.FuncType):
-            if value._callable and (not hasattr(value, "graph") or value.graph is None 
-                                    or getattr(value._callable, "suggested_primitive", False)):
+            if getattr(value._callable, "suggested_primitive", False):
                 node = ExternalFuncNode(self, value)
             else:
                 node = FuncNode(self, value)

Added: pypy/dist/pypy/translator/llvm2/extfuncnode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm2/extfuncnode.py	Thu Jul 21 00:42:22 2005
@@ -0,0 +1,37 @@
+import py
+from pypy.objspace.flow.model import Block, Constant, Variable, Link
+from pypy.objspace.flow.model import flatten, mkentrymap, traverse
+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, ConstantLLVMNode
+from pypy.translator.llvm2.atomic import is_atomic
+from pypy.translator.llvm2.log import log 
+from pypy.rpython.extfunctable import table as extfunctable
+log = log.extfuncnode
+
+class ExternalFuncNode(LLVMNode):
+
+    used_external_functions = {}
+
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        self.ref = "%" + value._callable.__name__
+
+    def setup(self):
+        self._issetup = True
+
+    def getdecl(self):
+        T = self.value._TYPE
+        args = [self.db.repr_arg_type(a) for a in T.ARGS]
+        decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT),
+                              self.ref,
+                              ", ".join(args))
+        return decl
+
+    def writedecl(self, codewriter): 
+        codewriter.declare(self.getdecl())
+
+    def writeimpl(self, codewriter): 
+        self.used_external_functions[self.ref] = True

Modified: pypy/dist/pypy/translator/llvm2/extfunction.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/extfunction.py	(original)
+++ pypy/dist/pypy/translator/llvm2/extfunction.py	Thu Jul 21 00:42:22 2005
@@ -5,6 +5,8 @@
 declare int %time(int*) ;void* actually
 declare int %clock()
 declare void %sleep(int)
+declare int %dup(int)
+declare void %close(int)
 declare int %open(sbyte*, int, int)
 declare int %write(int, sbyte*, int)
 declare int %read(int, sbyte*, int)
@@ -67,22 +69,6 @@
 
 """)
 
-extfunctions["%new.st.var.rpy_string.0.helper"] = ((), """
-%st.rpy_string.0 * %new.st.var.rpy_string.0.helper(int %len) {
-    %size = getelementptr %st.rpy_string.0* null, int 0, uint 1, uint 1, int %len
-    %usize = cast sbyte* %size to uint
-    %malloc.Size.5 = getelementptr sbyte* null, uint %usize
-    %malloc.SizeU.5 = cast sbyte* %malloc.Size.5 to uint
-    %malloc.Ptr.5 = call sbyte* %gc_malloc(uint %malloc.SizeU.5)
-    %ptr = cast sbyte* %malloc.Ptr.5 to sbyte*
-    %result = cast sbyte* %ptr to %st.rpy_string.0*
-    %arraylength = getelementptr %st.rpy_string.0* %result, int 0, uint 1, uint 0
-    store int %len, int* %arraylength
-    ret %st.rpy_string.0* %result
-}
-
-""")
-
 extfunctions["%ll_time_time"] = ((), """
 double %ll_time_time() {
     %v0 = call int %time(int* null)
@@ -96,7 +82,7 @@
 double %ll_time_clock() {
     %v0 = call int %clock()
     %v1 = cast int %v0 to double
-    ; XXX how to get at the proper division constant per platform? 
+    ; XXX how to get at the proper division (or any other) constant per platform? 
     %v2 = div double %v1, 1000000.0    ;CLOCKS_PER_SEC accrdoing to single unix spec
     ret double %v2
 }
@@ -112,6 +98,22 @@
 
 """)
 
+extfunctions["%ll_os_dup"] = ((), """
+int %ll_os_dup(int %fd) {
+    %ret = call int %dup(int %fd)
+    ret int %ret
+}
+
+""")
+
+extfunctions["%ll_os_close"] = ((), """
+void %ll_os_close(int %fd) {
+    call void %close(int %fd)
+    ret void
+}
+
+""")
+
 extfunctions["%ll_os_open"] = (("%cast",), """
 int %ll_os_open(%st.rpy_string.0* %structstring, int %flag, int %mode) {
     %dest  = call sbyte* %cast(%st.rpy_string.0* %structstring)
@@ -132,21 +134,16 @@
 
 """)
 
-extfunctions["%ll_os_read"] = (("%new.st.var.rpy_string.0.helper",), """
-%st.rpy_string.0* %ll_os_read(int %fd, int %buffersize) {
-    ;This is a bit simplistic! It really allocated a large enough buffer to hold all the data in.
-    %str = call %st.rpy_string.0* %new.st.var.rpy_string.0.helper(int %buffersize)
+extfunctions["%ll_read_into"] = ((), """
+int %ll_read_into(int %fd, %st.rpy_string.0* %structstring) {
+    %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0
+    %reallength    = load int* %reallengthptr 
 
-    ;load the actual data
-    %destptr   = getelementptr %st.rpy_string.0* %str, int 0, uint 1, uint 1
+    %destptr   = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1
     %dest      = cast [0 x sbyte]* %destptr to sbyte*
-    %bytesread = call int %read(int %fd, sbyte* %dest, int %buffersize)
-    
-    ;set str.length to number of bytes read
-    %reallengthptr = getelementptr %st.rpy_string.0* %str, int 0, uint 1, uint 0
-    store int %bytesread, int* %reallengthptr
 
-    ret %st.rpy_string.0* %str
+    %bytesread = call int %read(int %fd, sbyte* %dest, int %reallength)
+    ret int %bytesread
 }
 
 """)

Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py	Thu Jul 21 00:42:22 2005
@@ -5,13 +5,13 @@
 from pypy.translator.backendoptimization import remove_same_as 
 from pypy.translator.unsimplify import remove_double_links                     
 from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode
+from pypy.translator.llvm2.opwriter import OpWriter
 from pypy.translator.llvm2.atomic import is_atomic
 from pypy.translator.llvm2.log import log 
 from pypy.rpython.extfunctable import table as extfunctable
 nextnum = py.std.itertools.count().next
 log = log.funcnode
 
-
 class FuncTypeNode(LLVMNode):
     def __init__(self, db, type_):
         self.db = db
@@ -67,15 +67,6 @@
         codewriter.declare(self.getdecl())
 
     def writeimpl(self, codewriter):
-
-        # XXX Code checks for when the rpython extfunctable has set the annotable
-        # flag to True?????
-        _callable = self.value._callable
-        for func, extfuncinfo in extfunctable.iteritems():  # precompute a dict?
-            if _callable is extfuncinfo.ll_function:
-                log('skipped output of external function %s' % self.value._name)
-                return
-
         assert self._issetup 
         graph = self.graph
         log.writeimpl(graph.name)
@@ -155,305 +146,3 @@
             codewriter.ret(inputargtype, inputarg)
         else:
             codewriter.ret_void()
-
-
-class ExternalFuncNode(LLVMNode):
-
-    fnmapping = {   #functions that have one-to-one C equivalents
-        "%ll_os_dup": "%dup",
-        "%ll_os_close": "%close",
-        }
-
-    def __init__(self, db, value):
-        self.db = db
-        self.value = value
-        self.ref = "%" + value._callable.__name__
-
-    def setup(self):
-        self._issetup = True
-
-    def getdecl(self):
-        T = self.value._TYPE
-        args = [self.db.repr_arg_type(a) for a in T.ARGS]
-        decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT),
-                              self.ref,
-                              ", ".join(args))
-        return decl
-
-    def getcdecl(self):        
-        #XXX Mapping
-        T = self.value._TYPE
-        args = [self.db.repr_arg_type(a) for a in T.ARGS]
-        decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT),
-                              self.fnmapping[self.ref],
-                              ", ".join(args))
-        return decl        
-
-    # ______________________________________________________________________
-    # main entry points from genllvm 
-    def writedecl(self, codewriter): 
-        codewriter.declare(self.getdecl())
-
-        if self.ref in self.fnmapping:
-            codewriter.declare(self.getcdecl())
-
-    def writeimpl(self, codewriter): 
-        if self.ref not in self.fnmapping:
-            self.used_external_functions[self.ref] = True
-            return
-
-        T = self.value._TYPE
-        args = ["%s %%a%s" % (self.db.repr_arg_type(a), c)
-                for c, a in enumerate(T.ARGS)]
-
-        decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT),
-                              self.ref,
-                              ", ".join(args))
-
-        codewriter.openfunc(decl)
-
-        # go thru and map argsXXX
-        argrefs = ["%%a%s" % c for c in range(len(T.ARGS))]
-        argtypes = [self.db.repr_arg_type(a) for a in T.ARGS]
-
-        # get return type (mapped perhaps)
-        resulttype = self.db.repr_arg_type(T.RESULT)
-
-        # get function name
-        fnname = self.fnmapping[self.ref]
-        
-        # call
-        if resulttype != "void":
-            # map resulttype ??? XXX
-            codewriter.call("%res", resulttype, fnname, argrefs, argtypes)
-            codewriter.ret(resulttype, "%res")
-        else:
-            codewriter.call_void(fnname, argrefs, argtypes)
-            codewriter.ret_void()
-        
-        codewriter.closefunc()
-
-class OpWriter(object):
-    binary_operations = {'int_mul': 'mul',
-                         'int_add': 'add',
-                         'int_sub': 'sub',
-                         'int_floordiv': 'div',
-                         'int_mod': 'rem',
-                         'int_lt': 'setlt',
-                         'int_le': 'setle',
-                         'int_eq': 'seteq',
-                         'int_ne': 'setne',
-                         'int_ge': 'setge',
-                         'int_gt': 'setgt',
-
-                         'uint_mul': 'mul',
-                         'uint_add': 'add',
-                         'uint_sub': 'sub',
-                         'uint_floordiv': 'div',
-                         'uint_mod': 'rem',
-                         'uint_lt': 'setlt',
-                         'uint_le': 'setle',
-                         'uint_eq': 'seteq',
-                         'uint_ne': 'setne',
-                         'uint_ge': 'setge',
-                         'uint_gt': 'setgt',
-
-                         'char_lt': 'setlt',
-                         'char_le': 'setle',
-                         'char_eq': 'seteq',
-                         'char_ne': 'setne',
-                         'char_ge': 'setge',
-                         'char_gt': 'setgt',
-
-                         'float_mul': 'mul',
-                         'float_add': 'add',
-                         'float_sub': 'sub',
-                         'float_truediv': 'div',
-                         'float_mod': 'rem',
-                         'float_lt': 'setlt',
-                         'float_le': 'setle',
-                         'float_eq': 'seteq',
-                         'float_ne': 'setne',
-                         'float_ge': 'setge',
-                         'float_gt': 'setgt',
-                         }
-
-    def __init__(self, db, codewriter):
-        self.db = db
-        self.codewriter = codewriter
-
-    def write_operation(self, op):
-        if op.opname in self.binary_operations:
-            self.binaryop(op)
-        else:
-            meth = getattr(self, op.opname, None)
-            assert meth is not None, "operation %r not found" %(op.opname,)
-            meth(op)    
-
-    def int_neg(self, op): 
-        self.codewriter.binaryop("sub", 
-                                 self.db.repr_arg(op.result),
-                                 self.db.repr_arg_type(op.args[0]),
-                                 "0", 
-                                 self.db.repr_arg(op.args[0]),
-                                 )
-
-    def bool_not(self, op):
-        self.codewriter.binaryop("xor",
-                                 self.db.repr_arg(op.result),
-                                 self.db.repr_arg_type(op.args[0]),
-                                 self.db.repr_arg(op.args[0]), 
-                                 "true")
-
-                    
-
-    def binaryop(self, op):
-        name = self.binary_operations[op.opname]
-        assert len(op.args) == 2
-        self.codewriter.binaryop(name,
-                                 self.db.repr_arg(op.result),
-                                 self.db.repr_arg_type(op.args[0]),
-                                 self.db.repr_arg(op.args[0]),
-                                 self.db.repr_arg(op.args[1]))
-
-    def cast_primitive(self, op): #works for all primitives
-        assert len(op.args) == 1
-        targetvar = self.db.repr_arg(op.result)
-        targettype = self.db.repr_arg_type(op.result)
-        fromvar = self.db.repr_arg(op.args[0])
-        fromtype = self.db.repr_arg_type(op.args[0])
-        self.codewriter.cast(targetvar, fromtype, fromvar, targettype)
-
-    cast_pointer = cast_primitive
-    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",
-                                 self.db.repr_arg(op.result),
-                                 self.db.repr_arg_type(op.args[0]),
-                                 self.db.repr_arg(op.args[0]),
-                                 "0")
-
-    uint_is_true = int_is_true
-
-    def float_is_true(self, op):
-        self.codewriter.binaryop("setne",
-                                 self.db.repr_arg(op.result),
-                                 self.db.repr_arg_type(op.args[0]),
-                                 self.db.repr_arg(op.args[0]),
-                                 "0.0")
-    
-    def direct_call(self, op):
-        assert len(op.args) >= 1
-        targetvar = self.db.repr_arg(op.result)
-        returntype = self.db.repr_arg_type(op.result)
-        functionref = self.db.repr_arg(op.args[0])
-        argrefs = self.db.repr_arg_multi(op.args[1:])
-        argtypes = self.db.repr_arg_type_multi(op.args[1:])
-        if returntype != "void":
-            self.codewriter.call(targetvar, returntype, functionref, argrefs,
-                                 argtypes)
-        else:
-            self.codewriter.call_void(functionref, argrefs, argtypes)
-
-    def malloc(self, op): 
-        targetvar = self.db.repr_arg(op.result) 
-        arg = op.args[0]
-        assert (isinstance(arg, Constant) and 
-                isinstance(arg.value, lltype.Struct))
-        #XXX unclean
-        node  = self.db.obj2node[arg.value]
-        type_ = node.ref
-        self.codewriter.malloc(targetvar, type_, atomic=is_atomic(node)) 
-
-    def malloc_varsize(self, op):
-        targetvar = self.db.repr_arg(op.result)
-        arg_type = op.args[0]
-        assert (isinstance(arg_type, Constant) and 
-                isinstance(arg_type.value, (lltype.Array, lltype.Struct)))
-        #XXX unclean
-        struct_type = self.db.obj2node[arg_type.value].ref
-        struct_cons = self.db.obj2node[arg_type.value].constructor_ref
-        argrefs = self.db.repr_arg_multi(op.args[1:])
-        argtypes = self.db.repr_arg_type_multi(op.args[1:])
-        self.codewriter.call(targetvar, struct_type + "*", struct_cons,
-                             argrefs, argtypes)
-
-    def getfield(self, op): 
-        tmpvar = self.db.repr_tmpvar()
-        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)
-        targettype = self.db.repr_arg_type(op.result)
-        if targettype != "void":
-            self.codewriter.getelementptr(tmpvar, structtype, struct,
-                                          ("uint", index))        
-            self.codewriter.load(targetvar, targettype, tmpvar)
-        else:
-            self.codewriter.comment("***Skipping operation getfield()***",
-                                    indent=True)
-                        
-    def getsubstruct(self, op): 
-        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)
-        targettype = self.db.repr_arg_type(op.result)
-        assert targettype != "void"
-        self.codewriter.getelementptr(targetvar, structtype, 
-                                      struct, ("uint", index))        
-         
-    def setfield(self, op): 
-        tmpvar = self.db.repr_tmpvar()
-        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, 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):        
-        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, 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, 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, arraytype, array,
-                                      ("uint", 1), (indextype, index))
-
-        valuevar = self.db.repr_arg(op.args[2]) 
-        valuetype = self.db.repr_arg_type(op.args[2])
-        self.codewriter.store(valuetype, valuevar, tmpvar) 
-
-    def getarraysize(self, op):
-        array, arraytype = self.db.repr_argwithtype(op.args[0])
-        tmpvar = self.db.repr_tmpvar()
-        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/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm2/genllvm.py	Thu Jul 21 00:42:22 2005
@@ -11,7 +11,7 @@
 from pypy.rpython import lltype
 from pypy.tool.udir import udir
 from pypy.translator.llvm2.codewriter import CodeWriter
-from pypy.translator.llvm2.node import LLVMNode
+from pypy.translator.llvm2.extfuncnode import ExternalFuncNode
 from pypy.translator.backendoptimization import remove_void
 #from pypy.translator.backendoptimization import rename_extfunc_calls
 from pypy.translator.llvm2.extfunction import extdeclarations, \
@@ -31,7 +31,7 @@
         remove_void(translator)
         #rename_extfunc_calls(translator)
         translator.checkgraphs()
-        LLVMNode.used_external_functions = {}
+        ExternalFuncNode.used_external_functions = {}
 
     def compile(self, func=None):
         if func is None:
@@ -77,7 +77,7 @@
             typ_decl.writeimpl(codewriter)
 
         depdone = {}
-        for funcname,value in LLVMNode.used_external_functions.iteritems():
+        for funcname,value in ExternalFuncNode.used_external_functions.iteritems():
             deps = dependencies(funcname,[])
             deps.reverse()
             for dep in deps:

Modified: pypy/dist/pypy/translator/llvm2/node.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/node.py	(original)
+++ pypy/dist/pypy/translator/llvm2/node.py	Thu Jul 21 00:42:22 2005
@@ -1,7 +1,4 @@
 class LLVMNode(object):
-
-    used_external_functions = {}
-
     def ref(): 
         def _get_ref(self):
             return self._ref 

Added: pypy/dist/pypy/translator/llvm2/opwriter.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm2/opwriter.py	Thu Jul 21 00:42:22 2005
@@ -0,0 +1,236 @@
+import py
+from pypy.objspace.flow.model import Block, Constant, Variable, Link
+from pypy.objspace.flow.model import flatten, mkentrymap, traverse
+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, ConstantLLVMNode
+from pypy.translator.llvm2.atomic import is_atomic
+from pypy.translator.llvm2.log import log 
+from pypy.rpython.extfunctable import table as extfunctable
+log = log.opwriter
+
+class OpWriter(object):
+    binary_operations = {'int_mul': 'mul',
+                         'int_add': 'add',
+                         'int_sub': 'sub',
+                         'int_floordiv': 'div',
+                         'int_mod': 'rem',
+                         'int_lt': 'setlt',
+                         'int_le': 'setle',
+                         'int_eq': 'seteq',
+                         'int_ne': 'setne',
+                         'int_ge': 'setge',
+                         'int_gt': 'setgt',
+
+                         'uint_mul': 'mul',
+                         'uint_add': 'add',
+                         'uint_sub': 'sub',
+                         'uint_floordiv': 'div',
+                         'uint_mod': 'rem',
+                         'uint_lt': 'setlt',
+                         'uint_le': 'setle',
+                         'uint_eq': 'seteq',
+                         'uint_ne': 'setne',
+                         'uint_ge': 'setge',
+                         'uint_gt': 'setgt',
+
+                         'char_lt': 'setlt',
+                         'char_le': 'setle',
+                         'char_eq': 'seteq',
+                         'char_ne': 'setne',
+                         'char_ge': 'setge',
+                         'char_gt': 'setgt',
+
+                         'float_mul': 'mul',
+                         'float_add': 'add',
+                         'float_sub': 'sub',
+                         'float_truediv': 'div',
+                         'float_mod': 'rem',
+                         'float_lt': 'setlt',
+                         'float_le': 'setle',
+                         'float_eq': 'seteq',
+                         'float_ne': 'setne',
+                         'float_ge': 'setge',
+                         'float_gt': 'setgt',
+                         }
+
+    def __init__(self, db, codewriter):
+        self.db = db
+        self.codewriter = codewriter
+
+    def write_operation(self, op):
+        if op.opname in self.binary_operations:
+            self.binaryop(op)
+        else:
+            meth = getattr(self, op.opname, None)
+            assert meth is not None, "operation %r not found" %(op.opname,)
+            meth(op)    
+
+    def int_neg(self, op): 
+        self.codewriter.binaryop("sub", 
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 "0", 
+                                 self.db.repr_arg(op.args[0]),
+                                 )
+
+    def bool_not(self, op):
+        self.codewriter.binaryop("xor",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]), 
+                                 "true")
+
+                    
+
+    def binaryop(self, op):
+        name = self.binary_operations[op.opname]
+        assert len(op.args) == 2
+        self.codewriter.binaryop(name,
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 self.db.repr_arg(op.args[1]))
+
+    def cast_primitive(self, op): #works for all primitives
+        assert len(op.args) == 1
+        targetvar = self.db.repr_arg(op.result)
+        targettype = self.db.repr_arg_type(op.result)
+        fromvar = self.db.repr_arg(op.args[0])
+        fromtype = self.db.repr_arg_type(op.args[0])
+        self.codewriter.cast(targetvar, fromtype, fromvar, targettype)
+
+    cast_pointer = cast_primitive
+    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",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 "0")
+
+    uint_is_true = int_is_true
+
+    def float_is_true(self, op):
+        self.codewriter.binaryop("setne",
+                                 self.db.repr_arg(op.result),
+                                 self.db.repr_arg_type(op.args[0]),
+                                 self.db.repr_arg(op.args[0]),
+                                 "0.0")
+    
+    def direct_call(self, op):
+        assert len(op.args) >= 1
+        targetvar = self.db.repr_arg(op.result)
+        returntype = self.db.repr_arg_type(op.result)
+        functionref = self.db.repr_arg(op.args[0])
+        argrefs = self.db.repr_arg_multi(op.args[1:])
+        argtypes = self.db.repr_arg_type_multi(op.args[1:])
+        if returntype != "void":
+            self.codewriter.call(targetvar, returntype, functionref, argrefs,
+                                 argtypes)
+        else:
+            self.codewriter.call_void(functionref, argrefs, argtypes)
+
+    def malloc(self, op): 
+        targetvar = self.db.repr_arg(op.result) 
+        arg = op.args[0]
+        assert (isinstance(arg, Constant) and 
+                isinstance(arg.value, lltype.Struct))
+        #XXX unclean
+        node  = self.db.obj2node[arg.value]
+        type_ = node.ref
+        self.codewriter.malloc(targetvar, type_, atomic=is_atomic(node)) 
+
+    def malloc_varsize(self, op):
+        targetvar = self.db.repr_arg(op.result)
+        arg_type = op.args[0]
+        assert (isinstance(arg_type, Constant) and 
+                isinstance(arg_type.value, (lltype.Array, lltype.Struct)))
+        #XXX unclean
+        struct_type = self.db.obj2node[arg_type.value].ref
+        struct_cons = self.db.obj2node[arg_type.value].constructor_ref
+        argrefs = self.db.repr_arg_multi(op.args[1:])
+        argtypes = self.db.repr_arg_type_multi(op.args[1:])
+        self.codewriter.call(targetvar, struct_type + "*", struct_cons,
+                             argrefs, argtypes)
+
+    def getfield(self, op): 
+        tmpvar = self.db.repr_tmpvar()
+        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)
+        targettype = self.db.repr_arg_type(op.result)
+        if targettype != "void":
+            self.codewriter.getelementptr(tmpvar, structtype, struct,
+                                          ("uint", index))        
+            self.codewriter.load(targetvar, targettype, tmpvar)
+        else:
+            self.codewriter.comment("***Skipping operation getfield()***",
+                                    indent=True)
+                        
+    def getsubstruct(self, op): 
+        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)
+        targettype = self.db.repr_arg_type(op.result)
+        assert targettype != "void"
+        self.codewriter.getelementptr(targetvar, structtype, 
+                                      struct, ("uint", index))        
+         
+    def setfield(self, op): 
+        tmpvar = self.db.repr_tmpvar()
+        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, 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):        
+        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, 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, 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, arraytype, array,
+                                      ("uint", 1), (indextype, index))
+
+        valuevar = self.db.repr_arg(op.args[2]) 
+        valuetype = self.db.repr_arg_type(op.args[2])
+        self.codewriter.store(valuetype, valuevar, tmpvar) 
+
+    def getarraysize(self, op):
+        array, arraytype = self.db.repr_argwithtype(op.args[0])
+        tmpvar = self.db.repr_tmpvar()
+        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)



More information about the Pypy-commit mailing list