当使用lli运行时,rustc生成的LLVM会给出关于main的参数类型的错误

时间:2017-08-24 06:09:27

标签: rust llvm lli

我正在尝试学习一些关于LLVM IR的知识,特别是什么是rustc输出。我在运行一个非常简单的案例时遇到了一些麻烦。

我将以下内容放在源文件simple.rs中:

fn main() {
    let x = 7u32;
    let y = x + 2;
}

并运行rustc --emit llvm-ir simple.rs以获取包含

的文件simple.ll
; ModuleID = 'simple.cgu-0.rs'
source_filename = "simple.cgu-0.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: uwtable
define internal void @_ZN6simple4main17h8ac50d7470339b75E() unnamed_addr #0 {
start:
  br label %bb1

bb1:                                              ; preds = %start
  ret void
}

define i64 @main(i64, i8**) unnamed_addr {
top:
  %2 = call i64 @_ZN3std2rt10lang_start17ha09816a4e25587eaE(void ()* @_ZN6simple4main17h8ac50d7470339b75E, i64 %0, i8** %1)
  ret i64 %2
}

declare i64 @_ZN3std2rt10lang_start17ha09816a4e25587eaE(void ()*, i64, i8**) unnamed_addr

attributes #0 = { uwtable }

!llvm.module.flags = !{!0}

!0 = !{i32 1, !"PIE Level", i32 2}

然后我尝试使用命令

运行它
lli-3.9 -load ~/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/libstd-35ad9950c7e5074b.so simple.ll

但我收到错误消息

LLVM ERROR: Invalid type for first argument of main() supplied

我可以按如下方式对其进行最小化的再现:我创建一个名为s2.ll的文件,其中包含

define i32 @main(i64, i8**) {
    ret i32 42
}

并且运行lli-3.9 s2.ll会显示相同的错误消息。 如果我将s2.ll的内容更改为

define i32 @main(i32, i8**) {
    ret i32 42
}

(即我已更改主要内容中argc的类型),然后lli-3.9 s2.ll运行,echo $?显示确实已返回42

我认为我不应该明确地传递i64 - 我的参数列表或C字符串应该被放入内存中,指针和长度会自动传递给main,对吗?因此,我假设我在调用lli的方式上做错了 - 但我不知道是什么。

1 个答案:

答案 0 :(得分:5)

Rust将其入口点(标记为#[start]属性的函数,默认情况下标准库中的函数lang_start)标记为采用类型为isize的argc参数。 This is a bug因为它应该具有C int的类型,所以它应该是64位平台上的32位,但isize是64位。但是,由于64位调用约定的工作方式,这种情况仍然可以正常工作。返回类型也存在同样的问题。

A fix因此已于2017年10月1日承诺,并且应该出现在Rust 1.22中。

lli显然更加严格地检查main的类型,这就是它给出错误的原因。但是如果你改用llc,它应该可以正常工作。

要获得正确的main签名,您可以将main放在模块顶部取消默认#![no_main],然后提供标有main的{​​{1}} {1}}。但请注意,这将跳过标准库的初始化。

#[no_mangle]

另见: