Add an intrinsic that lowers to AggregateKind::RawPtr

This commit is contained in:
Scott McMurray 2024-04-11 15:33:37 -07:00
parent e6b2b764ec
commit 4f4442655e
8 changed files with 264 additions and 1 deletions

View File

@ -946,7 +946,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(location, "input pointer must be thin");
}
} else {
self.fail(location, "first operand to raw pointer aggregate must be a raw pointer");
self.fail(
location,
"first operand to raw pointer aggregate must be a raw pointer",
);
}
// FIXME: Check metadata more generally

View File

@ -128,6 +128,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
| sym::variant_count
| sym::is_val_statically_known
| sym::ptr_mask
| sym::aggregate_raw_ptr
| sym::ub_checks
| sym::fadd_algebraic
| sym::fsub_algebraic
@ -574,6 +575,10 @@ pub fn check_intrinsic_type(
(0, 0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
}
// This type check is not particularly useful, but the `where` bounds
// on the definition in `core` do the heavy lifting for checking it.
sym::aggregate_raw_ptr => (3, 1, vec![param(1), param(2)], param(0)),
sym::ub_checks => (0, 1, Vec::new(), tcx.types.bool),
sym::simd_eq

View File

@ -287,6 +287,34 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
terminator.kind = TerminatorKind::Unreachable;
}
}
sym::aggregate_raw_ptr => {
let Ok([data, meta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
span_bug!(
terminator.source_info.span,
"Wrong number of arguments for aggregate_raw_ptr intrinsic",
);
};
let target = target.unwrap();
let pointer_ty = generic_args.type_at(0);
let kind = if let ty::RawPtr(pointee_ty, mutability) = pointer_ty.kind() {
AggregateKind::RawPtr(*pointee_ty, *mutability)
} else {
span_bug!(
terminator.source_info.span,
"Return type of aggregate_raw_ptr intrinsic must be a raw pointer",
);
};
let fields = [data.node, meta.node];
block.statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new((
*destination,
Rvalue::Aggregate(Box::new(kind), fields.into()),
))),
});
terminator.kind = TerminatorKind::Goto { target };
}
_ => {}
}
}

View File

@ -361,6 +361,7 @@ symbols! {
adt_const_params,
advanced_slice_patterns,
adx_target_feature,
aggregate_raw_ptr,
alias,
align,
align_offset,

View File

@ -2779,6 +2779,32 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize {
unreachable!()
}
/// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`.
///
/// This is used to implement functions like `slice::from_raw_parts_mut` and
/// `ptr::from_raw_parts` in a way compatible with the compiler being able to
/// change the possible layouts of pointers.
#[rustc_nounwind]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[cfg(not(bootstrap))]
pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P {
// No fallback because `libcore` doesn't want to know the layout
unreachable!()
}
#[unstable(feature = "core_intrinsics", issue = "none")]
pub trait AggregateRawPtr<D> {
type Metadata: Copy;
}
impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*const T> for *const P {
type Metadata = <P as ptr::Pointee>::Metadata;
}
impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
type Metadata = <P as ptr::Pointee>::Metadata;
}
// Some functions are defined here because they accidentally got made
// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
// (`transmute` also falls into this category, but it cannot be wrapped due to the

View File

@ -0,0 +1,95 @@
- // MIR for `make_pointers` before LowerIntrinsics
+ // MIR for `make_pointers` after LowerIntrinsics
fn make_pointers(_1: *const u8, _2: *mut (), _3: usize) -> () {
debug a => _1;
debug b => _2;
debug n => _3;
let mut _0: ();
let _4: *const i32;
let mut _5: *const u8;
let mut _6: ();
let mut _8: *mut ();
let mut _9: ();
let mut _11: *const u8;
let mut _12: usize;
let mut _14: *mut ();
let mut _15: usize;
scope 1 {
debug _thin_const => _4;
let _7: *mut u8;
scope 2 {
debug _thin_mut => _7;
let _10: *const [u16];
scope 3 {
debug _slice_const => _10;
let _13: *mut [u64];
scope 4 {
debug _slice_mut => _13;
}
}
}
}
bb0: {
StorageLive(_4);
StorageLive(_5);
_5 = _1;
StorageLive(_6);
_6 = ();
- _4 = aggregate_raw_ptr::<*const i32, *const u8, ()>(move _5, move _6) -> [return: bb1, unwind unreachable];
+ _4 = *const i32 from (move _5, move _6);
+ goto -> bb1;
}
bb1: {
StorageDead(_6);
StorageDead(_5);
StorageLive(_7);
StorageLive(_8);
_8 = _2;
StorageLive(_9);
_9 = ();
- _7 = aggregate_raw_ptr::<*mut u8, *mut (), ()>(move _8, move _9) -> [return: bb2, unwind unreachable];
+ _7 = *mut u8 from (move _8, move _9);
+ goto -> bb2;
}
bb2: {
StorageDead(_9);
StorageDead(_8);
StorageLive(_10);
StorageLive(_11);
_11 = _1;
StorageLive(_12);
_12 = _3;
- _10 = aggregate_raw_ptr::<*const [u16], *const u8, usize>(move _11, move _12) -> [return: bb3, unwind unreachable];
+ _10 = *const [u16] from (move _11, move _12);
+ goto -> bb3;
}
bb3: {
StorageDead(_12);
StorageDead(_11);
StorageLive(_13);
StorageLive(_14);
_14 = _2;
StorageLive(_15);
_15 = _3;
- _13 = aggregate_raw_ptr::<*mut [u64], *mut (), usize>(move _14, move _15) -> [return: bb4, unwind unreachable];
+ _13 = *mut [u64] from (move _14, move _15);
+ goto -> bb4;
}
bb4: {
StorageDead(_15);
StorageDead(_14);
_0 = const ();
StorageDead(_13);
StorageDead(_10);
StorageDead(_7);
StorageDead(_4);
return;
}
}

View File

@ -0,0 +1,95 @@
- // MIR for `make_pointers` before LowerIntrinsics
+ // MIR for `make_pointers` after LowerIntrinsics
fn make_pointers(_1: *const u8, _2: *mut (), _3: usize) -> () {
debug a => _1;
debug b => _2;
debug n => _3;
let mut _0: ();
let _4: *const i32;
let mut _5: *const u8;
let mut _6: ();
let mut _8: *mut ();
let mut _9: ();
let mut _11: *const u8;
let mut _12: usize;
let mut _14: *mut ();
let mut _15: usize;
scope 1 {
debug _thin_const => _4;
let _7: *mut u8;
scope 2 {
debug _thin_mut => _7;
let _10: *const [u16];
scope 3 {
debug _slice_const => _10;
let _13: *mut [u64];
scope 4 {
debug _slice_mut => _13;
}
}
}
}
bb0: {
StorageLive(_4);
StorageLive(_5);
_5 = _1;
StorageLive(_6);
_6 = ();
- _4 = aggregate_raw_ptr::<*const i32, *const u8, ()>(move _5, move _6) -> [return: bb1, unwind unreachable];
+ _4 = *const i32 from (move _5, move _6);
+ goto -> bb1;
}
bb1: {
StorageDead(_6);
StorageDead(_5);
StorageLive(_7);
StorageLive(_8);
_8 = _2;
StorageLive(_9);
_9 = ();
- _7 = aggregate_raw_ptr::<*mut u8, *mut (), ()>(move _8, move _9) -> [return: bb2, unwind unreachable];
+ _7 = *mut u8 from (move _8, move _9);
+ goto -> bb2;
}
bb2: {
StorageDead(_9);
StorageDead(_8);
StorageLive(_10);
StorageLive(_11);
_11 = _1;
StorageLive(_12);
_12 = _3;
- _10 = aggregate_raw_ptr::<*const [u16], *const u8, usize>(move _11, move _12) -> [return: bb3, unwind unreachable];
+ _10 = *const [u16] from (move _11, move _12);
+ goto -> bb3;
}
bb3: {
StorageDead(_12);
StorageDead(_11);
StorageLive(_13);
StorageLive(_14);
_14 = _2;
StorageLive(_15);
_15 = _3;
- _13 = aggregate_raw_ptr::<*mut [u64], *mut (), usize>(move _14, move _15) -> [return: bb4, unwind unreachable];
+ _13 = *mut [u64] from (move _14, move _15);
+ goto -> bb4;
}
bb4: {
StorageDead(_15);
StorageDead(_14);
_0 = const ();
StorageDead(_13);
StorageDead(_10);
StorageDead(_7);
StorageDead(_4);
return;
}
}

View File

@ -248,3 +248,13 @@ pub fn three_way_compare_signed(a: i16, b: i16) {
pub fn three_way_compare_unsigned(a: u32, b: u32) {
let _x = core::intrinsics::three_way_compare(a, b);
}
// EMIT_MIR lower_intrinsics.make_pointers.LowerIntrinsics.diff
pub fn make_pointers(a: *const u8, b: *mut (), n: usize) {
use std::intrinsics::aggregate_raw_ptr;
let _thin_const: *const i32 = aggregate_raw_ptr(a, ());
let _thin_mut: *mut u8 = aggregate_raw_ptr(b, ());
let _slice_const: *const [u16] = aggregate_raw_ptr(a, n);
let _slice_mut: *mut [u64] = aggregate_raw_ptr(b, n);
}