Skip to content

Commit e2866c0

Browse files
committed
Add simd_cast_ptr, simd_expose_addr, and simd_from_exposed_addr intrinsics
1 parent 4334739 commit e2866c0

File tree

4 files changed

+120
-1
lines changed

4 files changed

+120
-1
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

+79
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,85 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
17041704
bitwise_red!(simd_reduce_all: vector_reduce_and, true);
17051705
bitwise_red!(simd_reduce_any: vector_reduce_or, true);
17061706

1707+
if name == sym::simd_cast_ptr {
1708+
require_simd!(ret_ty, "return");
1709+
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
1710+
require!(
1711+
in_len == out_len,
1712+
"expected return type with length {} (same as input type `{}`), \
1713+
found `{}` with length {}",
1714+
in_len,
1715+
in_ty,
1716+
ret_ty,
1717+
out_len
1718+
);
1719+
1720+
match in_elem.kind() {
1721+
ty::RawPtr(_) => {}
1722+
_ => return_error!("expected pointer, got `{}`", in_elem),
1723+
}
1724+
match out_elem.kind() {
1725+
ty::RawPtr(_) => {}
1726+
_ => return_error!("expected pointer, got `{}`", out_elem),
1727+
}
1728+
1729+
if in_elem == out_elem {
1730+
return Ok(args[0].immediate());
1731+
} else {
1732+
return Ok(bx.pointercast(args[0].immediate(), llret_ty));
1733+
}
1734+
}
1735+
1736+
if name == sym::simd_expose_addr {
1737+
require_simd!(ret_ty, "return");
1738+
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
1739+
require!(
1740+
in_len == out_len,
1741+
"expected return type with length {} (same as input type `{}`), \
1742+
found `{}` with length {}",
1743+
in_len,
1744+
in_ty,
1745+
ret_ty,
1746+
out_len
1747+
);
1748+
1749+
match in_elem.kind() {
1750+
ty::RawPtr(_) => {}
1751+
_ => return_error!("expected pointer, got `{}`", in_elem),
1752+
}
1753+
match out_elem.kind() {
1754+
ty::Uint(ty::UintTy::Usize) => {}
1755+
_ => return_error!("expected `usize`, got `{}`", out_elem),
1756+
}
1757+
1758+
return Ok(bx.ptrtoint(args[0].immediate(), llret_ty));
1759+
}
1760+
1761+
if name == sym::simd_from_exposed_addr {
1762+
require_simd!(ret_ty, "return");
1763+
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
1764+
require!(
1765+
in_len == out_len,
1766+
"expected return type with length {} (same as input type `{}`), \
1767+
found `{}` with length {}",
1768+
in_len,
1769+
in_ty,
1770+
ret_ty,
1771+
out_len
1772+
);
1773+
1774+
match in_elem.kind() {
1775+
ty::Uint(ty::UintTy::Usize) => {}
1776+
_ => return_error!("expected `usize`, got `{}`", in_elem),
1777+
}
1778+
match out_elem.kind() {
1779+
ty::RawPtr(_) => {}
1780+
_ => return_error!("expected pointer, got `{}`", out_elem),
1781+
}
1782+
1783+
return Ok(bx.inttoptr(args[0].immediate(), llret_ty));
1784+
}
1785+
17071786
if name == sym::simd_cast || name == sym::simd_as {
17081787
require_simd!(ret_ty, "return");
17091788
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());

compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1275,9 +1275,11 @@ symbols! {
12751275
simd_as,
12761276
simd_bitmask,
12771277
simd_cast,
1278+
simd_cast_ptr,
12781279
simd_ceil,
12791280
simd_div,
12801281
simd_eq,
1282+
simd_expose_addr,
12811283
simd_extract,
12821284
simd_fabs,
12831285
simd_fcos,
@@ -1293,6 +1295,7 @@ symbols! {
12931295
simd_fmin,
12941296
simd_fpow,
12951297
simd_fpowi,
1298+
simd_from_exposed_addr,
12961299
simd_fsin,
12971300
simd_fsqrt,
12981301
simd_gather,

compiler/rustc_typeck/src/check/intrinsic.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,11 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
461461
sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()),
462462
sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
463463
sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
464-
sym::simd_cast | sym::simd_as => (2, vec![param(0)], param(1)),
464+
sym::simd_cast
465+
| sym::simd_as
466+
| sym::simd_cast_ptr
467+
| sym::simd_expose_addr
468+
| sym::simd_from_exposed_addr => (2, vec![param(0)], param(1)),
465469
sym::simd_bitmask => (2, vec![param(0)], param(1)),
466470
sym::simd_select | sym::simd_select_bitmask => {
467471
(2, vec![param(0), param(1), param(1)], param(1))
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// run-pass
2+
3+
#![feature(repr_simd, platform_intrinsics)]
4+
5+
extern "platform-intrinsic" {
6+
fn simd_cast_ptr<T, U>(x: T) -> U;
7+
fn simd_expose_addr<T, U>(x: T) -> U;
8+
fn simd_from_exposed_addr<T, U>(x: T) -> U;
9+
}
10+
11+
#[derive(Copy, Clone)]
12+
#[repr(simd)]
13+
struct V<T>([T; 2]);
14+
15+
fn main() {
16+
unsafe {
17+
let mut foo = 4i8;
18+
let ptr = &mut foo as *mut i8;
19+
20+
let ptrs = V::<*mut i8>([ptr, core::ptr::null_mut()]);
21+
22+
// change constness and type
23+
let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs);
24+
25+
let exposed_addr: V<usize> = simd_expose_addr(const_ptrs);
26+
27+
let from_exposed_addr: V<*mut i8> = simd_from_exposed_addr(exposed_addr);
28+
29+
assert!(const_ptrs.0 == [ptr as *const u8, core::ptr::null()]);
30+
assert!(exposed_addr.0 == [ptr as usize, 0]);
31+
assert!(from_exposed_addr.0 == ptrs.0);
32+
}
33+
}

0 commit comments

Comments
 (0)