Skip to content

Commit cbd561d

Browse files
authored
Rollup merge of rust-lang#98441 - calebzulawski:simd_as, r=oli-obk
Implement simd_as for pointers Expands `simd_as` (and `simd_cast`) to handle pointer-to-pointer, pointer-to-integer, and integer-to-pointer conversions. cc ``@programmerjake`` ``@thomcc``
2 parents 3ad81e0 + 3f2ce06 commit cbd561d

File tree

4 files changed

+132
-1
lines changed

4 files changed

+132
-1
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

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

1708+
if name == sym::simd_cast_ptr {
1709+
require_simd!(ret_ty, "return");
1710+
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
1711+
require!(
1712+
in_len == out_len,
1713+
"expected return type with length {} (same as input type `{}`), \
1714+
found `{}` with length {}",
1715+
in_len,
1716+
in_ty,
1717+
ret_ty,
1718+
out_len
1719+
);
1720+
1721+
match in_elem.kind() {
1722+
ty::RawPtr(p) => {
1723+
let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
1724+
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
1725+
});
1726+
assert!(!check_sized); // we are in codegen, so we shouldn't see these types
1727+
require!(metadata.is_unit(), "cannot cast fat pointer `{}`", in_elem)
1728+
}
1729+
_ => return_error!("expected pointer, got `{}`", in_elem),
1730+
}
1731+
match out_elem.kind() {
1732+
ty::RawPtr(p) => {
1733+
let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
1734+
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
1735+
});
1736+
assert!(!check_sized); // we are in codegen, so we shouldn't see these types
1737+
require!(metadata.is_unit(), "cannot cast to fat pointer `{}`", out_elem)
1738+
}
1739+
_ => return_error!("expected pointer, got `{}`", out_elem),
1740+
}
1741+
1742+
if in_elem == out_elem {
1743+
return Ok(args[0].immediate());
1744+
} else {
1745+
return Ok(bx.pointercast(args[0].immediate(), llret_ty));
1746+
}
1747+
}
1748+
1749+
if name == sym::simd_expose_addr {
1750+
require_simd!(ret_ty, "return");
1751+
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
1752+
require!(
1753+
in_len == out_len,
1754+
"expected return type with length {} (same as input type `{}`), \
1755+
found `{}` with length {}",
1756+
in_len,
1757+
in_ty,
1758+
ret_ty,
1759+
out_len
1760+
);
1761+
1762+
match in_elem.kind() {
1763+
ty::RawPtr(_) => {}
1764+
_ => return_error!("expected pointer, got `{}`", in_elem),
1765+
}
1766+
match out_elem.kind() {
1767+
ty::Uint(ty::UintTy::Usize) => {}
1768+
_ => return_error!("expected `usize`, got `{}`", out_elem),
1769+
}
1770+
1771+
return Ok(bx.ptrtoint(args[0].immediate(), llret_ty));
1772+
}
1773+
1774+
if name == sym::simd_from_exposed_addr {
1775+
require_simd!(ret_ty, "return");
1776+
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
1777+
require!(
1778+
in_len == out_len,
1779+
"expected return type with length {} (same as input type `{}`), \
1780+
found `{}` with length {}",
1781+
in_len,
1782+
in_ty,
1783+
ret_ty,
1784+
out_len
1785+
);
1786+
1787+
match in_elem.kind() {
1788+
ty::Uint(ty::UintTy::Usize) => {}
1789+
_ => return_error!("expected `usize`, got `{}`", in_elem),
1790+
}
1791+
match out_elem.kind() {
1792+
ty::RawPtr(_) => {}
1793+
_ => return_error!("expected pointer, got `{}`", out_elem),
1794+
}
1795+
1796+
return Ok(bx.inttoptr(args[0].immediate(), llret_ty));
1797+
}
1798+
17081799
if name == sym::simd_cast || name == sym::simd_as {
17091800
require_simd!(ret_ty, "return");
17101801
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
@@ -1322,9 +1322,11 @@ symbols! {
13221322
simd_as,
13231323
simd_bitmask,
13241324
simd_cast,
1325+
simd_cast_ptr,
13251326
simd_ceil,
13261327
simd_div,
13271328
simd_eq,
1329+
simd_expose_addr,
13281330
simd_extract,
13291331
simd_fabs,
13301332
simd_fcos,
@@ -1340,6 +1342,7 @@ symbols! {
13401342
simd_fmin,
13411343
simd_fpow,
13421344
simd_fpowi,
1345+
simd_from_exposed_addr,
13431346
simd_fsin,
13441347
simd_fsqrt,
13451348
simd_gather,

compiler/rustc_typeck/src/check/intrinsic.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,11 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
477477
sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()),
478478
sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
479479
sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
480-
sym::simd_cast | sym::simd_as => (2, vec![param(0)], param(1)),
480+
sym::simd_cast
481+
| sym::simd_as
482+
| sym::simd_cast_ptr
483+
| sym::simd_expose_addr
484+
| sym::simd_from_exposed_addr => (2, vec![param(0)], param(1)),
481485
sym::simd_bitmask => (2, vec![param(0)], param(1)),
482486
sym::simd_select | sym::simd_select_bitmask => {
483487
(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)