minorum/llvm-nds32
GitHub: minorum/llvm-nds32
LLVM 22 分支,为 Andes NDS32 架构添加了代码生成后端,支持在该平台上编译 Rust no_std 固件。
Stars: 0 | Forks: 0
# 带有 Andes NDS32 后端的 LLVM
这是 [llvm/llvm-project](https://github.com/llvm/llvm-project) 的一个分支,基于
`llvmorg-22.1.0` 版本,添加了**用于 Andes NDS32 (AndeStar)
架构的代码生成器**,包含大端序。上游 LLVM 没有 NDS32 目标;该分支
存在的目的是为 NDS32 协处理器编译 Rust `no_std` 固件。
- **后端位于 [`llvm/lib/Target/NDS32/`](llvm/lib/Target/NDS32)。**
- **`nds32` 是包含该后端的分支**,也是默认分支。`main` 是
未经修改的上游 LLVM,完全不包含 NDS32 目标。
- 该分支追踪一条长期的开发线,而不是每个 LLVM 版本对应一个分支,
因此其名称和 URL 保持稳定。它当前所基于的上游版本通过标签标记:
`nds32-v-`,例如 `nds32-v22.1.0-1`。上游代码会被合并进来,
从不进行 rebase —— 重写该分支会破坏所有指向它的子模块 gitlink。
- 选择 LLVM 22 是为了匹配 rustc-nightly 捆绑的 LLVM,因此 rustc 的 IR 可以直接
解析和降低。
## 在 AI 辅助下开发
此后端在很大程度上是在 AI(Anthropic 的 Claude)的辅助下编写的,并在
人工指导和审查下进行。明确说明这一点是因为这会影响你阅读代码的方式:
将其视为任何陌生贡献者的作品,并依赖检查机制而非作者身份来判断。
关于“你如何信任它?”这个项目给出的回答是,这里没有任何内容是
仅凭看起来合理就被接受的:
- 指令编码是**与 Andes `nds32be-elf` binutils 进行逐字节的差分测试**,而
非人工推导。系统寄存器表是通过探测工具链生成的,而不是直接抄录(266 种
拼写,包含两种助记符,以及一次反汇编往返测试)。
- 编译后的代码**在 Andes nds32 ISS 上执行**,这捕获了严格匹配输出的 FileCheck 在结构上无法发现的静默错误编译。
- 行为变更伴随着针对性的 CodeGen 或 MC 测试一同提交。
当本 README 中的声明没有得到上述任一支持时,它仅仅是关于意图的声明,而非证据。
## 已实现的功能
完整的 ABI、帧指针 + alloca、varargs、寄存器偏移和后自增
寻址、PIC/TLS、单精度硬浮点、16 位压缩、系统
寄存器,以及完整的 MC 层(TableGen 驱动的编码器、反汇编器、
AsmParser)。Rust `core` 和 `compiler_builtins` 可以编译为有效的 NDS32 对象
文件,并在 Andes nds32 ISS 上正确执行。
处理器:`v2`(= `generic`)、`v3`、`v3f`、`v3f-hard`。主要 triple:
`nds32be-unknown-none-elf`。
### 核心配置特性
除了 ISA 级别之外,还有两个 subtarget 特性用于描述特定核心是
如何*构建*的。两者在真实的硅片上都很重要,而且过去它们都会静默失败:
| 特性 | 含义 |
|---|---|
| `+reduced-regs` | 仅存在 Andes 缩减寄存器集(r0–r10, r15, r28–r31)。在此类核心上分配 r11–r14 或 r16–r27 会产生**错误**。 |
| `+no-16bit` | 永不生成 16 位(压缩)形式。 |
与此相关,`bitci` 仅限 V3 基准 —— V2 核心在执行时会陷入异常 —— 因此
`(and reg, imm)` → `bitci` 模式受 `HasV3Ops` 限制,而 V2 会将
相同的表达式降级为 `movi`+`and`。
## 构建
```
cmake -S llvm -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_TARGETS_TO_BUILD=X86 \
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=NDS32 \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DLLVM_INCLUDE_TESTS=ON
ninja -C build llc llvm-mc llvm-objdump FileCheck not count
```
NDS32 是一个*实验性*目标,因此需要指定 `LLVM_EXPERIMENTAL_TARGETS_TO_BUILD`。
如果你打算将宿主 rustc 链接到此构建版本,请将你的宿主架构(上例中的 `X86`)保留在 `LLVM_TARGETS_TO_BUILD` 中。
## 测试
使用 `-DLLVM_INCLUDE_TESTS=ON` 进行配置(如上所述),测试套件将在
真实的 `llvm-lit` 下运行。所需的一切都包含在此代码库中:
```
# CodeGen + MC,exact-output FileCheck —— 标准 LLVM 工作流
./build/bin/llvm-lit -sv llvm/test/CodeGen/NDS32 llvm/test/MC/NDS32
# 每个 sysreg 拼写与 GNU assembler 进行 byte-compared
python3 llvm/utils/NDS32/verify-sysregs.py
# 编译后的代码实际在 Andes nds32 ISS 上运行
bash llvm/utils/NDS32/build-nds32-sim.sh # once
bash llvm/utils/NDS32/run-exec-test.sh
```
不要满足于“测试能够编译”。在 ISS 上运行代码已经捕获了静默
错误编译 —— 数据字节序、PIC 跳转表、1 位分支修复掩码 —— 这些是
基于汇编的 FileCheck 在结构上无法发现的。
`llvm/lib/Target/NDS32/NDS32SysRegs.td` 是**生成**的 —— 请勿手动编辑。
使用 `llvm/utils/NDS32/gen-sysregs.py` 重新生成,它通过探测 GNU 工具链来推导整个表:
规范名称是 `nds32be-elf-objdump` 为每个架构上不同的 SRIDX 打印的内容,别名是
`nds32be-elf-as` 接受的数字 `$crN`/`$irN`/`$drN`/… 拼写形式。
## 许可
此分支采用 **Apache-2.0 WITH LLVM-exception**,与上游相同。`LICENSE.TXT` 未被
修改,每个 NDS32 源文件均带有标准的 LLVM 头文件。
**不存在任何 GPL 代码或派生自 GPL 的数据。** 这一点值得明确说明,因为用于
验证此后端的工具链 —— GNU binutils 和提供 ISS 的 Andes `gdb` 分支 ——
是 GPL 许可的。该界限在两个方向上都保持清晰:
- 生成的系统寄存器表**仅基于工具输出构建**(字节
输入,字节输出)。早期版本曾从 binutils 的 `nds32-asm.c` 中解析
`keyword_sr` 表,这引发了一个可以避免的许可问题;该
依赖项已被移除,并且它生成的规范寄存器集在字节层面上
完全相同(136 个寄存器,相同的 SRIDX 值)。
- binutils 和 ISS **作为外部程序调用**,从未被链接、
引入或复制。`build-nds32-sim.sh` 在构建时将 Andes gdb 分支克隆
到你的机器上;这里不再分发其中的任何内容。
- 对你的输入运行 GPL 工具不会使其输出受到限制,因此由
此后端生成并针对这些工具进行验证的对象文件不承担任何 GPL
义务。
如果你重新分发此分支,你是在 Apache-2.0 WITH
LLVM-exception 许可下重新分发 LLVM,仅此而已。
## 状态与支持
**工作正常,并已投入实战使用** —— 此后端为以下
消费者项目编译固件,该项目在真实的 MT6785 硬件上运行。它不是一个
研究玩具。但它**也**不是上游 LLVM 目标,而且永远也不会是:
NDS32 是遗留物(Andes 已转向 RISC-V),因此此分支是永久的最终状态,
而非中转站。
坦诚的期望,以免大家失望:
- 这是一个**由单人维护的个人项目**,尽力而为,没有
SLA。欢迎提交 Issue 和补丁;回复可能缓慢或缺失,我可能
会拒绝我无法测试的功能范围。
- 我仅在 **Linux/x86-64 宿主机上测试大端序 `nds32be-unknown-none-elf`**。
小端序 NDS32 和非 Linux 宿主机未经测试 —— 可能差距
不大,但绝对未经核实。
- 当我需要更新的 rustc 时才会变基到更新的 LLVM,而不是按计划进行。
### 已验证和未验证的内容
| 领域 | 状态 |
|---|---|
| i32 ALU、移位、比较、分支、select | 已实现,lit + ISS 执行 |
| i64(寄存器对,ABI2 偶数对规则) | 已实现,lit + ISS 执行 |
| i8/i16 窄位加载/存储,符号/零扩展 | 已实现,lit + ISS 执行 |
| 调用、被调用者保存、varargs、alloca、帧指针 | 已实现,lit + ISS 执行 |
| 全局地址、常量池、跳转表 | 已实现,lit + ISS 执行 |
| PIC(通过 `$gp` 的 GOT/GOTOFF)和 TLS-LE | 已实现,ISS 执行 |
| 单精度硬浮点(`v3f`、`v3f-hard`) | 已实现,ISS 执行 |
| 16 位压缩 + 分支松弛 | 已实现,ISS 执行 |
| 系统寄存器(`mfsr`/`mtsr`) | 已实现,与 binutils 进行差分测试 |
| `+reduced-regs`、`+no-16bit` | 已实现,lit 测试 |
| ELF 对象、重定位、反汇编器往返测试 | 与 GNU `objdump`/`readelf` 进行交叉检查 |
| **双精度硬浮点** | **未实现** |
| **链接器松弛** | **未实现** |
| **硬浮点 ABI 中的被调用者保存 FPR** | **未实现** |
| **小端序 NDS32** | **未测试** |
| 执行测试广度 | 有限的;覆盖率良好,但并非详尽无遗 |
构建 ISS 执行循环发现了**八次静默错误编译**,这是
FileCheck 套件无法看到的。这是信任上述各行的主要原因 ——
也是最后一行被表述为剩余风险而非保证的原因。
## 相关代码库
- [minorum/nds32-llvm](https://github.com/minorum/nds32-llvm) —— 包装器:Rust
目标规格(包括 `nds32be-conn-mcu.json`)、构建和验证
脚本,以及作为子模块的此分支。
- [minorum/mt6785-connsys-firmware](https://github.com/minorum/mt6785-connsys-firmware)
—— 消费者:联发科 MT6785 连接
协处理器固件的 Rust 重构版。其 `docs/07-environment-setup.md` 记录了整个
工具链以及如何从零开始重新构建它。
以下是上游 LLVM 的 README。
# LLVM 编译器基础架构
[](https://securityscorecards.dev/viewer/?uri=github.com/llvm/llvm-project)
[](https://www.bestpractices.dev/projects/8273)
[](https://github.com/llvm/llvm-project/actions/workflows/libcxx-build-and-test.yaml?query=event%3Aschedule)
欢迎来到 LLVM 项目!
此代码库包含 LLVM 的源代码,这是一个用于
构建高度优化的编译器、优化器和运行时环境的工具包。
LLVM 项目包含多个组件。该项目的核心
本身被称为“LLVM”。它包含处理中间表示并将其转换为
目标文件所需的所有工具、库和头
文件。工具包括汇编器、反汇编器、bitcode 分析器和
bitcode 优化器。
类 C 语言使用 [Clang](https://clang.llvm.org/) 前端。该
组件将 C、C++、Objective-C 和 Objective-C++ 代码编译为 LLVM bitcode
—— 然后使用 LLVM 从那里将其转换为目标文件。
其他组件包括:
[libc++ C++ 标准库](https://libcxx.llvm.org)、
[LLD 链接器](https://lld.llvm.org) 等。
## 获取源代码并构建 LLVM
请查阅
[LLVM 入门](https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm)
页面以获取有关构建和运行 LLVM 的信息。
有关如何为 LLVM 项目做贡献的信息,请查看
[为 LLVM 做贡献](https://llvm.org/docs/Contributing.html)指南。
## 联系我们
加入 [LLVM Discourse 论坛](https://discourse.llvm.org/)、[Discord
聊天](https://discord.gg/xS7Z362)、
[LLVM 办公时间](https://llvm.org/docs/GettingInvolved.html#office-hours) 或
[定期同步会议](https://llvm.org/docs/GettingInvolved.html#online-sync-ups)。
LLVM 项目已为项目内所有沟通方式的参与者采用了
[行为准则](https://llvm.org/docs/CodeOfConduct.html)。
标签:Bash脚本, LLVM, NDS32, 代码生成器, 可视化界面, 嵌入式开发, 指令集架构, 编译器, 逆向工具