ZeDragon
ZeDragon

Reputation: 85

How to print floats from LLVM IR?

I have a problem using the printf() function from within LLVM IR. I just want to print the value of a float but I just get 0.000000. It works fine for integers and strings but not floats.

Simple example:

@.fstr = private unnamed_addr constant [4 x i8] c"%f\0A\00"

declare i32 @printf(i8*, ...)

define i32 @main() {
    %1 = getelementptr [4 x i8],[4 x i8]* @.fstr, i64 0, i64 0
    %2 = call i32 @printf(i8* %1, double 2.0)
    %3 = call i32 @printf(i8* %1, float 2.0)
    ret i32 0
}

When I compile this with LLVM and link it with Clang and run the executable I get:

0.000000
0.000000

Same result if I run the .bc file with lli. I have read this relevant post but as you see it doesn't work with doubles either.

Upvotes: 0

Views: 872

Answers (1)

droptop
droptop

Reputation: 1671

On running your example using lli-10 I get a @printf' defined with type 'i32 (i8*, ...)*' but expected 'i32 (i8*, double)*' error rather than a successful call that prints 0.000000.

This error is expected, and the reason why is explained here. The relevant bit from the post is

... if the type in front of the call is a function pointer type, then that is used as the type of the thing being called, while if it's not, then it is used as the return type, and the type of the call is inferred from the arguments present on the instruction.

That is why LLVM infers printf's type in the first call as i32 (i8*, double)* but later finds out it's declared as i32 (i8*, ...)*. To fix this simply annotate the calls properly,

%2 = call i32 (i8*, ...) @printf(i8* %1, double 2.0)
%3 = call i32 (i8*, ...) @printf(i8* %1, float 2.0)

You'd quickly notice that the second printf call still prints 0.000000. See why

Upvotes: 1

Related Questions