[pypy-svn] r65657 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm
arigo at codespeak.net
arigo at codespeak.net
Mon Jun 8 11:56:13 CEST 2009
Author: arigo
Date: Mon Jun 8 11:56:13 2009
New Revision: 65657
Added:
pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/compile.py
- copied, changed from r65656, pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py
Modified:
pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py
Log:
Split runner.py in two files.
Copied: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/compile.py (from r65656, pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py)
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py (original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/compile.py Mon Jun 8 11:56:13 2009
@@ -1,336 +1,13 @@
-import py, sys
-from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
+import py
+from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.unroll import unrolling_iterable
-from pypy.jit.metainterp.history import ConstInt, AbstractDescr, INT
-from pypy.jit.metainterp.history import BoxInt, BoxPtr
-from pypy.jit.backend import model
+from pypy.jit.metainterp.history import ConstInt, INT
from pypy.jit.backend.llvm import llvm_rffi
from pypy.jit.metainterp import resoperation
-from pypy.jit.metainterp import history
-from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.metainterp.resoperation import rop
from pypy.jit.backend.x86 import symbolic # xxx
-
-history.TreeLoop._llvm_compiled_index = -1
-
-
-class LLVMCPU(model.AbstractCPU):
- is_oo = False
- RAW_VALUE = rffi.CFixedArray(rffi.ULONGLONG, 1)
- SIGNED_VALUE = rffi.CFixedArray(lltype.Signed, 1)
- POINTER_VALUE = rffi.CFixedArray(llmemory.GCREF, 1)
-
- def __init__(self, rtyper, stats=None, translate_support_code=False,
- annmixlevel=None):
- self.rtyper = rtyper
- self.translate_support_code = translate_support_code
- self.compiled_functions = []
- self.fail_ops = []
- self.in_out_args = []
- self._descr_caches = {}
- self.fielddescr_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr')
- if sys.maxint == 2147483647:
- self.size_of_int = 4
- else:
- self.size_of_int = 8
-
- def setup_once(self):
- if not we_are_translated():
- llvm_rffi.teardown_now()
- llvm_rffi.LLVM_SetFlags()
- self.module = llvm_rffi.LLVMModuleCreateWithName("pypyjit")
- if self.size_of_int == 4:
- self.ty_int = llvm_rffi.LLVMInt32Type()
- else:
- self.ty_int = llvm_rffi.LLVMInt64Type()
- self.ty_void = llvm_rffi.LLVMVoidType()
- self.ty_bit = llvm_rffi.LLVMInt1Type()
- self.ty_char = llvm_rffi.LLVMInt8Type()
- self.ty_char_ptr = llvm_rffi.LLVMPointerType(self.ty_char, 0)
- self.ty_char_ptr_ptr = llvm_rffi.LLVMPointerType(self.ty_char_ptr, 0)
- self.ty_int_ptr = llvm_rffi.LLVMPointerType(self.ty_int, 0)
- self.ty_int_ptr_ptr = llvm_rffi.LLVMPointerType(self.ty_int_ptr, 0)
- self.const_zero = self._make_const_int(0)
- self.const_one = self._make_const_int(1)
- self.const_minint = self._make_const_int(-sys.maxint-1)
- self.const_null_charptr = self._make_const(0, self.ty_char_ptr)
- #
- arglist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMTypeRef), 0,
- flavor='raw')
- self.ty_func = llvm_rffi.LLVMFunctionType(self.ty_int, arglist, 0,
- False)
- lltype.free(arglist, flavor='raw')
- #
- self.f_add_ovf = llvm_rffi.LLVM_Intrinsic_add_ovf(self.module,
- self.ty_int)
- self.f_sub_ovf = llvm_rffi.LLVM_Intrinsic_sub_ovf(self.module,
- self.ty_int)
- self.f_mul_ovf = llvm_rffi.LLVM_Intrinsic_mul_ovf(self.module,
- self.ty_int)
- if we_are_translated():
- XXX - fix-me
- else:
- self.exc_type = lltype.malloc(rffi.CArray(lltype.Signed), 1,
- zero=True, flavor='raw')
- self.exc_value = lltype.malloc(rffi.CArray(llmemory.GCREF), 1,
- zero=True, flavor='raw')
- self.backup_exc_type = lltype.malloc(rffi.CArray(lltype.Signed), 1,
- zero=True, flavor='raw')
- self.backup_exc_value = lltype.malloc(rffi.CArray(llmemory.GCREF), 1,
- zero=True, flavor='raw')
- self.const_exc_type = self._make_const(self.exc_type,
- self.ty_char_ptr_ptr)
- self.const_exc_value = self._make_const(self.exc_value,
- self.ty_char_ptr_ptr)
- self.const_backup_exc_type = self._make_const(self.backup_exc_type,
- self.ty_char_ptr_ptr)
- self.const_backup_exc_value = self._make_const(self.backup_exc_value,
- self.ty_char_ptr_ptr)
- #
- self._setup_prebuilt_error('ovf', OverflowError)
- self._setup_prebuilt_error('zer', ZeroDivisionError)
- #
- self.ee = llvm_rffi.LLVM_EE_Create(self.module)
- if not we_are_translated():
- llvm_rffi.set_teardown_function(self._teardown)
-
- def _teardown(self):
- llvm_rffi.LLVMDisposeExecutionEngine(self.ee)
-
- def _setup_prebuilt_error(self, prefix, Class):
- if self.rtyper is not None: # normal case
- bk = self.rtyper.annotator.bookkeeper
- clsdef = bk.getuniqueclassdef(Class)
- ll_inst = self.rtyper.exceptiondata.get_standard_ll_exc_instance(
- self.rtyper, clsdef)
- else:
- # for tests, a random emulated ll_inst will do
- ll_inst = lltype.malloc(rclass.OBJECT)
- ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
- immortal=True)
- setattr(self, '_%s_error_type' % prefix,
- rffi.cast(lltype.Signed, ll_inst.typeptr))
- setattr(self, '_%s_error_value' % prefix,
- lltype.cast_opaque_ptr(llmemory.GCREF, ll_inst))
- setattr(self, 'const_%s_error_type' % prefix,
- self._make_const(ll_inst.typeptr, self.ty_char_ptr))
- setattr(self, 'const_%s_error_value' % prefix,
- self._make_const(ll_inst, self.ty_char_ptr))
-
- # ------------------------------
- # Compilation
-
- def compile_operations(self, loop):
- compiler = LLVMJITCompiler(self, loop)
- compiler.start_generating_function()
- compiler.generate_initial_arguments_load()
- compiler.generate_loop_body()
- compiler.close_phi_nodes()
- compiler.done_generating_function()
- llvm_rffi.LLVMDumpModule(self.module) # xxx for debugging
-
- def _ensure_in_args(self, count):
- while len(self.in_out_args) < count:
- self.in_out_args.append(lltype.malloc(self.RAW_VALUE, flavor='raw'))
-
- _ensure_out_args = _ensure_in_args
-
- def _make_const_int(self, value):
- return llvm_rffi.LLVMConstInt(self.ty_int, value, True)
-
- def _make_const_char(self, value):
- assert (value & ~255) == 0, "value is not in range(256)"
- return llvm_rffi.LLVMConstInt(self.ty_char, value, True)
-
- def _make_const_bit(self, value):
- assert (value & ~1) == 0, "value is not 0 or 1"
- return llvm_rffi.LLVMConstInt(self.ty_bit, value, True)
-
- def _make_const(self, value, ty_result):
- value_as_signed = rffi.cast(lltype.Signed, value)
- llvmconstint = self._make_const_int(value_as_signed)
- llvmconstptr = llvm_rffi.LLVMConstIntToPtr(llvmconstint, ty_result)
- return llvmconstptr
- _make_const._annspecialcase_ = 'specialize:argtype(1)'
-
- def _lltype2llvmtype(self, TYPE):
- if TYPE is lltype.Void:
- return self.ty_void
- elif isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
- return self.ty_char_ptr
- else:
- return self.ty_int
-
- def _get_var_type(self, v):
- if v.type == INT:
- return self.ty_int
- else:
- return self.ty_char_ptr
-
- def _get_pointer_type(self, v):
- if v.type == INT:
- return self.ty_int_ptr
- else:
- return self.ty_char_ptr_ptr
-
- # ------------------------------
- # Execution
-
- def set_future_value_int(self, index, intvalue):
- p = rffi.cast(lltype.Ptr(self.SIGNED_VALUE), self.in_out_args[index])
- p[0] = intvalue
-
- def set_future_value_ptr(self, index, ptrvalue):
- p = rffi.cast(lltype.Ptr(self.POINTER_VALUE), self.in_out_args[index])
- p[0] = ptrvalue
-
- def execute_operations(self, loop):
- index = loop._llvm_compiled_index
- assert index >= 0
- while True:
- func_ptr = self.compiled_functions[index]
- print 'execute_operations: %d (at 0x%x)' % (
- index, rffi.cast(lltype.Signed, func_ptr))
- index = func_ptr()
- print '\t--->', index
- if index < 0:
- break
- return self.fail_ops[~index]
-
- def get_latest_value_int(self, index):
- p = rffi.cast(lltype.Ptr(self.SIGNED_VALUE), self.in_out_args[index])
- return p[0]
-
- def get_latest_value_ptr(self, index):
- p = rffi.cast(lltype.Ptr(self.POINTER_VALUE), self.in_out_args[index])
- return p[0]
-
- def get_exception(self):
- return self.backup_exc_type[0]
-
- def get_exc_value(self):
- return self.backup_exc_value[0]
-
- def clear_exception(self):
- self.backup_exc_type[0] = 0
- self.backup_exc_value[0] = lltype.nullptr(llmemory.GCREF.TO)
-
- def set_overflow_error(self):
- self.backup_exc_type[0] = self._ovf_error_type
- self.backup_exc_value[0] = self._ovf_error_value
-
- def set_zero_division_error(self):
- self.backup_exc_type[0] = self._zer_error_type
- self.backup_exc_value[0] = self._zer_error_value
-
- @staticmethod
- def cast_adr_to_int(x):
- return rffi.cast(lltype.Signed, x)
-
- @staticmethod
- def cast_int_to_adr(x):
- if we_are_translated():
- return rffi.cast(llmemory.Address, x)
- else:
- # indirect casting because the above doesn't work with ll2ctypes
- return llmemory.cast_ptr_to_adr(rffi.cast(llmemory.GCREF, x))
-
- def fielddescrof(self, S, fieldname):
- try:
- return self._descr_caches['field', S, fieldname]
- except KeyError:
- pass
- ofs, size = symbolic.get_field_token(S, fieldname,
- self.translate_support_code)
- if (isinstance(getattr(S, fieldname), lltype.Ptr) and
- getattr(S, fieldname).TO._gckind == 'gc'):
- size = -1
- descr = FieldDescr(ofs, size)
- self._descr_caches['field', S, fieldname] = descr
- return descr
-
- def calldescrof(self, FUNC, ARGS, RESULT):
- try:
- return self._descr_caches['call', ARGS, RESULT]
- except KeyError:
- pass
- #
- param_types = lltype.malloc(rffi.CArray(llvm_rffi.LLVMTypeRef),
- len(ARGS), flavor='raw')
- for i in range(len(ARGS)):
- param_types[i] = self._lltype2llvmtype(ARGS[i])
- ty_func = llvm_rffi.LLVMFunctionType(self._lltype2llvmtype(RESULT),
- param_types, len(ARGS), 0)
- lltype.free(param_types, flavor='raw')
- ty_funcptr = llvm_rffi.LLVMPointerType(ty_func, 0)
- #
- if RESULT is lltype.Void:
- result_mask = 0
- elif isinstance(RESULT, lltype.Ptr) and RESULT.TO._gckind == 'gc':
- result_mask = -2
- else:
- result_size = symbolic.get_size(RESULT,
- self.translate_support_code)
- if result_size < self.size_of_int:
- result_mask = (1 << (result_size*8)) - 1
- else:
- result_mask = -1
- descr = CallDescr(ty_funcptr, result_mask)
- self._descr_caches['call', ARGS, RESULT] = descr
- return descr
-
- # ------------------------------
- # do_xxx methods
-
- def _new_box(self, ptr):
- if ptr:
- return BoxPtr(lltype.nullptr(llmemory.GCREF.TO))
- return BoxInt(0)
-
- def _get_loop_for_call(self, argnum, calldescr, ptr):
- loop = calldescr._generated_mp
- if loop is None:
- args = [BoxInt() for i in range(argnum + 1)]
- result = self._new_box(ptr)
- operations = [
- ResOperation(rop.CALL, args, result, calldescr),
- ResOperation(rop.GUARD_NO_EXCEPTION, [], None),
- ResOperation(rop.FAIL, [result], None)]
- operations[1].suboperations = [ResOperation(rop.FAIL, [], None)]
- loop = history.TreeLoop('call')
- loop.inputargs = args
- loop.operations = operations
- self.compile_operations(loop)
- calldescr._generated_mp = loop
- return loop
-
- def do_call(self, args, calldescr):
- assert isinstance(calldescr, CallDescr)
- num_args = len(args) - 1
- ptr = (calldescr.result_mask == -2)
- loop = self._get_loop_for_call(num_args, calldescr, ptr)
- history.set_future_values(self, args)
- self.execute_operations(loop)
- # Note: if an exception is set, the rest of the code does a bit of
- # nonsense but nothing wrong (the return value should be ignored)
- if calldescr.result_mask == 0:
- return None
- elif ptr:
- return BoxPtr(self.get_latest_value_ptr(0))
- else:
- return BoxInt(self.get_latest_value_int(0))
-
-
-class FieldDescr(AbstractDescr):
- def __init__(self, offset, size):
- self.offset = offset
- self.size = size # set to -1 to mark a pointer field
-
-class CallDescr(AbstractDescr):
- def __init__(self, ty_function_ptr, result_mask):
- self.ty_function_ptr = ty_function_ptr
- self.result_mask = result_mask # -2 to mark a ptr result
- self._generated_mp = None
+from pypy.jit.backend.llvm.runner import CallDescr, FieldDescr
# ____________________________________________________________
@@ -341,6 +18,13 @@
self.cpu = cpu
self.loop = loop
+ def compile(self):
+ self.start_generating_function()
+ self.generate_initial_arguments_load()
+ self.generate_loop_body()
+ self.close_phi_nodes()
+ self.done_generating_function()
+
def start_generating_function(self):
func = llvm_rffi.LLVMAddFunction(self.cpu.module, "", self.cpu.ty_func)
self.compiling_func = func
@@ -903,6 +587,3 @@
if hasattr(LLVMJITCompiler, methname):
all_operations[_value] = methname
all_operations = unrolling_iterable(all_operations.items())
-
-import pypy.jit.metainterp.executor
-pypy.jit.metainterp.executor.make_execute_list(LLVMCPU)
Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py (original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/llvm/runner.py Mon Jun 8 11:56:13 2009
@@ -1,12 +1,10 @@
-import py, sys
+import sys
from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.unroll import unrolling_iterable
-from pypy.jit.metainterp.history import ConstInt, AbstractDescr, INT
+from pypy.jit.metainterp.history import AbstractDescr, INT
from pypy.jit.metainterp.history import BoxInt, BoxPtr
from pypy.jit.backend import model
from pypy.jit.backend.llvm import llvm_rffi
-from pypy.jit.metainterp import resoperation
from pypy.jit.metainterp import history
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.backend.x86 import symbolic # xxx
@@ -121,12 +119,9 @@
# Compilation
def compile_operations(self, loop):
+ from pypy.jit.backend.llvm.compile import LLVMJITCompiler
compiler = LLVMJITCompiler(self, loop)
- compiler.start_generating_function()
- compiler.generate_initial_arguments_load()
- compiler.generate_loop_body()
- compiler.close_phi_nodes()
- compiler.done_generating_function()
+ compiler.compile()
llvm_rffi.LLVMDumpModule(self.module) # xxx for debugging
def _ensure_in_args(self, count):
@@ -334,575 +329,5 @@
# ____________________________________________________________
-class LLVMJITCompiler(object):
- FUNC = lltype.FuncType([], lltype.Signed)
-
- def __init__(self, cpu, loop):
- self.cpu = cpu
- self.loop = loop
-
- def start_generating_function(self):
- func = llvm_rffi.LLVMAddFunction(self.cpu.module, "", self.cpu.ty_func)
- self.compiling_func = func
- self.builder = llvm_rffi.LLVMCreateBuilder()
- self.vars = {}
-
- def generate_initial_arguments_load(self):
- loop = self.loop
- func = self.compiling_func
- bb_entry = llvm_rffi.LLVMAppendBasicBlock(func, "entry")
- llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_entry)
- self.cpu._ensure_in_args(len(loop.inputargs))
- self.phi_incoming_blocks = [bb_entry]
- self.phi_incoming_values = []
- for i in range(len(loop.inputargs)):
- ty = self.cpu._get_pointer_type(loop.inputargs[i])
- llvmconstptr = self.cpu._make_const(self.cpu.in_out_args[i], ty)
- res = llvm_rffi.LLVMBuildLoad(self.builder, llvmconstptr, "")
- self.phi_incoming_values.append([res])
- self.bb_start = llvm_rffi.LLVMAppendBasicBlock(func, "")
- llvm_rffi.LLVMBuildBr(self.builder, self.bb_start)
- #
- llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, self.bb_start)
- for v in loop.inputargs:
- ty = self.cpu._get_var_type(v)
- phi = llvm_rffi.LLVMBuildPhi(self.builder, ty, "")
- self.vars[v] = phi
-
- def generate_loop_body(self):
- func = self.compiling_func
- self.pending_blocks = [(self.loop.operations, self.bb_start, False)]
- while self.pending_blocks:
- operations, bb, exc = self.pending_blocks.pop()
- self._generate_branch(operations, bb, exc)
- self.bb_start = lltype.nullptr(llvm_rffi.LLVMBasicBlockRef.TO)
-
- def close_phi_nodes(self):
- incoming_blocks = lltype.malloc(
- rffi.CArray(llvm_rffi.LLVMBasicBlockRef),
- len(self.phi_incoming_blocks), flavor='raw')
- incoming_values = lltype.malloc(
- rffi.CArray(llvm_rffi.LLVMValueRef),
- len(self.phi_incoming_blocks), flavor='raw')
- for j in range(len(self.phi_incoming_blocks)):
- incoming_blocks[j] = self.phi_incoming_blocks[j]
- loop = self.loop
- for i in range(len(loop.inputargs)):
- phi = self.vars[loop.inputargs[i]]
- incoming = self.phi_incoming_values[i]
- for j in range(len(self.phi_incoming_blocks)):
- incoming_values[j] = incoming[j]
- llvm_rffi.LLVMAddIncoming(phi, incoming_values, incoming_blocks,
- len(self.phi_incoming_blocks))
- lltype.free(incoming_values, flavor='raw')
- lltype.free(incoming_blocks, flavor='raw')
-
- def done_generating_function(self):
- llvm_rffi.LLVMDisposeBuilder(self.builder)
- #
- func_addr = llvm_rffi.LLVM_EE_getPointerToFunction(self.cpu.ee,
- self.compiling_func)
- if not we_are_translated():
- print '--- function is at %r ---' % (func_addr,)
- #
- func_ptr = rffi.cast(lltype.Ptr(self.FUNC), func_addr)
- index = self.loop._llvm_compiled_index
- if index < 0:
- self.loop._llvm_compiled_index = len(self.cpu.compiled_functions)
- self.cpu.compiled_functions.append(func_ptr)
- else:
- self.cpu.compiled_functions[index] = func_ptr
-
- def _generate_branch(self, operations, basicblock, exc):
- llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, basicblock)
- # The flag 'exc' is set to True if we are a branch handling a
- # GUARD_EXCEPTION or GUARD_NO_EXCEPTION. In this case, we have to
- # store away the exception into self.backup_exc_xxx, *unless* the
- # branch starts with a further GUARD_EXCEPTION/GUARD_NO_EXCEPTION.
- if exc:
- opnum = operations[0].opnum
- if opnum not in (rop.GUARD_EXCEPTION, rop.GUARD_NO_EXCEPTION):
- self._store_away_exception()
- # Normal handling of the operations follows.
- for op in operations:
- self._generate_op(op)
-
- 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 _store_away_exception(self):
- # etype, evalue: ty_char_ptr
- etype = llvm_rffi.LLVMBuildLoad(self.builder,
- self.cpu.const_exc_type, "")
- llvm_rffi.LLVMBuildStore(self.builder,
- self.cpu.const_null_charptr,
- self.cpu.const_exc_type)
- llvm_rffi.LLVMBuildStore(self.builder,
- etype,
- self.cpu.const_backup_exc_type)
- evalue = llvm_rffi.LLVMBuildLoad(self.builder,
- self.cpu.const_exc_value, "")
- llvm_rffi.LLVMBuildStore(self.builder,
- self.cpu.const_null_charptr,
- self.cpu.const_exc_value)
- llvm_rffi.LLVMBuildStore(self.builder,
- evalue,
- self.cpu.const_backup_exc_value)
-
- def getintarg(self, v):
- try:
- value_ref = self.vars[v]
- except KeyError:
- assert isinstance(v, ConstInt)
- return self.cpu._make_const_int(v.value)
- else:
- return self._cast_to_int(value_ref)
-
- def _cast_to_int(self, value_ref):
- ty = llvm_rffi.LLVMTypeOf(value_ref)
- if ty == self.cpu.ty_int:
- return value_ref
- elif ty == self.cpu.ty_bit or ty == self.cpu.ty_char:
- return llvm_rffi.LLVMBuildZExt(self.builder, value_ref,
- self.cpu.ty_int, "")
- else:
- raise AssertionError("type is not an int nor a bit")
-
- def getbitarg(self, v):
- try:
- value_ref = self.vars[v]
- except KeyError:
- assert isinstance(v, ConstInt)
- return self.cpu._make_const_bit(v.value)
- else:
- return self._cast_to_bit(value_ref)
-
- def _cast_to_bit(self, value_ref):
- ty = llvm_rffi.LLVMTypeOf(value_ref)
- if ty == self.cpu.ty_bit:
- return value_ref
- elif ty == self.cpu.ty_int or ty == self.cpu.ty_char:
- return llvm_rffi.LLVMBuildTrunc(self.builder, value_ref,
- self.cpu.ty_bit, "")
- else:
- raise AssertionError("type is not an int nor a bit")
-
- def getchararg(self, v):
- try:
- value_ref = self.vars[v]
- except KeyError:
- assert isinstance(v, ConstInt)
- return self.cpu._make_const_char(v.value)
- else:
- return self._cast_to_char(value_ref)
-
- def _cast_to_char(self, value_ref):
- ty = llvm_rffi.LLVMTypeOf(value_ref)
- if ty == self.cpu.ty_char:
- return value_ref
- elif ty == self.cpu.ty_int:
- return llvm_rffi.LLVMBuildTrunc(self.builder, value_ref,
- self.cpu.ty_char, "")
- elif ty == self.cpu.ty_bit:
- return llvm_rffi.LLVMBuildZExt(self.builder, value_ref,
- self.cpu.ty_char, "")
- else:
- raise AssertionError("type is not an int nor a bit")
-
- def getptrarg(self, v):
- try:
- value_ref = self.vars[v]
- except KeyError:
- return self.cpu._make_const(v.getaddr(self.cpu),
- self.cpu.ty_char_ptr_ptr)
- else:
- ty = llvm_rffi.LLVMTypeOf(value_ref)
- assert (ty != self.cpu.ty_int and
- ty != self.cpu.ty_bit and
- ty != self.cpu.ty_char)
- return value_ref
-
- for _opname, _llvmname in [('INT_ADD', 'Add'),
- ('INT_SUB', 'Sub'),
- ('INT_MUL', 'Mul'),
- ('INT_FLOORDIV', 'SDiv'),
- ('INT_MOD', 'SRem'),
- ('INT_LSHIFT', 'Shl'),
- ('INT_RSHIFT', 'AShr'),
- ('UINT_RSHIFT', 'LShr'),
- ('INT_AND', 'And'),
- ('INT_OR', 'Or'),
- ('INT_XOR', 'Xor'),
- ]:
- exec py.code.Source('''
- def generate_%s(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuild%s(
- self.builder,
- self.getintarg(op.args[0]),
- self.getintarg(op.args[1]),
- "")
- ''' % (_opname, _llvmname)).compile()
-
- for _opname, _predicate in [('INT_LT', llvm_rffi.Predicate.SLT),
- ('INT_LE', llvm_rffi.Predicate.SLE),
- ('INT_EQ', llvm_rffi.Predicate.EQ),
- ('INT_NE', llvm_rffi.Predicate.NE),
- ('INT_GT', llvm_rffi.Predicate.SGT),
- ('INT_GE', llvm_rffi.Predicate.SGE),
- ('UINT_LT', llvm_rffi.Predicate.ULT),
- ('UINT_LE', llvm_rffi.Predicate.ULE),
- ('UINT_GT', llvm_rffi.Predicate.UGT),
- ('UINT_GE', llvm_rffi.Predicate.UGE)]:
- exec py.code.Source('''
- def generate_%s(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuildICmp(
- self.builder,
- %d,
- self.getintarg(op.args[0]),
- self.getintarg(op.args[1]),
- "")
- ''' % (_opname, _predicate)).compile()
-
- def generate_INT_NEG(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuildNeg(self.builder,
- self.getintarg(op.args[0]),
- "")
-
- def generate_INT_INVERT(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuildNot(self.builder,
- self.getintarg(op.args[0]),
- "")
-
- def generate_INT_IS_TRUE(self, op):
- v = op.args[0]
- try:
- value_ref = self.vars[v]
- if llvm_rffi.LLVMTypeOf(value_ref) != self.cpu.ty_bit:
- raise KeyError
- except KeyError:
- res = llvm_rffi.LLVMBuildICmp(self.builder,
- llvm_rffi.Predicate.NE,
- self.getintarg(op.args[0]),
- self.cpu.const_zero,
- "")
- else:
- res = value_ref # value_ref: ty_bit. this is a no-op
- self.vars[op.result] = res
-
- def generate_BOOL_NOT(self, op):
- v = op.args[0]
- try:
- value_ref = self.vars[v]
- if llvm_rffi.LLVMTypeOf(value_ref) != self.cpu.ty_bit:
- raise KeyError
- except KeyError:
- res = llvm_rffi.LLVMBuildICmp(self.builder,
- llvm_rffi.Predicate.EQ,
- self.getintarg(op.args[0]),
- self.cpu.const_zero,
- "")
- else:
- # value_ref: ty_int
- res = LLVMBuildNot(self.builder, value_ref, "")
- self.vars[op.result] = res
-
- def generate_INT_ADD_OVF(self, op):
- self._generate_ovf_op(op, self.cpu.f_add_ovf)
-
- def generate_INT_SUB_OVF(self, op):
- self._generate_ovf_op(op, self.cpu.f_sub_ovf)
-
- def generate_INT_MUL_OVF(self, op):
- self._generate_ovf_op(op, self.cpu.f_mul_ovf)
-
- def generate_INT_NEG_OVF(self, op):
- arg = self.getintarg(op.args[0])
- self.vars[op.result] = llvm_rffi.LLVMBuildNeg(self.builder, arg, "")
- ovf = llvm_rffi.LLVMBuildICmp(self.builder,
- llvm_rffi.Predicate.EQ,
- arg,
- self.cpu.const_minint,
- "")
- self._generate_set_ovf(ovf)
-
- def generate_INT_LSHIFT_OVF(self, op):
- arg0 = self.getintarg(op.args[0])
- arg1 = llvm_rffi.LLVMBuildShl(self.builder,
- self.cpu.const_one,
- self.getintarg(op.args[1]),
- "")
- self._generate_ovf_test(self.cpu.f_mul_ovf, arg0, arg1, op.result)
-
- def _generate_ovf_op(self, op, f_intrinsic):
- self._generate_ovf_test(f_intrinsic,
- self.getintarg(op.args[0]),
- self.getintarg(op.args[1]),
- op.result)
-
- def _generate_ovf_test(self, f_intrinsic, arg0, arg1, result):
- arglist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), 2,
- flavor='raw')
- arglist[0] = arg0
- arglist[1] = arg1
- tmp = llvm_rffi.LLVMBuildCall(self.builder, f_intrinsic,
- arglist, 2, "")
- lltype.free(arglist, flavor='raw')
- self.vars[result] = llvm_rffi.LLVMBuildExtractValue(self.builder,
- tmp, 0, "")
- ovf = llvm_rffi.LLVMBuildExtractValue(self.builder, tmp, 1, "")
- self._generate_set_ovf(ovf)
-
- def _generate_set_ovf(self, ovf_flag):
- exc_type = llvm_rffi.LLVMBuildSelect(self.builder, ovf_flag,
- self.cpu.const_ovf_error_type,
- self.cpu.const_null_charptr,
- "")
- llvm_rffi.LLVMBuildStore(self.builder, exc_type,
- self.cpu.const_exc_type)
- exc_value = llvm_rffi.LLVMBuildSelect(self.builder, ovf_flag,
- self.cpu.const_ovf_error_value,
- self.cpu.const_null_charptr,
- "")
- llvm_rffi.LLVMBuildStore(self.builder, exc_value,
- self.cpu.const_exc_value)
-
- def generate_GUARD_FALSE(self, op):
- self._generate_guard(op, self.getbitarg(op.args[0]), True)
-
- def generate_GUARD_TRUE(self, op):
- self._generate_guard(op, self.getbitarg(op.args[0]), False)
-
- def generate_GUARD_VALUE(self, op):
- if op.args[0].type == INT:
- arg0 = self.getintarg(op.args[0])
- arg1 = self.getintarg(op.args[1])
- else:
- arg0 = self.getptrarg(op.args[0])
- arg1 = self.getptrarg(op.args[1])
- equal = llvm_rffi.LLVMBuildICmp(self.builder,
- llvm_rffi.Predicate.EQ,
- arg0, arg1, "")
- self._generate_guard(op, equal, False)
-
- def generate_GUARD_CLASS(self, op):
- loc, _ = self._generate_field_gep(op.args[0],
- self.cpu.fielddescr_vtable)
- cls = llvm_rffi.LLVMBuildLoad(self.builder, loc, "")
- equal = llvm_rffi.LLVMBuildICmp(self.builder,
- llvm_rffi.Predicate.EQ,
- cls,
- self.getintarg(op.args[1]), "")
- self._generate_guard(op, equal, False)
-
- def generate_GUARD_NONVIRTUALIZED(self, op):
- pass # xxx ignored
-
- def generate_GUARD_NO_EXCEPTION(self, op):
- # etype: ty_char_ptr
- etype = llvm_rffi.LLVMBuildLoad(self.builder,
- self.cpu.const_exc_type, "")
- eisnull = llvm_rffi.LLVMBuildICmp(self.builder,
- llvm_rffi.Predicate.EQ,
- etype,
- self.cpu.const_null_charptr, "")
- self._generate_guard(op, eisnull, False, exc=True)
-
- def generate_GUARD_EXCEPTION(self, op):
- v = op.args[0]
- assert isinstance(v, ConstInt)
- # etype, expectedtype: ty_char_ptr
- expectedtype = self.cpu._make_const(v.value, self.cpu.ty_char_ptr)
- etype = llvm_rffi.LLVMBuildLoad(self.builder,
- self.cpu.const_exc_type, "")
- eisequal = llvm_rffi.LLVMBuildICmp(self.builder,
- llvm_rffi.Predicate.EQ,
- etype,
- expectedtype, "")
- self._generate_guard(op, eisequal, False, exc=True)
- self.vars[op.result] = llvm_rffi.LLVMBuildLoad(self.builder,
- self.cpu.const_exc_value,
- "")
-
- def _generate_guard(self, op, verify_condition, reversed, exc=False):
- func = self.compiling_func
- bb_on_track = llvm_rffi.LLVMAppendBasicBlock(func, "")
- bb_off_track = llvm_rffi.LLVMAppendBasicBlock(func, "")
- llvm_rffi.LLVMBuildCondBr(self.builder, verify_condition,
- bb_on_track, bb_off_track)
- if reversed:
- bb_on_track, bb_off_track = bb_off_track, bb_on_track
- # generate the on-track part first, and the off-track part later
- self.pending_blocks.append((op.suboperations, bb_off_track, exc))
- llvm_rffi.LLVMPositionBuilderAtEnd(self.builder, bb_on_track)
-
- def generate_JUMP(self, op):
- if op.jump_target is self.loop:
- basicblock = llvm_rffi.LLVMGetInsertBlock(self.builder)
- self.phi_incoming_blocks.append(basicblock)
- for i in range(len(op.args)):
- incoming = self.phi_incoming_values[i]
- v = op.args[i]
- if v.type == INT:
- value_ref = self.getintarg(v)
- else:
- value_ref = self.getptrarg(v)
- incoming.append(value_ref)
- llvm_rffi.LLVMBuildBr(self.builder, self.bb_start)
- else:
- index = op.jump_target._llvm_compiled_index
- assert index >= 0
- self._generate_fail(op.args, index)
-
- def generate_FAIL(self, op):
- i = len(self.cpu.fail_ops)
- self.cpu.fail_ops.append(op)
- self._generate_fail(op.args, ~i)
-
- def _generate_fail(self, args, index):
- self.cpu._ensure_out_args(len(args))
- for i in range(len(args)):
- v = args[i]
- if v.type == INT:
- value_ref = self.getintarg(v)
- ty = self.cpu.ty_int_ptr
- else:
- value_ref = self.getptrarg(v)
- ty = self.cpu.ty_char_ptr_ptr
- llvmconstptr = self.cpu._make_const(self.cpu.in_out_args[i], ty)
- llvm_rffi.LLVMBuildStore(self.builder, value_ref,
- llvmconstptr)
- llvm_rffi.LLVMBuildRet(self.builder, self.cpu._make_const_int(index))
-
- def _generate_field_gep(self, v_structure, fielddescr):
- assert isinstance(fielddescr, FieldDescr)
- indices = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), 1,
- flavor='raw')
- indices[0] = self.cpu._make_const_int(fielddescr.offset)
- location = llvm_rffi.LLVMBuildGEP(self.builder,
- self.getptrarg(v_structure),
- indices, 1, "")
- lltype.free(indices, flavor='raw')
- if fielddescr.size < 0: # pointer field
- ty_val = self.cpu.ty_char_ptr
- ty = self.cpu.ty_char_ptr_ptr
- elif fielddescr.size == symbolic.get_size(lltype.Signed,
- self.cpu.translate_support_code):
- ty_val = self.cpu.ty_int
- ty = self.cpu.ty_int_ptr
- elif fielddescr.size == 1:
- ty_val = self.cpu.ty_char
- ty = self.cpu.ty_char_ptr
- else:
- raise BadSizeError
- location = llvm_rffi.LLVMBuildBitCast(self.builder, location, ty, "")
- return location, ty_val
-
- def generate_GETFIELD_GC(self, op):
- loc, _ = self._generate_field_gep(op.args[0], op.descr)
- self.vars[op.result] = llvm_rffi.LLVMBuildLoad(self.builder, loc, "")
-
- def generate_SETFIELD_GC(self, op):
- loc, tyval = self._generate_field_gep(op.args[0], op.descr)
- if tyval == self.cpu.ty_char_ptr:
- value_ref = self.getptrarg(op.args[1])
- elif tyval == self.cpu.ty_char:
- value_ref = self.getchararg(op.args[1])
- else:
- value_ref = self.getintarg(op.args[1])
- llvm_rffi.LLVMBuildStore(self.builder, value_ref, loc, "")
-
- def generate_CALL(self, op):
- calldescr = op.descr
- assert isinstance(calldescr, CallDescr)
- v = op.args[0]
- if isinstance(v, ConstInt):
- func = self.cpu._make_const(v.value, calldescr.ty_function_ptr)
- else:
- func = self.getintarg(v)
- func = llvm_rffi.LLVMBuildIntToPtr(self.builder,
- func,
- calldescr.ty_function_ptr, "")
- nb_args = len(op.args) - 1
- arglist = lltype.malloc(rffi.CArray(llvm_rffi.LLVMValueRef), nb_args,
- flavor='raw')
- for i in range(nb_args):
- v = op.args[1 + i]
- if v.type == INT:
- value_ref = self.getintarg(v)
- else:
- value_ref = self.getptrarg(v)
- arglist[i] = value_ref
- res = llvm_rffi.LLVMBuildCall(self.builder,
- func, arglist, nb_args, "")
- lltype.free(arglist, flavor='raw')
- if op.result is not None:
- if calldescr.result_mask >= 0:
- mask = self.cpu._make_const_int(calldescr.result_mask)
- res = llvm_rffi.LLVMBuildAnd(self.builder,
- res, mask, "")
- self.vars[op.result] = res
-
- generate_CALL_PURE = generate_CALL
-
- def generate_CAST_PTR_TO_INT(self, op):
- res = llvm_rffi.LLVMBuildPtrToInt(self.builder,
- self.getptrarg(op.args[0]),
- self.cpu.ty_int, "")
- self.vars[op.result] = res
-
- def generate_CAST_INT_TO_PTR(self, op):
- res = llvm_rffi.LLVMBuildIntToPtr(self.builder,
- self.getintarg(op.args[0]),
- self.cpu.ty_char_ptr, "")
- self.vars[op.result] = res
-
- def generate_OOIS(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuildICmp(
- self.builder, llvm_rffi.Predicate.EQ,
- self.getptrarg(op.args[0]),
- self.getptrarg(op.args[1]), "")
-
- def generate_OOISNOT(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuildICmp(
- self.builder, llvm_rffi.Predicate.NE,
- self.getptrarg(op.args[0]),
- self.getptrarg(op.args[1]), "")
-
- def generate_OOISNULL(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuildICmp(
- self.builder, llvm_rffi.Predicate.EQ,
- self.getptrarg(op.args[0]),
- self.cpu.const_null_charptr, "")
-
- def generate_OONONNULL(self, op):
- self.vars[op.result] = llvm_rffi.LLVMBuildICmp(
- self.builder, llvm_rffi.Predicate.NE,
- self.getptrarg(op.args[0]),
- self.cpu.const_null_charptr, "")
-
-# ____________________________________________________________
-
-class MissingOperation(Exception):
- pass
-
-class BadSizeError(Exception):
- pass
-
-all_operations = {}
-for _key, _value in rop.__dict__.items():
- if 'A' <= _key <= 'Z':
- assert _value not in all_operations
- methname = 'generate_' + _key
- if hasattr(LLVMJITCompiler, methname):
- all_operations[_value] = methname
-all_operations = unrolling_iterable(all_operations.items())
-
import pypy.jit.metainterp.executor
pypy.jit.metainterp.executor.make_execute_list(LLVMCPU)
More information about the Pypy-commit
mailing list