[LLVMdev] Clone a function and change signature
John Criswell
criswell at illinois.edu
Tue Feb 22 11:46:45 PST 2011
On 2/22/11 1:31 PM, Arushi Aggarwal wrote:
> Hi,
>
> I want to clone a given function, and add an argument to it. I then
> want to add a call to that new function. I have a callInstruction CI,
> which I want to transform to call this new function, and to take a new
> argument.
If I understand correctly, you're cloning the function first and then
adding a new argument to the clone. Do I understand correctly?
If so, I don't believe you can do that. IIRC, you have to first create
a new, empty function with the additional argument and then use
CloneFunctionInto() to clone the body of the original function into the
new function. I believe that's what poolalloc does and what I did the
last time I had to add function arguments to a function.
-- John T.
>
> The code I added was as follows
>
> CI->getCalledFunction()->dump();
> Function* DirectF = CloneFunction(CI->getCalledFunction());
> DirectF->setName(CI->getCalledFunction()->getNameStr() + "_SPEC");
> DirectF->setLinkage(GlobalValue::InternalLinkage);
> // add the extra argument
> new Argument(GEP->getPointerOperand()->getType(),"arg",DirectF);
> M.getFunctionList().push_back(DirectF);
> DirectF->dump();
>
> SmallVector<Value*, 8> Args;
> for(unsigned j =1;j<CI->getNumOperands();j++) {
> Args.push_back(CI->getOperand(j));
> }
> //Add the extra parameter
> Args.push_back(GEP->getPointerOperand());
> CallInst *CallI = CallInst::Create(DirectF,Args.begin(),
> Args.end(),"", CI);
> CallI->dump();
>
>
> But I get the following exception
>
> call void @point_DIRECT(i16* %tmp1324mod, i16* %tmp1322mod) nounwind
>
> define internal void @point_DIRECT(i16* %x, i16* %y) nounwind {
> entry:
> %xx = alloca i32 ; <i32*> [#uses=3]
> %yy = alloca i32 ; <i32*> [#uses=3]
> %tmp = load %struct.MT** @mt, align 8, !dbg !1018 ; <%struct.MT*>
> [#uses=1]
> %tmp1 = icmp eq %struct.MT* %tmp, null, !dbg !1018 ; <i1> [#uses=1]
> br i1 %tmp1, label %return, label %bb, !dbg !1018
>
> bb: ; preds = %entry
> %tmp2 = load i16* %x, align 2, !dbg !1023 ; <i16> [#uses=1]
> %tmp3 = sext i16 %tmp2 to i32, !dbg !1023 ; <i32> [#uses=1]
> store i32 %tmp3, i32* %xx, align 4, !dbg !1023
> %tmp4 = load i16* %y, align 2, !dbg !1024 ; <i16> [#uses=1]
> %tmp5 = sext i16 %tmp4 to i32, !dbg !1024 ; <i32> [#uses=1]
> store i32 %tmp5, i32* %yy, align 4, !dbg !1024
> %tmp6 = load %struct.MT** @mt, align 8, !dbg !1025 ; <%struct.MT*>
> [#uses=1]
> call void @MTPoint_DIRECT(%struct.MT* %tmp6, i32* %xx, i32* %yy)
> nounwind
> %tmp8 = load i32* %xx, align 4, !dbg !1026 ; <i32> [#uses=1]
> %tmp9 = trunc i32 %tmp8 to i16, !dbg !1026 ; <i16> [#uses=1]
> store i16 %tmp9, i16* %x, align 2, !dbg !1026
> %tmp10 = load i32* %yy, align 4, !dbg !1027 ; <i32> [#uses=1]
> %tmp11 = trunc i32 %tmp10 to i16, !dbg !1027 ; <i16> [#uses=1]
> store i16 %tmp11, i16* %y, align 2, !dbg !1027
> ret void
>
> return: ; preds = %entry
> ret void
> }
>
>
> define internal void @point_DIRECT_SPEC(i16* %x, i16* %y,
> %struct.termbox* %arg) nounwind {
> entry:
> %xx = alloca i32 ; <i32*> [#uses=3]
> %yy = alloca i32 ; <i32*> [#uses=3]
> %tmp = load %struct.MT** @mt, align 8, !dbg !1018 ; <%struct.MT*>
> [#uses=1]
> %tmp1 = icmp eq %struct.MT* %tmp, null, !dbg !1018 ; <i1> [#uses=1]
> br i1 %tmp1, label %return, label %bb, !dbg !1018
>
> bb: ; preds = %entry
> %tmp2 = load i16* %x, align 2, !dbg !1023 ; <i16> [#uses=1]
> %tmp3 = sext i16 %tmp2 to i32, !dbg !1023 ; <i32> [#uses=1]
> store i32 %tmp3, i32* %xx, align 4, !dbg !1023
> %tmp4 = load i16* %y, align 2, !dbg !1024 ; <i16> [#uses=1]
> %tmp5 = sext i16 %tmp4 to i32, !dbg !1024 ; <i32> [#uses=1]
> store i32 %tmp5, i32* %yy, align 4, !dbg !1024
> %tmp6 = load %struct.MT** @mt, align 8, !dbg !1025 ; <%struct.MT*>
> [#uses=1]
> call void @MTPoint_DIRECT(%struct.MT* %tmp6, i32* %xx, i32* %yy)
> nounwind
> %tmp8 = load i32* %xx, align 4, !dbg !1026 ; <i32> [#uses=1]
> %tmp9 = trunc i32 %tmp8 to i16, !dbg !1026 ; <i16> [#uses=1]
> store i16 %tmp9, i16* %x, align 2, !dbg !1026
> %tmp10 = load i32* %yy, align 4, !dbg !1027 ; <i32> [#uses=1]
> %tmp11 = trunc i32 %tmp10 to i16, !dbg !1027 ; <i16> [#uses=1]
> store i16 %tmp11, i16* %y, align 2, !dbg !1027
> ret void
>
> return: ; preds = %entry
> ret void
> }
>
> opt:
> /home/vadve/aggarwa4/llvm27/llvm-2.7/lib/VMCore/Instructions.cpp:307:
> void llvm::CallInst::init(llvm::Value*, llvm::Value* const*, unsigned
> int): Assertion `(NumParams == FTy->getNumParams() || (FTy->isVarArg()
> && NumParams > FTy->getNumParams())) && "Calling a function with bad
> signature!"' failed.
>
>
> When I looked at the excption, it occurs when creating the CallInst.
>
> The type of the function being called at that point is still the old
> type, without the extra parameter, though the extra parameter seems to
> have been added when I dump DirectF.
>
> Can I get any pointers to what I am doing wrong, and what might be a
> potential solution.
>
> Thanks,
> Arushi
More information about the llvm-dev
mailing list