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 <andrewsadler122@gmail.com>
This commit is contained in:
parent
d7c8e0fb43
commit
a0b4d735e3
@ -434,6 +434,141 @@ macro_rules! require_simd {
|
||||
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 });
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user