def declare_runtime_library(self): self.runtime = {} self.runtime['_print_int'] = Function.new(self.module, Type.function(Type.void(), [int_type], False), "_print_int") self.runtime['_print_float'] = Function.new(self.module, Type.function(Type.void(), [float_type], False), "_print_float") self.runtime['_print_bool'] = Function.new(self.module, Type.function(Type.void(), [bool_type], False), "_print_bool")
def object_dump(self, obj): """ Dump a Python object on C stderr. For debugging purposes. """ fnty = Type.function(Type.void(), [self.pyobj]) fn = self._get_function(fnty, name="_PyObject_Dump") return self.builder.call(fn, (obj, ))
def complex128_power_impl(context, builder, sig, args): [ca, cb] = args a = Complex128(context, builder, value=ca) b = Complex128(context, builder, value=cb) c = Complex128(context, builder) module = cgutils.get_module(builder) pa = a._getpointer() pb = b._getpointer() pc = c._getpointer() # Optimize for square because cpow looses a lot of precsiion TWO = context.get_constant(types.float64, 2) ZERO = context.get_constant(types.float64, 0) b_real_is_two = builder.fcmp(lc.FCMP_OEQ, b.real, TWO) b_imag_is_zero = builder.fcmp(lc.FCMP_OEQ, b.imag, ZERO) b_is_two = builder.and_(b_real_is_two, b_imag_is_zero) with cgutils.ifelse(builder, b_is_two) as (then, otherwise): with then: # Lower as multiplication res = complex_mul_impl(context, builder, sig, (ca, ca)) cres = Complex128(context, builder, value=res) c.real = cres.real c.imag = cres.imag with otherwise: # Lower with call to external function fnty = Type.function(Type.void(), [pa.type] * 3) cpow = module.get_or_insert_function(fnty, name="numba.math.cpow") builder.call(cpow, (pa, pb, pc)) return builder.load(pc)
def ml(self, samples, weights, out): """ Emit computation of the estimated maximum-likelihood parameter. """ @Function.define( Type.void(), [samples.data.type_, weights.data.type_, out.data.type_], ) def mixed_binomial_ml(samples_data, weights_data, out_data): prior_data = qy.stack_allocate(self._model.prior_dtype) qy.value_from_any(1.0).store(prior_data.gep(0, 0)) qy.value_from_any(1.0).store(prior_data.gep(0, 1)) self._map( StridedArray.from_raw(prior_data, (), ()), samples.using(samples_data), weights.using(weights_data), out.using(out_data), ) qy.return_() mixed_binomial_ml(samples.data, weights.data, out.data)
def f_exit(mod): '''libc: cause normal process termination''' ret = Type.void() args = [Type.int(32)] type_ = Type.function(ret, args) return mod.get_or_insert_function(type_, "exit")
def test_atomic_ldst(self): mod = Module.new('mod') functype = Type.function(Type.void(), []) func = mod.add_function(functype, name='foo') bb = func.append_basic_block('entry') bldr = Builder.new(bb) ptr = bldr.alloca(Type.int()) val = Constant.int(Type.int(), 1234) for ordering in self.orderings: loaded = bldr.atomic_load(ptr, ordering) self.assert_('load atomic' in str(loaded)) self.assertEqual(ordering, str(loaded).strip().split(' ')[-3].rstrip(',')) self.assert_('align 1' in str(loaded)) stored = bldr.atomic_store(loaded, ptr, ordering) self.assert_('store atomic' in str(stored)) self.assertEqual(ordering, str(stored).strip().split(' ')[-3].rstrip(',')) self.assert_('align 1' in str(stored)) fenced = bldr.fence(ordering) self.assertEqual(['fence', ordering], str(fenced).strip().split(' '))
def test_atomic_rmw(self): mod = Module.new('mod') functype = Type.function(Type.void(), []) func = mod.add_function(functype, name='foo') bb = func.append_basic_block('entry') bldr = Builder.new(bb) ptr = bldr.alloca(Type.int()) old = bldr.load(ptr) val = Constant.int(Type.int(), 1234) for ordering in self.orderings: inst = bldr.atomic_rmw('xchg', ptr, val, ordering) self.assertEqual(ordering, str(inst).split(' ')[-1]) for op in self.atomic_op: inst = bldr.atomic_rmw(op, ptr, val, ordering) self.assertEqual(op, str(inst).strip().split(' ')[3]) inst = bldr.atomic_rmw('xchg', ptr, val, ordering, crossthread=False) self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) for op in self.atomic_op: atomic_op = getattr(bldr, 'atomic_%s' % op) inst = atomic_op(ptr, val, ordering) self.assertEqual(op, str(inst).strip().split(' ')[3])
def object_dump(self, obj): """ Dump a Python object on C stderr. For debugging purposes. """ fnty = Type.function(Type.void(), [self.pyobj]) fn = self._get_function(fnty, name="_PyObject_Dump") return self.builder.call(fn, (obj,))
def code_gen(self): function_prototype_and_context = self.prototype.code_gen(True) function_prototype = function_prototype_and_context[0] context = function_prototype_and_context[1] block = function_prototype.append_basic_block('entry') global g_llvm_builder g_llvm_builder = Builder.new(block) for i in range(len(self.prototype.args)): context.value_table[self.prototype.args[i][0]] = function_prototype.args[i] if self.body: for stmt in self.body: stmt.code_gen() key = self.prototype.func_name_token.word + '()' expected_return_type = self.context.type_table[key].return_type void_type = Type.void() if expected_return_type == void_type: g_llvm_builder.ret_void() else: if str(expected_return_type) == 'double': g_llvm_builder.ret(Constant.real(expected_return_type, 0)) else: g_llvm_builder.ret(Constant.int(expected_return_type, 0)) # Validate the generated code, checking for consistency. try: function_prototype.verify() g_llvm_pass_manager.run(function_prototype) except: print function_prototype.delete()
def code_gen(self): function_prototype_and_context = self.prototype.code_gen(True) function_prototype = function_prototype_and_context[0] context = function_prototype_and_context[1] block = function_prototype.append_basic_block('entry') global g_llvm_builder g_llvm_builder = Builder.new(block) for i in range(len(self.prototype.args)): context.value_table[self.prototype.args[i] [0]] = function_prototype.args[i] if self.body: for stmt in self.body: stmt.code_gen() key = self.prototype.func_name_token.word + '()' expected_return_type = self.context.type_table[key].return_type void_type = Type.void() if expected_return_type == void_type: g_llvm_builder.ret_void() else: if str(expected_return_type) == 'double': g_llvm_builder.ret(Constant.real(expected_return_type, 0)) else: g_llvm_builder.ret(Constant.int(expected_return_type, 0)) # Validate the generated code, checking for consistency. try: function_prototype.verify() g_llvm_pass_manager.run(function_prototype) except: print function_prototype.delete()
def f_main(mod): '''main function''' argc = Type.int(32) argv = Type.pointer(Type.pointer(Type.int(8))) type_ = Type.function(Type.void(), [argc, argv]) return mod.get_or_insert_function(type_, "main")
def test_atomic_rmw(self): mod = Module.new("mod") functype = Type.function(Type.void(), []) func = mod.add_function(functype, name="foo") bb = func.append_basic_block("entry") bldr = Builder.new(bb) ptr = bldr.alloca(Type.int()) old = bldr.load(ptr) val = Constant.int(Type.int(), 1234) for ordering in self.orderings: inst = bldr.atomic_rmw("xchg", ptr, val, ordering) self.assertEqual(ordering, str(inst).split(" ")[-1]) for op in self.atomic_op: inst = bldr.atomic_rmw(op, ptr, val, ordering) self.assertEqual(op, str(inst).strip().split(" ")[3]) inst = bldr.atomic_rmw("xchg", ptr, val, ordering, crossthread=False) self.assertEqual("singlethread", str(inst).strip().split(" ")[-2]) for op in self.atomic_op: atomic_op = getattr(bldr, "atomic_%s" % op) inst = atomic_op(ptr, val, ordering) self.assertEqual(op, str(inst).strip().split(" ")[3])
def ptx_syncthreads(context, builder, sig, args): assert not args fname = 'llvm.nvvm.barrier0' lmod = cgutils.get_module(builder) fnty = Type.function(Type.void(), ()) sync = lmod.get_or_insert_function(fnty, name=fname) builder.call(sync, ()) return context.get_dummy_value()
def err_set_string(self, exctype, msg): fnty = Type.function(Type.void(), [self.pyobj, self.cstring]) fn = self._get_function(fnty, name="PyErr_SetString") if isinstance(exctype, str): exctype = self.get_c_object(exctype) if isinstance(msg, str): msg = self.context.insert_const_string(self.module, msg) return self.builder.call(fn, (exctype, msg))
def test_constexpr_opcode(self): mod = Module.new("test_constexpr_opcode") func = mod.add_function(Type.function(Type.void(), []), name="foo") builder = Builder.new(func.append_basic_block("entry")) a = builder.inttoptr(Constant.int(Type.int(), 123), Type.pointer(Type.int())) self.assertTrue(isinstance(a, lc.ConstantExpr)) self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) self.assertEqual(a.opcode_name, "inttoptr")
def build_ufunc_wrapper(context, func, signature): """ Wrap the scalar function with a loop that iterates over the arguments """ module = func.module byte_t = Type.int(8) byte_ptr_t = Type.pointer(byte_t) byte_ptr_ptr_t = Type.pointer(byte_ptr_t) intp_t = context.get_value_type(types.intp) intp_ptr_t = Type.pointer(intp_t) fnty = Type.function(Type.void(), [byte_ptr_ptr_t, intp_ptr_t, intp_ptr_t, byte_ptr_t]) wrapper = module.add_function(fnty, "__ufunc__." + func.name) arg_args, arg_dims, arg_steps, arg_data = wrapper.args arg_args.name = "args" arg_dims.name = "dims" arg_steps.name = "steps" arg_data.name = "data" builder = Builder.new(wrapper.append_basic_block("entry")) loopcount = builder.load(arg_dims, name="loopcount") actual_args = context.get_arguments(func) # Prepare inputs arrays = [] for i, typ in enumerate(signature.args): arrays.append( UArrayArg(context, builder, arg_args, arg_steps, i, context.get_argument_type(typ))) # Prepare output out = UArrayArg(context, builder, arg_args, arg_steps, len(actual_args), context.get_value_type(signature.return_type)) # Loop with cgutils.for_range(builder, loopcount, intp=intp_t) as ind: # Load elems = [ary.load(ind) for ary in arrays] # Compute status, retval = context.call_function(builder, func, signature.return_type, signature.args, elems) # Ignoring error status and store result # Store if out.byref: retval = builder.load(retval) out.store(retval, ind) builder.ret_void() return wrapper
def gil_release(self, gil): """ Release the acquired GIL by gil_ensure(). Must be pair with a gil_ensure(). """ gilptrty = Type.pointer(self.gil_state) fnty = Type.function(Type.void(), [gilptrty]) fn = self._get_function(fnty, "numba_gil_release") return self.builder.call(fn, [gil])
def test_constexpr_opcode(self): mod = Module.new('test_constexpr_opcode') func = mod.add_function(Type.function(Type.void(), []), name="foo") builder = Builder.new(func.append_basic_block('entry')) a = builder.inttoptr(Constant.int(Type.int(), 123), Type.pointer(Type.int())) self.assertTrue(isinstance(a, lc.ConstantExpr)) self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) self.assertEqual(a.opcode_name, "inttoptr")
def build_ufunc_wrapper(context, func, signature): """ Wrap the scalar function with a loop that iterates over the arguments """ module = func.module byte_t = Type.int(8) byte_ptr_t = Type.pointer(byte_t) byte_ptr_ptr_t = Type.pointer(byte_ptr_t) intp_t = context.get_value_type(types.intp) intp_ptr_t = Type.pointer(intp_t) fnty = Type.function(Type.void(), [byte_ptr_ptr_t, intp_ptr_t, intp_ptr_t, byte_ptr_t]) wrapper = module.add_function(fnty, "__ufunc__." + func.name) arg_args, arg_dims, arg_steps, arg_data = wrapper.args arg_args.name = "args" arg_dims.name = "dims" arg_steps.name = "steps" arg_data.name = "data" builder = Builder.new(wrapper.append_basic_block("entry")) loopcount = builder.load(arg_dims, name="loopcount") actual_args = context.get_arguments(func) # Prepare inputs arrays = [] for i, typ in enumerate(signature.args): arrays.append(UArrayArg(context, builder, arg_args, arg_steps, i, context.get_argument_type(typ))) # Prepare output out = UArrayArg(context, builder, arg_args, arg_steps, len(actual_args), context.get_value_type(signature.return_type)) # Loop with cgutils.for_range(builder, loopcount, intp=intp_t) as ind: # Load elems = [ary.load(ind) for ary in arrays] # Compute status, retval = context.call_function(builder, func, signature.return_type, signature.args, elems) # Ignoring error status and store result # Store if out.byref: retval = builder.load(retval) out.store(retval, ind) builder.ret_void() return wrapper
def _build_module(self): m = Module.new("TestTargetMachines") fnty = Type.function(Type.void(), []) func = m.add_function(fnty, name="foo") bldr = Builder.new(func.append_basic_block("entry")) bldr.ret_void() m.verify() return m, func
def _build_module(self): m = lc.Module.new('TestTargetMachines') fnty = Type.function(Type.void(), []) func = m.add_function(fnty, name='foo') bldr = Builder.new(func.append_basic_block('entry')) bldr.ret_void() m.verify() return m, func
def create_store(): ft = Type.function(Type.void(), [ty], False) f = mod.add_function('store', ft) bb = f.append_basic_block('body') bldr = Builder.create(mod.context) bldr.position_at_end(bb) xt = f.get_param(0) bldr.store(xt, x) bldr.ret_void()
def gil_ensure(self): """ Ensure the GIL is acquired. The returned value must be consumed by gil_release(). """ gilptrty = Type.pointer(self.gil_state) fnty = Type.function(Type.void(), [gilptrty]) fn = self._get_function(fnty, "numba_gil_ensure") gilptr = cgutils.alloca_once(self.builder, self.gil_state) self.builder.call(fn, [gilptr]) return gilptr
def create_store(): ft = Type.function(Type.void(), [ty, ptr_ty], False) f = mod.add_function('store', ft) bb = f.append_basic_block('body') bldr = Builder.create(mod.context) bldr.position_at_end(bb) xt = f.get_param(0) offset = f.get_param(1) elem_ptr = bldr.gep(x, [v0, offset], 'elem') bldr.store(xt, elem_ptr) bldr.ret_void()
def test_struct_extract_value_2d(self): ta = Type.struct([Type.int(32), Type.float()]) tb = Type.struct([ta, Type.float()]) m = Module.new('') f = m.add_function(Type.function(Type.void(), []), "foo") b = Builder.new(f.append_basic_block('')) v = Constant.undef(tb) ins = b.insert_value(v, Constant.real(Type.float(), 1.234), [0, 1]) ext = b.extract_value(ins, [0, 1]) b.ret_void() m.verify() self.assertEqual(str(ext), 'float 0x3FF3BE76C0000000')
def get_type(typo): if typo == 'int' or typo == LexmeType.Integer: return Type.int(32) elif typo == 'double' or typo == LexmeType.Double: return Type.double() elif typo == 'String' or typo == LexmeType.String: ch = Type.int(8) return Type.pointer(ch) elif typo == 'char' or typo == LexmeType.Char: return Type.int(8) elif typo == 'void': return Type.void()
def test_arg_attr(self): m = Module.new('oifjda') vptr = Type.pointer(Type.float()) fnty = Type.function(Type.void(), [vptr] * 5) func = m.add_function(fnty, 'foo') attrs = [lc.ATTR_STRUCT_RET, lc.ATTR_BY_VAL, lc.ATTR_NEST, lc.ATTR_NO_ALIAS, lc.ATTR_NO_CAPTURE] for i, attr in enumerate(attrs): arg = func.args[i] self.assertEqual(i, arg.arg_no) arg.add_attribute(attr) self.assertTrue(attr in func.args[i])
def SetupPrintf(module): """ Emits the prototype for the libc printf function and returns the function. :param llvm.core.Module module: The current LLVM module. :param llvm.core.Builder builder: The current LLVM IR builder. :rtype: llvm.core.FunctionType """ # Prototype printf from libc so that we can use it. tp_string = Type.pointer(Type.int(8)) tp_print = Type.function(Type.void(), [tp_string], var_arg=True) return module.add_function(tp_print, 'printf')
def init_llvm(self): mod = Module.new("exprllvm") self.engine = ExecutionEngine.new(mod) # functions self.llvm_functions = {} func = Function.new(mod, Type.function( Type.void(), [], False), "main") self.llvm_functions['main'] = func block = func.append_basic_block("entry") # builder builder = Builder.new(block) self.builder = builder # add some pre-defined functions print_int = Function.new(mod, Type.function( Type.void(), [Type.int()], False), "print_int") self.llvm_functions['print_int'] = print_int self.builder.call(print_int, [Constant.int(Type.int(),3)]) self.builder.ret_void()
def test_alloca_alignment(self): m = Module.new('') f = m.add_function(Type.function(Type.void(), []), "foo") b = Builder.new(f.append_basic_block('')) inst = b.alloca(Type.int(32)) inst.alignment = 4 b.ret_void() m.verify() self.assertTrue(inst.is_static) self.assertFalse(inst.is_array) self.assertEqual(inst.alignment, 4) self.assertEqual(str(inst.array_size), 'i32 1')
def test_arg_attr(self): m = Module.new('oifjda') fnty = Type.function(Type.void(), [Type.int()]) func = m.add_function(fnty, 'foo') bb = func.append_basic_block('') bldr = Builder.new(bb) cmpinst = bldr.icmp(lc.ICMP_ULE, func.args[0], Constant.int(Type.int(), 123)) self.assertTrue(repr(cmpinst.predicate).startswith('ICMP_ULE')) self.assertEqual(cmpinst.predicate, lc.ICMP_ULE) bldr.ret_void() func.verify()
def marginal(self, parameter, out): """ Compute the marginal distribution. """ @Function.define( Type.void(), [parameter.data.type_, out.data.type_], ) def finite_mixture_marginal(parameter_data, out_data): self._marginal( parameter.using(parameter_data), out.using(out_data), ) finite_mixture_marginal(parameter.data, out.data)
def average(self, weights, parameters, out): """ Emit computation of the average parameter. """ @Function.define( Type.void(), [weights.data.type_, parameters.data.type_, out.data.type_], ) def binomial_average(weights_data, parameters_data, out_data): self._average( weights.using(weights_data), parameters.using(parameters_data), out.using(out_data), ) binomial_average(weights.data, parameters.data, out.data)
def ml(self, samples, weights, out): """ Emit computation of the estimated maximum-likelihood parameter. """ @Function.define( Type.void(), [samples.data.type_, weights.data.type_, out.data.type_], ) def finite_mixture_ml(samples_data, weights_data, out_data): self._ml( samples.using(samples_data), weights.using(weights_data), out.using(out_data), ) finite_mixture_ml(samples.data, weights.data, out.data)
def test_nvvm_from_llvm(self): m = Module.new("test_nvvm_from_llvm") fty = Type.function(Type.void(), [Type.int()]) kernel = m.add_function(fty, name='mycudakernel') bldr = Builder.new(kernel.append_basic_block('entry')) bldr.ret_void() print(m) set_cuda_kernel(kernel) fix_data_layout(m) ptx = llvm_to_ptx(str(m)).decode('utf8') print(ptx) self.assertTrue('mycudakernel' in ptx) if is64bit: self.assertTrue('.address_size 64' in ptx) else: self.assertTrue('.address_size 32' in ptx)
def test_atomic_cmpxchg(self): mod = Module.new('mod') functype = Type.function(Type.void(), []) func = mod.add_function(functype, name='foo') bb = func.append_basic_block('entry') bldr = Builder.new(bb) ptr = bldr.alloca(Type.int()) old = bldr.load(ptr) new = Constant.int(Type.int(), 1234) for ordering in self.orderings: inst = bldr.atomic_cmpxchg(ptr, old, new, ordering) self.assertEqual(ordering, str(inst).strip().split(' ')[-1]) inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) self.assertEqual('singlethread', str(inst).strip().split(' ')[-2])
def test_atomic_cmpxchg(self): mod = Module.new("mod") functype = Type.function(Type.void(), []) func = mod.add_function(functype, name="foo") bb = func.append_basic_block("entry") bldr = Builder.new(bb) ptr = bldr.alloca(Type.int()) old = bldr.load(ptr) new = Constant.int(Type.int(), 1234) for ordering in self.orderings: inst = bldr.atomic_cmpxchg(ptr, old, new, ordering) self.assertEqual(ordering, str(inst).strip().split(" ")[-1]) inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) self.assertEqual("singlethread", str(inst).strip().split(" ")[-2])
def given(self, parameter, samples, out): """ Compute the conditional distribution. """ @Function.define( Type.void(), [parameter.data.type_, samples.data.type_, out.data.type_], ) def finite_mixture_given(parameter_data, samples_data, out_data): self._given( parameter.using(parameter_data), samples.using(samples_data), out.using(out_data), ) qy.return_() finite_mixture_given(parameter.data, samples.data, out.data)
def ll(self, parameter, sample, out): """ Compute finite-mixture log-likelihood. """ @Function.define( Type.void(), [parameter.data.type_, sample.data.type_, out.type_], ) def finite_mixture_ll(parameter_data, sample_data, out_data): self._ll( parameter.using(parameter_data), sample.using(sample_data), out_data, ) qy.return_() finite_mixture_ll(parameter.data, sample.data, out)
def ll(self, parameter, sample, out): """ Compute log likelihood under this distribution. """ @Function.define( Type.void(), [parameter.data.type_, sample.data.type_, out.type_], ) def tuple_ll(parameter_data, sample_data, out_data): self._ll( parameter.using(parameter_data), sample.using(sample_data), out_data, ) qy.return_() tuple_ll(parameter.data, sample.data, out)
def ll(self, parameter, sample, out): """ Compute log probability under this distribution. """ @Function.define( Type.void(), [parameter.data.type_, sample.data.type_, out.type_], ) def mixed_binomial_ll(parameter_data, sample_data, out_data): self._ll( parameter.using(parameter_data), sample.using(sample_data), out_data, ) qy.return_() mixed_binomial_ll(parameter.data, sample.data, out)
def ll(self, parameter, sample, out): """ Compute log probability under this distribution. """ @Function.define( Type.void(), [parameter.data.type_, sample.data.type_, out.type_], ) def binomial_ll_emitted(parameter_data, sample_data, out_data): binomial_log_pdf( sample_data.load(), parameter_data.gep(0, 0).load(), parameter_data.gep(0, 1).load(), ) \ .store(out_data) qy.return_() binomial_ll_emitted(parameter.data, sample.data, out)
def map(self, prior, samples, weights, out): """ Emit computation of the estimated MAP parameter. """ @Function.define( Type.void(), [ prior.data.type_, samples.data.type_, weights.data.type_, out.data.type_ ], ) def binomial_map(prior_data, samples_data, weights_data, out_data): self._map( prior.using(prior_data), samples.using(samples_data), weights.using(weights_data), out.using(out_data), ) binomial_map(prior.data, samples.data, weights.data, out.data)