From 954f509f52fbc783b18c19f250385b49373d7b75 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 26 Apr 2019 09:04:41 +0200 Subject: [PATCH 1/5] Automatic-verification of x86-intrinsic should distinguish const/mut pointers --- crates/stdsimd-verify/src/lib.rs | 24 ++++- crates/stdsimd-verify/tests/mips.rs | 7 +- crates/stdsimd-verify/tests/x86-intel.rs | 118 +++++++++++++++-------- 3 files changed, 102 insertions(+), 47 deletions(-) diff --git a/crates/stdsimd-verify/src/lib.rs b/crates/stdsimd-verify/src/lib.rs index 884f956994..54230b664d 100644 --- a/crates/stdsimd-verify/src/lib.rs +++ b/crates/stdsimd-verify/src/lib.rs @@ -195,11 +195,27 @@ fn to_type(t: &syn::Type) -> proc_macro2::TokenStream { s => panic!("unspported type: \"{}\"", s), }, - syn::Type::Ptr(syn::TypePtr { ref elem, .. }) - | syn::Type::Reference(syn::TypeReference { ref elem, .. }) => { - let tokens = to_type(&elem); - quote! { &Type::Ptr(#tokens) } + syn::Type::Ptr(syn::TypePtr { + ref elem, + ref mutability, + .. + }) + | syn::Type::Reference(syn::TypeReference { + ref elem, + ref mutability, + .. + }) => { + // Both pointers and references can have a mut token (*mut and &mut) + if mutability.is_some() { + let tokens = to_type(&elem); + quote! { &Type::MutPtr(#tokens) } + } else { + // If they don't (*const or &) then they are "const" + let tokens = to_type(&elem); + quote! { &Type::ConstPtr(#tokens) } + } } + syn::Type::Slice(_) => panic!("unsupported slice"), syn::Type::Array(_) => panic!("unsupported array"), syn::Type::Tuple(_) => quote! { &TUPLE }, diff --git a/crates/stdsimd-verify/tests/mips.rs b/crates/stdsimd-verify/tests/mips.rs index 1239c4efbc..334b001566 100644 --- a/crates/stdsimd-verify/tests/mips.rs +++ b/crates/stdsimd-verify/tests/mips.rs @@ -51,7 +51,6 @@ enum Type { PrimPoly(u8), MutPtr(&'static Type), ConstPtr(&'static Type), - Ptr(&'static Type), Tuple, I(u8, u8, u8), U(u8, u8, u8), @@ -91,7 +90,7 @@ enum MsaTy { i64, u64, Void, - VoidPtr, + MutVoidPtr, } impl<'a> From<&'a str> for MsaTy { @@ -125,7 +124,7 @@ impl<'a> From<&'a str> for MsaTy { "i64" => MsaTy::i64, "u64" => MsaTy::u64, "void" => MsaTy::Void, - "void *" => MsaTy::VoidPtr, + "void *" => MsaTy::MutVoidPtr, v => panic!("unknown ty: \"{}\"", v), } } @@ -273,7 +272,7 @@ fn matches(rust: &Function, mips: &MsaIntrinsic) -> Result<(), String> { MsaTy::i64 if **rust_arg == I64 => (), MsaTy::u32 if **rust_arg == U32 => (), MsaTy::u64 if **rust_arg == U64 => (), - MsaTy::VoidPtr if **rust_arg == Type::Ptr(&U8) => (), + MsaTy::MutVoidPtr if **rust_arg == Type::MutPtr(&U8) => (), m => bail!( "mismatched argument \"{}\"= \"{:?}\" != \"{:?}\"", i, diff --git a/crates/stdsimd-verify/tests/x86-intel.rs b/crates/stdsimd-verify/tests/x86-intel.rs index 3de07f30f4..6ea284639c 100644 --- a/crates/stdsimd-verify/tests/x86-intel.rs +++ b/crates/stdsimd-verify/tests/x86-intel.rs @@ -62,7 +62,8 @@ enum Type { PrimFloat(u8), PrimSigned(u8), PrimUnsigned(u8), - Ptr(&'static Type), + MutPtr(&'static Type), + ConstPtr(&'static Type), M64, M128, M128D, @@ -409,8 +410,17 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> { } fn equate(t: &Type, intel: &str, intrinsic: &str, is_const: bool) -> Result<(), String> { - let intel = intel.replace(" *", "*"); - let intel = intel.replace(" const*", "*"); + // Make pointer adjacent to the type: float * foo => float* foo + let mut intel = intel.replace(" *", "*"); + // Make mutability modifier adjacent to the pointer: + // float const * foo => float const* foo + intel = intel.replace("const *", "const*"); + // Normalize mutability modifier to after the type: + // const float* foo => float const* + if intel.starts_with("const") && intel.ends_with("*") { + intel = intel.replace("const ", ""); + intel = intel.replace("*", " const*"); + } let require_const = || { if is_const { return Ok(()); @@ -434,54 +444,84 @@ fn equate(t: &Type, intel: &str, intrinsic: &str, is_const: bool) -> Result<(), (&Type::PrimUnsigned(32), "const unsigned int") => {} (&Type::PrimUnsigned(64), "unsigned __int64") => {} (&Type::PrimUnsigned(8), "unsigned char") => {} - - (&Type::Ptr(&Type::PrimFloat(32)), "float*") => {} - (&Type::Ptr(&Type::PrimFloat(64)), "double*") => {} - (&Type::Ptr(&Type::PrimSigned(32)), "int*") => {} - (&Type::Ptr(&Type::PrimSigned(32)), "__int32*") => {} - (&Type::Ptr(&Type::PrimSigned(64)), "__int64*") => {} - (&Type::Ptr(&Type::PrimSigned(8)), "char*") => {} - (&Type::Ptr(&Type::PrimUnsigned(16)), "unsigned short*") => {} - (&Type::Ptr(&Type::PrimUnsigned(32)), "unsigned int*") => {} - (&Type::Ptr(&Type::PrimUnsigned(64)), "unsigned __int64*") => {} - (&Type::Ptr(&Type::PrimUnsigned(8)), "const void*") => {} - (&Type::Ptr(&Type::PrimUnsigned(8)), "void*") => {} - - (&Type::M64, "__m64") | (&Type::Ptr(&Type::M64), "__m64*") => {} - - (&Type::M128I, "__m128i") - | (&Type::Ptr(&Type::M128I), "__m128i*") - | (&Type::M128D, "__m128d") - | (&Type::Ptr(&Type::M128D), "__m128d*") - | (&Type::M128, "__m128") - | (&Type::Ptr(&Type::M128), "__m128*") => {} - - (&Type::M256I, "__m256i") - | (&Type::Ptr(&Type::M256I), "__m256i*") - | (&Type::M256D, "__m256d") - | (&Type::Ptr(&Type::M256D), "__m256d*") - | (&Type::M256, "__m256") - | (&Type::Ptr(&Type::M256), "__m256*") => {} - - (&Type::M512I, "__m512i") - | (&Type::Ptr(&Type::M512I), "__m512i*") - | (&Type::M512D, "__m512d") - | (&Type::Ptr(&Type::M512D), "__m512d*") - | (&Type::M512, "__m512") - | (&Type::Ptr(&Type::M512), "__m512*") => {} + (&Type::M64, "__m64") => {} + (&Type::M128, "__m128") => {} + (&Type::M128I, "__m128i") => {} + (&Type::M128D, "__m128d") => {} + (&Type::M256, "__m256") => {} + (&Type::M256I, "__m256i") => {} + (&Type::M256D, "__m256d") => {} + (&Type::M512, "__m512") => {} + (&Type::M512I, "__m512i") => {} + (&Type::M512D, "__m512d") => {} + + (&Type::MutPtr(&Type::PrimFloat(32)), "float*") => {} + (&Type::MutPtr(&Type::PrimFloat(64)), "double*") => {} + (&Type::MutPtr(&Type::PrimSigned(32)), "int*") => {} + (&Type::MutPtr(&Type::PrimSigned(32)), "__int32*") => {} + (&Type::MutPtr(&Type::PrimSigned(64)), "__int64*") => {} + (&Type::MutPtr(&Type::PrimSigned(8)), "char*") => {} + (&Type::MutPtr(&Type::PrimUnsigned(16)), "unsigned short*") => {} + (&Type::MutPtr(&Type::PrimUnsigned(32)), "unsigned int*") => {} + (&Type::MutPtr(&Type::PrimUnsigned(64)), "unsigned __int64*") => {} + (&Type::MutPtr(&Type::PrimUnsigned(8)), "void*") => {} + (&Type::MutPtr(&Type::M64), "__m64*") => {} + (&Type::MutPtr(&Type::M128), "__m128*") => {} + (&Type::MutPtr(&Type::M128I), "__m128i*") => {} + (&Type::MutPtr(&Type::M128D), "__m128d*") => {} + (&Type::MutPtr(&Type::M256), "__m256*") => {} + (&Type::MutPtr(&Type::M256I), "__m256i*") => {} + (&Type::MutPtr(&Type::M256D), "__m256d*") => {} + (&Type::MutPtr(&Type::M512), "__m512*") => {} + (&Type::MutPtr(&Type::M512I), "__m512i*") => {} + (&Type::MutPtr(&Type::M512D), "__m512d*") => {} + + (&Type::ConstPtr(&Type::PrimFloat(32)), "float const*") => {} + (&Type::ConstPtr(&Type::PrimFloat(64)), "double const*") => {} + (&Type::ConstPtr(&Type::PrimSigned(32)), "int const*") => {} + (&Type::ConstPtr(&Type::PrimSigned(32)), "__int32 const*") => {} + (&Type::ConstPtr(&Type::PrimSigned(64)), "__int64 const*") => {} + (&Type::ConstPtr(&Type::PrimSigned(8)), "char const*") => {} + (&Type::ConstPtr(&Type::PrimUnsigned(16)), "unsigned short const*") => {} + (&Type::ConstPtr(&Type::PrimUnsigned(32)), "unsigned int const*") => {} + (&Type::ConstPtr(&Type::PrimUnsigned(64)), "unsigned __int64 const*") => {} + (&Type::ConstPtr(&Type::PrimUnsigned(8)), "void const*") => {} + (&Type::ConstPtr(&Type::M64), "__m64 const*") => {} + (&Type::ConstPtr(&Type::M128), "__m128 const*") => {} + (&Type::ConstPtr(&Type::M128I), "__m128i const*") => {} + (&Type::ConstPtr(&Type::M128D), "__m128d const*") => {} + (&Type::ConstPtr(&Type::M256), "__m256 const*") => {} + (&Type::ConstPtr(&Type::M256I), "__m256i const*") => {} + (&Type::ConstPtr(&Type::M256D), "__m256d const*") => {} + (&Type::ConstPtr(&Type::M512), "__m512 const*") => {} + (&Type::ConstPtr(&Type::M512I), "__m512i const*") => {} + (&Type::ConstPtr(&Type::M512D), "__m512d const*") => {} (&Type::MMASK16, "__mmask16") => {} // This is a macro (?) in C which seems to mutate its arguments, but // that means that we're taking pointers to arguments in rust // as we're not exposing it as a macro. - (&Type::Ptr(&Type::M128), "__m128") if intrinsic == "_MM_TRANSPOSE4_PS" => {} + (&Type::MutPtr(&Type::M128), "__m128") if intrinsic == "_MM_TRANSPOSE4_PS" => {} // The _rdtsc intrinsic uses a __int64 return type, but this is a bug in // the intrinsics guide: https://github.com/rust-lang-nursery/stdsimd/issues/559 // We have manually fixed the bug by changing the return type to `u64`. (&Type::PrimUnsigned(64), "__int64") if intrinsic == "_rdtsc" => {} + // The _bittest and _bittest64 intrinsics takes a mutable pointer in the + // intrinsics guide even though it never writes through the pointer: + (&Type::ConstPtr(&Type::PrimSigned(32)), "__int32*") if intrinsic == "_bittest" => {} + (&Type::ConstPtr(&Type::PrimSigned(64)), "__int64*") if intrinsic == "_bittest64" => {} + // The _xrstor, _fxrstor, _xrstor64, _fxrstor64 intrinsics take a + // mutable pointer in the intrinsics guide even though they never write + // through the pointer: + (&Type::ConstPtr(&Type::PrimUnsigned(8)), "void*") + if intrinsic == "_xrstor" + || intrinsic == "_xrstor64" + || intrinsic == "_fxrstor" + || intrinsic == "_fxrstor64" => {} + _ => bail!( "failed to equate: `{}` and {:?} for {}", intel, From 4cd3f7d3ef4d7103b7d678e9d4aae370ae79af6b Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 26 Apr 2019 09:06:17 +0200 Subject: [PATCH 2/5] [breaking change] _mm_clflush takes a const pointer --- crates/core_arch/src/x86/sse2.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/core_arch/src/x86/sse2.rs b/crates/core_arch/src/x86/sse2.rs index 560b2f538b..43faa8d582 100644 --- a/crates/core_arch/src/x86/sse2.rs +++ b/crates/core_arch/src/x86/sse2.rs @@ -33,7 +33,7 @@ pub unsafe fn _mm_pause() { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(clflush))] #[stable(feature = "simd_x86", since = "1.27.0")] -pub unsafe fn _mm_clflush(p: *mut u8) { +pub unsafe fn _mm_clflush(p: *const u8) { clflush(p) } @@ -3014,7 +3014,7 @@ extern "C" { #[link_name = "llvm.x86.sse2.pause"] fn pause(); #[link_name = "llvm.x86.sse2.clflush"] - fn clflush(p: *mut u8); + fn clflush(p: *const u8); #[link_name = "llvm.x86.sse2.lfence"] fn lfence(); #[link_name = "llvm.x86.sse2.mfence"] @@ -3203,7 +3203,7 @@ mod tests { #[simd_test(enable = "sse2")] unsafe fn test_mm_clflush() { let x = 0; - _mm_clflush(&x as *const _ as *mut u8); + _mm_clflush(&x as *const _); } #[simd_test(enable = "sse2")] From ca5ce9453173f97f95703116009487deeeb5ee3d Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 26 Apr 2019 09:09:14 +0200 Subject: [PATCH 3/5] [breaking change] _mm256_store_p{d, s} take a mut pointer Closes #743 . --- crates/core_arch/src/x86/avx.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core_arch/src/x86/avx.rs b/crates/core_arch/src/x86/avx.rs index 6d4e887447..180b6e7238 100644 --- a/crates/core_arch/src/x86/avx.rs +++ b/crates/core_arch/src/x86/avx.rs @@ -1634,7 +1634,7 @@ pub unsafe fn _mm256_load_pd(mem_addr: *const f64) -> __m256d { #[cfg_attr(test, assert_instr(vmovaps))] // FIXME vmovapd expected #[stable(feature = "simd_x86", since = "1.27.0")] #[allow(clippy::cast_ptr_alignment)] -pub unsafe fn _mm256_store_pd(mem_addr: *const f64, a: __m256d) { +pub unsafe fn _mm256_store_pd(mem_addr: *mut f64, a: __m256d) { *(mem_addr as *mut __m256d) = a; } @@ -1664,7 +1664,7 @@ pub unsafe fn _mm256_load_ps(mem_addr: *const f32) -> __m256 { #[cfg_attr(test, assert_instr(vmovaps))] #[stable(feature = "simd_x86", since = "1.27.0")] #[allow(clippy::cast_ptr_alignment)] -pub unsafe fn _mm256_store_ps(mem_addr: *const f32, a: __m256) { +pub unsafe fn _mm256_store_ps(mem_addr: *mut f32, a: __m256) { *(mem_addr as *mut __m256) = a; } From 8eab9a95cc6b6d88393e6428f84cf6faf2c7af31 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sun, 28 Apr 2019 13:34:15 +0200 Subject: [PATCH 4/5] Fix cast in test --- crates/core_arch/src/x86/sse2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core_arch/src/x86/sse2.rs b/crates/core_arch/src/x86/sse2.rs index 43faa8d582..71a9299f2e 100644 --- a/crates/core_arch/src/x86/sse2.rs +++ b/crates/core_arch/src/x86/sse2.rs @@ -3202,7 +3202,7 @@ mod tests { #[simd_test(enable = "sse2")] unsafe fn test_mm_clflush() { - let x = 0; + let x = 0_u8; _mm_clflush(&x as *const _); } From 3f3a8450f51838631e06e1257ac79ba80787eb73 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 30 Apr 2019 12:04:05 +0200 Subject: [PATCH 5/5] align_offset is stable --- crates/core_arch/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/core_arch/src/lib.rs b/crates/core_arch/src/lib.rs index d936d0cc1c..dcec914bcc 100644 --- a/crates/core_arch/src/lib.rs +++ b/crates/core_arch/src/lib.rs @@ -17,7 +17,6 @@ rustc_attrs, stdsimd, staged_api, - align_offset, maybe_uninit, doc_cfg, mmx_target_feature,