Introduce Rvalue::ShallowInitBox
This commit is contained in:
parent
308dffd25c
commit
c38da2e0a3
19 changed files with 68 additions and 11 deletions
|
@ -316,7 +316,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
|
|||
Rvalue::Use(ref operand)
|
||||
| Rvalue::Repeat(ref operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
|
||||
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
|
||||
self.consume_operand(location, operand)
|
||||
}
|
||||
|
||||
|
|
|
@ -1361,7 +1361,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
Rvalue::Use(ref operand)
|
||||
| Rvalue::Repeat(ref operand, _)
|
||||
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
|
||||
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
|
||||
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
|
||||
| Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
|
||||
self.consume_operand(location, (operand, span), flow_state)
|
||||
}
|
||||
|
||||
|
|
|
@ -2018,13 +2018,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
Rvalue::NullaryOp(_, ty) => {
|
||||
// Even with unsized locals cannot box an unsized value.
|
||||
if self.unsized_feature_enabled() {
|
||||
let span = body.source_info(location).span;
|
||||
self.ensure_place_sized(ty, span);
|
||||
}
|
||||
|
||||
Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, ty) => {
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
|
||||
substs: tcx.mk_substs_trait(ty, &[]),
|
||||
|
@ -2357,6 +2351,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
| Rvalue::AddressOf(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
| Rvalue::CheckedBinaryOp(..)
|
||||
| Rvalue::NullaryOp(..)
|
||||
|
|
|
@ -701,6 +701,13 @@ fn codegen_stmt<'tcx>(
|
|||
let len = codegen_array_len(fx, place);
|
||||
lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
|
||||
}
|
||||
Rvalue::ShallowInitBox(ref operand, content_ty) => {
|
||||
let content_ty = fx.monomorphize(content_ty);
|
||||
let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty));
|
||||
let operand = codegen_operand(fx, operand);
|
||||
let operand = operand.load_scalar(fx);
|
||||
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
|
||||
}
|
||||
Rvalue::NullaryOp(NullOp::Box, content_ty) => {
|
||||
let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap();
|
||||
let content_ty = fx.monomorphize(content_ty);
|
||||
|
|
|
@ -550,6 +550,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
OperandRef::new_zst(&mut bx, self.cx.layout_of(self.monomorphize(ty)));
|
||||
(bx, operand)
|
||||
}
|
||||
mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
|
||||
let operand = self.codegen_operand(&mut bx, operand);
|
||||
let lloperand = operand.immediate();
|
||||
|
||||
let content_ty = self.monomorphize(content_ty);
|
||||
let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty));
|
||||
let llty_ptr = bx.cx().backend_type(box_layout);
|
||||
|
||||
let val = bx.pointercast(lloperand, llty_ptr);
|
||||
let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
|
||||
(bx, operand)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -763,6 +775,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::Rvalue::AddressOf(..) |
|
||||
mir::Rvalue::Len(..) |
|
||||
mir::Rvalue::Cast(..) | // (*)
|
||||
mir::Rvalue::ShallowInitBox(..) | // (*)
|
||||
mir::Rvalue::BinaryOp(..) |
|
||||
mir::Rvalue::CheckedBinaryOp(..) |
|
||||
mir::Rvalue::UnaryOp(..) |
|
||||
|
|
|
@ -289,6 +289,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
|
||||
}
|
||||
|
||||
ShallowInitBox(ref operand, _) => {
|
||||
let src = self.eval_operand(operand, None)?;
|
||||
let v = self.read_immediate(&src)?;
|
||||
self.write_immediate(*v, &dest)?;
|
||||
}
|
||||
|
||||
Cast(cast_kind, ref operand, cast_ty) => {
|
||||
let src = self.eval_operand(operand, None)?;
|
||||
let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
|
||||
|
|
|
@ -650,6 +650,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
|
|||
|
||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
|
||||
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
|
||||
Rvalue::ShallowInitBox(_, _) => {}
|
||||
|
||||
Rvalue::UnaryOp(_, ref operand) => {
|
||||
let ty = operand.ty(self.body, self.tcx);
|
||||
|
|
|
@ -206,7 +206,8 @@ where
|
|||
Rvalue::Use(operand)
|
||||
| Rvalue::Repeat(operand, _)
|
||||
| Rvalue::UnaryOp(_, operand)
|
||||
| Rvalue::Cast(_, operand, _) => in_operand::<Q, _>(cx, in_local, operand),
|
||||
| Rvalue::Cast(_, operand, _)
|
||||
| Rvalue::ShallowInitBox(operand, _) => in_operand::<Q, _>(cx, in_local, operand),
|
||||
|
||||
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
|
||||
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
|
||||
|
|
|
@ -523,6 +523,8 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
NullOp::AlignOf => {}
|
||||
},
|
||||
|
||||
Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
|
||||
|
||||
Rvalue::UnaryOp(op, operand) => {
|
||||
match op {
|
||||
// These operations can never fail.
|
||||
|
|
|
@ -2200,6 +2200,12 @@ pub enum Rvalue<'tcx> {
|
|||
/// that `Foo` has a destructor. These rvalues can be optimized
|
||||
/// away after type-checking and before lowering.
|
||||
Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
|
||||
|
||||
/// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
|
||||
///
|
||||
/// This is different a normal transmute because dataflow analysis will treat the box
|
||||
/// as initialized but its content as uninitialized.
|
||||
ShallowInitBox(Operand<'tcx>, Ty<'tcx>),
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
|
@ -2450,6 +2456,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
|||
}),
|
||||
}
|
||||
}
|
||||
|
||||
ShallowInitBox(ref place, ref ty) => {
|
||||
write!(fmt, "ShallowInitBox({:?}, {:?})", place, ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,6 +206,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
tcx.mk_generator(did, substs, movability)
|
||||
}
|
||||
},
|
||||
Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,7 +215,9 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
/// whether its only shallowly initialized (`Rvalue::Box`).
|
||||
pub fn initialization_state(&self) -> RvalueInitializationState {
|
||||
match *self {
|
||||
Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow,
|
||||
Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => {
|
||||
RvalueInitializationState::Shallow
|
||||
}
|
||||
_ => RvalueInitializationState::Deep,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,6 +210,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
|||
});
|
||||
Aggregate(kind, fields.fold_with(folder))
|
||||
}
|
||||
ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,6 +256,10 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
|||
}
|
||||
fields.visit_with(visitor)
|
||||
}
|
||||
ShallowInitBox(ref op, ty) => {
|
||||
op.visit_with(visitor)?;
|
||||
ty.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -753,6 +753,11 @@ macro_rules! make_mir_visitor {
|
|||
self.visit_operand(operand, location);
|
||||
}
|
||||
}
|
||||
|
||||
Rvalue::ShallowInitBox(operand, ty) => {
|
||||
self.visit_operand(operand, location);
|
||||
self.visit_ty(ty, TyContext::Location(location));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ where
|
|||
}
|
||||
|
||||
mir::Rvalue::Cast(..)
|
||||
| mir::Rvalue::ShallowInitBox(..)
|
||||
| mir::Rvalue::Use(..)
|
||||
| mir::Rvalue::ThreadLocalRef(..)
|
||||
| mir::Rvalue::Repeat(..)
|
||||
|
|
|
@ -327,6 +327,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
|||
Rvalue::Use(ref operand)
|
||||
| Rvalue::Repeat(ref operand, _)
|
||||
| Rvalue::Cast(_, ref operand, _)
|
||||
| Rvalue::ShallowInitBox(ref operand, _)
|
||||
| Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
|
||||
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs))
|
||||
| Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
|
||||
|
|
|
@ -723,6 +723,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
| Rvalue::Repeat(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::Discriminant(..)
|
||||
| Rvalue::NullaryOp(..) => {}
|
||||
}
|
||||
|
|
|
@ -967,6 +967,7 @@ impl<'tcx> Visitor<'tcx> for BorrowCollector {
|
|||
}
|
||||
|
||||
Rvalue::Cast(..)
|
||||
| Rvalue::ShallowInitBox(..)
|
||||
| Rvalue::Use(..)
|
||||
| Rvalue::Repeat(..)
|
||||
| Rvalue::Len(..)
|
||||
|
|
|
@ -204,6 +204,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<
|
|||
| Rvalue::AddressOf(_, _)
|
||||
| Rvalue::Cast(_, Operand::Constant(_), _)
|
||||
| Rvalue::NullaryOp(_, _)
|
||||
| Rvalue::ShallowInitBox(_, _)
|
||||
| Rvalue::UnaryOp(_, Operand::Constant(_)) => return true,
|
||||
|
||||
// These rvalues make things ambiguous
|
||||
|
@ -301,6 +302,7 @@ fn find_determining_place<'tcx>(
|
|||
| Rvalue::ThreadLocalRef(_)
|
||||
| Rvalue::AddressOf(_, _)
|
||||
| Rvalue::NullaryOp(_, _)
|
||||
| Rvalue::ShallowInitBox(_, _)
|
||||
| Rvalue::UnaryOp(_, Operand::Constant(_))
|
||||
| Rvalue::Cast(_, Operand::Constant(_), _)
|
||||
=> return None,
|
||||
|
|
|
@ -194,6 +194,7 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv
|
|||
},
|
||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => Ok(()),
|
||||
Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
|
||||
Rvalue::ShallowInitBox(_, _) => Ok(()),
|
||||
Rvalue::UnaryOp(_, operand) => {
|
||||
let ty = operand.ty(body, tcx);
|
||||
if ty.is_integral() || ty.is_bool() {
|
||||
|
|
Loading…
Add table
Reference in a new issue