Skip to content

Commit

Permalink
Add simd_cast_ptr, simd_expose_addr, and simd_from_exposed_addr intri…
Browse files Browse the repository at this point in the history
…nsics
  • Loading branch information
calebzulawski committed Jul 22, 2022
1 parent 4334739 commit e2866c0
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 1 deletion.
79 changes: 79 additions & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,85 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
bitwise_red!(simd_reduce_all: vector_reduce_and, true);
bitwise_red!(simd_reduce_any: vector_reduce_or, true);

if name == sym::simd_cast_ptr {
require_simd!(ret_ty, "return");
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
"expected return type with length {} (same as input type `{}`), \
found `{}` with length {}",
in_len,
in_ty,
ret_ty,
out_len
);

match in_elem.kind() {
ty::RawPtr(_) => {}
_ => return_error!("expected pointer, got `{}`", in_elem),
}
match out_elem.kind() {
ty::RawPtr(_) => {}
_ => return_error!("expected pointer, got `{}`", out_elem),
}

if in_elem == out_elem {
return Ok(args[0].immediate());
} else {
return Ok(bx.pointercast(args[0].immediate(), llret_ty));
}
}

if name == sym::simd_expose_addr {
require_simd!(ret_ty, "return");
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
"expected return type with length {} (same as input type `{}`), \
found `{}` with length {}",
in_len,
in_ty,
ret_ty,
out_len
);

match in_elem.kind() {
ty::RawPtr(_) => {}
_ => return_error!("expected pointer, got `{}`", in_elem),
}
match out_elem.kind() {
ty::Uint(ty::UintTy::Usize) => {}
_ => return_error!("expected `usize`, got `{}`", out_elem),
}

return Ok(bx.ptrtoint(args[0].immediate(), llret_ty));
}

if name == sym::simd_from_exposed_addr {
require_simd!(ret_ty, "return");
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
"expected return type with length {} (same as input type `{}`), \
found `{}` with length {}",
in_len,
in_ty,
ret_ty,
out_len
);

match in_elem.kind() {
ty::Uint(ty::UintTy::Usize) => {}
_ => return_error!("expected `usize`, got `{}`", in_elem),
}
match out_elem.kind() {
ty::RawPtr(_) => {}
_ => return_error!("expected pointer, got `{}`", out_elem),
}

return Ok(bx.inttoptr(args[0].immediate(), llret_ty));
}

if name == sym::simd_cast || name == sym::simd_as {
require_simd!(ret_ty, "return");
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1275,9 +1275,11 @@ symbols! {
simd_as,
simd_bitmask,
simd_cast,
simd_cast_ptr,
simd_ceil,
simd_div,
simd_eq,
simd_expose_addr,
simd_extract,
simd_fabs,
simd_fcos,
Expand All @@ -1293,6 +1295,7 @@ symbols! {
simd_fmin,
simd_fpow,
simd_fpowi,
simd_from_exposed_addr,
simd_fsin,
simd_fsqrt,
simd_gather,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_typeck/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,11 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()),
sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
sym::simd_cast | sym::simd_as => (2, vec![param(0)], param(1)),
sym::simd_cast
| sym::simd_as
| sym::simd_cast_ptr
| sym::simd_expose_addr
| sym::simd_from_exposed_addr => (2, vec![param(0)], param(1)),
sym::simd_bitmask => (2, vec![param(0)], param(1)),
sym::simd_select | sym::simd_select_bitmask => {
(2, vec![param(0), param(1), param(1)], param(1))
Expand Down
33 changes: 33 additions & 0 deletions src/test/ui/simd/intrinsic/ptr-cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// run-pass

#![feature(repr_simd, platform_intrinsics)]

extern "platform-intrinsic" {
fn simd_cast_ptr<T, U>(x: T) -> U;
fn simd_expose_addr<T, U>(x: T) -> U;
fn simd_from_exposed_addr<T, U>(x: T) -> U;
}

#[derive(Copy, Clone)]
#[repr(simd)]
struct V<T>([T; 2]);

fn main() {
unsafe {
let mut foo = 4i8;
let ptr = &mut foo as *mut i8;

let ptrs = V::<*mut i8>([ptr, core::ptr::null_mut()]);

// change constness and type
let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs);

let exposed_addr: V<usize> = simd_expose_addr(const_ptrs);

let from_exposed_addr: V<*mut i8> = simd_from_exposed_addr(exposed_addr);

assert!(const_ptrs.0 == [ptr as *const u8, core::ptr::null()]);
assert!(exposed_addr.0 == [ptr as usize, 0]);
assert!(from_exposed_addr.0 == ptrs.0);
}
}

0 comments on commit e2866c0

Please sign in to comment.