<div dir="ltr">Hello, everyone!<div> I want to write a pass which can insert a call "printf" instructions before every instruction in the LLVM IR. here is what I wrote:</div><div><br></div><div><div>namespace {</div>
<div><span class="" style="white-space:pre"> </span>class call_print : public FunctionPass{</div><div><br></div><div><span class="" style="white-space:pre"> </span>private:</div><div><span class="" style="white-space:pre"> </span>DenseMap<const Value*, int> inst_map;</div>
<div><br></div><div><span class="" style="white-space:pre"> </span>public:</div><div><span class="" style="white-space:pre"> </span>static char ID;</div><div><span class="" style="white-space:pre"> </span>call_print() : FunctionPass(ID){}</div>
<div><span class="" style="white-space:pre"> </span></div><div><span class="" style="white-space:pre"> </span>//define a extern function "printf"</div><div><span class="" style="white-space:pre"> </span>static llvm::Function*<span class="" style="white-space:pre"> </span></div>
<div><span class="" style="white-space:pre"> </span>printf_prototype(llvm::LLVMContext& ctx, llvm::Module *mod)</div><div><span class="" style="white-space:pre"> </span>{</div><div> <span class="" style="white-space:pre"> </span>std::vector<llvm::Type*> printf_arg_types;</div>
<div> <span class="" style="white-space:pre"> </span>printf_arg_types.push_back(llvm::Type::getInt32Ty(ctx));</div><div><br></div><div> <span class="" style="white-space:pre"> </span>llvm::FunctionType* printf_type =</div>
<div> <span class="" style="white-space:pre"> </span>llvm::FunctionType::get(llvm::Type::getInt32Ty(ctx), printf_arg_types, true);</div><div><br></div><div> <span class="" style="white-space:pre"> </span>llvm::Function *func = llvm::Function::Create(printf_type, llvm::Function::ExternalLinkage,</div>
<div> llvm::Twine("printf"),mod);</div><div> <span class="" style="white-space:pre"> </span>func->setCallingConv(llvm::CallingConv::C);</div><div> <span class="" style="white-space:pre"> </span> return func;</div>
<div><span class="" style="white-space:pre"> </span>}</div><div><span class="" style="white-space:pre"> </span></div><div><span class="" style="white-space:pre"> </span>//get a printf function</div><div><span class="" style="white-space:pre"> </span>Function* Get_print()</div>
<div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>llvm::LLVMContext& ctx = llvm::getGlobalContext();</div><div><span class="" style="white-space:pre"> </span>Module* mod = new Module("test",ctx);</div>
<div><span class="" style="white-space:pre"> </span>//<span class="" style="white-space:pre"> </span>Constant* c = mod->getOrInsertFunction("printf");</div><div><span class="" style="white-space:pre"> </span>Function *printf_func = printf_prototype(ctx, mod);<span class="" style="white-space:pre"> </span></div>
<div><span class="" style="white-space:pre"> </span>printf_func->setCallingConv(CallingConv::C);</div><div><span class="" style="white-space:pre"> </span>return printf_func;</div><div><span class="" style="white-space:pre"> </span>}</div>
<div><br></div><div><span class="" style="white-space:pre"> </span>virtual bool runOnFunction(Function &F)</div><div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>int id = 0;</div>
<div><span class="" style="white-space:pre"> </span>// get a Function</div><div><span class="" style="white-space:pre"> </span>Function *call_print = Get_print();</div><div><span class="" style="white-space:pre"> </span>for(inst_iterator i = inst_begin(F),e = inst_end(F);i != e; i++,id++)</div>
<div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>errs()<<"@"<<id<<": "<<*i<<"\n";</div><div><span class="" style="white-space:pre"> </span>std::vector<llvm::Value*> paramArrayRef;</div>
<div><span class="" style="white-space:pre"> </span>Value *a = ConstantInt::get(Type::getInt32Ty(getGlobalContext()),1);</div><div><span class="" style="white-space:pre"> </span>paramArrayRef.push_back(a);</div><div>
<span class="" style="white-space:pre"> </span>// get an instruction pointer</div><div><span class="" style="white-space:pre"> </span>Instruction* ins_temp = &*i; </div><div><span class="" style="white-space:pre"> </span>//create a call instruction and insert it before every instruction</div>
<div><span class="" style="white-space:pre"> </span>CallInst *call_print = CallInst::Create(call_print,paramArrayRef,"",ins_temp);</div><div><span class="" style="white-space:pre"> </span></div><div><span class="" style="white-space:pre"> </span>DEBUG(errs()<<"insert an instruction:"<<*call_print<<"\n");</div>
<div><br></div><div><span class="" style="white-space:pre"> </span>}</div><div><span class="" style="white-space:pre"> </span></div><div><br></div><div><span class="" style="white-space:pre"> </span>return true;</div>
<div><span class="" style="white-space:pre"> </span>}</div><div><span class="" style="white-space:pre"> </span>};</div><div><span class="" style="white-space:pre"> </span></div><div><span class="" style="white-space:pre"> </span>char call_print::ID = 1;</div>
<div><span class="" style="white-space:pre"> </span>// register the printCode class: </div><div> // - give it a command-line argument (printCode)</div><div> // - a name ("print code")</div><div> // - a flag saying that we don't modify the CFG</div>
<div> // - a flag saying this is not an analysis pass</div><div> RegisterPass<call_print> X("call_print", "call print func",</div><div><span class="" style="white-space:pre"> </span> false, false);</div>
<div><br></div><div>}</div></div><div><br></div><div>I successfully compile it .but when I use the call_print.so to transform the test .bc file like this:</div><div><br></div><div>opt -load /home/king/llvm/Release+Asserts/lib/call_print.so -call_print <test_sum.bc> test_sum.call.bc -debug<br>
</div><div><br></div><div>It failed with such information:</div><div><br></div><div><div> /home/king/llvm/include/llvm/Support/Casting.h:237: typename enable_if<is_same<Y, typename simplify_type<Y>::SimpleType>, typename cast_retty<X, Y *>::ret_type>::type llvm::cast(Y *) [X = llvm::PointerType, Y = llvm::Type]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.</div>
</div><div><br></div><div>Can anyone tell me what the problem is ? And whether I wrote the pass right ?</div><div>Thank you!</div><div><br></div><div><br></div></div>