[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