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>