Extract both fixed and variable arguments from the current Function in LLVM Pass

66 Views Asked by At

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.

0

There are 0 best solutions below