feat(decompress): move platform BMI2 init to Rust

The decoder context remains allocated and laid out by C because optional members
change with the active build configuration. Previously, the C adapter also
owned the platform leaf: its DYNAMIC_BMI2 branch queried CPU features and
assigned the private bmi2 member directly. That kept the policy in C and made
the Rust boundary depend on the context layout.

Move the leaf to Rust and give it an opaque scalar address plus the active
configuration value. The C adapter now only extracts the optional address when
that member exists and forwards it, while DYNAMIC_BMI2=0 passes NULL. Rust
performs the dynamic decision, queries CPU support, and writes the scalar. The
existing 68-word DCtx view is unchanged. Focused unit coverage verifies that
disabled dynamic dispatch leaves the scalar untouched and enabled dispatch
publishes the CPU feature result.

Test Plan:
- `cc -fsyntax-only -Werror -DDYNAMIC_BMI2=0 -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/legacy lib/decompress/zstd_decompress.c` -- passed
- `cc -fsyntax-only -Werror -DDYNAMIC_BMI2=1 -Ilib -Ilib/common -Ilib/compress -Ilib/decompress -Ilib/dict -Ilib/legacy lib/decompress/zstd_decompress.c` -- passed
- `rustfmt --edition 2021 --check rust/src/zstd_decompress.rs` -- passed
- `git diff --check -- lib/decompress/zstd_decompress.c rust/src/zstd_decompress.rs` -- passed
This commit is contained in:
2026-07-20 14:59:22 +02:00
parent 40137b28bf
commit c2bed1242c
2 changed files with 38 additions and 5 deletions
+5 -3
View File
@@ -133,7 +133,8 @@ void ZSTD_rust_dctx_view(ZSTD_DCtx* dctx, ZSTD_rustDctxView* out);
void ZSTD_rust_dctx_trace_view(ZSTD_DCtx* dctx,
ZSTD_rustDctxTraceView* out);
size_t ZSTD_rust_dctx_sizeof(void);
void ZSTD_rust_dctx_init_platform(ZSTD_DCtx* dctx);
void ZSTD_dctx_init_platform(ZSTD_DCtx* dctx);
void ZSTD_rust_dctx_init_platform(void* bmi2, int dynamic_bmi2);
size_t ZSTD_rust_dctx_default_max_window_size(void);
int ZSTD_rust_no_forward_progress_max(void);
int ZSTD_rust_heapmode(void);
@@ -245,12 +246,13 @@ size_t ZSTD_rust_dctx_sizeof(void)
return sizeof(ZSTD_DCtx);
}
void ZSTD_rust_dctx_init_platform(ZSTD_DCtx* dctx)
void ZSTD_dctx_init_platform(ZSTD_DCtx* dctx)
{
#if DYNAMIC_BMI2
dctx->bmi2 = ZSTD_cpuSupportsBmi2();
ZSTD_rust_dctx_init_platform(&dctx->bmi2, DYNAMIC_BMI2);
#else
(void)dctx;
ZSTD_rust_dctx_init_platform(NULL, DYNAMIC_BMI2);
#endif
}
+33 -2
View File
@@ -344,7 +344,7 @@ unsafe extern "C" {
fn ZSTD_rust_dctx_view(dctx: *mut ZSTD_DCtx, out: *mut ZSTD_rustDctxView);
fn ZSTD_rust_dctx_trace_view(dctx: *mut ZSTD_DCtx, out: *mut ZSTD_rustDctxTraceView);
fn ZSTD_rust_dctx_sizeof() -> usize;
fn ZSTD_rust_dctx_init_platform(dctx: *mut ZSTD_DCtx);
fn ZSTD_dctx_init_platform(dctx: *mut ZSTD_DCtx);
fn ZSTD_rust_dctx_default_max_window_size() -> usize;
fn ZSTD_rust_no_forward_progress_max() -> c_int;
fn ZSTD_rust_heapmode() -> c_int;
@@ -378,6 +378,37 @@ unsafe extern "C" {
fn ZSTD_checkContinuity(dctx: *mut ZSTD_DCtx, dst: *const c_void, dst_size: usize);
}
#[no_mangle]
pub unsafe extern "C" fn ZSTD_rust_dctx_init_platform(bmi2: *mut c_void, dynamic_bmi2: c_int) {
if dynamic_bmi2 != 0 && !bmi2.is_null() {
unsafe {
bmi2.cast::<c_int>()
.write(c_int::from(crate::cpu::ZSTD_cpuSupportsBmi2()));
}
}
}
#[cfg(test)]
mod dctx_platform_tests {
use super::*;
#[test]
fn initializes_bmi2_only_when_dynamic_support_is_enabled() {
let mut bmi2 = c_int::MAX;
unsafe {
ZSTD_rust_dctx_init_platform((&mut bmi2 as *mut c_int).cast(), 0);
}
assert_eq!(bmi2, c_int::MAX);
let expected = c_int::from(crate::cpu::ZSTD_cpuSupportsBmi2());
bmi2 = c_int::MAX;
unsafe {
ZSTD_rust_dctx_init_platform((&mut bmi2 as *mut c_int).cast(), 1);
}
assert_eq!(bmi2, expected);
}
}
type ZstdDecompressDCtxFn =
unsafe extern "C" fn(*mut ZSTD_DCtx, *mut c_void, usize, *const c_void, usize) -> usize;
@@ -2576,7 +2607,7 @@ unsafe fn init_dctx_internal(view: &ZSTD_rustDctxView) {
if !view.fuzz_end.is_null() {
set_pointer(view.fuzz_end, ptr::null());
}
ZSTD_rust_dctx_init_platform(view.dctx.cast());
ZSTD_dctx_init_platform(view.dctx.cast());
}
}