Допустим, я хочу вручную преобразовать приведенный ниже код в код ИК:
#include <stdio.h>
int main()
{
int (*p)(const char *__s); // how to implement this?
p = puts; // and this?
p("Hello World!\n");
}
Я обнаружил, что ИК-представление указателя функции выглядит следующим образом:
%p = alloca i32 (i8*)*, align 8
store i32 (i8*)* @puts, i32 (i8*)** %p, align 8
, но я нене знаю, какой API мне следует использовать для генерации этого.
вот часть моей реализации:
#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);
}
Я обнаружил, что llvm::Function
является подклассом llvm::Value
, поэтому я предполагаю, чтоllvm::Constant *putFunction
Сам по себе указатель функции, который я ищу, но как сделать это значение представленным в коде IR?Более конкретно, как использовать конструктор для генерации ИК кода?