7个版本

0.2.1+llvm-462a31f5a5ab2024年7月11日
0.2.0+llvm-462a31f5a5ab2023年7月26日
0.1.3 2018年10月11日
0.0.0 2018年10月11日

#21 in 数学

Download history 16910/week @ 2024-04-26 19020/week @ 2024-05-03 23437/week @ 2024-05-10 24058/week @ 2024-05-17 24432/week @ 2024-05-24 20195/week @ 2024-05-31 18442/week @ 2024-06-07 17288/week @ 2024-06-14 19130/week @ 2024-06-21 17674/week @ 2024-06-28 18077/week @ 2024-07-05 19420/week @ 2024-07-12 20441/week @ 2024-07-19 20198/week @ 2024-07-26 20364/week @ 2024-08-02 18082/week @ 2024-08-09

82,324 每月下载量
18 个crate中(8个直接使用)

Apache-2.0 WITH LLVM-exception

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-projectgit 提交哈希的前 12 个十六进制数字
    的端口基于

测试

rustc_apfloat 包含了从 C++ llvm::APFloat 代码的所有测试,位于 tests/ieee.rstests/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