Add an intrinsic that lowers to AggregateKind::RawPtr
This commit is contained in:
parent
e6b2b764ec
commit
4f4442655e
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 };
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -361,6 +361,7 @@ symbols! {
|
||||
adt_const_params,
|
||||
advanced_slice_patterns,
|
||||
adx_target_feature,
|
||||
aggregate_raw_ptr,
|
||||
alias,
|
||||
align,
|
||||
align_offset,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user