如何通过模块构建器系统在LLVM中调用@printf

时间:2015-05-14 09:40:55

标签: llvm llvm-ir

我正在学习LLVM。据我所知,在LLVM中提供的许多有用的C函数已经作为内在函数。所以我试图从我的代码中调用@printf函数。

我在LLVM参考手册中找到了描述IR代码的相应部分,这是相对清楚的:

declare i32 @printf(i8* noalias nocapture, ...)
call i32 (i8*, ...)* @printf(i8* %msg, i32 12, i8 42)

等。但我无法使用IRBuilder<>找到如何做到这一点。类。我检查了建筑师课程,但我无法解决任何问题。

我不想传递任何花哨的变量,基本上就像

printf( "%lu", variable_64_bit );
在C或类似的东西中

任何人都可以告诉我通过构建器调用printf函数必须做些什么。

提前致谢

2 个答案:

答案 0 :(得分:3)

我在其他地方找到了answer to this problem。事实上它有点超出我原来的问题,但它对我有帮助,并希望它也能帮助其他人。

答案 1 :(得分:3)

void kprintf(Module *mod, BasicBlock *bb, const char *format, ...)
{
    Function *func_printf = mod->getFunction("printf");
    if (!func_printf) {
        PointerType *Pty = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
        FunctionType *FuncTy9 = FunctionType::get(IntegerType::get(mod->getContext(), 32), true);

        func_printf = Function::Create(FuncTy9, GlobalValue::ExternalLinkage, "printf", mod);
        func_printf->setCallingConv(CallingConv::C);

        AttrListPtr func_printf_PAL;
        func_printf->setAttributes(func_printf_PAL);
    }

    IRBuilder <> builder(mod->getContext());
    builder.SetInsertPoint(bb);

    Value *str = builder.CreateGlobalStringPtr(format);
    std::vector <Value *> int32_call_params;
    int32_call_params.push_back(str);

    va_list ap;
    va_start(ap, format);

    char *str_ptr = va_arg(ap, char*);
    Value *format_ptr = builder.CreateGlobalStringPtr(str_ptr);
    int32_call_params.push_back(format_ptr);

    std::vector<llvm::Value*> extra;
    do {
        llvm::Value *op = va_arg(ap, llvm::Value*);
        if (op) {
            int32_call_params.push_back(op);
        } else {
            break;
        }
    } while (1);
    va_end(ap);

    CallInst * int32_call = CallInst::Create(func_printf, int32_call_params, "call", bb);
}
#define oprintf(...) kprintf(__VA_ARGS__)
#define llvm_printf(...) oprintf(mod, bb, __VA_ARGS__, NULL)

llvm_printf("Output: 0x%08X %f %d\n", 0x12345678, 3.1415926, 12345);

希望对你有所帮助