My usual approach with these things is what Clang generates - both LLVM IR and C ++ API calls (C ++ backend). You can use the online copy for simplicity. So, compile this C code:
float foo(int a, float b) { return a + b; }
Gives me this LLVM IR:
define float @foo(i32 %a, float %b) #0 { entry: %conv = sitofp i32 %a to float %add = fadd float %conv, %b ret float %add }
And these are the C ++ API calls needed to recreate this:
// Function: foo (func_foo) { Function::arg_iterator args = func_foo->arg_begin(); Value* int32_a = args++; int32_a->setName("a"); Value* float_b = args++; float_b->setName("b"); BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry",func_foo,0); // Block entry (label_entry) CastInst* float_conv = new SIToFPInst(int32_a, Type::getFloatTy(mod->getContext()), "conv", label_entry); BinaryOperator* float_add = BinaryOperator::Create(Instruction::FAdd, float_conv, float_b, "add", label_entry); ReturnInst::Create(mod->getContext(), float_add, label_entry); }
You can configure the C input code (for example, replace vars with constants, etc.) and see what Clang / LLVM emits. This is the best / fastest way to find your way around the IR and API when you are not too familiar with it.
Eli bendersky
source share