如何在LLVM IR中使用printf正确打印float浮点数数值
问题原因
- C语言可变参数函数默认会将
float类型提升为double,直接传递float类型参数不符合ABI要求,会导致参数读取异常; - LLVM内置的
printf优化逻辑存在误判概率,会错误处理带浮点参数的printf调用,导致即便传入double类型参数也无法正常取值。
解决方法
- 所有传入
printf可变参数列表的浮点值,都显式通过fpext指令转换为double类型后再传递; - 编译LLVM IR时添加
-fno-builtin-printf参数,禁用LLVM对printf的内置优化,避免优化逻辑导致的参数异常。
修正后可正常运行的测试代码
@.fstr = private unnamed_addr constant [4 x i8] c"%f\0A\00" declare i32 @printf(i8*, ...) define i32 @main() { %str_ptr = getelementptr [4 x i8],[4 x i8]* @.fstr, i64 0, i64 0 ; 测试直接传递double常量 %ret1 = call i32 @printf(i8* %str_ptr, double 2.0) ; 测试float转double后传递 %float_val = fadd float 0.0, 2.0 %double_val = fpext float %float_val to double %ret2 = call i32 @printf(i8* %str_ptr, double %double_val) ret i32 0 }
编译运行命令示例
# 编译IR为目标文件,禁用printf内置优化 llc -filetype=obj test.ll -o test.o -fno-builtin-printf # 链接生成可执行文件 clang test.o -o test # 运行 ./test
运行后输出结果:
2.000000 2.000000
内容的提问来源于stack exchange,提问作者ZeDragon
相关产品推荐
相关产品推荐

