[pypy-svn] r65008 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test
arigo at codespeak.net
arigo at codespeak.net
Sun May 3 20:44:43 CEST 2009
Author: arigo
Date: Sun May 3 20:44:42 2009
New Revision: 65008
Added:
pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py (contents, props changed)
pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py (contents, props changed)
Modified:
pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py
Log:
Add the CPU class. The first test passes.
Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py Sun May 3 20:44:42 2009
@@ -71,8 +71,20 @@
[LLVMTypeRef, # return type
rffi.CArrayPtr(LLVMTypeRef), # param types
rffi.UINT, # param count
- rffi.INT], # flag: is vararg
+ rffi.INT], # flag: is_vararg
LLVMTypeRef)
+LLVMPointerType = llexternal('LLVMPointerType', [LLVMTypeRef, # element type
+ rffi.UINT], # address space
+ LLVMTypeRef)
+
+LLVMConstInt = llexternal('LLVMConstInt', [LLVMTypeRef, # type
+ rffi.ULONGLONG, # value
+ rffi.INT], # flag: is_signed
+ LLVMValueRef)
+LLVMConstIntToPtr = llexternal('LLVMConstIntToPtr',
+ [LLVMValueRef, # constant integer value
+ LLVMTypeRef], # type of the result
+ LLVMValueRef)
LLVMAddFunction = llexternal('LLVMAddFunction',
[LLVMModuleRef, # module
@@ -100,11 +112,27 @@
LLVMBuildRet = llexternal('LLVMBuildRet', [LLVMBuilderRef, # builder,
LLVMValueRef], # result
LLVMValueRef)
-LLVMBuildAdd = llexternal('LLVMBuildAdd', [LLVMBuilderRef, # builder
- LLVMValueRef, # left-hand side
- LLVMValueRef, # right-hand side
- rffi.CCHARP], # name of result
- LLVMValueRef)
+
+for _name in ['Add', 'Sub', 'LShr']:
+ globals()['LLVMBuild' + _name] = llexternal('LLVMBuild' + _name,
+ [LLVMBuilderRef, # builder
+ LLVMValueRef, # left-hand side
+ LLVMValueRef, # right-hand side
+ rffi.CCHARP], # name of result
+ LLVMValueRef)
+
+for _name in ['Neg', 'Not']:
+ globals()['LLVMBuild' + _name] = llexternal('LLVMBuild' + _name,
+ [LLVMBuilderRef, # builder
+ LLVMValueRef, # argument
+ rffi.CCHARP], # name of result
+ LLVMValueRef)
+
+LLVMBuildStore = llexternal('LLVMBuildStore',
+ [LLVMBuilderRef, # builder
+ LLVMValueRef, # value
+ LLVMValueRef], # pointer location
+ LLVMValueRef)
LLVMCreateModuleProviderForExistingModule = llexternal(
'LLVMCreateModuleProviderForExistingModule', [LLVMModuleRef],
Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py
==============================================================================
--- (empty file)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/runner.py Sun May 3 20:44:42 2009
@@ -0,0 +1,197 @@
+import sys
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.unroll import unrolling_iterable
+from pypy.jit.metainterp.history import ConstInt
+from pypy.jit.backend import model
+from pypy.jit.backend.llvm import llvm_rffi
+from pypy.jit.metainterp import resoperation
+from pypy.jit.metainterp.resoperation import rop
+
+
+class LLVMException(Exception):
+ pass
+
+
+class LLVMCPU(model.AbstractCPU):
+ ARRAY_OF_VALUE_REFS = rffi.CArray(llvm_rffi.LLVMGenericValueRef)
+ RAW_VALUE = rffi.CFixedArray(rffi.ULONGLONG, 1)
+
+ def __init__(self, rtyper, stats=None, translate_support_code=False,
+ annmixlevel=None):
+ self.rtyper = rtyper
+ self.translate_support_code = translate_support_code
+ self.ty_funcs = {}
+ self.fail_ops = []
+ self.in_args_count = 0
+ self.in_args = lltype.malloc(self.ARRAY_OF_VALUE_REFS, 0,
+ flavor='raw')
+ self.out_args = []
+
+ def setup_once(self):
+ self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit")
+ if sys.maxint == 2147483647:
+ self.ty_int = llvm_rffi.LLVMInt32Type()
+ else:
+ self.ty_int = llvm_rffi.LLVMInt64Type()
+ self.ty_int_ptr = llvm_rffi.LLVMPointerType(self.ty_int, 0)
+
+ mp = llvm_rffi.LLVMCreateModuleProviderForExistingModule(self.module)
+ ee_out = lltype.malloc(rffi.CArray(llvm_rffi.LLVMExecutionEngineRef),
+ 1, flavor='raw')
+ error_out = lltype.malloc(rffi.CArray(rffi.CCHARP), 1, flavor='raw')
+ error_out[0] = lltype.nullptr(rffi.CCHARP.TO)
+ try:
+ error = llvm_rffi.LLVMCreateJITCompiler(ee_out, mp, True,
+ error_out)
+ if rffi.cast(lltype.Signed, error) != 0:
+ raise LLVMException(rffi.charp2str(error_out[0]))
+ self.ee = ee_out[0]
+ finally:
+ if error_out[0]:
+ llvm_rffi.LLVMDisposeMessage(error_out[0])
+ lltype.free(error_out, flavor='raw')
+ lltype.free(ee_out, flavor='raw')
+
+ # ------------------------------
+ # Compilation
+
+ def compile_operations(self, loop):
+ self._ensure_in_args(len(loop.inputargs))
+ ty_func = self.get_ty_func(len(loop.inputargs))
+ func = llvm_rffi.LLVMAddFunction(self.module, "", ty_func)
+ self.vars = {}
+ for i in range(len(loop.inputargs)):
+ self.vars[loop.inputargs[i]] = llvm_rffi.LLVMGetParam(func, i)
+ self.builder = llvm_rffi.LLVMCreateBuilder()
+ self._generate_branch(loop.operations, func)
+ llvm_rffi.LLVMDisposeBuilder(self.builder)
+ self.builder = None
+ self.vars = None
+ #...
+ llvm_rffi.LLVMDumpModule(self.module)
+ loop._llvm_func = func
+
+ def get_ty_func(self, nb_args):
+ try:
+ return self.ty_funcs[nb_args]
+ except KeyError:
+ arglist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMTypeRef),
+ nb_args, flavor='raw')
+ for i in range(nb_args):
+ arglist[i] = self.ty_int
+ ty_func = llvm_rffi.LLVMFunctionType(self.ty_int, arglist,
+ nb_args, False)
+ lltype.free(arglist, flavor='raw')
+ self.ty_funcs[nb_args] = ty_func
+ return ty_func
+
+ def _ensure_in_args(self, count):
+ if self.in_args_count <= count:
+ count = (count + 8) & ~7 # increment by at least one
+ new = lltype.malloc(self.ARRAY_OF_VALUE_REFS, count, flavor='raw')
+ lltype.free(self.in_args, flavor='raw')
+ for i in range(count):
+ new[i] = lltype.nullptr(llvm_rffi.LLVMGenericValueRef.TO)
+ self.in_args = new
+ self.in_args_count = count
+
+ def _ensure_out_args(self, count):
+ while len(self.out_args) < count:
+ self.out_args.append(lltype.malloc(self.RAW_VALUE, flavor='raw'))
+
+ def _generate_branch(self, operations, func):
+ bb = llvm_rffi.LLVMAppendBasicBlock(func, "")
+ llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb)
+ #
+ for op in operations:
+ self._generate_op(op)
+ #
+ return bb
+
+ def _generate_op(self, op):
+ opnum = op.opnum
+ for i, name in all_operations:
+ if opnum == i:
+ meth = getattr(self, name)
+ meth(op)
+ return
+ else:
+ raise MissingOperation(resoperation.opname[opnum])
+
+ def getarg(self, v):
+ try:
+ return self.vars[v]
+ except KeyError:
+ assert isinstance(v, ConstInt)
+ return self._make_const_int(v.value)
+
+ def _make_const_int(self, value):
+ return llvm_rffi.LLVMConstInt(self.ty_int, value, True)
+
+ def generate_int_add(self, op):
+ self.vars[op.result] = llvm_rffi.LLVMBuildAdd(self.builder,
+ self.getarg(op.args[0]),
+ self.getarg(op.args[1]),
+ "")
+
+ def generate_uint_rshift(self, op):
+ self.vars[op.result] = llvm_rffi.LLVMBuildLShr(self.builder,
+ self.getarg(op.args[0]),
+ self.getarg(op.args[1]),
+ "")
+
+ def generate_int_invert(self, op):
+ self.vars[op.result] = llvm_rffi.LLVMBuildNot(self.builder,
+ self.vars[op.args[0]],
+ "")
+
+ def generate_fail(self, op):
+ self._ensure_out_args(len(op.args))
+ for i in range(len(op.args)):
+ addr_as_signed = rffi.cast(lltype.Signed, self.out_args[i])
+ llvmconstint = self._make_const_int(addr_as_signed)
+ llvmconstptr = llvm_rffi.LLVMConstIntToPtr(llvmconstint,
+ self.ty_int_ptr)
+ llvm_rffi.LLVMBuildStore(self.builder, self.vars[op.args[i]],
+ llvmconstptr)
+ i = len(self.fail_ops)
+ self.fail_ops.append(op)
+ llvm_rffi.LLVMBuildRet(self.builder, self._make_const_int(i))
+
+ # ------------------------------
+ # Execution
+
+ def set_future_value_int(self, index, intvalue):
+ assert index < self.in_args_count - 1
+ self.in_args[index] = llvm_rffi.LLVMCreateGenericValueOfInt(
+ self.ty_int, intvalue, True)
+
+ def execute_operations(self, loop):
+ retval = llvm_rffi.LLVMRunFunction(self.ee, loop._llvm_func,
+ len(loop.inputargs),
+ self.in_args)
+ ulonglong = llvm_rffi.LLVMGenericValueToInt(retval, True)
+ res = rffi.cast(lltype.Signed, ulonglong)
+ llvm_rffi.LLVMDisposeGenericValue(retval)
+ i = 0
+ while self.in_args[i]:
+ llvm_rffi.LLVMDisposeGenericValue(self.in_args[i])
+ self.in_args[i] = lltype.nullptr(llvm_rffi.LLVMGenericValueRef.TO)
+ i += 1
+
+ def get_latest_value_int(self, index):
+ return rffi.cast(lltype.Signed, self.out_args[index][0])
+
+# ____________________________________________________________
+
+class MissingOperation(Exception):
+ pass
+
+all_operations = {}
+for _key, _value in rop.__dict__.items():
+ if 'A' <= _key <= 'Z':
+ assert _value not in all_operations
+ methname = 'generate_' + _key.lower()
+ if hasattr(LLVMCPU, methname):
+ all_operations[_value] = methname
+all_operations = unrolling_iterable(all_operations.items())
Added: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py
==============================================================================
--- (empty file)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_runner.py Sun May 3 20:44:42 2009
@@ -0,0 +1,27 @@
+
+from pypy.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\
+ BoxPtr, ConstPtr, TreeLoop
+from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.backend.llvm.runner import LLVMCPU
+
+
+def test_simple_case():
+ v1 = BoxInt()
+ v2 = BoxInt()
+ v3 = BoxInt()
+ v4 = BoxInt()
+ loop = TreeLoop('test')
+ loop.inputargs = [v1]
+ loop.operations = [
+ ResOperation(rop.INT_ADD, [v1, v1], v2),
+ ResOperation(rop.INT_INVERT, [v2], v3),
+ ResOperation(rop.UINT_RSHIFT, [v1, ConstInt(3)], v4),
+ ResOperation(rop.FAIL, [v4, v3], None),
+ ]
+ cpu = LLVMCPU(None)
+ cpu.setup_once()
+ cpu.compile_operations(loop)
+ cpu.set_future_value_int(0, 19)
+ cpu.execute_operations(loop)
+ assert cpu.get_latest_value_int(0) == (19 >> 3)
+ assert cpu.get_latest_value_int(1) == (~38)
More information about the Pypy-commit
mailing list