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)
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))
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))
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))
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 )
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)