From 835520d64ce03d52085cca57eec154434317e91c Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 19 Oct 2024 20:50:33 +0900 Subject: [PATCH] detect: Auto-generate static assertions for functions --- src/imp/detect/aarch64_aa64reg.rs | 81 +++++++++-------------- src/imp/detect/aarch64_apple.rs | 48 ++++---------- src/imp/detect/aarch64_fuchsia.rs | 8 +-- src/imp/detect/aarch64_illumos.rs | 44 +++---------- src/imp/detect/aarch64_windows.rs | 7 +- src/imp/detect/auxv.rs | 104 ++++++++++-------------------- src/imp/detect/common.rs | 38 +++++++++++ src/imp/detect/riscv_linux.rs | 2 +- 8 files changed, 128 insertions(+), 204 deletions(-) diff --git a/src/imp/detect/aarch64_aa64reg.rs b/src/imp/detect/aarch64_aa64reg.rs index 8d6f765b..00e53eb7 100644 --- a/src/imp/detect/aarch64_aa64reg.rs +++ b/src/imp/detect/aarch64_aa64reg.rs @@ -153,18 +153,20 @@ mod imp { pub(crate) ctr: u64, } - extern "C" { - // Defined in sys/sysctl.h. - // https://man.netbsd.org/sysctl.3 - // https://github.com/NetBSD/src/blob/432a1357026b10c184d8a0ddb683008a23cc7cd9/sys/sys/sysctl.h - pub(crate) fn sysctlbyname( - name: *const c_char, - old_p: *mut c_void, - old_len_p: *mut c_size_t, - new_p: *const c_void, - new_len: c_size_t, - ) -> c_int; - } + sys_fn!({ + extern "C" { + // Defined in sys/sysctl.h. + // https://man.netbsd.org/sysctl.3 + // https://github.com/NetBSD/src/blob/432a1357026b10c184d8a0ddb683008a23cc7cd9/sys/sys/sysctl.h + pub(crate) fn sysctlbyname( + name: *const c_char, + old_p: *mut c_void, + old_len_p: *mut c_size_t, + new_p: *const c_void, + new_len: c_size_t, + ) -> c_int; + } + }); } pub(super) unsafe fn sysctl_cpu_id(name: &[u8]) -> Option { @@ -248,19 +250,21 @@ mod imp { pub(crate) const CPU_ID_AA64MMFR2: c_int = 7; }); - extern "C" { - // Defined in sys/sysctl.h. - // https://man.openbsd.org/sysctl.2 - // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/sysctl.h - pub(crate) fn sysctl( - name: *const c_int, - name_len: c_uint, - old_p: *mut c_void, - old_len_p: *mut c_size_t, - new_p: *mut c_void, - new_len: c_size_t, - ) -> c_int; - } + sys_fn!({ + extern "C" { + // Defined in sys/sysctl.h. + // https://man.openbsd.org/sysctl.2 + // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/sysctl.h + pub(crate) fn sysctl( + name: *const c_int, + name_len: c_uint, + old_p: *mut c_void, + old_len_p: *mut c_size_t, + new_p: *mut c_void, + new_len: c_size_t, + ) -> c_int; + } + }); } // sysctl returns an unsupported error if operation is not supported, @@ -512,10 +516,10 @@ mod tests { // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // As for constants, they are checked by static assertions generated by sys_const!. + // As for functions, they are checked by static assertions generated by sys_fn!. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[cfg(target_os = "netbsd")] - #[allow(clippy::no_effect_underscore_binding, clippy::used_underscore_binding)] const _: fn() = || { use imp::ffi; use std::mem; @@ -551,30 +555,5 @@ mod tests { ac_clidr: ffi.clidr, ac_ctr: ffi.ctr, }; - let mut _sysctlbyname: unsafe extern "C" fn( - *const ffi::c_char, - *mut ffi::c_void, - *mut ffi::c_size_t, - *const ffi::c_void, - ffi::c_size_t, - ) -> ffi::c_int = ffi::sysctlbyname; - _sysctlbyname = libc::sysctlbyname; - _sysctlbyname = sys::sysctlbyname; - }; - #[cfg(target_os = "openbsd")] - #[allow(clippy::no_effect_underscore_binding)] - const _: fn() = || { - use imp::ffi; - use test_helper::sys; - let mut _sysctl: unsafe extern "C" fn( - *const ffi::c_int, - ffi::c_uint, - *mut ffi::c_void, - *mut ffi::c_size_t, - *mut ffi::c_void, - ffi::c_size_t, - ) -> ffi::c_int = ffi::sysctl; - _sysctl = libc::sysctl; - _sysctl = sys::sysctl; }; } diff --git a/src/imp/detect/aarch64_apple.rs b/src/imp/detect/aarch64_apple.rs index 0b5a1952..7710dfa3 100644 --- a/src/imp/detect/aarch64_apple.rs +++ b/src/imp/detect/aarch64_apple.rs @@ -27,17 +27,19 @@ use core::{mem, ptr}; mod ffi { pub(crate) use super::c_types::{c_char, c_int, c_size_t, c_void}; - extern "C" { - // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname - // https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/sys/sysctl.h - pub(crate) fn sysctlbyname( - name: *const c_char, - old_p: *mut c_void, - old_len_p: *mut c_size_t, - new_p: *mut c_void, - new_len: c_size_t, - ) -> c_int; - } + sys_fn!({ + extern "C" { + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname + // https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/sys/sysctl.h + pub(crate) fn sysctlbyname( + name: *const c_char, + old_p: *mut c_void, + old_len_p: *mut c_size_t, + new_p: *mut c_void, + new_len: c_size_t, + ) -> c_int; + } + }); } unsafe fn sysctlbyname32(name: &[u8]) -> Option { @@ -258,28 +260,4 @@ mod tests { } } } - - // Static assertions for FFI bindings. - // This checks that FFI bindings defined in this crate, FFI bindings defined - // in libc, and FFI bindings generated for the platform's latest header file - // using bindgen have compatible signatures. - // Since this is static assertion, we can detect problems with - // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) - // without actually running tests on these platforms. - // As for constants, they are checked by static assertions generated by sys_const!. - // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. - // TODO(codegen): auto-generate this test - #[allow(clippy::no_effect_underscore_binding)] - const _: fn() = || { - use test_helper::sys; - let mut _sysctlbyname: unsafe extern "C" fn( - *const ffi::c_char, - *mut ffi::c_void, - *mut ffi::c_size_t, - *mut ffi::c_void, - ffi::c_size_t, - ) -> ffi::c_int = ffi::sysctlbyname; - _sysctlbyname = libc::sysctlbyname; - _sysctlbyname = sys::sysctlbyname; - }; } diff --git a/src/imp/detect/aarch64_fuchsia.rs b/src/imp/detect/aarch64_fuchsia.rs index cdb4bac1..7a207a5a 100644 --- a/src/imp/detect/aarch64_fuchsia.rs +++ b/src/imp/detect/aarch64_fuchsia.rs @@ -27,6 +27,7 @@ mod ffi { pub(crate) const ZX_ARM64_FEATURE_ISA_ATOMICS: u32 = 1 << 8; }); + // TODO: use sys_fn! #[link(name = "zircon")] extern "C" { // https://fuchsia.dev/reference/syscalls/system_get_features @@ -80,12 +81,7 @@ mod tests { // As for constants, they are checked by static assertions generated by sys_const!. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test - #[allow( - clippy::cast_possible_wrap, - clippy::cast_sign_loss, - clippy::cast_possible_truncation, - clippy::no_effect_underscore_binding - )] + #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation)] const _: fn() = || { use test_helper::sys; // TODO(codegen): zx_system_get_features diff --git a/src/imp/detect/aarch64_illumos.rs b/src/imp/detect/aarch64_illumos.rs index 4704dfaa..a401f600 100644 --- a/src/imp/detect/aarch64_illumos.rs +++ b/src/imp/detect/aarch64_illumos.rs @@ -23,12 +23,14 @@ mod ffi { pub(crate) const AV_AARCH64_2_LSE2: u32 = 1 << 2; }); - extern "C" { - // Defined in sys/auxv.h. - // https://illumos.org/man/2/getisax - // https://github.com/richlowe/illumos-gate/blob/arm64-gate/usr/src/uts/common/sys/auxv.h - pub(crate) fn getisax(array: *mut u32, n: c_uint) -> c_uint; - } + sys_fn!({ + extern "C" { + // Defined in sys/auxv.h. + // https://illumos.org/man/2/getisax + // https://github.com/richlowe/illumos-gate/blob/arm64-gate/usr/src/uts/common/sys/auxv.h + pub(crate) fn getisax(array: *mut u32, n: c_uint) -> c_uint; + } + }); } #[cold] @@ -46,33 +48,3 @@ fn _detect(info: &mut CpuInfo) { info.set(CpuInfo::HAS_LSE2); } } - -#[allow( - clippy::alloc_instead_of_core, - clippy::std_instead_of_alloc, - clippy::std_instead_of_core, - clippy::undocumented_unsafe_blocks, - clippy::wildcard_imports -)] -#[cfg(test)] -mod tests { - use super::*; - - // Static assertions for FFI bindings. - // This checks that FFI bindings defined in this crate, FFI bindings defined - // in libc, and FFI bindings generated for the platform's latest header file - // using bindgen have compatible signatures. - // Since this is static assertion, we can detect problems with - // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) - // without actually running tests on these platforms. - // As for constants, they are checked by static assertions generated by sys_const!. - // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. - // TODO(codegen): auto-generate this test - #[allow(clippy::no_effect_underscore_binding)] - const _: fn() = || { - use test_helper::sys; - let mut _getisax: unsafe extern "C" fn(*mut u32, ffi::c_uint) -> ffi::c_uint = ffi::getisax; - _getisax = libc::getisax; - _getisax = sys::getisax; - }; -} diff --git a/src/imp/detect/aarch64_windows.rs b/src/imp/detect/aarch64_windows.rs index 7eb3b875..c4f67db8 100644 --- a/src/imp/detect/aarch64_windows.rs +++ b/src/imp/detect/aarch64_windows.rs @@ -61,12 +61,7 @@ mod tests { // windows-sys' signatures/values.) // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test - #[allow( - clippy::cast_possible_wrap, - clippy::cast_sign_loss, - clippy::cast_possible_truncation, - clippy::no_effect_underscore_binding - )] + #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation)] const _: fn() = || { let _: ffi::DWORD = 0 as windows_sys::Win32::System::Threading::PROCESSOR_FEATURE_ID; let _: ffi::BOOL = 0 as windows_sys::Win32::Foundation::BOOL; diff --git a/src/imp/detect/auxv.rs b/src/imp/detect/auxv.rs index 43d11872..83083d96 100644 --- a/src/imp/detect/auxv.rs +++ b/src/imp/detect/auxv.rs @@ -137,21 +137,26 @@ mod os { pub(crate) const PROP_VALUE_MAX: c_int = 92; }); - extern "C" { - // Defined in sys/auxv.h. - // https://man7.org/linux/man-pages/man3/getauxval.3.html - // https://github.com/bminor/glibc/blob/glibc-2.40/misc/sys/auxv.h - // https://github.com/bminor/musl/blob/v1.2.5/include/sys/auxv.h - // https://github.com/wbx-github/uclibc-ng/blob/v1.0.47/include/sys/auxv.h - // https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h - // https://github.com/picolibc/picolibc/blob/1.8.6/newlib/libc/include/sys/auxv.h - pub(crate) fn getauxval(type_: c_ulong) -> c_ulong; - - // Defined in sys/system_properties.h. - // https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/system_properties.h - #[cfg(all(target_arch = "aarch64", target_os = "android"))] - pub(crate) fn __system_property_get(name: *const c_char, value: *mut c_char) -> c_int; - } + sys_fn!({ + extern "C" { + // Defined in sys/auxv.h. + // https://man7.org/linux/man-pages/man3/getauxval.3.html + // https://github.com/bminor/glibc/blob/glibc-2.40/misc/sys/auxv.h + // https://github.com/bminor/musl/blob/v1.2.5/include/sys/auxv.h + // https://github.com/wbx-github/uclibc-ng/blob/v1.0.47/include/sys/auxv.h + // https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h + // https://github.com/picolibc/picolibc/blob/1.8.6/newlib/libc/include/sys/auxv.h + pub(crate) fn getauxval(type_: c_ulong) -> c_ulong; + + // Defined in sys/system_properties.h. + // https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/system_properties.h + #[cfg(all(target_arch = "aarch64", target_os = "android"))] + pub(crate) fn __system_property_get( + name: *const c_char, + value: *mut c_char, + ) -> c_int; + } + }); } pub(super) fn getauxval(type_: ffi::c_ulong) -> ffi::c_ulong { @@ -202,17 +207,19 @@ mod os { pub(crate) const AT_HWCAP2: c_int = 26; }); - extern "C" { - // FreeBSD - // Defined in sys/auxv.h. - // https://man.freebsd.org/elf_aux_info(3) - // https://github.com/freebsd/freebsd-src/blob/release/14.1.0/sys/sys/auxv.h - // OpenBSD - // Defined in sys/auxv.h. - // https://man.openbsd.org/elf_aux_info.3 - // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/auxv.h - pub(crate) fn elf_aux_info(aux: c_int, buf: *mut c_void, buf_len: c_int) -> c_int; - } + sys_fn!({ + extern "C" { + // FreeBSD + // Defined in sys/auxv.h. + // https://man.freebsd.org/elf_aux_info(3) + // https://github.com/freebsd/freebsd-src/blob/release/14.1.0/sys/sys/auxv.h + // OpenBSD + // Defined in sys/auxv.h. + // https://man.openbsd.org/elf_aux_info.3 + // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/auxv.h + pub(crate) fn elf_aux_info(aux: c_int, buf: *mut c_void, buf_len: c_int) -> c_int; + } + }); } pub(super) fn getauxval(aux: ffi::c_int) -> ffi::c_ulong { @@ -370,6 +377,8 @@ mod arch { )] #[cfg(test)] mod tests { + #[cfg(not(target_os = "openbsd"))] + #[cfg(not(all(target_os = "linux", target_arch = "aarch64", target_pointer_width = "32")))] use super::*; #[allow(clippy::cast_sign_loss)] @@ -817,47 +826,4 @@ mod tests { getauxval_sysctl_no_libc(ffi::AT_HWCAP2).unwrap_or_else(hwcap2_else) ); } - - // Static assertions for FFI bindings. - // This checks that FFI bindings defined in this crate, FFI bindings defined - // in libc, and FFI bindings generated for the platform's latest header file - // using bindgen have compatible signatures. - // Since this is static assertion, we can detect problems with - // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) - // without actually running tests on these platforms. - // As for constants, they are checked by static assertions generated by sys_const!. - // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. - // TODO(codegen): auto-generate this test - #[allow(clippy::no_effect_underscore_binding)] - const _: fn() = || { - use test_helper::sys; - #[cfg(any(target_os = "linux", target_os = "android"))] - { - let mut _getauxval: unsafe extern "C" fn(ffi::c_ulong) -> ffi::c_ulong = ffi::getauxval; - _getauxval = libc::getauxval; - _getauxval = sys::getauxval; - } - #[cfg(all(target_arch = "aarch64", target_os = "android"))] - { - let mut ___system_property_get: unsafe extern "C" fn( - *const ffi::c_char, - *mut ffi::c_char, - ) -> ffi::c_int = ffi::__system_property_get; - ___system_property_get = libc::__system_property_get; - ___system_property_get = sys::__system_property_get; - } - #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] - { - let mut _elf_aux_info: unsafe extern "C" fn( - ffi::c_int, - *mut ffi::c_void, - ffi::c_int, - ) -> ffi::c_int = ffi::elf_aux_info; - #[cfg(not(target_os = "openbsd"))] // libc doesn't have this on OpenBSD - { - _elf_aux_info = libc::elf_aux_info; - } - _elf_aux_info = sys::elf_aux_info; - } - }; } diff --git a/src/imp/detect/common.rs b/src/imp/detect/common.rs index ccb6b4fa..028471a4 100644 --- a/src/imp/detect/common.rs +++ b/src/imp/detect/common.rs @@ -127,6 +127,8 @@ flags! { #[allow(dead_code, unused_macros, non_camel_case_types)] #[macro_use] mod c_types { + /// Defines constants with #[cfg(test)] static assertions which checks + /// values are the same as the platform's latest header files' ones. // Note: This macro is sys_const!({ }), not sys_const! { }. // An extra brace is used in input to make contents rustfmt-able:. macro_rules! sys_const { @@ -159,6 +161,42 @@ mod c_types { }; }; } + /// Defines functions with #[cfg(test)] static assertions which checks + /// signatures are the same as the platform's latest header files' ones. + // Note: This macro is sys_fn!({ }), not sys_fn! { }. + // An extra brace is used in input to make contents rustfmt-able:. + macro_rules! sys_fn { + ({ + $(#[$extern_attr:meta])* + extern $abi:literal {$( + $(#[$fn_attr:meta])* + $vis:vis fn $name:ident($($arg_pat:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?; + )*} + }) => { + $(#[$extern_attr])* + extern $abi {$( + $(#[$fn_attr])* + $vis fn $name($($arg_pat: $arg_ty),*) $(-> $ret_ty)?; + )*} + // Static assertions for FFI bindings. + // This checks that FFI bindings defined in this crate and FFI bindings generated for + // the platform's latest header file using bindgen have the same signatures. + // Since this is static assertion, we can detect problems with + // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) + // without actually running tests on these platforms. + // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. + #[cfg(test)] + const _: fn() = || { + $( + $(#[$fn_attr])* + { + let mut _f: unsafe extern $abi fn($($arg_ty),*) $(-> $ret_ty)? = $name; + _f = test_helper::sys::$name; + } + )* + }; + }; + } pub(crate) type c_void = core::ffi::c_void; // c_{,u}int is {i,u}32 on non-16-bit architectures diff --git a/src/imp/detect/riscv_linux.rs b/src/imp/detect/riscv_linux.rs index ae102d40..a223b4b7 100644 --- a/src/imp/detect/riscv_linux.rs +++ b/src/imp/detect/riscv_linux.rs @@ -37,6 +37,7 @@ mod ffi { pub(crate) const RISCV_HWPROBE_EXT_ZACAS: u64 = 1 << 34; }); + // TODO: use sys_fn! #[cfg(not(all( target_os = "linux", any(target_arch = "riscv32", all(target_arch = "riscv64", target_pointer_width = "64")), @@ -159,7 +160,6 @@ mod tests { // As for constants, they are checked by static assertions generated by sys_const!. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test - #[allow(clippy::no_effect_underscore_binding)] const _: fn() = || { use std::mem; use test_helper::sys;