mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Add an intrinsic for ptr::metadata
This commit is contained in:
parent
7717a306b2
commit
459ce3f6bb
@ -619,22 +619,34 @@ fn codegen_stmt<'tcx>(
|
|||||||
Rvalue::UnaryOp(un_op, ref operand) => {
|
Rvalue::UnaryOp(un_op, ref operand) => {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
let layout = operand.layout();
|
let layout = operand.layout();
|
||||||
let val = operand.load_scalar(fx);
|
|
||||||
let res = match un_op {
|
let res = match un_op {
|
||||||
UnOp::Not => match layout.ty.kind() {
|
UnOp::Not => {
|
||||||
ty::Bool => {
|
let val = operand.load_scalar(fx);
|
||||||
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
|
match layout.ty.kind() {
|
||||||
CValue::by_val(res, layout)
|
ty::Bool => {
|
||||||
|
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
|
||||||
|
CValue::by_val(res, layout)
|
||||||
|
}
|
||||||
|
ty::Uint(_) | ty::Int(_) => {
|
||||||
|
CValue::by_val(fx.bcx.ins().bnot(val), layout)
|
||||||
|
}
|
||||||
|
_ => unreachable!("un op Not for {:?}", layout.ty),
|
||||||
}
|
}
|
||||||
ty::Uint(_) | ty::Int(_) => {
|
}
|
||||||
CValue::by_val(fx.bcx.ins().bnot(val), layout)
|
UnOp::Neg => {
|
||||||
|
let val = operand.load_scalar(fx);
|
||||||
|
match layout.ty.kind() {
|
||||||
|
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
|
||||||
|
ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
|
||||||
|
_ => unreachable!("un op Neg for {:?}", layout.ty),
|
||||||
}
|
}
|
||||||
_ => unreachable!("un op Not for {:?}", layout.ty),
|
}
|
||||||
},
|
UnOp::PtrMetadata => match layout.abi {
|
||||||
UnOp::Neg => match layout.ty.kind() {
|
Abi::Scalar(_) => CValue::zst(dest_layout),
|
||||||
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
|
Abi::ScalarPair(_, _) => {
|
||||||
ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
|
CValue::by_val(operand.load_scalar_pair(fx).1, dest_layout)
|
||||||
_ => unreachable!("un op Neg for {:?}", layout.ty),
|
}
|
||||||
|
_ => bug!("Unexpected `PtrToMetadata` operand: {operand:?}"),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
lval.write_cvalue(fx, res);
|
lval.write_cvalue(fx, res);
|
||||||
|
@ -100,7 +100,7 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||||||
assert!(layout.is_sized(), "unsized const value");
|
assert!(layout.is_sized(), "unsized const value");
|
||||||
|
|
||||||
if layout.is_zst() {
|
if layout.is_zst() {
|
||||||
return CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout);
|
return CValue::zst(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
match const_val {
|
match const_val {
|
||||||
|
@ -95,6 +95,14 @@ impl<'tcx> CValue<'tcx> {
|
|||||||
CValue(CValueInner::ByValPair(value, extra), layout)
|
CValue(CValueInner::ByValPair(value, extra), layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create an instance of a ZST
|
||||||
|
///
|
||||||
|
/// The is represented by a dangling pointer of suitable alignment.
|
||||||
|
pub(crate) fn zst(layout: TyAndLayout<'tcx>) -> CValue<'tcx> {
|
||||||
|
assert!(layout.is_zst());
|
||||||
|
CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn layout(&self) -> TyAndLayout<'tcx> {
|
pub(crate) fn layout(&self) -> TyAndLayout<'tcx> {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
|
@ -565,6 +565,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
for elem in place_ref.projection.iter() {
|
for elem in place_ref.projection.iter() {
|
||||||
match elem {
|
match elem {
|
||||||
mir::ProjectionElem::Field(ref f, _) => {
|
mir::ProjectionElem::Field(ref f, _) => {
|
||||||
|
debug_assert!(
|
||||||
|
!o.layout.ty.is_any_ptr(),
|
||||||
|
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
|
||||||
|
but tried to access field {f:?} of pointer {o:?}",
|
||||||
|
);
|
||||||
o = o.extract_field(bx, f.index());
|
o = o.extract_field(bx, f.index());
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::Index(_)
|
mir::ProjectionElem::Index(_)
|
||||||
|
@ -480,6 +480,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
cg_base = match *elem {
|
cg_base = match *elem {
|
||||||
mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()),
|
mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()),
|
||||||
mir::ProjectionElem::Field(ref field, _) => {
|
mir::ProjectionElem::Field(ref field, _) => {
|
||||||
|
debug_assert!(
|
||||||
|
!cg_base.layout.ty.is_any_ptr(),
|
||||||
|
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
|
||||||
|
but tried to access field {field:?} of pointer {cg_base:?}",
|
||||||
|
);
|
||||||
cg_base.project_field(bx, field.index())
|
cg_base.project_field(bx, field.index())
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::OpaqueCast(ty) => {
|
mir::ProjectionElem::OpaqueCast(ty) => {
|
||||||
|
@ -623,19 +623,36 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
|
|
||||||
mir::Rvalue::UnaryOp(op, ref operand) => {
|
mir::Rvalue::UnaryOp(op, ref operand) => {
|
||||||
let operand = self.codegen_operand(bx, operand);
|
let operand = self.codegen_operand(bx, operand);
|
||||||
let lloperand = operand.immediate();
|
|
||||||
let is_float = operand.layout.ty.is_floating_point();
|
let is_float = operand.layout.ty.is_floating_point();
|
||||||
let llval = match op {
|
let (val, layout) = match op {
|
||||||
mir::UnOp::Not => bx.not(lloperand),
|
mir::UnOp::Not => {
|
||||||
|
let llval = bx.not(operand.immediate());
|
||||||
|
(OperandValue::Immediate(llval), operand.layout)
|
||||||
|
}
|
||||||
mir::UnOp::Neg => {
|
mir::UnOp::Neg => {
|
||||||
if is_float {
|
let llval = if is_float {
|
||||||
bx.fneg(lloperand)
|
bx.fneg(operand.immediate())
|
||||||
} else {
|
} else {
|
||||||
bx.neg(lloperand)
|
bx.neg(operand.immediate())
|
||||||
|
};
|
||||||
|
(OperandValue::Immediate(llval), operand.layout)
|
||||||
|
}
|
||||||
|
mir::UnOp::PtrMetadata => {
|
||||||
|
debug_assert!(operand.layout.ty.is_unsafe_ptr());
|
||||||
|
let (_, meta) = operand.val.pointer_parts();
|
||||||
|
assert_eq!(operand.layout.fields.count() > 1, meta.is_some());
|
||||||
|
if let Some(meta) = meta {
|
||||||
|
(OperandValue::Immediate(meta), operand.layout.field(self.cx, 1))
|
||||||
|
} else {
|
||||||
|
(OperandValue::ZeroSized, bx.cx().layout_of(bx.tcx().types.unit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
OperandRef { val: OperandValue::Immediate(llval), layout: operand.layout }
|
debug_assert!(
|
||||||
|
val.is_expected_variant_for_type(self.cx, layout),
|
||||||
|
"Made wrong variant {val:?} for type {layout:?}",
|
||||||
|
);
|
||||||
|
OperandRef { val, layout }
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Discriminant(ref place) => {
|
mir::Rvalue::Discriminant(ref place) => {
|
||||||
@ -718,8 +735,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
let values = op.val.immediates_or_place().left_or_else(|p| {
|
let values = op.val.immediates_or_place().left_or_else(|p| {
|
||||||
bug!("Field {field_idx:?} is {p:?} making {layout:?}");
|
bug!("Field {field_idx:?} is {p:?} making {layout:?}");
|
||||||
});
|
});
|
||||||
inputs.extend(values);
|
|
||||||
let scalars = self.value_kind(op.layout).scalars().unwrap();
|
let scalars = self.value_kind(op.layout).scalars().unwrap();
|
||||||
|
debug_assert_eq!(values.len(), scalars.len());
|
||||||
|
inputs.extend(values);
|
||||||
input_scalars.extend(scalars);
|
input_scalars.extend(scalars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
assert!(cast_to.ty.is_unsafe_ptr());
|
assert!(cast_to.ty.is_unsafe_ptr());
|
||||||
// Handle casting any ptr to raw ptr (might be a fat ptr).
|
// Handle casting any ptr to raw ptr (might be a fat ptr).
|
||||||
if cast_to.size == src.layout.size {
|
if cast_to.size == src.layout.size {
|
||||||
// Thin or fat pointer that just hast the ptr kind of target type changed.
|
// Thin or fat pointer that just has the ptr kind of target type changed.
|
||||||
return Ok(ImmTy::from_immediate(**src, cast_to));
|
return Ok(ImmTy::from_immediate(**src, cast_to));
|
||||||
} else {
|
} else {
|
||||||
// Casting the metadata away from a fat ptr.
|
// Casting the metadata away from a fat ptr.
|
||||||
|
@ -9,7 +9,7 @@ use rustc_middle::{bug, span_bug};
|
|||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine};
|
use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta};
|
||||||
|
|
||||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
|
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
|
||||||
@ -415,11 +415,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
use rustc_middle::mir::UnOp::*;
|
use rustc_middle::mir::UnOp::*;
|
||||||
|
|
||||||
let layout = val.layout;
|
let layout = val.layout;
|
||||||
let val = val.to_scalar();
|
|
||||||
trace!("Running unary op {:?}: {:?} ({})", un_op, val, layout.ty);
|
trace!("Running unary op {:?}: {:?} ({})", un_op, val, layout.ty);
|
||||||
|
|
||||||
match layout.ty.kind() {
|
match layout.ty.kind() {
|
||||||
ty::Bool => {
|
ty::Bool => {
|
||||||
|
let val = val.to_scalar();
|
||||||
let val = val.to_bool()?;
|
let val = val.to_bool()?;
|
||||||
let res = match un_op {
|
let res = match un_op {
|
||||||
Not => !val,
|
Not => !val,
|
||||||
@ -428,6 +428,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
Ok(ImmTy::from_bool(res, *self.tcx))
|
Ok(ImmTy::from_bool(res, *self.tcx))
|
||||||
}
|
}
|
||||||
ty::Float(fty) => {
|
ty::Float(fty) => {
|
||||||
|
let val = val.to_scalar();
|
||||||
// No NaN adjustment here, `-` is a bitwise operation!
|
// No NaN adjustment here, `-` is a bitwise operation!
|
||||||
let res = match (un_op, fty) {
|
let res = match (un_op, fty) {
|
||||||
(Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?),
|
(Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?),
|
||||||
@ -436,8 +437,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
};
|
};
|
||||||
Ok(ImmTy::from_scalar(res, layout))
|
Ok(ImmTy::from_scalar(res, layout))
|
||||||
}
|
}
|
||||||
_ => {
|
_ if layout.ty.is_integral() => {
|
||||||
assert!(layout.ty.is_integral());
|
let val = val.to_scalar();
|
||||||
let val = val.to_bits(layout.size)?;
|
let val = val.to_bits(layout.size)?;
|
||||||
let res = match un_op {
|
let res = match un_op {
|
||||||
Not => self.truncate(!val, layout), // bitwise negation, then truncate
|
Not => self.truncate(!val, layout), // bitwise negation, then truncate
|
||||||
@ -450,9 +451,28 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
// Truncate to target type.
|
// Truncate to target type.
|
||||||
self.truncate(res, layout)
|
self.truncate(res, layout)
|
||||||
}
|
}
|
||||||
|
_ => span_bug!(self.cur_span(), "Invalid integer op {:?}", un_op),
|
||||||
};
|
};
|
||||||
Ok(ImmTy::from_uint(res, layout))
|
Ok(ImmTy::from_uint(res, layout))
|
||||||
}
|
}
|
||||||
|
ty::RawPtr(..) => {
|
||||||
|
assert_eq!(un_op, PtrMetadata);
|
||||||
|
let (_, meta) = val.to_scalar_and_meta();
|
||||||
|
Ok(match meta {
|
||||||
|
MemPlaceMeta::Meta(scalar) => {
|
||||||
|
let ty = un_op.ty(*self.tcx, val.layout.ty);
|
||||||
|
let layout = self.layout_of(ty)?;
|
||||||
|
ImmTy::from_scalar(scalar, layout)
|
||||||
|
}
|
||||||
|
MemPlaceMeta::None => {
|
||||||
|
let unit_layout = self.layout_of(self.tcx.types.unit)?;
|
||||||
|
ImmTy::uninit(unit_layout)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
bug!("Unexpected unary op argument {val:?}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
|
|||||||
| sym::is_val_statically_known
|
| sym::is_val_statically_known
|
||||||
| sym::ptr_mask
|
| sym::ptr_mask
|
||||||
| sym::aggregate_raw_ptr
|
| sym::aggregate_raw_ptr
|
||||||
|
| sym::ptr_metadata
|
||||||
| sym::ub_checks
|
| sym::ub_checks
|
||||||
| sym::fadd_algebraic
|
| sym::fadd_algebraic
|
||||||
| sym::fsub_algebraic
|
| sym::fsub_algebraic
|
||||||
@ -576,6 +577,7 @@ pub fn check_intrinsic_type(
|
|||||||
// This type check is not particularly useful, but the `where` bounds
|
// This type check is not particularly useful, but the `where` bounds
|
||||||
// on the definition in `core` do the heavy lifting for checking it.
|
// 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::aggregate_raw_ptr => (3, 1, vec![param(1), param(2)], param(0)),
|
||||||
|
sym::ptr_metadata => (2, 1, vec![Ty::new_imm_ptr(tcx, param(0))], param(1)),
|
||||||
|
|
||||||
sym::ub_checks => (0, 1, Vec::new(), tcx.types.bool),
|
sym::ub_checks => (0, 1, Vec::new(), tcx.types.bool),
|
||||||
|
|
||||||
|
@ -1434,6 +1434,13 @@ pub enum UnOp {
|
|||||||
Not,
|
Not,
|
||||||
/// The `-` operator for negation
|
/// The `-` operator for negation
|
||||||
Neg,
|
Neg,
|
||||||
|
/// Get the metadata `M` from a `*const/mut impl Pointee<Metadata = M>`.
|
||||||
|
///
|
||||||
|
/// For example, this will give a `()` from `*const i32`, a `usize` from
|
||||||
|
/// `*mut [u8]`, or a pointer to a vtable from a `*const dyn Foo`.
|
||||||
|
///
|
||||||
|
/// Allowed only in [`MirPhase::Runtime`]; earlier it's an intrinsic.
|
||||||
|
PtrMetadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
||||||
|
@ -180,7 +180,10 @@ impl<'tcx> Rvalue<'tcx> {
|
|||||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||||
op.ty(tcx, lhs_ty, rhs_ty)
|
op.ty(tcx, lhs_ty, rhs_ty)
|
||||||
}
|
}
|
||||||
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
|
Rvalue::UnaryOp(op, ref operand) => {
|
||||||
|
let arg_ty = operand.ty(local_decls, tcx);
|
||||||
|
op.ty(tcx, arg_ty)
|
||||||
|
}
|
||||||
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
|
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
|
||||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
|
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
|
||||||
tcx.types.usize
|
tcx.types.usize
|
||||||
@ -282,6 +285,27 @@ impl<'tcx> BinOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> UnOp {
|
||||||
|
pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
|
match self {
|
||||||
|
UnOp::Not | UnOp::Neg => arg_ty,
|
||||||
|
UnOp::PtrMetadata => {
|
||||||
|
let pointee_ty = arg_ty
|
||||||
|
.builtin_deref(true)
|
||||||
|
.unwrap_or_else(|| bug!("PtrMetadata of non-dereferenceable ty {arg_ty:?}"));
|
||||||
|
if pointee_ty.is_trivially_sized(tcx) {
|
||||||
|
tcx.types.unit
|
||||||
|
} else {
|
||||||
|
let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
|
||||||
|
bug!("No metadata_type lang item while looking at {arg_ty:?}")
|
||||||
|
};
|
||||||
|
Ty::new_projection(tcx, metadata_def_id, [pointee_ty])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BorrowKind {
|
impl BorrowKind {
|
||||||
pub fn to_mutbl_lossy(self) -> hir::Mutability {
|
pub fn to_mutbl_lossy(self) -> hir::Mutability {
|
||||||
match self {
|
match self {
|
||||||
|
@ -1579,8 +1579,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||||||
let formatted_op = match op {
|
let formatted_op = match op {
|
||||||
UnOp::Not => "!",
|
UnOp::Not => "!",
|
||||||
UnOp::Neg => "-",
|
UnOp::Neg => "-",
|
||||||
|
UnOp::PtrMetadata => "PtrMetadata",
|
||||||
};
|
};
|
||||||
let parenthesized = match ct.kind() {
|
let parenthesized = match ct.kind() {
|
||||||
|
_ if op == UnOp::PtrMetadata => true,
|
||||||
ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op,
|
ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op,
|
||||||
ty::ConstKind::Expr(_) => true,
|
ty::ConstKind::Expr(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -316,6 +316,23 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
|||||||
|
|
||||||
terminator.kind = TerminatorKind::Goto { target };
|
terminator.kind = TerminatorKind::Goto { target };
|
||||||
}
|
}
|
||||||
|
sym::ptr_metadata => {
|
||||||
|
let Ok([ptr]) = <[_; 1]>::try_from(std::mem::take(args)) else {
|
||||||
|
span_bug!(
|
||||||
|
terminator.source_info.span,
|
||||||
|
"Wrong number of arguments for ptr_metadata intrinsic",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
let target = target.unwrap();
|
||||||
|
block.statements.push(Statement {
|
||||||
|
source_info: terminator.source_info,
|
||||||
|
kind: StatementKind::Assign(Box::new((
|
||||||
|
*destination,
|
||||||
|
Rvalue::UnaryOp(UnOp::PtrMetadata, ptr.node),
|
||||||
|
))),
|
||||||
|
});
|
||||||
|
terminator.kind = TerminatorKind::Goto { target };
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,7 +464,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||||||
Rvalue::UnaryOp(op, operand) => {
|
Rvalue::UnaryOp(op, operand) => {
|
||||||
match op {
|
match op {
|
||||||
// These operations can never fail.
|
// These operations can never fail.
|
||||||
UnOp::Neg | UnOp::Not => {}
|
UnOp::Neg | UnOp::Not | UnOp::PtrMetadata => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.validate_operand(operand)?;
|
self.validate_operand(operand)?;
|
||||||
|
@ -1109,6 +1109,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
ty::Int(..) | ty::Uint(..) | ty::Bool
|
ty::Int(..) | ty::Uint(..) | ty::Bool
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
UnOp::PtrMetadata => {
|
||||||
|
if !matches!(self.mir_phase, MirPhase::Runtime(_)) {
|
||||||
|
// It would probably be fine to support this in earlier phases,
|
||||||
|
// but at the time of writing it's only ever introduced from intrinsic lowering,
|
||||||
|
// so earlier things can just `bug!` on it.
|
||||||
|
self.fail(location, "PtrMetadata should be in runtime MIR only");
|
||||||
|
}
|
||||||
|
|
||||||
|
check_kinds!(a, "Cannot PtrMetadata non-pointer type {:?}", ty::RawPtr(..));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rvalue::ShallowInitBox(operand, _) => {
|
Rvalue::ShallowInitBox(operand, _) => {
|
||||||
|
@ -10,7 +10,7 @@ use rustc_span::Symbol;
|
|||||||
use stable_mir::abi::Layout;
|
use stable_mir::abi::Layout;
|
||||||
use stable_mir::mir::alloc::AllocId;
|
use stable_mir::mir::alloc::AllocId;
|
||||||
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
|
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
|
||||||
use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, Safety};
|
use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, Safety, UnOp};
|
||||||
use stable_mir::ty::{
|
use stable_mir::ty::{
|
||||||
Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
|
Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const,
|
||||||
DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
|
DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
|
||||||
@ -582,6 +582,18 @@ impl RustcInternal for BinOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RustcInternal for UnOp {
|
||||||
|
type T<'tcx> = rustc_middle::mir::UnOp;
|
||||||
|
|
||||||
|
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||||
|
match self {
|
||||||
|
UnOp::Not => rustc_middle::mir::UnOp::Not,
|
||||||
|
UnOp::Neg => rustc_middle::mir::UnOp::Neg,
|
||||||
|
UnOp::PtrMetadata => rustc_middle::mir::UnOp::PtrMetadata,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> RustcInternal for &T
|
impl<T> RustcInternal for &T
|
||||||
where
|
where
|
||||||
T: RustcInternal,
|
T: RustcInternal,
|
||||||
|
@ -19,7 +19,7 @@ use stable_mir::abi::{FnAbi, Layout, LayoutShape};
|
|||||||
use stable_mir::compiler_interface::Context;
|
use stable_mir::compiler_interface::Context;
|
||||||
use stable_mir::mir::alloc::GlobalAlloc;
|
use stable_mir::mir::alloc::GlobalAlloc;
|
||||||
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||||
use stable_mir::mir::{BinOp, Body, Place};
|
use stable_mir::mir::{BinOp, Body, Place, UnOp};
|
||||||
use stable_mir::target::{MachineInfo, MachineSize};
|
use stable_mir::target::{MachineInfo, MachineSize};
|
||||||
use stable_mir::ty::{
|
use stable_mir::ty::{
|
||||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
||||||
@ -700,6 +700,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||||||
let ty = bin_op.internal(&mut *tables, tcx).ty(tcx, rhs_internal, lhs_internal);
|
let ty = bin_op.internal(&mut *tables, tcx).ty(tcx, rhs_internal, lhs_internal);
|
||||||
ty.stable(&mut *tables)
|
ty.stable(&mut *tables)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
let arg_internal = arg.internal(&mut *tables, tcx);
|
||||||
|
let ty = un_op.internal(&mut *tables, tcx).ty(tcx, arg_internal);
|
||||||
|
ty.stable(&mut *tables)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
|
pub struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
|
||||||
|
@ -526,6 +526,7 @@ impl<'tcx> Stable<'tcx> for mir::UnOp {
|
|||||||
match self {
|
match self {
|
||||||
UnOp::Not => stable_mir::mir::UnOp::Not,
|
UnOp::Not => stable_mir::mir::UnOp::Not,
|
||||||
UnOp::Neg => stable_mir::mir::UnOp::Neg,
|
UnOp::Neg => stable_mir::mir::UnOp::Neg,
|
||||||
|
UnOp::PtrMetadata => stable_mir::mir::UnOp::PtrMetadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1433,6 +1433,7 @@ symbols! {
|
|||||||
ptr_guaranteed_cmp,
|
ptr_guaranteed_cmp,
|
||||||
ptr_is_null,
|
ptr_is_null,
|
||||||
ptr_mask,
|
ptr_mask,
|
||||||
|
ptr_metadata,
|
||||||
ptr_null,
|
ptr_null,
|
||||||
ptr_null_mut,
|
ptr_null_mut,
|
||||||
ptr_offset_from,
|
ptr_offset_from,
|
||||||
|
@ -94,7 +94,7 @@ fn check_binop(op: mir::BinOp) -> bool {
|
|||||||
fn check_unop(op: mir::UnOp) -> bool {
|
fn check_unop(op: mir::UnOp) -> bool {
|
||||||
use mir::UnOp::*;
|
use mir::UnOp::*;
|
||||||
match op {
|
match op {
|
||||||
Not | Neg => true,
|
Not | Neg | PtrMetadata => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use std::cell::Cell;
|
|||||||
use crate::abi::{FnAbi, Layout, LayoutShape};
|
use crate::abi::{FnAbi, Layout, LayoutShape};
|
||||||
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
||||||
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
||||||
use crate::mir::{BinOp, Body, Place};
|
use crate::mir::{BinOp, Body, Place, UnOp};
|
||||||
use crate::target::MachineInfo;
|
use crate::target::MachineInfo;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
|
||||||
@ -226,6 +226,9 @@ pub trait Context {
|
|||||||
|
|
||||||
/// Get the resulting type of binary operation.
|
/// Get the resulting type of binary operation.
|
||||||
fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty;
|
fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty;
|
||||||
|
|
||||||
|
/// Get the resulting type of unary operation.
|
||||||
|
fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||||
|
@ -346,6 +346,15 @@ impl BinOp {
|
|||||||
pub enum UnOp {
|
pub enum UnOp {
|
||||||
Not,
|
Not,
|
||||||
Neg,
|
Neg,
|
||||||
|
PtrMetadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnOp {
|
||||||
|
/// Return the type of this operation for the given input Ty.
|
||||||
|
/// This function does not perform type checking, and it currently doesn't handle SIMD.
|
||||||
|
pub fn ty(&self, arg_ty: Ty) -> Ty {
|
||||||
|
with(|ctx| ctx.unop_ty(*self, arg_ty))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
@ -580,7 +589,10 @@ impl Rvalue {
|
|||||||
let ty = op.ty(lhs_ty, rhs_ty);
|
let ty = op.ty(lhs_ty, rhs_ty);
|
||||||
Ok(Ty::new_tuple(&[ty, Ty::bool_ty()]))
|
Ok(Ty::new_tuple(&[ty, Ty::bool_ty()]))
|
||||||
}
|
}
|
||||||
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, operand) => operand.ty(locals),
|
Rvalue::UnaryOp(op, operand) => {
|
||||||
|
let arg_ty = operand.ty(locals)?;
|
||||||
|
Ok(op.ty(arg_ty))
|
||||||
|
}
|
||||||
Rvalue::Discriminant(place) => {
|
Rvalue::Discriminant(place) => {
|
||||||
let place_ty = place.ty(locals)?;
|
let place_ty = place.ty(locals)?;
|
||||||
place_ty
|
place_ty
|
||||||
|
@ -2821,6 +2821,21 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
|
|||||||
type Metadata = <P as ptr::Pointee>::Metadata;
|
type Metadata = <P as ptr::Pointee>::Metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lowers in MIR to `Rvalue::UnaryOp` with `UnOp::PtrMetadata`.
|
||||||
|
///
|
||||||
|
/// This is used to implement functions like `ptr::metadata`.
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
|
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M {
|
||||||
|
// To implement a fallback we'd have to assume the layout of the pointer,
|
||||||
|
// but the whole point of this intrinsic is that we shouldn't do that.
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
// Some functions are defined here because they accidentally got made
|
// 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>.
|
// 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
|
// (`transmute` also falls into this category, but it cannot be wrapped due to the
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::hash::{Hash, Hasher};
|
use crate::hash::{Hash, Hasher};
|
||||||
use crate::intrinsics::aggregate_raw_ptr;
|
use crate::intrinsics::aggregate_raw_ptr;
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
use crate::intrinsics::ptr_metadata;
|
||||||
use crate::marker::Freeze;
|
use crate::marker::Freeze;
|
||||||
|
|
||||||
/// Provides the pointer metadata type of any pointed-to type.
|
/// Provides the pointer metadata type of any pointed-to type.
|
||||||
@ -94,10 +96,17 @@ pub trait Thin = Pointee<Metadata = ()>;
|
|||||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
|
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
||||||
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
|
#[cfg(bootstrap)]
|
||||||
// and PtrComponents<T> have the same memory layouts. Only std can make this
|
{
|
||||||
// guarantee.
|
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
|
||||||
unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
|
// and PtrComponents<T> have the same memory layouts. Only std can make this
|
||||||
|
// guarantee.
|
||||||
|
unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
|
||||||
|
}
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
{
|
||||||
|
ptr_metadata(ptr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forms a (possibly-wide) raw pointer from a data pointer and metadata.
|
/// Forms a (possibly-wide) raw pointer from a data pointer and metadata.
|
||||||
@ -132,6 +141,7 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[cfg(bootstrap)]
|
||||||
union PtrRepr<T: ?Sized> {
|
union PtrRepr<T: ?Sized> {
|
||||||
const_ptr: *const T,
|
const_ptr: *const T,
|
||||||
mut_ptr: *mut T,
|
mut_ptr: *mut T,
|
||||||
@ -139,15 +149,18 @@ union PtrRepr<T: ?Sized> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[cfg(bootstrap)]
|
||||||
struct PtrComponents<T: ?Sized> {
|
struct PtrComponents<T: ?Sized> {
|
||||||
data_pointer: *const (),
|
data_pointer: *const (),
|
||||||
metadata: <T as Pointee>::Metadata,
|
metadata: <T as Pointee>::Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manual impl needed to avoid `T: Copy` bound.
|
// Manual impl needed to avoid `T: Copy` bound.
|
||||||
|
#[cfg(bootstrap)]
|
||||||
impl<T: ?Sized> Copy for PtrComponents<T> {}
|
impl<T: ?Sized> Copy for PtrComponents<T> {}
|
||||||
|
|
||||||
// Manual impl needed to avoid `T: Clone` bound.
|
// Manual impl needed to avoid `T: Clone` bound.
|
||||||
|
#[cfg(bootstrap)]
|
||||||
impl<T: ?Sized> Clone for PtrComponents<T> {
|
impl<T: ?Sized> Clone for PtrComponents<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
|
@ -1171,3 +1171,15 @@ fn test_ptr_from_raw_parts_in_const() {
|
|||||||
assert_eq!(EMPTY_SLICE_PTR.addr(), 123);
|
assert_eq!(EMPTY_SLICE_PTR.addr(), 123);
|
||||||
assert_eq!(EMPTY_SLICE_PTR.len(), 456);
|
assert_eq!(EMPTY_SLICE_PTR.len(), 456);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ptr_metadata_in_const() {
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
const ARRAY_META: () = std::ptr::metadata::<[u16; 3]>(&[1, 2, 3]);
|
||||||
|
const SLICE_META: usize = std::ptr::metadata::<[u16]>(&[1, 2, 3]);
|
||||||
|
const DYN_META: DynMetadata<dyn Debug> = std::ptr::metadata::<dyn Debug>(&[0_u8; 42]);
|
||||||
|
assert_eq!(ARRAY_META, ());
|
||||||
|
assert_eq!(SLICE_META, 3);
|
||||||
|
assert_eq!(DYN_META.size_of(), 42);
|
||||||
|
}
|
||||||
|
36
tests/codegen/intrinsics/ptr_metadata.rs
Normal file
36
tests/codegen/intrinsics/ptr_metadata.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//@ compile-flags: -O -C no-prepopulate-passes -Z inline-mir
|
||||||
|
//@ only-64bit (so I don't need to worry about usize)
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
|
||||||
|
use std::intrinsics::ptr_metadata;
|
||||||
|
|
||||||
|
// CHECK-LABEL: @thin_metadata(
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn thin_metadata(p: *const ()) {
|
||||||
|
// CHECK: start
|
||||||
|
// CHECK-NEXT: ret void
|
||||||
|
ptr_metadata(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @slice_metadata(
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn slice_metadata(p: *const [u8]) -> usize {
|
||||||
|
// CHECK: start
|
||||||
|
// CHECK-NEXT: ret i64 %p.1
|
||||||
|
ptr_metadata(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @dyn_byte_offset(
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn dyn_byte_offset(
|
||||||
|
p: *const dyn std::fmt::Debug,
|
||||||
|
n: usize,
|
||||||
|
) -> *const dyn std::fmt::Debug {
|
||||||
|
// CHECK: %[[Q:.+]] = getelementptr inbounds i8, ptr %p.0, i64 %n
|
||||||
|
// CHECK: %[[TEMP1:.+]] = insertvalue { ptr, ptr } poison, ptr %[[Q]], 0
|
||||||
|
// CHECK: %[[TEMP2:.+]] = insertvalue { ptr, ptr } %[[TEMP1]], ptr %p.1, 1
|
||||||
|
// CHECK: ret { ptr, ptr } %[[TEMP2]]
|
||||||
|
p.byte_add(n)
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
- // MIR for `get_metadata` before LowerIntrinsics
|
||||||
|
+ // MIR for `get_metadata` after LowerIntrinsics
|
||||||
|
|
||||||
|
fn get_metadata(_1: *const i32, _2: *const [u8], _3: *const dyn Debug) -> () {
|
||||||
|
debug a => _1;
|
||||||
|
debug b => _2;
|
||||||
|
debug c => _3;
|
||||||
|
let mut _0: ();
|
||||||
|
let _4: ();
|
||||||
|
let mut _5: *const i32;
|
||||||
|
let mut _7: *const [u8];
|
||||||
|
let mut _9: *const dyn std::fmt::Debug;
|
||||||
|
scope 1 {
|
||||||
|
debug _unit => _4;
|
||||||
|
let _6: usize;
|
||||||
|
scope 2 {
|
||||||
|
debug _usize => _6;
|
||||||
|
let _8: std::ptr::DynMetadata<dyn std::fmt::Debug>;
|
||||||
|
scope 3 {
|
||||||
|
debug _vtable => _8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_4);
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = _1;
|
||||||
|
- _4 = ptr_metadata::<i32, ()>(move _5) -> [return: bb1, unwind unreachable];
|
||||||
|
+ _4 = PtrMetadata(move _5);
|
||||||
|
+ goto -> bb1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = _2;
|
||||||
|
- _6 = ptr_metadata::<[u8], usize>(move _7) -> [return: bb2, unwind unreachable];
|
||||||
|
+ _6 = PtrMetadata(move _7);
|
||||||
|
+ goto -> bb2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageDead(_7);
|
||||||
|
StorageLive(_8);
|
||||||
|
StorageLive(_9);
|
||||||
|
_9 = _3;
|
||||||
|
- _8 = ptr_metadata::<dyn Debug, DynMetadata<dyn Debug>>(move _9) -> [return: bb3, unwind unreachable];
|
||||||
|
+ _8 = PtrMetadata(move _9);
|
||||||
|
+ goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageDead(_9);
|
||||||
|
_0 = const ();
|
||||||
|
StorageDead(_8);
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
|||||||
|
- // MIR for `get_metadata` before LowerIntrinsics
|
||||||
|
+ // MIR for `get_metadata` after LowerIntrinsics
|
||||||
|
|
||||||
|
fn get_metadata(_1: *const i32, _2: *const [u8], _3: *const dyn Debug) -> () {
|
||||||
|
debug a => _1;
|
||||||
|
debug b => _2;
|
||||||
|
debug c => _3;
|
||||||
|
let mut _0: ();
|
||||||
|
let _4: ();
|
||||||
|
let mut _5: *const i32;
|
||||||
|
let mut _7: *const [u8];
|
||||||
|
let mut _9: *const dyn std::fmt::Debug;
|
||||||
|
scope 1 {
|
||||||
|
debug _unit => _4;
|
||||||
|
let _6: usize;
|
||||||
|
scope 2 {
|
||||||
|
debug _usize => _6;
|
||||||
|
let _8: std::ptr::DynMetadata<dyn std::fmt::Debug>;
|
||||||
|
scope 3 {
|
||||||
|
debug _vtable => _8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_4);
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = _1;
|
||||||
|
- _4 = ptr_metadata::<i32, ()>(move _5) -> [return: bb1, unwind unreachable];
|
||||||
|
+ _4 = PtrMetadata(move _5);
|
||||||
|
+ goto -> bb1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = _2;
|
||||||
|
- _6 = ptr_metadata::<[u8], usize>(move _7) -> [return: bb2, unwind unreachable];
|
||||||
|
+ _6 = PtrMetadata(move _7);
|
||||||
|
+ goto -> bb2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageDead(_7);
|
||||||
|
StorageLive(_8);
|
||||||
|
StorageLive(_9);
|
||||||
|
_9 = _3;
|
||||||
|
- _8 = ptr_metadata::<dyn Debug, DynMetadata<dyn Debug>>(move _9) -> [return: bb3, unwind unreachable];
|
||||||
|
+ _8 = PtrMetadata(move _9);
|
||||||
|
+ goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageDead(_9);
|
||||||
|
_0 = const ();
|
||||||
|
StorageDead(_8);
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -258,3 +258,12 @@ pub fn make_pointers(a: *const u8, b: *mut (), n: usize) {
|
|||||||
let _slice_const: *const [u16] = aggregate_raw_ptr(a, n);
|
let _slice_const: *const [u16] = aggregate_raw_ptr(a, n);
|
||||||
let _slice_mut: *mut [u64] = aggregate_raw_ptr(b, n);
|
let _slice_mut: *mut [u64] = aggregate_raw_ptr(b, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR lower_intrinsics.get_metadata.LowerIntrinsics.diff
|
||||||
|
pub fn get_metadata(a: *const i32, b: *const [u8], c: *const dyn std::fmt::Debug) {
|
||||||
|
use std::intrinsics::ptr_metadata;
|
||||||
|
|
||||||
|
let _unit = ptr_metadata(a);
|
||||||
|
let _usize = ptr_metadata(b);
|
||||||
|
let _vtable = ptr_metadata(c);
|
||||||
|
}
|
||||||
|
@ -13,9 +13,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
|
|||||||
}
|
}
|
||||||
scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
||||||
let mut _5: *const ();
|
let mut _5: *const ();
|
||||||
let mut _7: usize;
|
let mut _6: usize;
|
||||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||||
let mut _6: std::ptr::metadata::PtrRepr<[u32]>;
|
|
||||||
}
|
}
|
||||||
scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) {
|
scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) {
|
||||||
}
|
}
|
||||||
@ -30,13 +29,10 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
|
|||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = _4 as *const () (PtrToPtr);
|
_5 = _4 as *const () (PtrToPtr);
|
||||||
StorageLive(_7);
|
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: _1 };
|
_6 = PtrMetadata(_1);
|
||||||
_7 = ((_6.2: std::ptr::metadata::PtrComponents<[u32]>).1: usize);
|
_0 = *const [u32] from (_5, _6);
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
_0 = *const [u32] from (_5, _7);
|
|
||||||
StorageDead(_7);
|
|
||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
return;
|
return;
|
||||||
|
@ -13,9 +13,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
|
|||||||
}
|
}
|
||||||
scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
||||||
let mut _5: *const ();
|
let mut _5: *const ();
|
||||||
let mut _7: usize;
|
let mut _6: usize;
|
||||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||||
let mut _6: std::ptr::metadata::PtrRepr<[u32]>;
|
|
||||||
}
|
}
|
||||||
scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) {
|
scope 6 (inlined std::ptr::from_raw_parts::<[u32]>) {
|
||||||
}
|
}
|
||||||
@ -30,13 +29,10 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
|
|||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = _4 as *const () (PtrToPtr);
|
_5 = _4 as *const () (PtrToPtr);
|
||||||
StorageLive(_7);
|
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: _1 };
|
_6 = PtrMetadata(_1);
|
||||||
_7 = ((_6.2: std::ptr::metadata::PtrComponents<[u32]>).1: usize);
|
_0 = *const [u32] from (_5, _6);
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
_0 = *const [u32] from (_5, _7);
|
|
||||||
StorageDead(_7);
|
|
||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user