[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