从 LLVM 位码生成 Rust 可执行文件

Generating Rust executable from LLVM bitcode

如何生成用 Rust 编写并编译成 LLVM-IR 位码的应用程序的可执行文件?

如果我尝试用 rustc 编译 .bc 文件,它会告诉我 stream did not contain valid UTF-8 我似乎无法弄清楚 rustc 中是否有特定的选项。

基本上我想实现这个: program.rs -> program.bc -> program。 其中 program 是最终的可执行文件。我应该采取哪些步骤来实现这一目标?

从这个源代码开始:

fn main() {
    println!("Hello, world!");
}

您可以创建 LLVM 中间表示 (IR) 或 bitcode (BC):

# IR in hello.ll
rustc hello.rs --emit=llvm-ir
# BC in hello.bc
rustc hello.rs --emit=llvm-bc

然后 LLVM 可以进一步处理这些文件以生成 assemblyobject 文件:

# Assembly in hello.s
llc hello.bc
# Object in hello.o
llc hello.bc --filetype=obj

然后您需要link 文件来生成可执行文件。这需要 linking 到 Rust 标准库。该路径依赖于平台和版本:

cc -L/path/to/stage2/lib/rustlib/x86_64-apple-darwin/lib/ -lstd-f4a73f2c70e583e1 -o hello2 hello.o

然后您可以运行程序:

DYLD_LIBRARY_PATH=/path/to/stage2/lib/rustlib/x86_64-apple-darwin/lib/ ./hello2

这个答案有 macOS 特定的解决方案,但是一般概念 应该 可以扩展到 Linux 和 Windows。 Linux 的实现会略有不同,Windows 的实现可能会有很大不同。值得注意的是,我正在使用 DYLD_LIBRARY_PATH,因为我动态 linked 到 Rust 标准库,它不在我通常的库搜索路径中。

请注意,LLVM IR 和 BC 文件没有最强的前向/后向兼容性保证。这意味着您需要使用与您正在使用的 rustc 版本兼容的 llc 版本。对于这个答案,我使用了由我的本地 Rust 开发构建生成的 llc

% rustc --version --verbose
rustc 1.53.0 (53cb7b09b 2021-06-17)
binary: rustc
commit-hash: 53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b
commit-date: 2021-06-17
host: x86_64-apple-darwin
release: 1.53.0
LLVM version: 12.0.1

% llc --version
LLVM (http://llvm.org/):
  LLVM version 12.0.1-rust-dev
  Optimized build.
  Default target: x86_64-apple-darwin20.5.0
  Host CPU: skylake

另请参阅:

  • How stable is the LLVM assembly language?

这并不明显,因为 LLVM 文档非常晦涩,但是 clang 将同时编译 LLVM IR 文件 (".ll") 和位码文件 (".bc") ),以及 link 与您的系统库。

在 Linux 上使用 Rust 1.9:

clang -dynamic-linker /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-d16b8f0e.so  hello.ll -o hello