def test_multi_module_linking(self): # generate external library module m = Module.new('external-library-module') fnty = Type.function(Type.int(), [Type.int(), Type.int()]) libfname = 'myadd' func = m.add_function(fnty, libfname) bb = func.append_basic_block('') bldr = Builder.new(bb) bldr.ret(bldr.add(*func.args)) func.verify() # JIT the lib module and bind dynamic symbol libengine = EngineBuilder.new(m).mcjit(True).create() myadd_ptr = libengine.get_pointer_to_function(func) le.dylib_add_symbol(libfname, myadd_ptr) # reference external library m = Module.new('user') fnty = Type.function(Type.int(), [Type.int(), Type.int()]) func = m.add_function(fnty, 'foo') bb = func.append_basic_block('') bldr = Builder.new(bb) extadd = m.get_or_insert_function(fnty, name=libfname) bldr.ret(bldr.call(extadd, func.args)) func.verify() # JIT the user module engine = EngineBuilder.new(m).mcjit(True).create() ptr = engine.get_pointer_to_function(func) self.assertEqual(myadd_ptr, engine.get_pointer_to_named_function(libfname)) from ctypes import c_int, CFUNCTYPE callee = CFUNCTYPE(c_int, c_int, c_int)(ptr) self.assertEqual(321 + 123, callee(321, 123))
def __init__(self, context, fndesc, interp): self.context = context self.fndesc = fndesc self.blocks = utils.SortedMap(utils.iteritems(interp.blocks)) # Initialize LLVM self.module = Module.new("module.%s" % self.fndesc.unique_name) # Python execution environment (will be available to the compiled # function). self.env = _dynfunc.Environment( globals=self.fndesc.lookup_module().__dict__) # Setup function self.function = context.declare_function(self.module, fndesc) self.entry_block = self.function.append_basic_block('entry') self.builder = Builder.new(self.entry_block) # Internal states self.blkmap = {} self.varmap = {} self.firstblk = min(self.blocks.keys()) self.loc = -1 # Subclass initialization self.init()
def CodeGen(self): print >> stderr, "codegening function node" G_NAMED_VALUES.clear() old_bindings = {} function = self.prototype.CodeGen() if self.prototype.IsBinaryOp(): operator = self.prototype.GetOperatorName() G_BINOP_PRECEDENCE[operator] = self.prototype.precedence block = function.append_basic_block('entry') global G_LLVM_BUILDER G_LLVM_BUILDER = Builder.new(block) self.prototype.CreateArgumentAllocas(function, old_bindings) try: return_value = self.body.CodeGen() G_LLVM_BUILDER.ret(return_value) function.verify() G_LLVM_PASS_MANAGER.run(function) except: function.delete() if self.prototype.IsBinaryOp(): del G_BINOP_PRECEDENCE[self.prototype.GetOperatorName()] raise # self.prototype.RestoreArguments(old_bindings) return function
def CodeGen(self): # Clear scope g_named_values.clear() # Create function object function = self.prototype.CodeGen() # LOOK INTO WHAT THIS DOES, NOT SURE # Create new basic block to start insertion into block = function.append_basic_block('entry') global g_llvm_builder g_llbm_builder = Builder.new(block) # Finish off the function try: return_value = self.body.CodeGen() g_llvm_builder.ret(return_value) # Validate the generated code, check for consistency function.verify() except: function.delete() raise return function
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 test_uses(self): m = Module.new("a") t = Type.int() ft = Type.function(t, [t, t, t]) f = m.add_function(ft, "func") b = f.append_basic_block("entry") bld = Builder.new(b) tmp1 = bld.add(Constant.int(t, 100), f.args[0], "tmp1") tmp2 = bld.add(tmp1, f.args[1], "tmp2") tmp3 = bld.add(tmp1, f.args[2], "tmp3") bld.ret(tmp3) # Testing use count self.assertEqual(f.args[0].use_count, 1) self.assertEqual(f.args[1].use_count, 1) self.assertEqual(f.args[2].use_count, 1) self.assertEqual(tmp1.use_count, 2) self.assertEqual(tmp2.use_count, 0) self.assertEqual(tmp3.use_count, 1) # Testing uses self.assert_(f.args[0].uses[0] is tmp1) self.assertEqual(len(f.args[0].uses), 1) self.assert_(f.args[1].uses[0] is tmp2) self.assertEqual(len(f.args[1].uses), 1) self.assert_(f.args[2].uses[0] is tmp3) self.assertEqual(len(f.args[2].uses), 1) self.assertEqual(len(tmp1.uses), 2) self.assertEqual(len(tmp2.uses), 0) self.assertEqual(len(tmp3.uses), 1)
def test_issue100(self): m = Module.new('a') pm = FunctionPassManager.new(m) ee = ExecutionEngine.new(m) pm.add(ee.target_data) ti = Type.int() tf = Type.function(ti, []) f = m.add_function(tf, "func1") bb = f.append_basic_block('entry') b = Builder.new(bb) b.ret(Constant.int(ti, 0)) f.verify() pm.run(f) assert ee.run_function(f, []).as_int() == 0
def _build_module(self, float): mod = Module.new('test') functy = Type.function(float, [float]) func = mod.add_function(functy, "mytest%s" % float) block = func.append_basic_block("entry") b = Builder.new(block) return mod, func, b
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 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 test_bswap(self): # setup a function and a builder mod = Module.new('test') functy = Type.function(Type.int(), []) func = mod.add_function(functy, "showme") block = func.append_basic_block("entry") b = Builder.new(block) # let's do bswap on a 32-bit integer using llvm.bswap val = Constant.int(Type.int(), 0x42) bswap = Function.intrinsic(mod, lc.INTR_BSWAP, [Type.int()]) bswap_res = b.call(bswap, [val]) b.ret(bswap_res) # logging.debug(mod) # the output is: # # ; ModuleID = 'test' # # define void @showme() { # entry: # %0 = call i32 @llvm.bswap.i32(i32 42) # ret i32 %0 # } # let's run the function ee = le.ExecutionEngine.new(mod) retval = ee.run_function(func, []) self.assertEqual(retval.as_int(), 0x42000000)
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 test_bswap(self): # setup a function and a builder mod = Module.new("test") functy = Type.function(Type.int(), []) func = mod.add_function(functy, "showme") block = func.append_basic_block("entry") b = Builder.new(block) # let's do bswap on a 32-bit integer using llvm.bswap val = Constant.int(Type.int(), 0x42) bswap = Function.intrinsic(mod, lc.INTR_BSWAP, [Type.int()]) bswap_res = b.call(bswap, [val]) b.ret(bswap_res) # logging.debug(mod) # the output is: # # ; ModuleID = 'test' # # define void @showme() { # entry: # %0 = call i32 @llvm.bswap.i32(i32 42) # ret i32 %0 # } # let's run the function ee = le.ExecutionEngine.new(mod) retval = ee.run_function(func, []) self.assertEqual(retval.as_int(), 0x42000000)
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 CodeGen(self): # Clear scope. g_named_values.clear() # Create a function object. function = self.prototype.CodeGen() # Create a new basic block to start insertion into. block = function.append_basic_block('entry') global g_llvm_builder g_llvm_builder = Builder.new(block) # Finish off the function. try: return_value = self.body.CodeGen() g_llvm_builder.ret(return_value) # Validate the generated code, checking for consistency. function.verify() except: function.delete() raise return function
def test_uses(self): m = Module.new('a') t = Type.int() ft = Type.function(t, [t, t, t]) f = m.add_function(ft, "func") b = f.append_basic_block('entry') bld = Builder.new(b) tmp1 = bld.add(Constant.int(t, 100), f.args[0], "tmp1") tmp2 = bld.add(tmp1, f.args[1], "tmp2") tmp3 = bld.add(tmp1, f.args[2], "tmp3") bld.ret(tmp3) # Testing use count self.assertEqual(f.args[0].use_count, 1) self.assertEqual(f.args[1].use_count, 1) self.assertEqual(f.args[2].use_count, 1) self.assertEqual(tmp1.use_count, 2) self.assertEqual(tmp2.use_count, 0) self.assertEqual(tmp3.use_count, 1) # Testing uses self.assert_(f.args[0].uses[0] is tmp1) self.assertEqual(len(f.args[0].uses), 1) self.assert_(f.args[1].uses[0] is tmp2) self.assertEqual(len(f.args[1].uses), 1) self.assert_(f.args[2].uses[0] is tmp3) self.assertEqual(len(f.args[2].uses), 1) self.assertEqual(len(tmp1.uses), 2) self.assertEqual(len(tmp2.uses), 0) self.assertEqual(len(tmp3.uses), 1)
def test_mysin(self): if sys.platform == 'win32' and BITS == 32: # float32 support is known to fail on 32-bit Windows return # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) mod = Module.new('test') float = Type.float() mysinty = Type.function( float, [float] ) mysin = mod.add_function(mysinty, "mysin") block = mysin.append_basic_block("entry") b = Builder.new(block) sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) cos = Function.intrinsic(mod, lc.INTR_COS, [float]) mysin.args[0].name = "x" x = mysin.args[0] one = Constant.real(float, "1") cosx = b.call(cos, [x], "cosx") cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub sin = b.call(sqrt, [onemc2], "sin") b.ret(sin) #logging.debug(mod) # ; ModuleID = 'test' # # define void @showme() { # entry: # call i32 @llvm.bswap.i32( i32 42 ) ; <i32>:0 [#uses # } # # declare i32 @llvm.bswap.i32(i32) nounwind readnone # # define float @mysin(float %x) { # entry: # %cosx = call float @llvm.cos.f32( float %x ) ; <float # %cos2 = call float @llvm.powi.f32( float %cosx, i32 2 ) # %onemc2 = sub float 1.000000e+00, %cos2 ; <float> [#uses # %sin = call float @llvm.sqrt.f32( float %onemc2 ) # ret float %sin # } # # declare float @llvm.sqrt.f32(float) nounwind readnone # # declare float @llvm.powi.f32(float, i32) nounwind readnone # # declare float @llvm.cos.f32(float) nounwind readnone # let's run the function ee = le.ExecutionEngine.new(mod) arg = le.GenericValue.real(Type.float(), 1.234) retval = ee.run_function(mysin, [arg]) golden = math.sin(1.234) answer = retval.as_real(Type.float()) self.assertTrue(abs(answer-golden)/golden < 1e-5)
def build(self): wrapname = "wrapper.%s" % self.func.name # This is the signature of PyCFunctionWithKeywords # (see CPython's methodobject.h) pyobj = self.context.get_argument_type(types.pyobject) wrapty = Type.function(pyobj, [pyobj, pyobj, pyobj]) wrapper = self.module.add_function(wrapty, name=wrapname) builder = Builder.new(wrapper.append_basic_block('entry')) # - `closure` will receive the `self` pointer stored in the # PyCFunction object (see _dynfunc.c) # - `args` and `kws` will receive the tuple and dict objects # of positional and keyword arguments, respectively. closure, args, kws = wrapper.args closure.name = 'py_closure' args.name = 'py_args' kws.name = 'py_kws' api = self.context.get_python_api(builder) self.build_wrapper(api, builder, closure, args, kws) wrapper.verify() return wrapper, api
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 argv(func): global module blk = func.append_basic_block("args") builder = Builder.new(blk) # fn = module.get_function_named("mainargs") fn = LLVMFunction("mainargs", args=[Int32, STRArray], ret=PTR(STRList), m=module) # print(fn.type.pointee.args) builder.call(fn, [Int32, STRArray], "whatisit")
def codegen(self): global module func = LLVMFunction("main", [Int32, STRArray], Int32, module) argv(func) blk = func.append_basic_block("entry") builder = Builder.new(blk) builder.ret(Constant.int(Int32, 0)) func.verify()
def wrapper(m, r, a): t = llvm.core.Type.function(r, a) fn = m.add_function(t, pfn.__name__) fn.add_attribute(llvm.core.ATTR_ALWAYS_INLINE) fn.linkage = llvm.core.LINKAGE_INTERNAL bb = fn.append_basic_block("entry") builder = Builder.new(bb) pfn(m, fn, bb, builder)
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_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 make_test_module(self): module = Module.new("testmodule") fnty = Type.function(Type.int(), []) function = module.add_function(fnty, 'foo') bb_entry = function.append_basic_block('entry') builder = Builder.new(bb_entry) builder.ret(Constant.int(Type.int(), 0xcafe)) module.verify() return module
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 make_test_module(self): module = Module.new("testmodule") fnty = Type.function(Type.int(), []) function = module.add_function(fnty, "foo") bb_entry = function.append_basic_block("entry") builder = Builder.new(bb_entry) builder.ret(Constant.int(Type.int(), 0xCAFE)) module.verify() return module
def __init__(self): self.module = Module.new("module") # int main() { ... } tyfunc = Type.function(llIntType, []) func = self.module.add_function(tyfunc, "main") entry = func.append_basic_block("entry") self.builder = Builder.new(entry)
def test_mysin(self): # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) mod = Module.new('test') float = Type.float() mysinty = Type.function(float, [float]) mysin = mod.add_function(mysinty, "mysin") block = mysin.append_basic_block("entry") b = Builder.new(block) sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) cos = Function.intrinsic(mod, lc.INTR_COS, [float]) mysin.args[0].name = "x" x = mysin.args[0] one = Constant.real(float, "1") cosx = b.call(cos, [x], "cosx") cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub sin = b.call(sqrt, [onemc2], "sin") b.ret(sin) #logging.debug(mod) # ; ModuleID = 'test' # # define void @showme() { # entry: # call i32 @llvm.bswap.i32( i32 42 ) ; <i32>:0 [#uses # } # # declare i32 @llvm.bswap.i32(i32) nounwind readnone # # define float @mysin(float %x) { # entry: # %cosx = call float @llvm.cos.f32( float %x ) ; <float # %cos2 = call float @llvm.powi.f32( float %cosx, i32 2 ) # %onemc2 = sub float 1.000000e+00, %cos2 ; <float> [#uses # %sin = call float @llvm.sqrt.f32( float %onemc2 ) # ret float %sin # } # # declare float @llvm.sqrt.f32(float) nounwind readnone # # declare float @llvm.powi.f32(float, i32) nounwind readnone # # declare float @llvm.cos.f32(float) nounwind readnone # let's run the function ee = le.ExecutionEngine.new(mod) arg = le.GenericValue.real(Type.float(), 1.234) retval = ee.run_function(mysin, [arg]) golden = math.sin(1.234) answer = retval.as_real(Type.float()) self.assertTrue(abs(answer - golden) / golden < 1e-5)
def begin_function(self, name, ret_type, arg_types): ret_type, arg_types = typemap[ret_type], [typemap[a] for a in arg_types] self.locals.clear() self.function = self.functions[name] self.block = self.function.append_basic_block("start") self.builder = Builder.new(self.block) self.set_block(self.block) self.exit_block = self.function.append_basic_block("exit") if ret_type is not void_type: self.locals['return'] = self.builder.alloca(ret_type, name="return")
def build_test(name): (retty, args), impl = INTRINSICS[name] module = Module.new("test.%s" % name) fn = module.add_function(Type.function(retty, args), name="test_%s" % name) builder = Builder.new(fn.append_basic_block("")) retval = impl(module, builder, fn.args) builder.ret(retval) fn.verify() module.verify() return module, fn
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 _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 _make_module(self): m = Module.new('module1') m.add_global_variable(Type.int(), 'i') fty = Type.function(Type.int(), []) f = m.add_function(fty, name='main') bldr = Builder.new(f.append_basic_block('entry')) bldr.ret(Constant.int(Type.int(), 0xab)) return m
def test_jit_ctypes(self): # This example demonstrates calling an LLVM defined function using # ctypes. It illustrates the common C pattern of having an output # variable in the argument list to the function. The function also # returns an error code upon exit. # setup llvm types ty_errcode = Type.int() ty_float = Type.float() ty_ptr_float = Type.pointer(Type.float()) ty_func = Type.function(ty_errcode, [ty_float, ty_float, ty_ptr_float]) # setup ctypes types ct_errcode = ctypes.c_int ct_float = ctypes.c_float ct_ptr_float = ctypes.POINTER(ct_float) ct_argtypes = [ct_float, ct_float, ct_ptr_float] # generate the function using LLVM my_module = Module.new('my_module') mult = my_module.add_function(ty_func, "mult") mult.args[0].name = "a" mult.args[1].name = "b" mult.args[2].name = "out" # add nocapture to output arg mult.args[2].add_attribute(llvm.core.ATTR_NO_CAPTURE) mult.does_not_throw = True # add nounwind attribute to function bb = mult.append_basic_block("entry") builder = Builder.new(bb) tmp = builder.fmul(mult.args[0], mult.args[1]) builder.store(tmp, mult.args[2]) builder.ret(llvm.core.Constant.int(ty_errcode, 0)) # print the created module logging.debug(my_module) # compile the function ee = ExecutionEngine.new(my_module) # let ctypes know about the function func_ptr_int = ee.get_pointer_to_function(mult) FUNC_TYPE = ctypes.CFUNCTYPE(ct_errcode, *ct_argtypes) py_mult = FUNC_TYPE(func_ptr_int) # now run the function, calling via ctypes output_value = ct_float(123456.0) errcode = py_mult(2.0, 3.0, ctypes.byref(output_value)) self.assertEqual(errcode, 0, msg='unexpected error') self.assertEqual(output_value.value, 6.0)
def _make_module(self): m = Module.new("module1") m.add_global_variable(Type.int(), "i") fty = Type.function(Type.int(), []) f = m.add_function(fty, name="main") bldr = Builder.new(f.append_basic_block("entry")) bldr.ret(Constant.int(Type.int(), 0xAB)) return m
def test_jit_ctypes(self): # This example demonstrates calling an LLVM defined function using # ctypes. It illustrates the common C pattern of having an output # variable in the argument list to the function. The function also # returns an error code upon exit. # setup llvm types ty_errcode = Type.int() ty_float = Type.float() ty_ptr_float = Type.pointer(Type.float()) ty_func = Type.function(ty_errcode, [ty_float, ty_float, ty_ptr_float]) # setup ctypes types ct_errcode = ctypes.c_int ct_float = ctypes.c_float ct_ptr_float = ctypes.POINTER(ct_float) ct_argtypes = [ct_float, ct_float, ct_ptr_float] # generate the function using LLVM my_module = Module.new('my_module') mult = my_module.add_function(ty_func, "mult") mult.args[0].name = "a" mult.args[1].name = "b" mult.args[2].name = "out" # add nocapture to output arg mult.args[2].add_attribute(llvm.core.ATTR_NO_CAPTURE) mult.does_not_throw = True # add nounwind attribute to function bb = mult.append_basic_block("entry") builder = Builder.new(bb) tmp = builder.fmul( mult.args[0], mult.args[1] ) builder.store( tmp, mult.args[2] ) builder.ret(llvm.core.Constant.int(ty_errcode, 0)) # print the created module logging.debug(my_module) # compile the function ee = ExecutionEngine.new(my_module) # let ctypes know about the function func_ptr_int = ee.get_pointer_to_function( mult ) FUNC_TYPE = ctypes.CFUNCTYPE(ct_errcode, *ct_argtypes) py_mult = FUNC_TYPE(func_ptr_int) # now run the function, calling via ctypes output_value = ct_float(123456.0) errcode = py_mult( 2.0, 3.0, ctypes.byref(output_value) ) self.assertEqual(errcode, 0, msg='unexpected error') self.assertEqual(output_value.value, 6.0)
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 test_inline_call(self): mod = Module.new(__name__) callee = mod.add_function(Type.function(Type.int(), [Type.int()]), name="bar") builder = Builder.new(callee.append_basic_block("entry")) builder.ret(builder.add(callee.args[0], callee.args[0])) caller = mod.add_function(Type.function(Type.int(), []), name="foo") builder = Builder.new(caller.append_basic_block("entry")) callinst = builder.call(callee, [Constant.int(Type.int(), 1234)]) builder.ret(callinst) pre_inlining = str(caller) self.assertIn("call", pre_inlining) self.assertTrue(inline_function(callinst)) post_inlining = str(caller) self.assertNotIn("call", post_inlining) self.assertIn("2468", post_inlining)
def main(file): # Get the abstract syntax tree. try: ast = SimpleParse(file) except: print "Supplied file path is invalid!" return 1 # Create main function. # # Create the main function signature and add it to the module. # Signature: int main() g_llvm_module = Module.new('simple') # Holds all of the IR code. tp_main = Type.function(tp_int, []) f_main = g_llvm_module.add_function(tp_main, "main") # Set up the entry block for the main function and create a builder for it. entry_block = f_main.append_basic_block("entry") nodes.g_llvm_builder = Builder.new(entry_block) # Emit the programs main code. ast.emit() # Setup of printf and a formatting string for printing variables to stdout. f_printf = SetupPrintf(g_llvm_module) p_fs = EmitGlobalString(g_llvm_module, nodes.g_llvm_builder, "%s = %i\n") # Calls to printf to print out the variables. scope = ast.getScope() sorted_vars = sorted(list(scope)) for var in sorted_vars: name = EmitGlobalString(g_llvm_module, nodes.g_llvm_builder, var) value = nodes.g_llvm_builder.load(scope[var]) nodes.g_llvm_builder.call(f_printf, [p_fs, name, value]) # Exit with return code 0 (RET_SUCCESS). nodes.g_llvm_builder.ret(Constant.int(tp_int, 0)) ModuleToNativeBinary(g_llvm_module) nameMap = dict() LabelAst(ast, 0, nameMap) transitions = [] tails = AstToCfg(ast, transitions, [-1]) nameMap[-1] = "Start" nameMap[-2] = "End" # Add transitions from all hanging tails to end block. for tail in tails: transitions.append((tail, -2)) simple_graph.renderCFG(transitions, nameMap) simple_graph.renderGraph(ast) return 0
def add4impl(lfunc): '''For LLVMBackend, the implementation receives an empty llvm.core.Function to begin implementation. ''' bb = lfunc.append_basic_block('entry') builder = Builder.new(bb) arg0, arg1 = lfunc.args pvty = Type.pointer(Type.vector(Type.float(), 4)) v0 = builder.load(builder.bitcast(arg0, pvty)) v1 = builder.load(builder.bitcast(arg1, pvty)) vs = builder.fadd(v0, v1) builder.store(vs, builder.bitcast(arg0, pvty)) builder.ret_void()
def test_inline_call(self): mod = Module.new(__name__) callee = mod.add_function(Type.function(Type.int(), [Type.int()]), name='bar') builder = Builder.new(callee.append_basic_block('entry')) builder.ret(builder.add(callee.args[0], callee.args[0])) caller = mod.add_function(Type.function(Type.int(), []), name='foo') builder = Builder.new(caller.append_basic_block('entry')) callinst = builder.call(callee, [Constant.int(Type.int(), 1234)]) builder.ret(callinst) pre_inlining = str(caller) self.assertIn('call', pre_inlining) self.assertTrue(inline_function(callinst)) post_inlining = str(caller) self.assertNotIn('call', post_inlining) self.assertIn('2468', post_inlining)
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 codegen_func(func): proto, body = func[1], func[2] named_values.clear() func = codegen_proto(proto) bb = func.append_basic_block('entry') builder = Builder.new(bb) try: ret_val = codegen_expr(builder, body) builder.ret(ret_val) func.verify() return func except: func.delete() raise
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 test_issue10(self): m = Module.new('a') ti = Type.int() tf = Type.function(ti, [ti, ti]) f = m.add_function(tf, "func1") bb = f.append_basic_block('entry') b = Builder.new(bb) # There are no instructions in bb. Positioning of the # builder at beginning (or end) should succeed (trivially). b.position_at_end(bb) b.position_at_beginning(bb)
def test_asm(self): m = Module.new('module1') foo = m.add_function(Type.function(Type.int(), [Type.int(), Type.int()]), name="foo") bldr = Builder.new(foo.append_basic_block('entry')) x = bldr.add(foo.args[0], foo.args[1]) bldr.ret(x) att_syntax = m.to_native_assembly() os.environ["LLVMPY_OPTIONS"] = "-x86-asm-syntax=intel" lc.parse_environment_options(sys.argv[0], "LLVMPY_OPTIONS") intel_syntax = m.to_native_assembly() self.assertNotEqual(att_syntax, intel_syntax)
def build_constructor(fn, ty, spine, j): freev = free() entry = fn.append_basic_block('entry') builder = Builder.new(entry) retval = builder.alloca(spine, name='ret') #tag = builder.gep(retval, [const(0), const(0)], 'tag') #builder.store(const(j), tag) for i, arg in enumerate(fn.args): idx1 = builder.gep(retval, [const(0), const(0)], next(freev)) idx2 = builder.gep(idx1, [const(0), const(i)], next(freev)) builder.store(arg, idx2) return builder.ret(retval)
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 build(self): wrapname = "wrapper.%s" % self.func.name pyobj = self.context.get_argument_type(types.pyobject) fnty = Type.function(pyobj, [pyobj, pyobj, pyobj]) wrapper = self.module.add_function(fnty, name=wrapname) builder = Builder.new(wrapper.append_basic_block('entry')) # builder = cgutils.VerboseProxy(builder) _, args, kws = wrapper.args api = self.context.get_python_api(builder) self.build_wrapper(api, builder, args, kws) wrapper.verify() return wrapper, api
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])