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 _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 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 testAppendBasicBlock(self): mod = Module.CreateWithName('module') ty = Type.int8(context=mod.context) ft = Type.function(ty, [ty], False) f = mod.add_function('timestwo', ft) bb = f.append_basic_block('body') self.assertEqual('body', bb.name)
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 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 create_global_load_save_module(): mod = Module.CreateWithName('module') ty = Type.int8(mod.context) x = Global.add(mod, ty, 'x') x.initializer = Value.const_int(ty, 0, True) 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 create_load(): ft = Type.function(ty, [], False) f = mod.add_function('load', ft) bb = f.append_basic_block('body') bldr = Builder.create(mod.context) bldr.position_at_end(bb) xt = bldr.load(x, "xt") bldr.ret(xt) create_store() create_load() return mod
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_operands(self): m = Module.from_assembly(StringIO(self.test_module)) test_func = m.get_function_named("test_func") prod = m.get_function_named("prod") # test operands i1 = test_func.basic_blocks[0].instructions[0] i2 = test_func.basic_blocks[0].instructions[1] i3 = test_func.basic_blocks[0].instructions[2] i4 = test_func.basic_blocks[0].instructions[3] i5 = test_func.basic_blocks[0].instructions[4] self.assertEqual(i1.operand_count, 3) self.assertEqual(i2.operand_count, 2) self.assertEqual(i3.operands[1].z_ext_value, 1) self.assertEqual(i3.operands[1].s_ext_value, 1) self.assertEqual(i4.operands[1].z_ext_value, 0xffffffff) self.assertEqual(i4.operands[1].s_ext_value, -1) self.assertEqual(i5.operands[0].s_ext_value, -81985529216486895) self.assertEqual(i5.operands[1].z_ext_value, 12297829382473034410) self.assert_(i1.operands[-1] is prod) self.assert_(i1.operands[0] is test_func.args[0]) self.assert_(i1.operands[1] is test_func.args[1]) self.assert_(i2.operands[0] is i1) self.assert_(i2.operands[1] is test_func.args[2]) self.assertEqual(len(i1.operands), 3) self.assertEqual(len(i2.operands), 2) self.assert_(i1.called_function is prod)
def create_abs_module(): mod = Module.CreateWithName('module') ty = Type.int8(context=mod.context) ft = Type.function(ty, [ty], False) f = mod.add_function('abs', ft) bb1 = f.append_basic_block('body') bbt = f.append_basic_block('true') bbf = f.append_basic_block('false') bbm = f.append_basic_block('merge') bldr = Builder.create(mod.context) bldr.position_at_end(bb1) x = f.get_param(0) zero = Value.const_int(ty, 0, True) c = bldr.int_signed_lt(x, zero, 'comp') bldr.conditional_branch(c, bbt, bbf) # True branch bldr.position_at_end(bbt) y_t = bldr.neg(x, 'neg_x') bldr.branch(bbm) # False branch bldr.position_at_end(bbf) bldr.branch(bbm) bldr.position_at_end(bbm) y = bldr.phi(ty, 'y') y.add_incoming([y_t, x], [bbt, bbf]) bldr.ret(y) return (mod, f)
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 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_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 create_cumsum_module(): mod = Module.CreateWithName('module') ty = Type.int8(context=mod.context) ft = Type.function(ty, [ty], False) f = mod.add_function('cumsum', ft) bb1 = f.append_basic_block('body') bb_hdr = f.append_basic_block('hdr') bb_loop = f.append_basic_block('loop') bb_exit = f.append_basic_block('exit') bldr = Builder.create(mod.context) bldr.position_at_end(bb1) bldr.branch(bb_hdr) bldr.position_at_end(bb_hdr) i = bldr.phi(ty, 'i') s = bldr.phi(ty, 's') zero = Value.const_int(ty, 0, True) c = bldr.int_signed_lt(zero, i, 'comp') bldr.conditional_branch(c, bb_loop, bb_exit) bldr.position_at_end(bb_loop) s1 = bldr.add(s, i, 's1') i1 = bldr.sub(i, Value.const_int(ty, 1, True), 'i1') bldr.branch(bb_hdr) i.add_incoming([f.get_param(0), i1], [bb1, bb_loop]) s.add_incoming([Value.const_int(ty, 0, True), s1], [bb1, bb_loop]) bldr.position_at_end(bb_exit) bldr.ret(s) return (mod, f)
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 test_named_md(self): m = Module.new('test_named_md') nmd = m.get_or_insert_named_metadata('something') md = MetaData.get(m, [Constant.int(Type.int(), 0xbeef)]) nmd.add(md) self.assertTrue(str(nmd).startswith('!something')) ir = str(m) self.assertTrue('!something' in ir)
def test_named_md(self): m = Module.new("test_named_md") nmd = m.get_or_insert_named_metadata("something") md = MetaData.get(m, [Constant.int(Type.int(), 0xBEEF)]) nmd.add(md) self.assertTrue(str(nmd).startswith("!something")) ir = str(m) self.assertTrue("!something" in ir)
def cg_load_bitcode_from_file(file_name): try: with open(file_name, "rb") as fin: mod = Module.from_bitcode(fin) except: log.debug("Failed to load bitcode: " + file_name) return None log.debug("Loaded bitcode from file: " + file_name) return mod
def fromctypes(func, module=None): if func.argtypes is None: raise ValueError("ctypes function must have argtypes and restype set") if module is None: names = [arg.__name__ for arg in func.argtypes] names.append(func.restype.__name__) name = "mod__{0}_{1}".format(func.__name__, '_'.join(names)) module = Module.new(name) raise NotImplementedError
def bitey_reconstruct(md, bitcode): name, = md mod = new_module(name) llvm_module = Module.from_bitcode(BytesIO(bitcode)) engine = ExecutionEngine.new(llvm_module) make_all_wrappers(llvm_module, engine, mod) return mod
def codegen(tree, name="(no name)", output="/tmp/llvm.ir"): global module module = Module.new(name) stdlib = STDLib() stdlib.codegen() function = MainFun() function.codegen() print(module)
def make_module(self): test_module = """ define void @sum(i32*, i32*) { entry: ret void } """ buf = StringIO(test_module) return Module.from_assembly(buf)
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 make_module(self): test_module = """ define i32 @sum(i32, i32) { entry: %2 = add i32 %0, %1 ret i32 %2 } """ return Module.from_assembly(StringIO(test_module))
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 testAddGlobal(self): mod = Module.CreateWithName('module') ty = Type.int8(context=mod.context) a = Value.const_int(ty, 1, True) g = Global.add(mod, ty, 'x') g.initializer = Value.const_int(ty, 4, True) bldr = Builder.create() c = bldr.add(g.initializer, a, 'tmp1') self.assertEqual(5, c.get_signext_value())
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 testCreateNamedStructInMod(self): ctx = Context() mod = Module.CreateWithName('mod', ctx) ty = Type.create_named_structure(mod.context, 'mystruct') el = Type.int8(context=mod.context) ty.set_body([el, el], True) t = mod.get_type('mystruct') self.assertEqual(ty, t)
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 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 _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 test_bitcode(self): # create a module m = Module.new('module1') m.add_global_variable(Type.int(), 'i') # write it's assembly representation to a file asm = str(m) testasm_bc = os.path.join(self.tmpdir, 'testasm.bc') with open(testasm_bc, "wb") as fout: m.to_bitcode(fout) # read it back into a module with open(testasm_bc, "rb") as fin: m2 = Module.from_bitcode(fin) # The default `m.id` is '<string>'. m2.id = m.id # Copy the name from `m` self.assertEqual(str(m2).strip(), asm.strip())
def test_asm(self): # create a module m = Module.new("module1") m.add_global_variable(Type.int(), "i") # write it's assembly representation to a file asm = str(m) testasm_ll = os.path.join(self.tmpdir, "testasm.ll") with open(testasm_ll, "w") as fout: fout.write(asm) # read it back into a module with open(testasm_ll) as fin: m2 = Module.from_assembly(fin) # The default `m.id` is '<string>'. m2.id = m.id # Copy the name from `m` self.assertEqual(str(m2).strip(), asm.strip())
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_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 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 wrap_llvm_bitcode(bitcode, py_module): ''' Given a byte-string of LLVM bitcode and a Python module, populate the module with ctypes bindings for public methods in the bitcode. ''' llvm_module = Module.from_bitcode(io.BytesIO(bitcode)) engine = llvm.ee.ExecutionEngine.new(llvm_module) wrap_llvm_module(llvm_module, engine, py_module) setattr(py_module, '_llvm_module', llvm_module) setattr(py_module, '_llvm_engine', engine)
def test_forloop(self): mod = Module.new(__name__) lfoo = FooForRange()(mod) print(mod) mod.verify() exe = CExecutor(mod) foo = exe.get_ctype_function(lfoo, 'int') self.assertEqual(foo(10), sum(range(10+1))) self.assertEqual(foo(1324), sum(range(1324+1)))
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_bitcode_roundtrip(self): m = self.create_module() testasm_bc = os.path.join(self.tmpdir, 'testasm.bc') with open(testasm_bc, "wb") as fout: m.to_bitcode(fout) # read it back into a module with open(testasm_bc, "rb") as fin: m2 = Module.from_bitcode(fin) # The default `m.id` is '<string>'. m2.id = m.id # Copy the name from `m` with open(testasm_bc, "rb") as fin: m3 = Module.from_bitcode(fin.read()) # The default `m.id` is '<string>'. m3.id = m.id # Copy the name from `m` self.assertEqual(str(m2).strip(), str(m).strip()) self.assertEqual(str(m3).strip(), str(m).strip())
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_metadata(self): m = Module.new("a") t = Type.int() metadata = MetaData.get(m, [Constant.int(t, 100), MetaDataString.get(m, "abcdef"), None]) MetaData.add_named_operand(m, "foo", metadata) self.assertEqual(MetaData.get_named_operands(m, "foo"), [metadata]) self.assertEqual(MetaData.get_named_operands(m, "bar"), []) self.assertEqual(len(metadata.operands), 3) self.assertEqual(metadata.operands[0].z_ext_value, 100) self.assertEqual(metadata.operands[1].string, "abcdef") self.assertTrue(metadata.operands[2] is None)