-
-
Notifications
You must be signed in to change notification settings - Fork 16k
implement VaArgSafe for f128
#161424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
implement VaArgSafe for f128
#161424
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| #![crate_type = "staticlib"] | ||
| #![feature(c_variadic_int128, c_variadic_experimental_arch)] | ||
| #![feature(c_variadic_int128, c_variadic_experimental_arch, f128)] | ||
|
|
||
| use core::ffi::{CStr, VaList, c_char, c_double, c_int, c_long, c_longlong}; | ||
|
|
||
|
|
@@ -100,6 +100,59 @@ pub unsafe extern "C" fn check_list_i128(mut ap: VaList) -> usize { | |
| } | ||
| } | ||
|
|
||
| cfg_select! { | ||
| any( | ||
| all(target_arch = "x86_64", not(target_vendor = "apple"), not(target_env = "msvc")), | ||
| all(target_arch = "x86", not(target_vendor = "apple"), not(target_env = "msvc")), | ||
| all(target_arch = "powerpc64", target_feature = "vsx"), | ||
| all( | ||
| not(windows), | ||
| not(target_vendor = "apple"), | ||
| any( | ||
| target_arch = "aarch64", | ||
| target_arch = "loongarch32", | ||
| target_arch = "loongarch64", | ||
| target_arch = "mips64", | ||
| target_arch = "mips64r6", | ||
| target_arch = "riscv64", | ||
| target_arch = "s390x", | ||
| target_arch = "sparc", | ||
| target_arch = "sparc64", | ||
| target_arch = "wasm32", | ||
| target_arch = "wasm64", | ||
| ), | ||
| ), | ||
| ) => { | ||
| #[unsafe(no_mangle)] | ||
| pub static RUST_HAS_F128: c_int = 1; | ||
|
Comment on lines
+126
to
+127
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is needed on powerpc64 where (at least my) GCC does have f128 support but our baseline does not. |
||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub unsafe extern "C" fn check_list_f128(mut ap: VaList) -> usize { | ||
| continue_if!(ap.next_arg::<f128>() == -42.0); | ||
| // use a 32-bit value here to test the alignment logic. | ||
| continue_if!(ap.next_arg::<c_int>() == 0xAAAA_AAAAu32.cast_signed()); | ||
| continue_if!(ap.next_arg::<f128>() == f128::MAX); | ||
|
|
||
| return 0; | ||
| } | ||
| } | ||
| _ => { | ||
| #[unsafe(no_mangle)] | ||
| pub static RUST_HAS_F128: c_int = 0; | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub unsafe extern "C" fn check_list_f128(_: VaList) -> usize { | ||
| // This function was called a platform where rustc does not implement | ||
| // VaArgSafe for f128 but clang does define _Float128. | ||
| // | ||
| // This occurs on powerpc64 where f128 support depends on a target feature. | ||
| // | ||
| // Otherwise, rustc should add the implementation if this comes up. | ||
| 0xFF | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[unsafe(no_mangle)] | ||
| pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize { | ||
| continue_if!(ap.next_arg::<c_int>() == 42); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,12 +3,14 @@ | |
| #include <stdint.h> | ||
| #include <stdlib.h> | ||
| #include <stdio.h> | ||
| #include <math.h> | ||
|
|
||
| extern size_t check_list_0(va_list ap); | ||
| extern size_t check_list_1(va_list ap); | ||
| extern size_t check_list_2(va_list ap); | ||
| extern size_t check_list_copy_0(va_list ap); | ||
| extern size_t check_list_i128(va_list ap); | ||
| extern size_t check_list_f128(va_list ap); | ||
| extern size_t check_varargs_0(int fixed, ...); | ||
| extern size_t check_varargs_1(int fixed, ...); | ||
| extern size_t check_varargs_2(int fixed, ...); | ||
|
|
@@ -21,6 +23,9 @@ extern size_t run_test_va_list_by_value(); | |
| extern size_t run_test_va_list_by_pointer(); | ||
| extern size_t run_test_va_list_by_pointer_pointer(); | ||
|
|
||
| // Was the rust side compiled with f128 support? | ||
| extern const int RUST_HAS_F128; | ||
|
|
||
| int test_rust(size_t (*fn)(va_list), ...) { | ||
| size_t ret = 0; | ||
| va_list ap; | ||
|
|
@@ -40,9 +45,43 @@ int main(int argc, char* argv[]) { | |
| assert(test_rust(check_list_copy_0, 6.28, 16, 'A', "Skip Me!", "Correct") == 0); | ||
|
|
||
| #if defined(__SIZEOF_INT128__) | ||
|
|
||
| assert(test_rust(check_list_i128, (__int128)-42, 0xAAAAAAAA, (unsigned __int128)-1) == 0); | ||
| #endif | ||
|
|
||
| // Run the f128 test when __float128/_Float128 is defined or long double is IEEE f128. | ||
| // Use #define instead of typedef so that `#ifdef` can detect it. | ||
| #if defined(__LDBL_MANT_DIG__) && __LDBL_MANT_DIG__ == 113 | ||
| #define f128 long double | ||
| #elif defined(__SIZEOF_FLOAT128__) | ||
| #ifdef __clang__ | ||
| #define f128 __float128 | ||
| #else | ||
| #define f128 _Float128 | ||
| #endif | ||
| #endif | ||
|
|
||
| #ifdef f128 | ||
| // construct f128::MAX. | ||
| union cvt128 { | ||
| struct { | ||
| #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) | ||
| uint64_t hi, lo; | ||
| #else | ||
| uint64_t lo, hi; | ||
| #endif | ||
| } i; | ||
| f128 f; | ||
| }; | ||
| union cvt128 f128_max; | ||
| f128_max.i.hi = 0x7ffeffffffffffff; | ||
| f128_max.i.lo = 0xffffffffffffffff; | ||
|
|
||
| if (RUST_HAS_F128) { | ||
| assert(test_rust(check_list_f128, (f128)-42.0, 0xAAAAAAAA, f128_max.f) == 0); | ||
| } | ||
| #endif | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better to load a literal for union cvt128 {
struct {
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
uint64_t lo, hi;
#else
uint64_t hi, lo;
#endif
} i;
_Float128 f;
};
union cvt128 f128_max;
f128_max.i.hi = 0x7ffeffffffffffff;
f128_max.i.lo = 0xffffffffffffffff;
assert(test_rust(check_list_f128, (f128)-42.0, 0xAAAAAAAA, f128_max.f) == 0);Kind of annoying that llvm/llvm-project#97335 is still open and we can't just use |
||
|
|
||
| assert(check_varargs_0(0, 42, "Hello, World!") == 0); | ||
|
|
||
| assert(check_varargs_1(0, 3.14, 12l, 'A', 0x1LL) == 0); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.