How to get a function pointer (in order to get function address at runtime) in llvm

In C or C++, I can get the address of function func_1 at run time with the following code.

#include <stdio.h>
#include <string.h>
void func_1()
{
    printf("this is func_1\n");
}

int main()
{   
    printf("this is main\n");
    func_1();
    void *addr = (void*)func_1; // get the addr of func_1
    printf("func_1 addr = %p\n",addr);
    return 0;
}

When I convert this code to IR, I can see that the corresponding statement to get the address of the function is:

  store i8* bitcast (void ()* @func_1 to i8*), i8** %addr, align 8
  %2 = load i8*, i8** %addr, align 8
  %call1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.3, i64 0, i64 0), i8* %2)

Now, I want to use the LLVM compiler to use the pass optimization phase to add one such instruction for each function in the target program to get the function address. How do I achieve this? Maybe a storeInst and a loadInst, but how to set the parameters? In particular, void ()* @func_1 to i8*

Something like ConstantExpr::getBitCast(MyFunction, Type::getInt8PtrTy(Ctx)).

If you’re going to call printf on it, you don’t even need the load/store, it can be passed as a direct argument.

If not, you need to decide where you do want to store it.

2 Likes

Thanks. But there’s one more question. As for the parameter MyFunction, my current code is as follows, I am not sure how to convert it to the correct form.

for(auto &F:M)
{
Value* func_getbitcast = ConstantExpr::getBitCast(&F, Type::getInt8PtrTy(*Ctx));
}

I got the following error:

Invalid user of intrinsic instruction!
i8* bitcast (void (metadata, metadata, metadata)* @llvm.dbg.declare to i8*)
Invalid user of intrinsic instruction!
i8* bitcast (void (i64, i8*)* @llvm.lifetime.start.p0i8 to i8*)
Invalid user of intrinsic instruction!
i8* bitcast (void (metadata, metadata, metadata)* @llvm.dbg.value to i8*)
fatal error: error in backend: Broken module found, compilation aborted!
clang-12: error: clang frontend command failed with exit code 70 (use -v to see invocation)

Makes sense. Intrinsics aren’t real functions so they don’t have an address. You should use Function::isIntrinsic and skip them.

Thank you so much! I worked it out.