Let's say I want manually turn code below to IR code:
#include <stdio.h>
int main()
{
int (*p)(const char *__s); // how to implement this?
p = puts; // and this?
p("Hello World!\n");
}
I found that the IR representation of the function pointer is this:
%p = alloca i32 (i8*)*, align 8
store i32 (i8*)* @puts, i32 (i8*)** %p, align 8
but I don't know which api I should use to generate this.
here's part of my implementation:
#include "llvm/Support/raw_ostream.h"
int main() {
llvm::LLVMContext context;
llvm::IRBuilder<> builder(context);
llvm::Module *module = new llvm::Module("top", context);
llvm::FunctionType *functionType = llvm::FunctionType::get(builder.getInt32Ty(), false);
llvm::Function *mainFunction = llvm::Function::Create(functionType, llvm::Function::ExternalLinkage, "main", module);
llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "entrypoint", mainFunction);
builder.SetInsertPoint(entry);
llvm::Value *helloWorld = builder.CreateGlobalStringPtr("hello world\n");
std::vector<llvm::Type *> putArgs;
putArgs.push_back(builder.getInt8Ty()->getPointerTo());
llvm::ArrayRef<llvm::Type *> argsRef(putArgs);
llvm::FunctionType *putsType = llvm::FunctionType::get(builder.getInt32Ty(), argsRef, false);
llvm::Constant *putFunction = module->getOrInsertFunction("puts", putsType);
// code to implement function pointer
// code to assign puts() to function pointer
builder.CreateCall(putFunction, helloWorld); // call the function pointer instead of the function it self
builder.CreateRet(llvm::ConstantInt::get(builder.getInt32Ty(), 0));
module->print(llvm::errs(), nullptr);
}
I found that llvm::Function is a subclass of llvm::Value, so I guess the llvm::Constant *putFunction itself is the function pointer I'm looking for, but how to make this value represented in IR code? More specific, how to use the builder to generate the IR code?
@putsis already a function pointer. Theallocacode just copies that pointer onto the stack. Depending on what you're trying to do, you won't need that (for example, if you're trying to create a vtable, like in your other question, you can just use@putsdirectly in the global array - and by "directly" I mean "with a bitcast attached to it" because generally not every function in a vtable has the same type).