本文介绍了如何使用自定义LLC编译Rust程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个自定义LLVM后端,并希望为该自定义(Nostd)目标交叉编译Rust。我想分两步编译Rust程序:- 使用
rustc
生成LLVM IR。 - 使用我自己的
opt
和llc
将LLVM IR转换为机器码。
我尝试使用cargo rustc -- --emit=llvm-ir
。我获取.ll
个文件,然后使用llc
获取.o
个文件。然后,我以同样的方式交叉编译libcore
。当我尝试将所有对象链接在一起时,它告诉我一个未定义的引用。我使用的是libcore
和rustc
的相同提交。这似乎是LLVM版本的问题,但我不确定。
推荐答案
您应该注意几件事。最重要的是,如果您从Rustup或发行版包管理器获得,rustc默认使用的LLVM版本是/不是/LLVM的实际发行版,并且可能与特定的LLVM发行版实际上不兼容Bitcode。我们在我的项目中解决了这个问题,方法是使用--llvm-root
标志配置从源构建Ruust。然后,您可以使用rustup toolchain link
将构建的Rustc链接到自定义Rustup工具链。
#!/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进行最后的链接,则必须自己实现这些符号。
std, core, alloc, unwind, compiler_builtins, panic_abort, backtrace_sys, rustc_demangle
。如果您使用Panic=Unind,显然您将不得不使用它来代替。如果您发现仍然有丢失的符号,我建议您使用nm查找包含丢失的符号的库,并通过反复尝试找出它在链接器顺序中的位置。希望这会有所帮助,因为我已经花了相当多的精力来设计这个问题的解决方案(尽管不是为了交叉编译)。
这篇关于如何使用自定义LLC编译Rust程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!