提交 c38da2e0 编写于 作者: G Gary Guo

Introduce `Rvalue::ShallowInitBox`

上级 308dffd2
...@@ -316,7 +316,8 @@ fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) { ...@@ -316,7 +316,8 @@ fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
Rvalue::Use(ref operand) Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _) | Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, 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) self.consume_operand(location, operand)
} }
......
...@@ -1361,7 +1361,8 @@ fn consume_rvalue( ...@@ -1361,7 +1361,8 @@ fn consume_rvalue(
Rvalue::Use(ref operand) Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _) | Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, 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) self.consume_operand(location, (operand, span), flow_state)
} }
......
...@@ -2018,13 +2018,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L ...@@ -2018,13 +2018,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
} }
} }
Rvalue::NullaryOp(_, ty) => { Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, 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);
}
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)), def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
substs: tcx.mk_substs_trait(ty, &[]), substs: tcx.mk_substs_trait(ty, &[]),
...@@ -2357,6 +2351,7 @@ fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationInde ...@@ -2357,6 +2351,7 @@ fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationInde
| Rvalue::AddressOf(..) | Rvalue::AddressOf(..)
| Rvalue::Len(..) | Rvalue::Len(..)
| Rvalue::Cast(..) | Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::BinaryOp(..) | Rvalue::BinaryOp(..)
| Rvalue::CheckedBinaryOp(..) | Rvalue::CheckedBinaryOp(..)
| Rvalue::NullaryOp(..) | Rvalue::NullaryOp(..)
......
...@@ -701,6 +701,13 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { ...@@ -701,6 +701,13 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
let len = codegen_array_len(fx, place); let len = codegen_array_len(fx, place);
lval.write_cvalue(fx, CValue::by_val(len, usize_layout)); 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) => { Rvalue::NullaryOp(NullOp::Box, content_ty) => {
let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap(); let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap();
let content_ty = fx.monomorphize(content_ty); let content_ty = fx.monomorphize(content_ty);
......
...@@ -550,6 +550,18 @@ pub fn codegen_rvalue_operand( ...@@ -550,6 +550,18 @@ pub fn codegen_rvalue_operand(
OperandRef::new_zst(&mut bx, self.cx.layout_of(self.monomorphize(ty))); OperandRef::new_zst(&mut bx, self.cx.layout_of(self.monomorphize(ty)));
(bx, operand) (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 @@ pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> ...@@ -763,6 +775,7 @@ pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) ->
mir::Rvalue::AddressOf(..) | mir::Rvalue::AddressOf(..) |
mir::Rvalue::Len(..) | mir::Rvalue::Len(..) |
mir::Rvalue::Cast(..) | // (*) mir::Rvalue::Cast(..) | // (*)
mir::Rvalue::ShallowInitBox(..) | // (*)
mir::Rvalue::BinaryOp(..) | mir::Rvalue::BinaryOp(..) |
mir::Rvalue::CheckedBinaryOp(..) | mir::Rvalue::CheckedBinaryOp(..) |
mir::Rvalue::UnaryOp(..) | mir::Rvalue::UnaryOp(..) |
......
...@@ -289,6 +289,12 @@ pub fn eval_rvalue_into_place( ...@@ -289,6 +289,12 @@ pub fn eval_rvalue_into_place(
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?; 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) => { Cast(cast_kind, ref operand, cast_ty) => {
let src = self.eval_operand(operand, None)?; let src = self.eval_operand(operand, None)?;
let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty); let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
......
...@@ -650,6 +650,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { ...@@ -650,6 +650,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation), Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
Rvalue::ShallowInitBox(_, _) => {}
Rvalue::UnaryOp(_, ref operand) => { Rvalue::UnaryOp(_, ref operand) => {
let ty = operand.ty(self.body, self.tcx); let ty = operand.ty(self.body, self.tcx);
......
...@@ -206,7 +206,8 @@ pub fn in_rvalue<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue ...@@ -206,7 +206,8 @@ pub fn in_rvalue<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue
Rvalue::Use(operand) Rvalue::Use(operand)
| Rvalue::Repeat(operand, _) | Rvalue::Repeat(operand, _)
| Rvalue::UnaryOp(_, 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)) => { Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs) in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
......
...@@ -523,6 +523,8 @@ fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> { ...@@ -523,6 +523,8 @@ fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
NullOp::AlignOf => {} NullOp::AlignOf => {}
}, },
Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
Rvalue::UnaryOp(op, operand) => { Rvalue::UnaryOp(op, operand) => {
match op { match op {
// These operations can never fail. // These operations can never fail.
......
...@@ -2200,6 +2200,12 @@ pub enum Rvalue<'tcx> { ...@@ -2200,6 +2200,12 @@ pub enum Rvalue<'tcx> {
/// that `Foo` has a destructor. These rvalues can be optimized /// that `Foo` has a destructor. These rvalues can be optimized
/// away after type-checking and before lowering. /// away after type-checking and before lowering.
Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>), 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"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
...@@ -2450,6 +2456,10 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { ...@@ -2450,6 +2456,10 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
}), }),
} }
} }
ShallowInitBox(ref place, ref ty) => {
write!(fmt, "ShallowInitBox({:?}, {:?})", place, ty)
}
} }
} }
} }
......
...@@ -206,6 +206,7 @@ pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx> ...@@ -206,6 +206,7 @@ pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
tcx.mk_generator(did, substs, movability) tcx.mk_generator(did, substs, movability)
} }
}, },
Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
} }
} }
...@@ -214,7 +215,9 @@ pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx> ...@@ -214,7 +215,9 @@ pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
/// whether its only shallowly initialized (`Rvalue::Box`). /// whether its only shallowly initialized (`Rvalue::Box`).
pub fn initialization_state(&self) -> RvalueInitializationState { pub fn initialization_state(&self) -> RvalueInitializationState {
match *self { match *self {
Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow, Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => {
RvalueInitializationState::Shallow
}
_ => RvalueInitializationState::Deep, _ => RvalueInitializationState::Deep,
} }
} }
......
...@@ -210,6 +210,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { ...@@ -210,6 +210,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
}); });
Aggregate(kind, fields.fold_with(folder)) Aggregate(kind, fields.fold_with(folder))
} }
ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
} }
} }
...@@ -255,6 +256,10 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow ...@@ -255,6 +256,10 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
} }
fields.visit_with(visitor) fields.visit_with(visitor)
} }
ShallowInitBox(ref op, ty) => {
op.visit_with(visitor)?;
ty.visit_with(visitor)
}
} }
} }
} }
......
...@@ -753,6 +753,11 @@ fn super_rvalue(&mut self, ...@@ -753,6 +753,11 @@ fn super_rvalue(&mut self,
self.visit_operand(operand, location); 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 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { ...@@ -169,6 +169,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
} }
mir::Rvalue::Cast(..) mir::Rvalue::Cast(..)
| mir::Rvalue::ShallowInitBox(..)
| mir::Rvalue::Use(..) | mir::Rvalue::Use(..)
| mir::Rvalue::ThreadLocalRef(..) | mir::Rvalue::ThreadLocalRef(..)
| mir::Rvalue::Repeat(..) | mir::Rvalue::Repeat(..)
......
...@@ -327,6 +327,7 @@ fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { ...@@ -327,6 +327,7 @@ fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
Rvalue::Use(ref operand) Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _) | Rvalue::Repeat(ref operand, _)
| Rvalue::Cast(_, ref operand, _) | Rvalue::Cast(_, ref operand, _)
| Rvalue::ShallowInitBox(ref operand, _)
| Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand), | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs)) Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs))
| Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => { | Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
......
...@@ -723,6 +723,7 @@ fn const_prop( ...@@ -723,6 +723,7 @@ fn const_prop(
| Rvalue::Repeat(..) | Rvalue::Repeat(..)
| Rvalue::Len(..) | Rvalue::Len(..)
| Rvalue::Cast(..) | Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::Discriminant(..) | Rvalue::Discriminant(..)
| Rvalue::NullaryOp(..) => {} | Rvalue::NullaryOp(..) => {}
} }
......
...@@ -967,6 +967,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { ...@@ -967,6 +967,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
} }
Rvalue::Cast(..) Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::Use(..) | Rvalue::Use(..)
| Rvalue::Repeat(..) | Rvalue::Repeat(..)
| Rvalue::Len(..) | Rvalue::Len(..)
......
...@@ -204,6 +204,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData< ...@@ -204,6 +204,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<
| Rvalue::AddressOf(_, _) | Rvalue::AddressOf(_, _)
| Rvalue::Cast(_, Operand::Constant(_), _) | Rvalue::Cast(_, Operand::Constant(_), _)
| Rvalue::NullaryOp(_, _) | Rvalue::NullaryOp(_, _)
| Rvalue::ShallowInitBox(_, _)
| Rvalue::UnaryOp(_, Operand::Constant(_)) => return true, | Rvalue::UnaryOp(_, Operand::Constant(_)) => return true,
// These rvalues make things ambiguous // These rvalues make things ambiguous
...@@ -301,6 +302,7 @@ fn find_determining_place<'tcx>( ...@@ -301,6 +302,7 @@ fn find_determining_place<'tcx>(
| Rvalue::ThreadLocalRef(_) | Rvalue::ThreadLocalRef(_)
| Rvalue::AddressOf(_, _) | Rvalue::AddressOf(_, _)
| Rvalue::NullaryOp(_, _) | Rvalue::NullaryOp(_, _)
| Rvalue::ShallowInitBox(_, _)
| Rvalue::UnaryOp(_, Operand::Constant(_)) | Rvalue::UnaryOp(_, Operand::Constant(_))
| Rvalue::Cast(_, Operand::Constant(_), _) | Rvalue::Cast(_, Operand::Constant(_), _)
=> return None, => return None,
......
...@@ -194,6 +194,7 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv ...@@ -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::SizeOf | NullOp::AlignOf, _) => Ok(()),
Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())), Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
Rvalue::ShallowInitBox(_, _) => Ok(()),
Rvalue::UnaryOp(_, operand) => { Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx); let ty = operand.ty(body, tcx);
if ty.is_integral() || ty.is_bool() { if ty.is_integral() || ty.is_bool() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册