use llir::types::*;
use llir::values::*;
use llir::*;
use llvm_sys::core::*;
use std::path::Path;
fn test_global<'ctx>(glob: &Global<'ctx>) -> Result<(), String> {
let _ = glob.name();
let _ = glob.aliasee();
let _ = glob.is_alias();
Ok(())
}
fn test_pointer_type<'ctx>(p: &PointerType<'ctx>) -> Result<(), String> {
let _ = p.element_type();
Ok(())
}
fn test_function_type<'ctx>(t: &FunctionType<'ctx>) -> Result<(), String> {
let _ = t.num_argument_types();
let _ = t.argument_types();
let _ = t.return_type();
let _ = t.has_return_type();
Ok(())
}
fn test_type<'ctx>(t: &Type<'ctx>) -> Result<(), String> {
match t {
Type::Function(f) => {
test_function_type(f)?;
}
Type::Pointer(p) => {
test_pointer_type(p)?;
}
Type::Other(o) => println!("Unknown type kind {:?}", unsafe { LLVMGetTypeKind(o.type_ref()) }),
_ => {}
}
Ok(())
}
fn test_int_constant<'ctx>(i: &IntConstant<'ctx>) -> Result<(), String> {
let _ = i.zext_value();
Ok(())
}
fn test_const_expr<'ctx>(ce: &ConstExpr<'ctx>) -> Result<(), String> {
match ce {
ConstExpr::Other(o) => {
println!("Unknown const expr {:?}", unsafe { LLVMGetConstOpcode(o.value_ref()) });
}
_ => {}
}
Ok(())
}
fn test_constant<'ctx>(c: &Constant<'ctx>) -> Result<(), String> {
test_type(&c.get_type())?;
match c {
Constant::Int(i) => {
test_int_constant(i)?;
}
Constant::ConstExpr(ce) => {
test_const_expr(ce)?;
}
Constant::Other(o) => {
println!("Other constant {:?}", unsafe { LLVMGetValueKind(o.value_ref()) });
}
_ => {}
}
Ok(())
}
fn test_operand<'ctx>(op: &Operand<'ctx>) -> Result<(), String> {
test_type(&op.get_type())?;
use Operand::*;
match op {
Instruction(_) => {}
Argument(arg) => {
let _ = arg.parent();
let _ = arg.index();
}
Constant(c) => {
test_constant(c)?;
}
InlineAsm(_) => {
}
Metadata(_) => {}
}
Ok(())
}
fn test_instruction<'ctx>(instr: &Instruction<'ctx>) -> Result<(), String> {
use Instruction::*;
match instr {
Alloca(a) => {
test_pointer_type(&a.get_pointer_type())?;
}
Binary(b) => {
let _ = b.opcode();
test_operand(&b.op0())?;
test_operand(&b.op1())?;
}
Branch(b) => {
let _ = b.destinations();
match b {
BranchInstruction::Conditional(c) => {
test_operand(&c.condition())?;
let _ = c.then_block();
let _ = c.else_block();
}
BranchInstruction::Unconditional(u) => {
let _ = u.destination();
let _ = u.is_loop_jump();
}
}
}
Call(c) => {
let _ = c.callee_function();
let _ = c.callee_inline_asm();
test_operand(&c.callee())?;
test_function_type(&c.callee_function_type())?;
let _ = c.num_arguments();
let _ = c.arguments();
}
CallBr(_) => {}
ExtractValue(ev) => {
test_operand(&ev.aggregate())?;
let _ = ev.num_indices();
let _ = ev.indices();
}
FCmp(f) => {
let _ = f.predicate();
test_operand(&f.op0())?;
test_operand(&f.op1())?;
}
GetElementPtr(g) => {
test_operand(&g.location())?;
let _ = g.num_indices();
let _ = g.indices();
test_pointer_type(&g.get_pointer_type())?;
}
IndirectBranch(ib) => {
let _ = ib.address();
let _ = ib.destinations();
}
ICmp(i) => {
let _ = i.predicate();
test_operand(&i.op0())?;
test_operand(&i.op1())?;
}
InsertValue(iv) => {
test_operand(&iv.aggregate())?;
test_operand(&iv.value())?;
let _ = iv.num_indices();
let _ = iv.indices();
}
Load(l) => {
test_operand(&l.location())?;
}
Phi(p) => {
let _ = p.num_incomings();
for inc in p.incomings() {
test_operand(&inc.value)?;
}
}
Return(r) => {
if r.has_op() {
test_operand(&r.op().unwrap())?;
}
}
Select(s) => {
test_operand(&s.condition())?;
test_operand(&s.true_value())?;
test_operand(&s.false_value())?;
}
Store(s) => {
test_operand(&s.location())?;
test_operand(&s.value())?;
}
Switch(s) => {
test_operand(&s.condition())?;
let _ = s.default_destination();
let _ = s.num_cases();
for case in s.cases() {
test_int_constant(&case.case)?;
}
}
Unary(u) => {
let _ = u.opcode();
test_operand(&u.op0())?;
}
Unreachable(_) => {}
Other(o) => {
println!("Other instruction: {:?}", unsafe {
LLVMGetInstructionOpcode(o.value_ref())
});
}
}
Ok(())
}
fn test_block<'ctx>(blk: &Block<'ctx>) -> Result<(), String> {
let _ = blk.first_instruction();
let _ = blk.last_instruction();
for instr in blk.iter_instructions() {
test_instruction(&instr)?;
}
Ok(())
}
fn test_func<'ctx>(func: &Function<'ctx>) -> Result<(), String> {
let _ = func.name();
let _ = func.is_declaration_only();
let _ = func.first_block();
let _ = func.last_block();
let _ = func.is_var_arg();
let _ = func.num_arguments();
let _ = func.arguments();
for blk in func.iter_blocks() {
assert_eq!(blk.parent_function(), *func);
test_block(&blk)?;
}
Ok(())
}
fn test_module<'ctx>(module: &Module<'ctx>) -> Result<(), String> {
for glob in module.iter_globals() {
test_global(&glob)?;
}
for func in module.iter_functions() {
test_func(&func)?;
}
Ok(())
}
#[test]
fn test_kernel() -> Result<(), String> {
let kernel_path = Path::new("/home/aspire/programs/linux_kernel/linux-4.5-rc4/vmlinux.bc");
let ctx = Context::create();
let module = ctx.load_module(kernel_path)?;
test_module(&module)
}