From a0b4d735e33811941e0eceb4cbedc8aaec6af3d3 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Wed, 8 May 2024 20:51:21 -0500 Subject: [PATCH] simd: implement pointer provenance intrinsics This adds support for the simd variants of the pointer provenance intrinsics, which are `simd_cast_ptr`, `simd_expose_addr`, and `simd_from_exposed_addr`. The preconditions for each intrinsic are adapted from rustc_codegen_llvm to preserve compatibility. Each of these intrinsics are implemented as calling the non-simd variant of each intrinsic on each lane. This is enough to enable the UI test `ui/simd/intrinsic/ptr-cast.rs` to pass. Signed-off-by: Andy Sadler --- src/intrinsic/simd.rs | 135 +++++++++++++++++++++++++++++++++++++ tests/failing-ui-tests.txt | 1 - 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 6d8ed519b4c..a8d7c37dc87 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -434,6 +434,141 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); } + if name == sym::simd_cast_ptr { + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); + let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); + + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); + + match *in_elem.kind() { + ty::RawPtr(p) => { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + }); + require!( + metadata.is_unit(), + InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem } + ); + } + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) + } + } + match *out_elem.kind() { + ty::RawPtr(p) => { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) + }); + require!( + metadata.is_unit(), + InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem } + ); + } + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) + } + } + + let arg = args[0].immediate(); + let elem_type = llret_ty.dyncast_vector().expect("vector return type").get_element_type(); + let values: Vec<_> = (0..in_len) + .map(|i| { + let idx = bx.gcc_int(bx.usize_type, i as _); + let value = bx.extract_element(arg, idx); + bx.pointercast(value, elem_type) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); + } + + if name == sym::simd_expose_addr { + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); + let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); + + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); + + match *in_elem.kind() { + ty::RawPtr(_) => {} + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) + } + } + match *out_elem.kind() { + ty::Uint(ty::UintTy::Usize) => {} + _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: out_elem }), + } + + let arg = args[0].immediate(); + let elem_type = llret_ty.dyncast_vector().expect("vector return type").get_element_type(); + let values: Vec<_> = (0..in_len) + .map(|i| { + let idx = bx.gcc_int(bx.usize_type, i as _); + let value = bx.extract_element(arg, idx); + bx.ptrtoint(value, elem_type) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); + } + + if name == sym::simd_from_exposed_addr { + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); + let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); + + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); + + match *in_elem.kind() { + ty::Uint(ty::UintTy::Usize) => {} + _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: in_elem }), + } + match *out_elem.kind() { + ty::RawPtr(_) => {} + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) + } + } + + let arg = args[0].immediate(); + let elem_type = llret_ty.dyncast_vector().expect("vector return type").get_element_type(); + let values: Vec<_> = (0..in_len) + .map(|i| { + let idx = bx.gcc_int(bx.usize_type, i as _); + let value = bx.extract_element(arg, idx); + bx.inttoptr(value, elem_type) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); + } + #[cfg(feature = "master")] if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 4f0c9814e73..1521a4d2547 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -33,7 +33,6 @@ tests/ui/panic-runtime/abort.rs tests/ui/panic-runtime/link-to-abort.rs tests/ui/unwind-no-uwtable.rs tests/ui/parser/unclosed-delimiter-in-dep.rs -tests/ui/simd/intrinsic/ptr-cast.rs tests/ui/consts/missing_span_in_backtrace.rs tests/ui/drop/dynamic-drop.rs tests/ui/issues/issue-40883.rs