Esempio n. 1
0
def gv_from_python(x, llvm_type = None):
  if isinstance(x, GenericValue):
    return x
  elif isinstance(x, (int,long)):
    llvm_type =  ty_int64 if llvm_type is None else llvm_type
    assert is_llvm_int_type(llvm_type), \
      "Expected LLVM integer type, not %s" % (llvm_type,) 
    return GenericValue.int(llvm_type, x)
  elif isinstance(x, float):
    llvm_type = ty_float64 if llvm_type is None else llvm_type
    assert is_llvm_float_type(llvm_type), \
        "Expected LLVM float type, not %s" % (llvm_type,)
    return GenericValue.real(llvm_type, x)  
  elif isinstance(x, bool):
    llvm_type = ty_int8 if llvm_type is None else llvm_type
    assert is_llvm_int_type(llvm_type), \
      "Expected LLVM integer type, not %s" % (llvm_type,)
    return GenericValue.int(llvm_type, x)
  else:
    assert isinstance(x, np.ndarray)
    assert llvm_type is not None 
    assert is_llvm_ptr_type(llvm_type), \
      "Native argument receiving numpy array must be a pointer, not %s" % (llvm_type,)
    elt_type = llvm_type.pointee
    assert is_llvm_float_type(elt_type) or is_llvm_int_type(elt_type)
    assert elt_type == python_to_lltype(x.dtype), \
        "Can't pass array with %s* data pointer to function that expects %s*" % (x.dtype, elt_type)
    return GenericValue.pointer(x.ctypes.data)
Esempio n. 2
0
def ctypes_to_generic_value(cval, t):
  if isinstance(t, core_types.FloatT):
    llvm_t = llvm_types.llvm_value_type(t)
    return GenericValue.real(llvm_t, cval.value)
  elif isinstance(t, core_types.SignedT):
    llvm_t = llvm_types.llvm_value_type(t)
    return GenericValue.int_signed(llvm_t, cval.value)
  elif isinstance(t, core_types.IntT):
    llvm_t = llvm_types.llvm_value_type(t)
    return GenericValue.int(llvm_t, cval.value)
  elif isinstance(t, core_types.PtrT):
    return GenericValue.pointer(ctypes.addressof(cval.contents))
  else:
    return GenericValue.pointer(ctypes.addressof(cval))
Esempio n. 3
0
def python_to_generic_value(x, t):
  if isinstance(t, core_types.FloatT):
    llvm_t = llvm_types.llvm_value_type(t)
    return GenericValue.real(llvm_t, x)
  elif isinstance(t, core_types.SignedT):
    llvm_t = llvm_types.llvm_value_type(t)
    return GenericValue.int_signed(llvm_t, x)
  elif isinstance(t, core_types.IntT):
    llvm_t = llvm_types.llvm_value_type(t)
    return GenericValue.int(llvm_t, x)
  elif isinstance(t, core_types.PtrT):
    return GenericValue.pointer(x)
  else:
    ctypes_obj = type_conv.from_python(x)
    return GenericValue.pointer(ctypes.addressof(ctypes_obj))
Esempio n. 4
0
def python_to_generic_value(x, t):
    if isinstance(t, FloatT):
        llvm_t = llvm_types.llvm_value_type(t)
        return GenericValue.real(llvm_t, x)
    elif isinstance(t, SignedT):
        llvm_t = llvm_types.llvm_value_type(t)
        return GenericValue.int_signed(llvm_t, x)
    elif isinstance(t, IntT):
        llvm_t = llvm_types.llvm_value_type(t)
        return GenericValue.int(llvm_t, x)
    elif isinstance(t, PtrT):
        return GenericValue.pointer(x)
    else:
        ctypes_obj = type_conv.from_python(x)
        return GenericValue.pointer(ctypes.addressof(ctypes_obj))
Esempio n. 5
0
def parfor(fn, niters, fixed_args = (), ee = shared_exec_engine):
  """
  Given a function from index integers to void, run it in parallel 
  over the index range specified by the tuple 'niters'
  """
  assert isinstance(fn, Function), \
    "Can only run LLVM functions, not %s" % type(fn)
  
  # in case fixed arguments aren't yet GenericValues, convert them
  fixed_args = tuple(gv_from_python(v, arg.type) 
                     for (v,arg) in 
                     zip(fixed_args, fn.args))
  iter_ranges, steps, shape = parse_iters(niters)
  result_lltype = return_type(fn) 
  if result_lltype == ty_void:
    work_fn = parfor_wrapper(fn, steps)
    launch(work_fn, iter_ranges, fixed_args, ee)
    return 
  else:
    assert is_llvm_float_type(result_lltype) or is_llvm_int_type(result_lltype)
    dtype = lltype_to_dtype(result_lltype)
    result_array = np.empty(shape = shape, dtype = dtype)
    fixed_args = (GenericValue.pointer(result_array.ctypes.data),) + fixed_args
    work_fn = parfor_wrapper(fn, steps, shape)
    n_given = len(fixed_args) + 2*len(steps)
    n_expected = len(work_fn.args)
    assert n_given == n_expected, \
       "Work function expects %d arguments but got %d" % (n_expected, n_given)
    launch(work_fn, iter_ranges, fixed_args, ee)
    return result_array
    assert False, "Collecting results not yet implemented"
Esempio n. 6
0
def ctypes_to_generic_value(cval, t):
    if isinstance(t, FloatT):
        llvm_t = llvm_types.llvm_value_type(t)
        return GenericValue.real(llvm_t, cval.value)
    elif isinstance(t, SignedT):
        llvm_t = llvm_types.llvm_value_type(t)
        return GenericValue.int_signed(llvm_t, cval.value)
    elif isinstance(t, IntT):
        llvm_t = llvm_types.llvm_value_type(t)
        return GenericValue.int(llvm_t, cval.value)
    elif isinstance(t, NoneT):
        return GenericValue.int(llvm_types.int64_t, 0)
    elif isinstance(t, PtrT):
        return GenericValue.pointer(ctypes.addressof(cval.contents))
    else:
        return GenericValue.pointer(ctypes.addressof(cval))
Esempio n. 7
0
def run( py_main_func, *call_args ):
    from rpy.rtypes import ConstantTypeRegistry
    registry = ConstantTypeRegistry()
    # Annotates call graph types (local var, functions param/return...)
    print( '\nAnalysing call graph...\n%s' % ('='*70) )
    annotator = CallableGraphAnnotator( registry )
    annotator.set_entry_point( py_main_func, call_args )
    annotator.annotate_dependencies()
    # Generate LLVM code
    from rpy.codegenerator import ModuleGenerator, FunctionCodeGenerator, L_INT_TYPE, L_BOOL_TYPE
    module = ModuleGenerator( registry )
    l_func_entry, l_func_type = None, None
    # Declares all function in modules
    fn_code_generators = []
    for r_func_type, type_annotator in annotator.annotator_by_callable.items():
        py_func = r_func_type.get_function_object()
        print( '\nDeclaring function:\n%s\nPython: %s\nRType: %s' % ('-'*70, py_func, r_func_type) )
        func_generator = FunctionCodeGenerator( py_func, module,
                                                annotator )
        fn_code_generators.append( (r_func_type, func_generator) )
    # Makes sure that all class type have their struct/attribute index dict initialized
    for r_func_type, _ in fn_code_generators:
        if r_func_type.is_constructor():
            module.llvm_type_from_rtype( r_func_type )
    # Generates function's code, possibly referencing previously declared functions
    for r_func_type, func_generator in fn_code_generators:
        print( '\nGenerating code for function:\n%s\n%s\nSouce:\n' % ('-'*70, r_func_type) )
        print( func_generator.annotation.get_function_source() )
        func_generator.generate_llvm_code()
        func_generator.report()
        if r_func_type.get_function_object() is py_main_func:
            l_func_entry = func_generator.l_func
            l_func_type = func_generator.l_func_type
    print( 'Generated module code:' )
    print( '----------------------\n%s', module.l_module )
    optimize( module )
    print( 'Generated module code after optimization:' )
    print( '-----------------------------------------\n', module.l_module )
    
    # Execute generate code
    # 1) Convert call args into generic value
    print( 'Invoking function with %r' % (call_args,) )
    from llvm.core import ModuleProvider, TYPE_VOID
    from llvm.ee import ExecutionEngine, GenericValue
    module_provider = ModuleProvider.new( module.l_module )
    engine = ExecutionEngine.new( module_provider )
    l_call_args = []
    for py_call_arg, l_arg in zip( call_args, l_func_entry.args ):
        if l_arg.type == L_INT_TYPE:
            l_call_args.append( GenericValue.int_signed( L_INT_TYPE, py_call_arg ) )
        elif l_arg.type == L_BOOL_TYPE:
            l_call_args.append( GenericValue.int( L_BOOL_TYPE, py_call_arg ) )
        else:
            raise ValueError( 'Unsupported parameter "%s" of type: %r' % (py_call_arg, l_arg_type) )
    # 2) run the functions
    l_return_value = engine.run_function( l_func_entry, l_call_args )
    # 3) convert LLVM return value into python type
    if l_func_type.return_type == L_INT_TYPE:
        return l_return_value.as_int_signed()
    elif l_func_type.return_type == L_BOOL_TYPE:
        return l_return_value.as_int() and True or False
    elif l_func_type.return_type.kind == TYPE_VOID:
        return None
    print( 'Return:',  l_return_value )
    raise ValueError( 'Unsupported return type "%s"' % l_func_entry.return_type )
    
Esempio n. 8
0
dsquared_func = Function.new(mod, Type.function(Type.double(), [Type.double(),
                             Type.double()], False), "dsquared")
block = dsquared_func.append_basic_block("entry")
builder = Builder.new(block)

x = dsquared_func.args[0]
xsquared = builder.fmul(x, x)
y = dsquared_func.args[1]
ysquared = builder.fmul(y, y)

d2 = builder.fadd(xsquared, ysquared)
builder.ret(d2)
#print(mod)

a = GenericValue.real(Type.double(), 3.0)
b = GenericValue.real(Type.double(), 4.0)
result = engine.run_function(dsquared_func, [a, b])
#print(result.as_real(Type.double()))


sqrt_func = Function.new(mod, Type.function(Type.double(), [Type.double()], False), "sqrt")
r = engine.run_function(sqrt_func, [result])
#print(r.as_real(Type.double()))

# define a function that calls a function
distance_func = Function.new(mod, Type.function(Type.double(),
                             [Type.double(), Type.double()], False), "distance")
block = distance_func.append_basic_block("entry")
builder = Builder.new(block)
x = distance_func.args[0]
Esempio n. 9
0
def run(py_main_func, *call_args):
    from rpy.rtypes import ConstantTypeRegistry
    registry = ConstantTypeRegistry()
    # Annotates call graph types (local var, functions param/return...)
    print('\nAnalysing call graph...\n%s' % ('=' * 70))
    annotator = CallableGraphAnnotator(registry)
    annotator.set_entry_point(py_main_func, call_args)
    annotator.annotate_dependencies()
    # Generate LLVM code
    from rpy.codegenerator import ModuleGenerator, FunctionCodeGenerator, L_INT_TYPE, L_BOOL_TYPE
    module = ModuleGenerator(registry)
    l_func_entry, l_func_type = None, None
    # Declares all function in modules
    fn_code_generators = []
    for r_func_type, type_annotator in annotator.annotator_by_callable.items():
        py_func = r_func_type.get_function_object()
        print('\nDeclaring function:\n%s\nPython: %s\nRType: %s' %
              ('-' * 70, py_func, r_func_type))
        func_generator = FunctionCodeGenerator(py_func, module, annotator)
        fn_code_generators.append((r_func_type, func_generator))
    # Makes sure that all class type have their struct/attribute index dict initialized
    for r_func_type, _ in fn_code_generators:
        if r_func_type.is_constructor():
            module.llvm_type_from_rtype(r_func_type)
    # Generates function's code, possibly referencing previously declared functions
    for r_func_type, func_generator in fn_code_generators:
        print('\nGenerating code for function:\n%s\n%s\nSouce:\n' %
              ('-' * 70, r_func_type))
        print(func_generator.annotation.get_function_source())
        func_generator.generate_llvm_code()
        func_generator.report()
        if r_func_type.get_function_object() is py_main_func:
            l_func_entry = func_generator.l_func
            l_func_type = func_generator.l_func_type
    print('Generated module code:')
    print('----------------------\n%s', module.l_module)
    optimize(module)
    print('Generated module code after optimization:')
    print('-----------------------------------------\n', module.l_module)

    # Execute generate code
    # 1) Convert call args into generic value
    print('Invoking function with %r' % (call_args, ))
    from llvm.core import ModuleProvider, TYPE_VOID
    from llvm.ee import ExecutionEngine, GenericValue
    module_provider = ModuleProvider.new(module.l_module)
    engine = ExecutionEngine.new(module_provider)
    l_call_args = []
    for py_call_arg, l_arg in zip(call_args, l_func_entry.args):
        if l_arg.type == L_INT_TYPE:
            l_call_args.append(GenericValue.int_signed(L_INT_TYPE,
                                                       py_call_arg))
        elif l_arg.type == L_BOOL_TYPE:
            l_call_args.append(GenericValue.int(L_BOOL_TYPE, py_call_arg))
        else:
            raise ValueError('Unsupported parameter "%s" of type: %r' %
                             (py_call_arg, l_arg_type))
    # 2) run the functions
    l_return_value = engine.run_function(l_func_entry, l_call_args)
    # 3) convert LLVM return value into python type
    if l_func_type.return_type == L_INT_TYPE:
        return l_return_value.as_int_signed()
    elif l_func_type.return_type == L_BOOL_TYPE:
        return l_return_value.as_int() and True or False
    elif l_func_type.return_type.kind == TYPE_VOID:
        return None
    print('Return:', l_return_value)
    raise ValueError('Unsupported return type "%s"' % l_func_entry.return_type)