1
Fork 0

Add AggregateKind::RawPtr and enough support to compile

This commit is contained in:
Scott McMurray 2024-04-11 14:44:02 -07:00
parent 70df9d9a13
commit e6b2b764ec
11 changed files with 84 additions and 3 deletions

View file

@ -1315,7 +1315,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
AggregateKind::Adt(..) AggregateKind::Adt(..)
| AggregateKind::Array(..) | AggregateKind::Array(..)
| AggregateKind::Tuple { .. } => (), | AggregateKind::Tuple { .. }
| AggregateKind::RawPtr(..) => (),
} }
for operand in operands { for operand in operands {

View file

@ -1921,7 +1921,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
AggregateKind::Array(ty) => Ok(ty), AggregateKind::Array(ty) => Ok(ty),
AggregateKind::Tuple => { AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
unreachable!("This should have been covered in check_rvalues"); unreachable!("This should have been covered in check_rvalues");
} }
} }
@ -2518,6 +2518,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
AggregateKind::Closure(_, _) => None, AggregateKind::Closure(_, _) => None,
AggregateKind::Coroutine(_, _) => None, AggregateKind::Coroutine(_, _) => None,
AggregateKind::CoroutineClosure(_, _) => None, AggregateKind::CoroutineClosure(_, _) => None,
AggregateKind::RawPtr(_, _) => None,
}, },
} }
} }
@ -2539,6 +2540,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return; return;
} }
if let AggregateKind::RawPtr(..) = aggregate_kind {
bug!("RawPtr should only be in runtime MIR");
}
for (i, operand) in operands.iter_enumerated() { for (i, operand) in operands.iter_enumerated() {
let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) { let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
Ok(field_ty) => field_ty, Ok(field_ty) => field_ty,
@ -2757,7 +2762,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
), ),
), ),
AggregateKind::Array(_) | AggregateKind::Tuple => { AggregateKind::Array(_) | AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
(CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty()) (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
} }
}; };

View file

@ -923,6 +923,44 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
} }
} }
} }
AggregateKind::RawPtr(pointee_ty, mutability) => {
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 just `bug!` on it.
self.fail(location, "RawPtr should be in runtime MIR only");
}
if fields.len() != 2 {
self.fail(location, "raw pointer aggregate must have 2 fields");
} else {
let data_ptr_ty = fields.raw[0].ty(self.body, self.tcx);
let metadata_ty = fields.raw[1].ty(self.body, self.tcx);
if let ty::RawPtr(in_pointee, in_mut) = data_ptr_ty.kind() {
if *in_mut != mutability {
self.fail(location, "input and output mutability must match");
}
// FIXME: check `Thin` instead of `Sized`
if !in_pointee.is_sized(self.tcx, self.param_env) {
self.fail(location, "input pointer must be thin");
}
} else {
self.fail(location, "first operand to raw pointer aggregate must be a raw pointer");
}
// FIXME: Check metadata more generally
if pointee_ty.is_slice() {
if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) {
self.fail(location, "slice metadata must be usize");
}
} else if pointee_ty.is_sized(self.tcx, self.param_env) {
if metadata_ty != self.tcx.types.unit {
self.fail(location, "metadata for pointer-to-thin must be unit");
}
}
}
}
}, },
Rvalue::Ref(_, BorrowKind::Fake, _) => { Rvalue::Ref(_, BorrowKind::Fake, _) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {

View file

@ -1094,6 +1094,15 @@ impl<'tcx> Debug for Rvalue<'tcx> {
struct_fmt.finish() struct_fmt.finish()
}), }),
AggregateKind::RawPtr(pointee_ty, mutability) => {
let kind_str = match mutability {
Mutability::Mut => "mut",
Mutability::Not => "const",
};
with_no_trimmed_paths!(write!(fmt, "*{kind_str} {pointee_ty} from "))?;
fmt_tuple(fmt, "")
}
} }
} }

View file

@ -1351,6 +1351,21 @@ pub enum AggregateKind<'tcx> {
Closure(DefId, GenericArgsRef<'tcx>), Closure(DefId, GenericArgsRef<'tcx>),
Coroutine(DefId, GenericArgsRef<'tcx>), Coroutine(DefId, GenericArgsRef<'tcx>),
CoroutineClosure(DefId, GenericArgsRef<'tcx>), CoroutineClosure(DefId, GenericArgsRef<'tcx>),
/// Construct a raw pointer from the data pointer and metadata.
///
/// The `Ty` here is the type of the *pointee*, not the pointer itself.
/// The `Mutability` indicates whether this produces a `*const` or `*mut`.
///
/// The [`Rvalue::Aggregate`] operands for thus must be
///
/// 0. A raw pointer of matching mutability with any [`core::ptr::Thin`] pointee
/// 1. A value of the appropriate [`core::ptr::Pointee::Metadata`] type
///
/// *Both* operands must always be included, even the unit value if this is
/// creating a thin pointer. If you're just converting between thin pointers,
/// you may want an [`Rvalue::Cast`] with [`CastKind::PtrToPtr`] instead.
RawPtr(Ty<'tcx>, Mutability),
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]

View file

@ -206,6 +206,7 @@ impl<'tcx> Rvalue<'tcx> {
AggregateKind::CoroutineClosure(did, args) => { AggregateKind::CoroutineClosure(did, args) => {
Ty::new_coroutine_closure(tcx, did, args) Ty::new_coroutine_closure(tcx, did, args)
} }
AggregateKind::RawPtr(ty, mutability) => Ty::new_ptr(tcx, ty, mutability),
}, },
Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty,

View file

@ -751,6 +751,9 @@ macro_rules! make_mir_visitor {
) => { ) => {
self.visit_args(coroutine_closure_args, location); self.visit_args(coroutine_closure_args, location);
} }
AggregateKind::RawPtr(ty, _) => {
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
} }
for operand in operands { for operand in operands {

View file

@ -885,6 +885,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
AggregateKind::Adt(did, ..) => tcx.def_kind(did) != DefKind::Enum, AggregateKind::Adt(did, ..) => tcx.def_kind(did) != DefKind::Enum,
// Coroutines are never ZST, as they at least contain the implicit states. // Coroutines are never ZST, as they at least contain the implicit states.
AggregateKind::Coroutine(..) => false, AggregateKind::Coroutine(..) => false,
AggregateKind::RawPtr(..) => bug!("MIR for RawPtr aggregate must have 2 fields"),
}; };
if is_zst { if is_zst {
@ -910,6 +911,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
} }
// Do not track unions. // Do not track unions.
AggregateKind::Adt(_, _, _, _, Some(_)) => return None, AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
// FIXME: Do the extra work to GVN `from_raw_parts`
AggregateKind::RawPtr(..) => return None,
}; };
let fields: Option<Vec<_>> = fields let fields: Option<Vec<_>> = fields

View file

@ -603,6 +603,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
AggregateKind::Adt(_, variant, _, _, _) => variant, AggregateKind::Adt(_, variant, _, _, _) => variant,
AggregateKind::Array(_) AggregateKind::Array(_)
| AggregateKind::Tuple | AggregateKind::Tuple
| AggregateKind::RawPtr(_, _)
| AggregateKind::Closure(_, _) | AggregateKind::Closure(_, _)
| AggregateKind::Coroutine(_, _) | AggregateKind::Coroutine(_, _)
| AggregateKind::CoroutineClosure(_, _) => VariantIdx::ZERO, | AggregateKind::CoroutineClosure(_, _) => VariantIdx::ZERO,

View file

@ -543,6 +543,9 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
mir::AggregateKind::CoroutineClosure(..) => { mir::AggregateKind::CoroutineClosure(..) => {
todo!("FIXME(async_closures): Lower these to SMIR") todo!("FIXME(async_closures): Lower these to SMIR")
} }
mir::AggregateKind::RawPtr(ty, mutability) => {
stable_mir::mir::AggregateKind::RawPtr(ty.stable(tables), mutability.stable(tables))
}
} }
} }
} }

View file

@ -602,6 +602,7 @@ impl Rvalue {
AggregateKind::Coroutine(def, ref args, mov) => { AggregateKind::Coroutine(def, ref args, mov) => {
Ok(Ty::new_coroutine(def, args.clone(), mov)) Ok(Ty::new_coroutine(def, args.clone(), mov))
} }
AggregateKind::RawPtr(ty, mutability) => Ok(Ty::new_ptr(ty, mutability)),
}, },
Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)), Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)),
Rvalue::CopyForDeref(place) => place.ty(locals), Rvalue::CopyForDeref(place) => place.ty(locals),
@ -617,6 +618,7 @@ pub enum AggregateKind {
Closure(ClosureDef, GenericArgs), Closure(ClosureDef, GenericArgs),
// FIXME(stable_mir): Movability here is redundant // FIXME(stable_mir): Movability here is redundant
Coroutine(CoroutineDef, GenericArgs, Movability), Coroutine(CoroutineDef, GenericArgs, Movability),
RawPtr(Ty, Mutability),
} }
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]