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?
I worked it out.
the missing puzzle is blow:
llvm::Value *p = builder.CreateAlloca(putFunction->getType(), nullptr, "p");
builder.CreateStore(putFunction, p, false);
llvm::Value *temp = builder.CreateLoad(p);
builder.CreateCall(temp, helloWorld);
the key concept is that putFunction->getType() and llvm::FunctionType::get() are different type, I take the llvm::FunctionType::get() as a function pointer by mistake.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With