Hello, everyone! 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: namespace { class call_print : public FunctionPass{ private: DenseMap<const Value*, int> inst_map; public: static char ID; call_print() : FunctionPass(ID){} //define a extern function "printf" static llvm::Function* printf_prototype(llvm::LLVMContext& ctx, llvm::Module *mod) { std::vector<llvm::Type*> printf_arg_types; printf_arg_types.push_back(llvm::Type::getInt32Ty(ctx)); llvm::FunctionType* printf_type llvm::FunctionType::get(llvm::Type::getInt32Ty(ctx), printf_arg_types, true); llvm::Function *func = llvm::Function::Create(printf_type, llvm::Function::ExternalLinkage, llvm::Twine("printf"),mod); func->setCallingConv(llvm::CallingConv::C); return func; } //get a printf function Function* Get_print() { llvm::LLVMContext& ctx = llvm::getGlobalContext(); Module* mod = new Module("test",ctx); // Constant* c = mod->getOrInsertFunction("printf"); Function *printf_func = printf_prototype(ctx, mod); printf_func->setCallingConv(CallingConv::C); return printf_func; } virtual bool runOnFunction(Function &F) { int id = 0; // get a Function Function *call_print = Get_print(); for(inst_iterator i = inst_begin(F),e = inst_end(F);i != e; i++,id++) { errs()<<"@"<<id<<": "<<*i<<"\n"; std::vector<llvm::Value*> paramArrayRef; Value *a = ConstantInt::get(Type::getInt32Ty(getGlobalContext()),1); paramArrayRef.push_back(a); // get an instruction pointer Instruction* ins_temp = &*i; //create a call instruction and insert it before every instruction CallInst *call_print CallInst::Create(call_print,paramArrayRef,"",ins_temp); DEBUG(errs()<<"insert an instruction:"<<*call_print<<"\n"); } return true; } }; char call_print::ID = 1; // register the printCode class: // - give it a command-line argument (printCode) // - a name ("print code") // - a flag saying that we don't modify the CFG // - a flag saying this is not an analysis pass RegisterPass<call_print> X("call_print", "call print func", false, false); } I successfully compile it .but when I use the call_print.so to transform the test .bc file like this: opt -load /home/king/llvm/Release+Asserts/lib/call_print.so -call_print <test_sum.bc> test_sum.call.bc -debug It failed with such information: /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. Can anyone tell me what the problem is ? And whether I wrote the pass right ? Thank you! -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131216/0b1c364b/attachment.html>
Hi Jin, It's difficult to say just from looking at a pass, but one thing looked odd:> CallInst *call_print = CallInst::Create(call_print,paramArrayRef,"",ins_temp);This looks very dodgy. The "call_print" being used as an argument is the (uninitialised) one that's just been declared. This could be the source of the assertion failure (though a segfault is just as likely). Other than that I'd suggest hooking up a debugger and going up the call frames when that assertion hits. That should tell you exactly which line of your pass is causing trouble. Cheers. Tim.
As Tim said, call_print is one of the root causes. Another problem is that for a pass, you'd better use llvm::Module::getOrInsertFunction API. Best Regards, Hongxu Chen On Mon, Dec 16, 2013 at 11:22 PM, Tim Northover-2 [via LLVM] < ml-node+s1065342n64417h18 at n5.nabble.com> wrote:> Hi Jin, > > It's difficult to say just from looking at a pass, but one thing looked > odd: > > > CallInst *call_print > CallInst::Create(call_print,paramArrayRef,"",ins_temp); > > This looks very dodgy. The "call_print" being used as an argument is > the (uninitialised) one that's just been declared. This could be the > source of the assertion failure (though a segfault is just as likely). > > Other than that I'd suggest hooking up a debugger and going up the > call frames when that assertion hits. That should tell you exactly > which line of your pass is causing trouble. > > Cheers. > > Tim. > _______________________________________________ > LLVM Developers mailing list > [hidden email] <http://user/SendEmail.jtp?type=node&node=64417&i=0> > http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > ------------------------------ > If you reply to this email, your message will be added to the discussion > below: > > http://llvm.1065342.n5.nabble.com/Add-call-printf-instructions-problems-tp64415p64417.html > To start a new topic under LLVM - Dev, email > ml-node+s1065342n3h84 at n5.nabble.com > To unsubscribe from LLVM, click here<http://llvm.1065342.n5.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=2&code=bGVmdGNvcHkuY2h4QGdtYWlsLmNvbXwyfC0xMjc2Njc5OTI2> > . > NAML<http://llvm.1065342.n5.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml> >-- View this message in context: http://llvm.1065342.n5.nabble.com/Add-call-printf-instructions-problems-tp64415p64418.html Sent from the LLVM - Dev mailing list archive at Nabble.com. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131216/3d6e45a4/attachment.html>
Thanks,Cheers! I found the problem is that the "Function *call_print" using the same name as the “class call_print”, which made the compiler wrongly resolved the call_print type! But I got another problems. I successfully compile the pass and I can insert the call printf (C Lib function) instructions in the LLVM IR(eg: call.bc). If the call.bc didn't contain call printf instruction ,I can call printf successfully ,but if not ,there exists a problem. the llvm will rename my inserted call function , and the transformed code can not run correctly! the original .bc file: ; ModuleID = 'call.bc' target datalayout "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 ; Function Attrs: nounwind uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 %a = alloca i32, align 4 store i32 0, i32* %retval store i32 3, i32* %a, align 4 %0 = load i32* %a, align 4 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %0) %1 = load i32* %a, align 4 ret i32 %1 } //contains call printf declare i32 @printf(i8*, ...) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } here is the .bc file that I get after the transform: ; ModuleID = 'call.opt.bc' target datalayout "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 @.str2 = private constant [4 x i8] c"%d\0A\00" ; Function Attrs: nounwind uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 %a = alloca i32, align 4 store i32 0, i32* %retval // this is the instruction that I inserted ,which calls a C Lib "printf" %0 = call i32 (i8*, ...)* @printf1(i8* getelementptr inbounds ([4 x i8]* @.str2, i32 0, i32 0), i32 2) store i32 3, i32* %a, align 4 %1 = load i32* %a, align 4 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %1) %2 = load i32* %a, align 4 ret i32 %2 } declare i32 @printf(i8*, ...) #1 // if the program didn't contain call printf instruction ,this declaration should be as the one above,but now it was renamed and can not be resolved declare i32 @printf1(i8*, ...) attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } Is there any method to avoid the rename manipulation ? Thanks! 2013/12/16 Tim Northover <t.p.northover at gmail.com>> Hi Jin, > > It's difficult to say just from looking at a pass, but one thing looked > odd: > > > CallInst *call_print > CallInst::Create(call_print,paramArrayRef,"",ins_temp); > > This looks very dodgy. The "call_print" being used as an argument is > the (uninitialised) one that's just been declared. This could be the > source of the assertion failure (though a segfault is just as likely). > > Other than that I'd suggest hooking up a debugger and going up the > call frames when that assertion hits. That should tell you exactly > which line of your pass is causing trouble. > > Cheers. > > Tim. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131217/321ff37e/attachment.html>