printf在LLVM IR中不适用于浮点数 [英] printf doesn't work for floats in LLVM IR
问题描述
我想将浮点变量的值打印到屏幕上.我在LLVM IR代码中声明了printf()
函数,它已成功链接.
I want to print the value of a floating point variable to the screen. I am declaring printf()
function in the LLVM IR code, and it is linking in successfully.
每当我打印整数,字符数据类型或字符串时,printf()
都会在C代码中将它们正常打印到屏幕上.但是,如果我将float
传递给printf()
,它会打印0.000000
,而不是打印浮点数.我多次检查了源代码,似乎语法是正确的.它应该正在打印2.75
!我正在看这段代码,我绝对不明白代码与我编写的代码有何不同之处.
Whenever I print an integer or a character data type, or a string, printf()
prints them normally to the screen as it prints them in the C code. However, if I pass a float
to printf()
, instead of printing the floating point number, it prints 0.000000
. I checked the source code multiple times and it seems that the syntax is correct. It should be printing 2.75
! I am looking at this code and I absolutely do not understand how code has a different behavior than what I wrote it.
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@obj1 = global {i32, float, i8} zeroinitializer
@format_string = constant [10 x i8] c"%i %f %c\0A\00"
declare i32 @printf(i8*, ...)
define i32 @main() {
entry:
%obj1 = load {i32, float, i8}, {i32, float, i8}* @obj1
%obj2 = insertvalue {i32, float, i8} %obj1, i32 44, 0
%obj3 = insertvalue {i32, float, i8} %obj2, float 2.75, 1
%obj4 = insertvalue {i32, float, i8} %obj3, i8 36, 2
store {i32, float, i8} %obj4, {i32, float, i8}* @obj1
%ptr.i32 = getelementptr {i32, float, i8}, {i32, float, i8}* @obj1, i32 0, i32 0
%0 = load i32, i32* %ptr.i32
%ptr.float = getelementptr {i32, float, i8}, {i32, float, i8}* @obj1, i32 0, i32 1
%1 = load float, float* %ptr.float
%ptr.i8 = getelementptr {i32, float, i8}, {i32, float, i8}* @obj1, i32 0, i32 2
%2 = load i8, i8* %ptr.i8
%format_ptr = getelementptr [10 x i8], [10 x i8]* @format_string, i64 0, i64 0
call i32 (i8*, ...) @printf(i8* %format_ptr, i32 %0, float %1, i8 %2)
ret i32 0
}
当我编译LLVM IR代码时,这是输出:
When I compile the LLVM IR code, this is the output:
$ llvm-as code.ll -o code.bc
$ lli code.bc
44 0.000000 $
它成功打印了整数和字符,但没有打印浮点数!
It successfully printed the integer and the character, but not the floating point number!
推荐答案
原因是printf
是可变函数,可变函数将float
参数提升为double
.请参见为什么printf()将浮点数提高为两倍?
The reason is printf
is a variadic function and variadic functions promote float
arguments to double
. See Why does printf() promote a float to a double?
因此,您应该先将%1
转换为double,然后再将其传递给printf
,这是clang所做的.例如
So you should first cast %1
to double before passing passing it to printf
, which is what clang does. For example
void f() {
float a = 1;
printf("%f", a);
}
给予
@.str = private unnamed_addr constant [3 x i8] c"%f\00", align 1
define dso_local void @f() #0 !dbg !7 {
%1 = alloca float, align 4
call void @llvm.dbg.declare(metadata float* %1, metadata !11,
metadata !DIExpression()), !dbg !13
store float 1.000000e+00, float* %1, align 4, !dbg !13
%2 = load float, float* %1, align 4, !dbg !14
%3 = fpext float %2 to double, !dbg !14
%4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x
i8], [3 x i8]* @.str, i64 0, i64 0), double %3), !dbg !15
ret void, !dbg !16
}
请注意fpext
这篇关于printf在LLVM IR中不适用于浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!