|
1 | 1 | //! `chelae` — a FASTQ trimming and filtering toolkit. This file is the CLI entry |
2 | 2 | //! point; it dispatches to the set of subcommands via the [`Command`] trait and |
3 | | -//! `enum_dispatch`. Installs `mimalloc` as the global allocator and, on x86_64, runs |
4 | | -//! a startup CPU check against the AVX2 baseline that `.cargo/config.toml` requires. |
| 3 | +//! `enum_dispatch`. Installs `mimalloc` as the global allocator. |
5 | 4 |
|
6 | 5 | extern crate core; |
7 | 6 |
|
@@ -40,52 +39,11 @@ enum Subcommand { |
40 | 39 | Trim(Trim), |
41 | 40 | } |
42 | 41 |
|
43 | | -/// Best-effort guard against running an AVX2-compiled binary on a CPU that lacks |
44 | | -/// AVX2 (pre-2013 Intel Haswell / pre-2017 AMD Zen / pre-2021 Intel Gracemont |
45 | | -/// Atom). The crate's `.cargo/config.toml` targets `x86-64-v3` for x86_64 |
46 | | -/// release builds, which emits AVX2 instructions throughout the binary; hitting |
47 | | -/// one of those on an older CPU produces `SIGILL` with no explanation. |
48 | | -/// |
49 | | -/// This runs at the top of `main()` and probes CPUID directly (the `cpuid` |
50 | | -/// instruction carries no SIMD baggage, so the check itself is safe on any |
51 | | -/// x86_64 CPU). If AVX2 is missing we print a clear message and exit 1. |
52 | | -/// |
53 | | -/// **Caveat:** the guard only covers code that runs after `main()` starts. If |
54 | | -/// the Rust runtime emits AVX2 ops during pre-main startup (TLS setup, allocator |
55 | | -/// init, etc.), the `SIGILL` will still beat us. In practice Rust's pre-main |
56 | | -/// path is small enough that we don't observe this, but we can't guarantee it. |
57 | | -#[cfg(target_arch = "x86_64")] |
58 | | -fn ensure_avx2_or_die() { |
59 | | - // `__cpuid`/`__cpuid_count` were stabilized as safe in Rust 1.89 — the `cpuid` |
60 | | - // instruction is unconditionally available on every x86_64 CPU and has no memory |
61 | | - // side effects. |
62 | | - use std::arch::x86_64::{__cpuid, __cpuid_count}; |
63 | | - // Leaf 1: ECX bit 27 = OSXSAVE (OS supports xsave, required to use YMM state); |
64 | | - // bit 28 = AVX. Leaf 7 sub-leaf 0: EBX bit 5 = AVX2. |
65 | | - let l1 = __cpuid(1); |
66 | | - let osxsave = (l1.ecx >> 27) & 1 != 0; |
67 | | - let avx = (l1.ecx >> 28) & 1 != 0; |
68 | | - let l7 = __cpuid_count(7, 0); |
69 | | - let avx2 = (l7.ebx >> 5) & 1 != 0; |
70 | | - if !(osxsave && avx && avx2) { |
71 | | - eprintln!( |
72 | | - "error: this chelae binary was built for x86-64-v3 (AVX2+) but this\n\ |
73 | | - CPU does not report AVX2 support. Required features: AVX, AVX2,\n\ |
74 | | - OSXSAVE. Rebuild from source with a portable baseline:\n\ |
75 | | - \n\ |
76 | | - \tRUSTFLAGS=\"-C target-cpu=x86-64\" cargo build --release\n" |
77 | | - ); |
78 | | - std::process::exit(1); |
79 | | - } |
80 | | -} |
81 | | - |
82 | | -/// Process entry point. Runs the AVX2 guard (x86_64 only), initializes env_logger with |
83 | | -/// a default of `info` level, parses argv, and dispatches to the selected subcommand's |
84 | | -/// `execute()`. Errors propagate out as `anyhow::Error` for the runtime's default |
85 | | -/// `eprintln!` + nonzero-exit handling. |
| 42 | +/// Process entry point. Initializes env_logger with a default of `info` level, |
| 43 | +/// parses argv, and dispatches to the selected subcommand's `execute()`. Errors |
| 44 | +/// propagate out as `anyhow::Error` for the runtime's default `eprintln!` + |
| 45 | +/// nonzero-exit handling. |
86 | 46 | fn main() -> Result<()> { |
87 | | - #[cfg(target_arch = "x86_64")] |
88 | | - ensure_avx2_or_die(); |
89 | 47 | env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); |
90 | 48 | let args: Args = Args::parse(); |
91 | 49 | args.subcommand.execute() |
|
0 commit comments