如何使用自定义LLC编译Rust程序? [英] How can I compile a Rust program with a custom llc?

查看:28
本文介绍了如何使用自定义LLC编译Rust程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义LLVM后端,并希望为该自定义(Nostd)目标交叉编译Rust。我想分两步编译Rust程序:

  1. 使用rustc生成LLVM IR。
  2. 使用我自己的optllc将LLVM IR转换为机器码。

我尝试使用cargo rustc -- --emit=llvm-ir。我获取.ll个文件,然后使用llc获取.o个文件。 然后,我以同样的方式交叉编译libcore。当我尝试将所有对象链接在一起时,它告诉我一个未定义的引用。我使用的是libcorerustc的相同提交。这似乎是LLVM版本的问题,但我不确定。

推荐答案

您应该注意几件事。最重要的是,如果您从Rustup或发行版包管理器获得,rustc默认使用的LLVM版本是/不是/LLVM的实际发行版,并且可能与特定的LLVM发行版实际上不兼容Bitcode。我们在我的项目中解决了这个问题,方法是使用--llvm-root标志配置从源构建Ruust。然后,您可以使用rustup toolchain link将构建的Rustc链接到自定义Rustup工具链。

其次,如果您至少使用rustc 1.34并将-C linker-plugin-lto标志传递给rustc,则可以让rustc发出包含llvm位码而不是机器码的.rlib文件。如果上述方法对您不起作用,我还编写了以下脚本,该脚本可以解压包含目标代码的RLIB文件,并将其打包为包含llvm位码的RLIB文件。

#!/bin/bash
dir="$(mktemp -d)"
trap "rm -rf $dir" INT TERM EXIT
archive=$(realpath -m $1)
cd "$dir"
ar x "$archive"
rm ./*.rcgu.o
for file in *.bc.z; do
len=`od -An -t u4 -j 15 -N4 $file`
blen=`od -An -t u8 -j $((len+19)) -N8 $file`
tail -c+$((len+28)) $file | head -c $blen > $file.bc.gz
printf "x1fx8bx08x00x00x00x00x00x00x00" |cat - $file.bc.gz |gzip -dc > ${file%.bc.z}.o
done
rm *.bc.z
rm *.gz
rm "$archive"
llvm-ar rs "${archive}" ./*

一旦有了RLIB文件,您就可以对它们使用任何llvm工具链工具,就像处理包含llvm位码的.a文件一样。

关于执行最后一个环节,有几件事需要牢记。首先,rustc自动生成符号__rust_alloc__rust_alloc_zeroed__rust_dealloc__rust_realloc,并将它们指向__rg_alloc(和类似的__rg_符号)或__rdl_alloc(和类似的__rdl_符号),这是由libc Malloc支持的系统分配器。如果您不使用rustc进行最后的链接,则必须自己实现这些符号。

其次,libstd和libcore依赖于一些其他库,您可能也必须链接到这些库。根据您使用的标准库的不同部分,您可能会发现需要不同的库集,因此我无法在没有特定错误消息的情况下为您提供帮助,但我可以告诉您,我的应用程序最终需要的库列表是:std, core, alloc, unwind, compiler_builtins, panic_abort, backtrace_sys, rustc_demangle。如果您使用Panic=Unind,显然您将不得不使用它来代替。如果您发现仍然有丢失的符号,我建议您使用nm查找包含丢失的符号的库,并通过反复尝试找出它在链接器顺序中的位置。

希望这会有所帮助,因为我已经花了相当多的精力来设计这个问题的解决方案(尽管不是为了交叉编译)。

这篇关于如何使用自定义LLC编译Rust程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆