7个版本
0.2.1+llvm-462a31f5a5ab | 2024年7月11日 |
---|---|
0.2.0+llvm-462a31f5a5ab | 2023年7月26日 |
0.1.3 | 2018年10月11日 |
0.0.0 | 2018年10月11日 |
#21 in 数学
82,324 每月下载量
在 18 个crate中(8个直接使用)
180KB
3K SLoC
rustc_apfloat
(C++ llvm::APFloat
"软浮点"库的Rust版本)
历史
LLVM的APFloat
(又称llvm::APFloat
)软件浮点库最初于2017年移植到Rust(命名为rustc_apfloat
),这是在Rust的pull request rust-lang/rust#43554
中,作为扩展Rust编译时功能(不牺牲确定性)的一部分。
注意:虽然直接使用原始C++的llvm::APFloat
是一个选择,但由于在Rust移植中做出的某些高级API设计差异(没有行为影响:C++原始指针和动态分配与Rust泛型、特性和#![no_std]
),从确定性的角度来看,Rust移植更具吸引力(主要得益于缺少所有3个:unsafe
代码、主机浮点数使用、std
访问 - 并且仅分配以处理从十进制转换所需的任意精度),尽管它可能存在独有的正确性问题。
然而,该移植有一个致命的缺陷:它在没有正确跟踪、沟通、考虑其独特的许可状态(作为具有自身许可的C++库的移植)的情况下被添加到rust-lang/rust
仓库中。
最终结果是几年的悬而未决,主要记录在Rust问题rust-lang/rust#55993
中,其中树内移植无法真正接收适当的更新甚至维护,因为其状态不明确。
复苏(作为rust-lang/rustc_apfloat
)
此仓库(rust-lang/rustc_apfloat
)是2022年计划的成果,该计划在2023年全面实施
- 提取了树内
compiler/rustc_apfloat
库的git
历史记录
(有关更多详细信息,请参阅单独的rustc_apfloat-git-history-extraction
仓库) - 仅保留既必要又具有明确版权状态的提交
- 任何缺失的功能或错误修复,必须要么重新贡献,
要么从头开始重建(大多数情况都是后者,见下文)
自原始移植以来的大多数更改都是美观的(例如,拼写检查、rustfmt
),因此在过程中损失很小。
从这么一个小型的“可信”基础开始
- 一切都可以使用自2019年以来LLVM的新许可“Apache 2.0 WITH LLVM exception”
(请参阅下面的“许可”部分和/或LICENSE-DETAILS.md以获取更多详细信息) - 建立了新的设施(基准测试和一个比较Rust/C++/硬件的模糊器)
- 进行了过度的测试(通过模糊测试和暴力搜索的组合)
- 发现了潜在的错误(例如,LLVM问题#63895和#63938)
- 移植已经更新,以包括上游(
llvm/llvm-project
)
对llvm::APFloat
多年的更改(自2017年以来),消除了选择性回滚的需求
版本
由于这是一个“活移植”,因此跟踪上游(llvm/llvm-project
)
llvm::APFloat
的变更,rustc_apfloat
crate 将会有形式为
0.X.Y+llvm-ZZZZZZZZZZZZ
X
的版本在 API 不兼容的变更后总是会增加,
或者在更新上游(llvm/llvm-project
)基于的提交时Y
只有在版本的其他部分不需要变更时才会增加(例如,用于修复错误)+llvm-ZZZZZZZZZZZZ
是 "版本元数据"(Cargo 本身忽略),
并且ZZZZZZZZZZZZ
总是保留上游(llvm/llvm-project
)git
提交哈希的前 12 个十六进制数字
的端口基于
测试
rustc_apfloat
包含了从 C++ llvm::APFloat
代码的所有测试,位于 tests/ieee.rs
和 tests/ppc.rs
。
对于特定于 rustc_apfloat
的测试(没有 C++ 等效的),使用 tests/downstream.rs
(主要包含由模糊测试发现的已修复错误的测试)。
模糊测试
由于 llvm::APFloat
测试远非全面,唯一深入比较原始 C++ 代码和 Rust 端口(以及它们和硬件浮点行为)的方法是采用 模糊测试。
模糊测试基础设施位于 fuzz/
,需要 cargo-afl
,但也涉及使用 clang
自动构建原始 C++ llvm::APFloat
代码(以便能够通过 LLVM 仪器化,就像 cargo-afl
对 Rust 代码所做的那样),并在 Linux 上进行了原型设计和测试(不太可能在其他平台上工作,甚至某些 Linux 发行版,尽管它主要假定 UNIX)。
示例用法
待办事项:也许可以将此移至 fuzz/README.md
并/或对其进行扩展)
# Install `cargo-afl` (used below to build/run the fuzzing binary).
cargo install afl
# Build the fuzzing binary (`target/release/rustc_apfloat-fuzz`).
cargo afl build -p rustc_apfloat-fuzz --release
# Seed the inputs for a run `foo` (while not ideal, even this one minimal input works).
mkdir fuzz/in-foo && echo > fuzz/in-foo/empty
# Start the fuzzing run `foo`, which should bring up the AFL++ progress TUI
# (see also `cargo run -p rustc_apfloat-fuzz` for extra flags available).
cargo afl fuzz -i fuzz/in-foo -o fuzz/out-foo target/release/rustc_apfloat-fuzz
要可视化模糊测试测试用例,可以使用 decode
子命令
cargo run -p rustc_apfloat-fuzz decode fuzz/out-foo/default/crashes/*
(这甚至可以在 cargo afl fuzz
运行时工作,即 AFL++)
许可
此项目根据 Apache 2 许可证和 LLVM 异常 许可证授权。有关本项目许可的更完整讨论,请参阅 LICENSE-DETAILS.md。
依赖关系
~180KB