In LLVM11 Function Pass, I am trying to insert a self-call to the current function with variable arguments based on the condition.
//Original Function
#include <stdio.h>
double test_function(int num,...) {
va_list valist;
double sum = 0.0;
int i;
/* initialize valist for num number of arguments */
va_start(valist, num);
/* access all the arguments assigned to valist */
for (i = 0; i < num; i++) {
sum += va_arg(valist, int);
}
/* clean memory reserved for valist */
va_end(valist);
return sum/num;
}
int main() {
test_function(2, 10, 20);
return 0;
}
//Instrumented Function
double test_function(int num,...) {
va_list valist;
double sum = 0.0;
int i;
**if (condition) { // Insert this block of code using LLVM Pass.
test_function(2, 10, 20);
}**
/* initialize valist for num number of arguments */
va_start(valist, num);
/* access all the arguments assigned to valist */
for (i = 0; i < num; i++) {
sum += va_arg(valist, int);
}
/* clean memory reserved for valist */
va_end(valist);
return sum/num;
}
I could understand that we can use va_arg family of Intrinsics to extract the variable arguments values and then we can call CreateCall() with extracted argument values.
I tried the below code and could not manage to make it work on LLVM11. Can you please suggest me the solution?
std::vector<Value *> callArgs;
if (funcType->isVarArg()) {
// Create a va_list variable
AllocaInst *vaList = builder.CreateAlloca(builder.getInt8Ty()->getPointerTo(), nullptr, "va_list");
// Insert a call to llvm.va_start
builder.CreateCall(Intrinsic::getDeclaration(F.getParent(), Intrinsic::vastart), {vaList, callArgs.back()});
// Iterate over the remaining arguments using va_arg
for (unsigned i = funcType->getNumParams(); i < funcType->getNumParams() + 3; ++i) {
Value *arg = builder.CreateCall(Intrinsic::getDeclaration(F.getParent(), Intrinsic::va_arg), {vaList, builder.getInt8Ty()});
callArgs.push_back(arg);
}
// Insert a call to llvm.va_end
builder.CreateCall(Intrinsic::getDeclaration(F.getParent(), Intrinsic::vaend), vaList);
}
// Create a call instruction for the self-call
CallInst *selfCall = builder.CreateCall(F.getCallee(), callArgs);
Currently, I am seeing the below build error.
error: no member named 'va_arg' in namespace 'llvm::Intrinsic' 16 Value *arg = builder.CreateCall(Intrinsic::getDeclaration(F.getParent(), Intrinsic::va_arg), {vaList, builder.getInt8Ty()}); 17 ~~~~~~~~~~~^ 18 1 error generated.