Rick
Rick

Reputation: 730

How To Call @printf in LLVM through the module builder system

I am learning LLVM. I understand that thre are a number of useful C functions that are provided in LLVM already as intrinsic. So I'm trying to call the @printf function from my code.

I found the respective parts in the LLVM reference manual that describe the IR code to do that, which is relative clear:

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

etc. But I am not able to find how to do that using the IRBuilder<> class. I checked the builder class but I wasn't able to figure anything out.

I don't want to pass any fancy variables, basically just something like

printf( "%lu", variable_64_bit );

in C or something like that.

Could anybody give me an idea what I must do to call the printf function through the builder.

Thanks in advance

Upvotes: 13

Views: 11597

Answers (2)

Silent_DXX
Silent_DXX

Reputation: 41

    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);

Hope to be of help to you

Upvotes: 4

Rick
Rick

Reputation: 730

I found an answer to this problem elsewhere. In fact it goes somewhat beyond my original question but it was helpful for me and hopefully it will help somebody else as well.

Upvotes: 9

Related Questions