Clone a function and change signature

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.

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;jgetNumOperands();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 ; [#uses=1]
br i1 %tmp1, label %return, label %bb, !dbg !1018

bb: ; preds = %entry
%tmp2 = load i16* %x, align 2, !dbg !1023 ; [#uses=1]
%tmp3 = sext i16 %tmp2 to i32, !dbg !1023 ; [#uses=1]
store i32 %tmp3, i32* %xx, align 4, !dbg !1023
%tmp4 = load i16* %y, align 2, !dbg !1024 ; [#uses=1]
%tmp5 = sext i16 %tmp4 to i32, !dbg !1024 ; [#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 ; [#uses=1]
%tmp9 = trunc i32 %tmp8 to i16, !dbg !1026 ; [#uses=1]
store i16 %tmp9, i16* %x, align 2, !dbg !1026
%tmp10 = load i32* %yy, align 4, !dbg !1027 ; [#uses=1]
%tmp11 = trunc i32 %tmp10 to i16, !dbg !1027 ; [#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 ; [#uses=1]
br i1 %tmp1, label %return, label %bb, !dbg !1018

bb: ; preds = %entry
%tmp2 = load i16* %x, align 2, !dbg !1023 ; [#uses=1]
%tmp3 = sext i16 %tmp2 to i32, !dbg !1023 ; [#uses=1]
store i32 %tmp3, i32* %xx, align 4, !dbg !1023
%tmp4 = load i16* %y, align 2, !dbg !1024 ; [#uses=1]
%tmp5 = sext i16 %tmp4 to i32, !dbg !1024 ; [#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 ; [#uses=1]
%tmp9 = trunc i32 %tmp8 to i16, !dbg !1026 ; [#uses=1]
store i16 %tmp9, i16* %x, align 2, !dbg !1026
%tmp10 = load i32* %yy, align 4, !dbg !1027 ; [#uses=1]
%tmp11 = trunc i32 %tmp10 to i16, !dbg !1027 ; [#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

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.

Right, you can also take a look at the dead argument elimination or argument promotion passes for examples.

-Chris

Thanks a lot. That worked.

Arushi