如何从 LLVM IR 打印浮点数?

Posted

技术标签:

【中文标题】如何从 LLVM IR 打印浮点数?【英文标题】:How to print floats from LLVM IR? 【发布时间】:2021-10-19 18:59:42 【问题描述】:

我在使用 LLVM IR 中的 printf() 函数时遇到问题。我只想打印浮点数的值,但我只得到0.000000。它适用于整数和字符串,但不适用于浮点数。

简单示例:

@.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

当我用 LLVM 编译它并用 Clang 链接它并运行我得到的可执行文件时:

0.000000
0.000000

如果我使用lli 运行.bc 文件,结果相同。我已经阅读了相关的post,但正如您所见,它也不适用于双打。

【问题讨论】:

【参考方案1】:

在使用 lli-10 运行您的示例时,我得到一个 @printf' defined with type 'i32 (i8*, ...)*' but expected 'i32 (i8*, double)*' 错误而不是打印 0.000000 的成功调用。

这个错误是意料之中的,原因解释here。帖子中的相关位是

...如果调用前面的类型是 函数指针类型,然后使用 作为事物的类型 调用,如果不是,则使用作为返回类型, 调用的类型是从指令中存在的参数推断出来的。

这就是为什么 LLVM 在第一次调用中将printf 的类型推断为i32 (i8*, double)*,但后来发现它被声明为i32 (i8*, ...)*。要解决此问题,只需正确注释调用,

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

您很快就会注意到第二个 printf 调用仍然打印 0.000000。见why

【讨论】:

以上是关于如何从 LLVM IR 打印浮点数?的主要内容,如果未能解决你的问题,请参考以下文章

如何将浮点数打印到 n 位小数,包括尾随 0?

将 python 浮点数打印为单精度浮点数

如何在lisp中以指定格式将数字打印为浮点数?

如何在 Rust 中使用前导零打印 2 位浮点数的整数部分?

如何以所有可用精度打印Rust浮点数?

C编程以十六进制的长双精度打印浮点数