diff --git a/library/stdarch/crates/stdsimd-verify/src/lib.rs b/library/stdarch/crates/stdsimd-verify/src/lib.rs index bf5bab42c26d..cbe0530970b8 100644 --- a/library/stdarch/crates/stdsimd-verify/src/lib.rs +++ b/library/stdarch/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/library/stdarch/crates/stdsimd-verify/tests/mips.rs b/library/stdarch/crates/stdsimd-verify/tests/mips.rs index 1239c4efbc56..334b001566e6 100644 --- a/library/stdarch/crates/stdsimd-verify/tests/mips.rs +++ b/library/stdarch/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/library/stdarch/crates/stdsimd-verify/tests/x86-intel.rs b/library/stdarch/crates/stdsimd-verify/tests/x86-intel.rs index fe6d80144007..0b1eee07c475 100644 --- a/library/stdarch/crates/stdsimd-verify/tests/x86-intel.rs +++ b/library/stdarch/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, @@ -413,8 +414,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(()); @@ -438,54 +448,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::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::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::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::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::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,