[pypy-svn] r35332 - in pypy/dist/pypy/jit/codegen/llvm: . test

ericvrp at codespeak.net ericvrp at codespeak.net
Tue Dec 5 20:43:54 CET 2006


Author: ericvrp
Date: Tue Dec  5 20:43:53 2006
New Revision: 35332

Modified:
   pypy/dist/pypy/jit/codegen/llvm/llvmjit.py
   pypy/dist/pypy/jit/codegen/llvm/rgenop.py
   pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py
   pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py
Log:
First jit/codegen/llvm rgenop test that actualy passes


Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llvm/llvmjit.py	(original)
+++ pypy/dist/pypy/jit/codegen/llvm/llvmjit.py	Tue Dec  5 20:43:53 2006
@@ -44,6 +44,9 @@
     libraries = (os.path.join(os.path.dirname(path), 'llvmjit'),)
 llvmjit._FuncPtr = _FuncPtr
 
+#ensure stable state
+llvmjit.restart()
+
 #exposed functions...
 restart = llvmjit.restart
 
@@ -63,6 +66,10 @@
 getNamedGlobal.restype  = c_void_p
 getNamedGlobal.argtypes = [c_char_p]
 
+getPointerToFunction = llvmjit.getPointerToFunction
+getPointerToFunction.restype = c_void_p
+getPointerToFunction.argtypes = [c_void_p]
+
 freeMachineCodeForFunction = llvmjit.freeMachineCodeForFunction
 freeMachineCodeForFunction.restype  = c_int
 freeMachineCodeForFunction.argtypes = [c_void_p]

Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llvm/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py	Tue Dec  5 20:43:53 2006
@@ -2,6 +2,7 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder
 from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch
+from pypy.jit.codegen.llvm import llvmjit
 
 
 def log(s):
@@ -9,10 +10,20 @@
     pass
 
 
+n_vars = 0
+
 class Var(GenVar):
 
     def __init__(self):
-        pass
+        global n_vars
+        self.name = '%v' + str(n_vars) 
+        n_vars += 1
+
+    def operand(self):
+        return 'int ' + self.name
+
+    def operand2(self):
+        return self.name
 
     #repr?
 
@@ -22,6 +33,12 @@
     def __init__(self, value):
         self.value = value
 
+    def operand(self):
+        return 'int ' + str(self.value)
+
+    def operand2(self):
+        return str(self.value)
+
     @specialize.arg(1)
     def revealconst(self, T):
         if isinstance(T, lltype.Ptr):
@@ -39,6 +56,12 @@
     def __init__(self, addr):
         self.addr = addr
 
+    def operand(self):
+        return 'int* ' + str(llmemory.cast_adr_to_int(self.addr))
+
+    def operand2(self):
+        return str(llmemory.cast_adr_to_int(self.addr))
+
     @specialize.arg(1)
     def revealconst(self, T):
         if T is llmemory.Address:
@@ -63,85 +86,81 @@
 
 class FlexSwitch(CodeGenSwitch):
 
-    #<comment>
-
     def __init__(self, rgenop):
         log('FlexSwitch.__init__')
         self.rgenop = rgenop
-        self.default_case_addr = 0
+        #self.default_case_addr = 0
 
     def initialize(self, builder, gv_exitswitch):
-        log('FlexSwitch.initialize')
-        mc = builder.mc
-        mc.MOV(eax, gv_exitswitch.operand(builder))
-        self.saved_state = builder._save_state()
-        self._reserve(mc)
+        log('FlexSwitch.initialize TODO')
+        #mc = builder.mc
+        #mc.MOV(eax, gv_exitswitch.operand(builder))
+        #self.saved_state = builder._save_state()
+        #self._reserve(mc)
 
     def _reserve(self, mc):
-        log('FlexSwitch._reserve')
-        RESERVED = 11*4+5      # XXX quite a lot for now :-/
-        pos = mc.tell()
-        mc.UD2()
-        mc.write('\x00' * (RESERVED-1))
-        self.nextfreepos = pos
-        self.endfreepos = pos + RESERVED
+        log('FlexSwitch._reserve TODO')
+        #RESERVED = 11*4+5      # XXX quite a lot for now :-/
+        #pos = mc.tell()
+        #mc.UD2()
+        #mc.write('\x00' * (RESERVED-1))
+        #self.nextfreepos = pos
+        #self.endfreepos = pos + RESERVED
 
     def _reserve_more(self):
-        log('FlexSwitch._reserve_more')
-        start = self.nextfreepos
-        end   = self.endfreepos
-        newmc = self.rgenop.open_mc()
-        self._reserve(newmc)
-        self.rgenop.close_mc(newmc)
-        fullmc = InMemoryCodeBuilder(start, end)
-        fullmc.JMP(rel32(self.nextfreepos))
-        fullmc.done()
+        log('FlexSwitch._reserve_more TODO')
+        #start = self.nextfreepos
+        #end   = self.endfreepos
+        #newmc = self.rgenop.open_mc()
+        #self._reserve(newmc)
+        #self.rgenop.close_mc(newmc)
+        #fullmc = InMemoryCodeBuilder(start, end)
+        #fullmc.JMP(rel32(self.nextfreepos))
+        #fullmc.done()
 
     def add_case(self, gv_case):
-        log('FlexSwitch.add_case')
-        rgenop = self.rgenop
-        targetbuilder = Builder._new_from_state(rgenop, self.saved_state)
-        target_addr = targetbuilder.mc.tell()
-        try:
-            self._add_case(gv_case, target_addr)
-        except CodeBlockOverflow:
-            self._reserve_more()
-            self._add_case(gv_case, target_addr)
-        return targetbuilder
+        log('FlexSwitch.add_case TODO')
+        #rgenop = self.rgenop
+        #targetbuilder = Builder._new_from_state(rgenop, self.saved_state)
+        #target_addr = targetbuilder.mc.tell()
+        #try:
+        #    self._add_case(gv_case, target_addr)
+        #except CodeBlockOverflow:
+        #    self._reserve_more()
+        #    self._add_case(gv_case, target_addr)
+        #return targetbuilder
 
     def _add_case(self, gv_case, target_addr):
-        log('FlexSwitch._add_case')
-        start = self.nextfreepos
-        end   = self.endfreepos
-        mc = InMemoryCodeBuilder(start, end)
-        mc.CMP(eax, gv_case.operand(None))
-        mc.JE(rel32(target_addr))
-        pos = mc.tell()
-        if self.default_case_addr:
-            mc.JMP(rel32(self.default_case_addr))
-        else:
-            illegal_start = mc.tell()
-            mc.JMP(rel32(0))
-            ud2_addr = mc.tell()
-            mc.UD2()
-            illegal_mc = InMemoryCodeBuilder(illegal_start, end)
-            illegal_mc.JMP(rel32(ud2_addr))
-        mc.done()
-        self.nextfreepos = pos
+        log('FlexSwitch._add_case TODO')
+        #start = self.nextfreepos
+        #end   = self.endfreepos
+        #mc = InMemoryCodeBuilder(start, end)
+        #mc.CMP(eax, gv_case.operand(None))
+        #mc.JE(rel32(target_addr))
+        #pos = mc.tell()
+        #if self.default_case_addr:
+        #    mc.JMP(rel32(self.default_case_addr))
+        #else:
+        #    illegal_start = mc.tell()
+        #    mc.JMP(rel32(0))
+        #    ud2_addr = mc.tell()
+        #    mc.UD2()
+        #    illegal_mc = InMemoryCodeBuilder(illegal_start, end)
+        #    illegal_mc.JMP(rel32(ud2_addr))
+        #mc.done()
+        #self.nextfreepos = pos
 
     def add_default(self):
-        log('FlexSwitch.add_default')
-        rgenop = self.rgenop
-        targetbuilder = Builder._new_from_state(rgenop, self.saved_state)
-        self.default_case_addr = targetbuilder.mc.tell()
-        start = self.nextfreepos
-        end   = self.endfreepos
-        mc = InMemoryCodeBuilder(start, end)
-        mc.JMP(rel32(self.default_case_addr))
-        mc.done()
-        return targetbuilder
-
-    #</comment>
+        log('FlexSwitch.add_default TODO')
+        #rgenop = self.rgenop
+        #targetbuilder = Builder._new_from_state(rgenop, self.saved_state)
+        #self.default_case_addr = targetbuilder.mc.tell()
+        #start = self.nextfreepos
+        #end   = self.endfreepos
+        #mc = InMemoryCodeBuilder(start, end)
+        #mc.JMP(rel32(self.default_case_addr))
+        #mc.done()
+        #return targetbuilder
 
 
 class Builder(object):  #changed baseclass from (GenBuilder) for better error messages
@@ -156,20 +175,29 @@
 
     def end(self):
         log('Builder.end')
-        pass
+        self.asm.append('}')
+        asm_string = '\n'.join(self.asm)
+        log(asm_string)
+        llvmjit.parse(asm_string)
+        function   = llvmjit.getNamedFunction(self.rgenop.name)
+        entrypoint = llvmjit.getPointerToFunction(function)
+        self.rgenop.gv_entrypoint.value = entrypoint
+        #print self.rgenop.name, 'entrypoint', entrypoint
+        #print self.rgenop.gv_entrypoint, self.rgenop.gv_entrypoint.value
 
     def _write_prologue(self, sigtoken):
         log('Builder._write_prologue')
         numargs = sigtoken     # for now
-        #self.mc.BREAKPOINT()
-        return [Var() for i in range(numargs)]
+        inputargs_gv = [Var() for i in range(numargs)]
+        self.asm.append('int %%%s(%s){' % (
+            self.rgenop.name, ','.join([v.operand() for v in inputargs_gv])))
+        return inputargs_gv
 
     def _close(self):
         log('Builder._close')
-        return
-        self.mc.done()
-        self.rgenop.close_mc(self.mc)
-        self.mc = None
+        #self.mc.done()
+        #self.rgenop.close_mc(self.mc)
+        #self.mc = None
 
     @specialize.arg(1)
     def genop1(self, opname, gv_arg):
@@ -186,47 +214,45 @@
     def op_int_add(self, gv_x, gv_y):
         log('Builder.op_int_add')
         gv_result = Var()
+        self.asm.append(" %s=add %s,%s" % (gv_result.name, gv_x.operand(), gv_y.operand2()))
         return gv_result
-        self.mc.MOV(eax, gv_x.operand(self))
-        self.mc.ADD(eax, gv_y.operand(self))
-        return self.returnvar(eax) 
+        #self.mc.MOV(eax, gv_x.operand(self))
+        #self.mc.ADD(eax, gv_y.operand(self))
+        #return self.returnvar(eax) 
 
     def enter_next_block(self, kinds, args_gv):
-        log('Builder.enter_next_block')
-        return
-        arg_positions = []
-        seen = {}
-        for i in range(len(args_gv)):
-            gv = args_gv[i]
-            # turn constants into variables; also make copies of vars that
-            # are duplicate in args_gv
-            if not isinstance(gv, Var) or gv.stackpos in seen:
-                gv = args_gv[i] = self.returnvar(gv.operand(self))
-            # remember the var's position in the stack
-            arg_positions.append(gv.stackpos)
-            seen[gv.stackpos] = None
-        return Label(self.mc.tell(), arg_positions, self.stackdepth)
+        log('Builder.enter_next_block TODO')
+        #arg_positions = []
+        #seen = {}
+        #for i in range(len(args_gv)):
+        #    gv = args_gv[i]
+        #    # turn constants into variables; also make copies of vars that
+        #    # are duplicate in args_gv
+        #    if not isinstance(gv, Var) or gv.stackpos in seen:
+        #        gv = args_gv[i] = self.returnvar(gv.operand(self))
+        #    # remember the var's position in the stack
+        #    arg_positions.append(gv.stackpos)
+        #    seen[gv.stackpos] = None
+        #return Label(self.mc.tell(), arg_positions, self.stackdepth)
 
     def finish_and_return(self, sigtoken, gv_returnvar):
         log('Builder.finish_and_return')
-        return
-        numargs = sigtoken      # for now
-        initialstackdepth = numargs + 1
-        self.mc.MOV(eax, gv_returnvar.operand(self))
-        self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth)))
-        self.mc.RET()
+        self.asm.append(' ret ' + gv_returnvar.operand())
+        #numargs = sigtoken      # for now
+        #initialstackdepth = numargs + 1
+        #self.mc.MOV(eax, gv_returnvar.operand(self))
+        #self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth)))
+        #self.mc.RET()
         self._close()
 
     def finish_and_goto(self, outputargs_gv, target):
-        log('Builder.finish_and_goto')
-        return
-        remap_stack_layout(self, outputargs_gv, target)
-        self.mc.JMP(rel32(target.startaddr))
+        log('Builder.finish_and_goto TODO')
+        #remap_stack_layout(self, outputargs_gv, target)
+        #self.mc.JMP(rel32(target.startaddr))
         self._close()
 
     def flexswitch(self, gv_exitswitch):
-        log('Builder.flexswitch')
-        return
+        log('Builder.flexswitch TODO')
         result = FlexSwitch(self.rgenop)
         result.initialize(self, gv_exitswitch)
         self._close()
@@ -254,11 +280,12 @@
     def newgraph(self, sigtoken, name):
         log('RLLVMGenOp.newgraph')
         numargs = sigtoken          # for now
+        self.name = name
         builder = self.openbuilder()
         #entrypoint = builder.asm.mc.tell()
-        entrypoint = 0 #XXX
+        self.gv_entrypoint = IntConst(0)
         inputargs_gv = builder._write_prologue(sigtoken)
-        return builder, IntConst(entrypoint), inputargs_gv
+        return builder, self.gv_entrypoint, inputargs_gv
 
     @specialize.genconst(1)
     def genconst(self, llvalue):    #i386 version (ppc version is slightly different)

Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py	(original)
+++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py	Tue Dec  5 20:43:53 2006
@@ -132,6 +132,12 @@
     llvmjit.restart()
     assert execute(llsquare, 'square', 4) == 4 * 4
 
+def test_execute_with_ctypes():
+    py.test.skip('TODO: implement execute with ctypes thru real pointer to function')
+    llvmjit.restart()
+    #should use function.getPointerToFunction
+    assert execute(llsquare, 'square', 4) == 4 * 4
+
 def test_execute_nothing():
     llvmjit.restart()
     assert llvmjit.execute(None, 4) == -1 #-1 == no function supplied

Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py	Tue Dec  5 20:43:53 2006
@@ -1,9 +1,31 @@
 import py
 from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp
 from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests
+from pypy.rpython.lltypesystem import lltype
+from ctypes import c_void_p, cast, CFUNCTYPE, c_int
 
 
-py.test.skip("WIP")
+FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
+
+def make_adder(rgenop, n):
+    # 'return x+n'
+    sigtoken = rgenop.sigToken(FUNC)
+    builder, gv_add_one, [gv_x] = rgenop.newgraph(sigtoken, "adder")
+    #note: entrypoint (gv_add_one.value) gets updated by builder.end() (don't use before that!)
+    gv_result = builder.genop2("int_add", gv_x, rgenop.genconst(n))
+    builder.finish_and_return(sigtoken, gv_result)
+    builder.end()
+    return gv_add_one
+
+def test_adder_direct():
+    rgenop = RLLVMGenOp()
+    gv_add_5 = make_adder(rgenop, 5)
+    fnptr = cast(c_void_p(gv_add_5.value), CFUNCTYPE(c_int, c_int))
+    #fnptr = gv_add_5.revealconst(lltype.Ptr(FUNC))
+    res = fnptr(37)
+    assert res == 42
+
+
+#class TestRLLVMGenop(AbstractRGenOpTests):
+#    RGenOp = RLLVMGenOp
 
-class TestRLLVMGenop(AbstractRGenOpTests):
-    RGenOp = RLLVMGenOp


More information about the pypy-svn mailing list