#!/usr/bin/env python # # This script attempts to achieve 100% function and branch coverage for # all APIs in the llvm package. It only exercises the APIs, doesn't test # them for correctness. # from llvm import * from llvm.core import * from llvm.ee import * from llvm.passes import * ti = Type.int() def do_llvmexception(): print(" Testing class LLVMException") e = LLVMException() def do_misc(): print(" Testing miscellaneous functions") try: load_library_permanently("/usr/lib/libm.so") except LLVMException: pass try: print(" ... second one now") load_library_permanently("no*such*so") except LLVMException: pass def do_llvm(): print(" Testing module llvm") do_llvmexception() do_misc() def do_module(): print(" Testing class Module") m = Module.new('test') m.target = 'a' a = m.target m.data_layout = 'a' a = m.data_layout # m.add_type_name('a', ti) # m.delete_type_name('a') Type.struct([ti], name='a') m.get_type_named('a').name='' s = str(m) s = m == Module.new('a') m.add_global_variable(ti, 'b') m.get_global_variable_named('b') gvs = list(m.global_variables) ft = Type.function(ti, [ti]) m.add_function(ft, "func") m.get_function_named("func") m.get_or_insert_function(ft, "func") m.get_or_insert_function(Type.function(ti, []), "func") m.get_or_insert_function(ft, "func2") fns = list(m.functions) try: m.verify() except LLVMException: pass class strstream(object): def __init__(self): self.s = b'' def write(self, data): if not isinstance(data, bytes): data = data.encode('utf-8') self.s += data def read(self): return self.s ss = strstream() m2 = Module.new('test') # m2.add_type_name('myint', ti) Type.struct([ti], 'myint') m2.to_bitcode(ss) m3 = Module.from_bitcode(ss) t = m2 == m3 ss2 = strstream() ss2.write(str(m)) m4 = Module.from_assembly(ss2) t = m4 == m t = m4.pointer_size mA = Module.new('ma') mB = Module.new('mb') mA.link_in(mB) def do_type(): print(" Testing class Type") for i in range(1,100): Type.int(i) Type.float() Type.double() Type.x86_fp80() Type.fp128() Type.ppc_fp128() Type.function(ti, [ti]*100, True) Type.function(ti, [ti]*100, False) Type.struct([ti]*100) Type.packed_struct([ti]*100) Type.array(ti, 100) ptr = Type.pointer(ti, 4) pte = ptr.pointee Type.vector(ti, 100) Type.void() Type.label() Type.opaque('an_opaque_type') s = str(ti) s = ti == Type.float() Type.opaque('whatever').set_body([Type.int()]) s = ti.width ft = Type.function(ti, [ti]*10) ft.return_type ft.vararg s = list(ft.args) ft.arg_count st = Type.struct([ti]*10) s = st.element_count s = list(st.elements) s = st.packed st = Type.packed_struct([ti]*10) s = st.element_count s = list(st.elements) s = st.packed at = Type.array(ti, 100) s = at.element s = at.count pt = Type.pointer(ti, 10) pt.address_space vt = Type.vector(ti, 100) s = vt.element s = vt.count Type.int(32) == Type.int(64) Type.int(32) != Type.int(64) Type.int(32) != Type.float() ### Removed #def do_typehandle(): # print(" Testing class TypeHandle") # th = TypeHandle.new(Type.opaque()) # ts = Type.struct([ Type.int(), Type.pointer(th.type) ]) # th.type.refine(ts) def do_value(): print(" Testing class Value") k = Constant.int(ti, 42) k.name = 'a' s = k.name t = k.type s = str(k) s = k == Constant.int(ti, 43) i = k.value_id i = k.use_count i = k.uses def do_user(): m = Module.new('a') ft = Type.function(ti, [ti]*2) f = Function.new(m, ft, 'func') b = f.append_basic_block('a') bb = Builder.new(b) i1 = bb.add(f.args[0], f.args[1]) i2 = bb.ret(i1) i1.operand_count == 2 i2.operand_count == 1 i1.operands[0] is f.args[0] i1.operands[1] is f.args[1] i2.operands[0] is i1 def do_constant(): print(" Testing class Constant") Constant.null(ti) Constant.all_ones(ti) Constant.undef(ti) Constant.int(ti, 10) Constant.int_signextend(ti, 10) Constant.real(Type.float(), "10.0") Constant.real(Type.float(), 3.14) Constant.string("test") Constant.stringz("test2") Constant.array(ti, [Constant.int(ti,42)]*10) Constant.struct([Constant.int(ti,42)]*10) Constant.packed_struct([Constant.int(ti,42)]*10) Constant.vector([Constant.int(ti,42)]*10) Constant.sizeof(ti) k = Constant.int(ti, 10) f = Constant.real(Type.float(), 3.1415) k.neg().not_().add(k).sub(k).mul(k).udiv(k).sdiv(k).urem(k) k.srem(k).and_(k).or_(k).xor(k).icmp(IPRED_ULT, k) f.fdiv(f).frem(f).fcmp(RPRED_ULT, f) f.fadd(f).fmul(f).fsub(f) vi = Constant.vector([Constant.int(ti,42)]*10) vf = Constant.vector([Constant.real(Type.float(), 3.14)]*10) k.shl(k).lshr(k).ashr(k) return # TODO gep k.trunc(Type.int(1)) k.sext(Type.int(64)) k.zext(Type.int(64)) Constant.real(Type.double(), 1.0).fptrunc(Type.float()) Constant.real(Type.float(), 1.0).fpext(Type.double()) k.uitofp(Type.float()) k.sitofp(Type.float()) f.fptoui(ti) f.fptosi(ti) p = Type.pointer(ti) # TODO ptrtoint k.inttoptr(p) f.bitcast(Type.int(32)) k.trunc(Type.int(1)).select(k, k) vi.extract_element( Constant.int(ti,0) ) vi.insert_element( k, k ) vi.shuffle_vector( vi, vi ) def do_global_value(): print(" Testing class GlobalValue") m = Module.new('a') gv = GlobalVariable.new(m, Type.int(), 'b') s = gv.is_declaration m = gv.module gv.linkage = LINKAGE_EXTERNAL s = gv.linkage gv.section = '.text' s = gv.section gv.visibility = VISIBILITY_HIDDEN s = gv.visibility gv.alignment = 8 s = gv.alignment def do_global_variable(): print(" Testing class GlobalVariable") m = Module.new('a') gv = GlobalVariable.new(m, Type.int(), 'b') gv = GlobalVariable.get(m, 'b') gv.delete() gv = GlobalVariable.new(m, Type.int(), 'c') gv.initializer = Constant.int( ti, 10 ) s = gv.initializer gv.global_constant = True s = gv.global_constant def do_argument(): print(" Testing class Argument") m = Module.new('a') tip = Type.pointer(ti) ft = Type.function(tip, [tip]) f = Function.new(m, ft, 'func') a = f.args[0] a.add_attribute(ATTR_ZEXT) a.remove_attribute(ATTR_ZEXT) a.alignment = 16 a1 = a.alignment def do_function(): print(" Testing class Function") ft = Type.function(ti, [ti]*20) zz = Function.new(Module.new('z'), ft, 'foobar') del zz Function.new(Module.new('zz'), ft, 'foobar') m = Module.new('a') f = Function.new(m, ft, 'func') f.delete() ft = Type.function(ti, [ti]*20) f = Function.new(m, ft, 'func2') has_nounwind = f.does_not_throw f.does_not_throw = True f2 = Function.intrinsic(m, INTR_COS, [ti]) g = f.intrinsic_id f.calling_convenion = CC_FASTCALL g = f.calling_convenion f.collector = 'a' c = f.collector a = list(f.args) g = f.basic_block_count # g = f.entry_basic_block # g = f.append_basic_block('a') # g = f.entry_basic_block g = list(f.basic_blocks) f.add_attribute(ATTR_NO_RETURN) f.add_attribute(ATTR_ALWAYS_INLINE) f.remove_attribute(ATTR_NO_RETURN) # LLVM misbehaves: #try: # f.verify() #except LLVMException: # pass def do_instruction(): print(" Testing class Instruction") m = Module.new('a') ft = Type.function(ti, [ti]*20) f = Function.new(m, ft, 'func') b = f.append_basic_block('a') bb = Builder.new(b) i = bb.ret_void() bb2 = i.basic_block ops = i.operands opcount = i.operand_count def do_callorinvokeinstruction(): print(" Testing class CallOrInvokeInstruction") m = Module.new('a') ft = Type.function(ti, [ti]) f = Function.new(m, ft, 'func') b = f.append_basic_block('a') bb = Builder.new(b) i = bb.invoke(f, [Constant.int(ti, 10)], b, b) a = i.calling_convention i.calling_convention = CC_FASTCALL i.add_parameter_attribute(0, ATTR_SEXT) i.remove_parameter_attribute(0, ATTR_SEXT) i.set_parameter_alignment(0, 8) #tc = i.tail_call #i.tail_call = 1 def do_phinode(): print(" Testing class PhiNode") m = Module.new('a') ft = Type.function(ti, [ti]) f = Function.new(m, ft, 'func') b = f.append_basic_block('b') c = f.append_basic_block('c') d = f.append_basic_block('d') bb = Builder.new(d) p = bb.phi(ti) v = p.incoming_count p.add_incoming( Constant.int(ti, 10), b ) p.add_incoming( Constant.int(ti, 10), c ) p.get_incoming_value(0) p.get_incoming_block(0) def do_switchinstruction(): print(" Testing class SwitchInstruction") m = Module.new('a') ft = Type.function(ti, [ti]) f = Function.new(m, ft, 'func') b = f.append_basic_block('b') bb = Builder.new(b) s = bb.switch(f.args[0], b) s.add_case(Constant.int(ti, 10), b) def do_basicblock(): print(" Testing class BasicBlock") m = Module.new('a') ft = Type.function(ti, [ti]) f = Function.new(m, ft, 'func') b = f.append_basic_block('b') bb = Builder.new(b) s = bb.switch(f.args[0], b) s.add_case(Constant.int(ti, 10), b) s = list(b.instructions) b2 = b.insert_before('before') b2.delete() ff = b.function m2 = ff.module t = m == m2 def _do_builder_mrv(): m = Module.new('mrv') ft = Type.function(Type.array(ti, 2), [ti]) f = Function.new(m, ft, 'divrem') blk = f.append_basic_block('b') b = Builder.new(blk) v = b.call(f, [Constant.int(ti, 1)]) v1 = b.extract_value(v, 0) v2 = b.extract_value(v, 1) b.ret_many([v1, v2]) #print f def do_builder(): print(" Testing class Builder") m = Module.new('a') ft = Type.function(ti, [ti]) f = Function.new(m, ft, 'func') blk = f.append_basic_block('b') b = Builder.new(blk) b.ret(Constant.int(ti, 10)) b.position_at_beginning(blk) b.position_at_end(blk) b.position_before(blk.instructions[0]) blk2 = b.basic_block b.ret_void() b.ret(Constant.int(ti, 10)) _do_builder_mrv() #b.ret_many([Constant.int(ti, 10)]*10) b.branch(blk) b.cbranch(Constant.int(Type.int(1), 1), blk, blk) b.switch(f.args[0], blk) b.invoke(f, [Constant.int(ti,10)], blk, blk) # b.unwind() # removed b.unreachable() v = f.args[0] fv = Constant.real(Type.float(), "1.0") k = Constant.int(ti, 10) b.add(v, v) b.fadd(fv, fv) b.sub(v, v) b.fsub(fv, fv) b.mul(v, v) b.fmul(fv, fv) b.udiv(v, v) b.sdiv(v, v) b.fdiv(fv, fv) b.urem(v, v) b.srem(v, v) b.frem(fv, fv) b.shl(v, k) b.lshr(v, k) b.ashr(v, k) b.and_(v, v) b.or_(v, v) b.xor(v, v) b.neg(v) b.not_(v) p = b.malloc(Type.int()) b.malloc_array(Type.int(), k) b.alloca(Type.int()) b.alloca_array(Type.int(), k) b.free(p) b.load(p) b.store(k, p) # TODO gep b.trunc(v, Type.int(1)) b.zext(v, Type.int(64)) b.sext(v, Type.int(64)) b.fptoui(fv, ti) b.fptosi(fv, ti) b.uitofp(k, Type.float()) b.sitofp(k, Type.float()) b.fptrunc(Constant.real(Type.double(), "1.0"), Type.float()) b.fpext(Constant.real(Type.float(), "1.0"), Type.double()) b.ptrtoint(p, ti) b.inttoptr(k, Type.pointer(Type.int())) b.bitcast(v, Type.float()) b.icmp(IPRED_ULT, v, v) b.fcmp(RPRED_ULT, fv, fv) vi = Constant.vector([Constant.int(ti,42)]*10) vi_mask = Constant.vector([Constant.int(ti, X) for X in range(20)]) vf = Constant.vector([Constant.real(Type.float(), 3.14)]*10) # TODO b.extract_value(v, 0) b.call(f, [v]) b.select(Constant.int(Type.int(1), 1), blk, blk) b.vaarg(v, Type.int()) b.extract_element(vi, v) b.insert_element(vi, v, v) b.shuffle_vector(vi, vi, vi_mask) # NOTE: phi nodes without incoming values segfaults in LLVM during # destruction. i = b.phi(Type.int()) i.add_incoming(v, blk) t = i.is_terminator == False t = i.is_binary_op == False t = i.is_shift == False t = i.is_cast == False t = i.is_logical_shift == False t = i.is_arithmetic_shift == False t = i.is_associative == False t = i.is_commutative == False t = i.is_volatile == False t = i.opcode t = i.opcode_name def do_llvm_core(): print(" Testing module llvm.core") do_module() do_type() # do_typehandle() do_value() do_user() do_constant() do_global_value() do_global_variable() do_argument() do_function() do_instruction() do_callorinvokeinstruction() do_phinode() do_switchinstruction() do_basicblock() do_builder() def do_targetdata(): print(" Testing class TargetData") t = TargetData.new('') v = str(t) v = t.byte_order v = t.pointer_size v = t.target_integer_type ty = Type.int() v = t.size(ty) v = t.store_size(ty) v = t.abi_size(ty) v = t.abi_alignment(ty) v = t.callframe_alignment(ty) v = t.preferred_alignment(ty) sty = Type.struct([ty, ty]) v = t.element_at_offset(sty, 0) v = t.offset_of_element(sty, 0) m = Module.new('a') gv = m.add_global_variable(ty, 'gv') v = t.preferred_alignment(gv) def do_genericvalue(): print(" Testing class GenericValue") v = GenericValue.int(ti, 1) v = GenericValue.int_signed(ti, 1) v = GenericValue.real(Type.float(), 3.14) a = v.as_int() a = v.as_int_signed() a = v.as_real(Type.float()) def do_executionengine(): print(" Testing class ExecutionEngine") m = Module.new('a') ee = ExecutionEngine.new(m, False) # True) ft = Type.function(ti, []) f = m.add_function(ft, 'func') bb = f.append_basic_block('entry') b = Builder.new(bb) b.ret(Constant.int(ti, 42)) ee.run_static_ctors() gv = ee.run_function(f, []) is42 = gv.as_int() == 42 ee.run_static_dtors() ee.free_machine_code_for(f) t = ee.target_data m2 = Module.new('b') ee.add_module(m2) m3 = Module.new('c') ee2 = ExecutionEngine.new(m3, False) m4 = Module.new('d') m5 = Module.new('e') ee3 = ExecutionEngine.new(m4, False) ee3.add_module(m5) x = ee3.remove_module(m5) isinstance(x, Module) def do_llvm_ee(): print(" Testing module llvm.ee") do_targetdata() do_genericvalue() do_executionengine() def do_passmanager(): print(" Testing class PassManager") pm = PassManager.new() pm.add(TargetData.new('')) print('.........Begging for rewrite!!!') ### It is not practical to maintain all PASS_* constants. # # passes = ('PASS_OPTIMAL_EDGE_PROFILER', 'PASS_EDGE_PROFILER', # 'PASS_PROFILE_LOADER', 'PASS_AAEVAL') # all_these = [getattr(llvm.passes, x) # for x in dir(llvm.passes) # if x.startswith('PASS_') and x not in passes] # for i in all_these: # print i # pm.add(i) pm.run(Module.new('a')) def do_functionpassmanager(): print(" Testing class FunctionPassManager") m = Module.new('a') ft = Type.function(ti, []) f = m.add_function(ft, 'func') bb = f.append_basic_block('entry') b = Builder.new(bb) b.ret(Constant.int(ti, 42)) fpm = FunctionPassManager.new(m) fpm.add(TargetData.new('')) fpm.add(PASS_ADCE) fpm.initialize() fpm.run(f) fpm.finalize() def do_llvm_passes(): print(" Testing module llvm.passes") do_passmanager() do_functionpassmanager() def main(): print("Testing package llvm") do_llvm() do_llvm_core() do_llvm_ee() do_llvm_passes() if __name__ == '__main__': main() # to add: # IntegerType # FunctionType # StructType # ArrayType # PointerType # VectorType # ConstantExpr # ConstantAggregateZero # ConstantInt # ConstantFP # ConstantArray # ConstantStruct # ConstantVector # ConstantPointerNull # MemoryBuffer