如何使用LLVM/Clang将代码编译为RISC-V目标?

8
我想编译一个简单的程序 "int main(){return 0;}" 到 RISC-V 处理器。使用的 LLVM/Clang 版本是 9.0,我希望能够在 RISC-V 模拟器上运行编译好的程序,就像这个链接中提到的 https://github.com/riscv/riscv-tools
我的问题是,我无法列出 Clang 支持的目标,仅能使用以下命令列出支持的 LLC-s:
llc --version
llc -march=xxARCHTYPExx -mattr=help

没有任何类型的RISC-V处理器列出。

所以我尝试查找三元组文件:llvm-project\llvm\include\llvm\ADT\Triple.h

并尝试执行如下命令:clang hello.c -target riscv32 -march=rv32imafd

但我遇到了以下错误:

错误:无法创建目标:'No available targets are compatible with triple "riscv32"'

有人可以帮我获取有效的RISC-V目标吗?我不能编译程序,但我知道LLVM支持RISC-V。


LLVM源代码支持RISC-V,但这并不意味着您编译的版本已启用该目标。cmake -DDLLVM_TARGETS_TO_BUILD=all .会给您提供一个支持所有目标的LLVM版本。 - arnt
我尝试了这个命令并在CMake完成后得到了以下错误:CMake警告: 手动指定的变量未被项目使用:DLLVM_TARGETS_TO_BUILD根据此网页,如果我不指定目标,则默认为“all”: https://llvm.org/docs/CMake.html - Zoltán
问题出在-DDLLVM_TARGETS_TO_BUILD=all上。 正确的是-DLLVM_TARGETS_TO_BUILD=all。 但原始问题仍然存在。 - Zoltán
我能够使用以下选项构建: cmake -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="RISCV" -DLLVM_USE_LINKER=gold -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON ../llvm但是当我想创建可运行程序时: clang hello.c --target=riscv64 -march=rv64i -c -o hello.o ld.lld hello.o -o hello它会创建一个可运行文件,但似乎文件中缺少指令。因此它无法正常工作。 - Zoltán
也许我在这里找到了答案:https://llvm.org/docs/WritingAnLLVMBackend.html该文档侧重于在下载的LLVM版本中的llvm/lib/Target子目录中找到的现有示例。特别是,该文档侧重于为SPARC目标创建静态编译器(发出文本汇编代码)的示例,因为SPARC具有相当标准的特征,例如RISC指令集和直接调用约定。因此,它只会生成汇编代码而不是可运行文件... - Zoltán
在这里回答:https://dev59.com/gWYLtIcB2Jgan1znwnwj - Celuk
1个回答

7

LLVM 9 发布说明 明确表示 RISC-V 支持已从实验阶段升级为官方支持。

事实上,在我的 Fedora 31 机器上,LLVM 9 Fedora 包确实支持 RISC-V:

$ llvm-objdump --version | grep riscv
    riscv32    - 32-bit RISC-V
    riscv64    - 64-bit RISC-V

此外,我可以使用LLVM工具链创建RISC-V二进制代码:
$ clang --target=riscv64 -march=rv64gc rotate.s -c -o rotate.o
$ file rotate.o
rotate.o: ELF 64-bit LSB relocatable, UCB RISC-V, version 1 (SYSV), not stripped

尽管它不包括适用于 RISC-V 目标的 libc:
$ clang --target=riscv64 -march=rv64gc hello-world.c -o hello-world
hello-world.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
         ^~~~~~~~~
1 error generated.

然而,你并不真正需要一个 - 你可以直接调用系统调用来实现你的 hello world,例如:

$ clang  --target=riscv64 -march=rv64gc  hello.s -c -o hello.o
$ ld.lld hello.o -o hello
$ spike --isa=RV64gc ~/local/riscv/pk/riscv64-unknown-elf/bin/pk ./hello
bbl loader
Hello World

我不使用clang进行链接,因为似乎我无法用-fuse-ld说服clang使用除了/usr/bin/ld之外的其他链接器。


-fuse-ld 问题是由上游错误引起的:https://bugzilla.redhat.com/show_bug.cgi?id=1803698 - maxschlepzig
在你上面的示例中,你是如何生成rotate.s和hello.s文件的? - erwaman
@erwaman - 我写了它们 - rotate.s 可在我的 riscv github 存储库中找到。 - maxschlepzig
现在也添加了hello.s - maxschlepzig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接