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

Introduce `Rvalue::ShallowInitBox`

上级 308dffd2
......@@ -316,7 +316,8 @@ fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'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 @@ fn consume_rvalue(
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 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
}
}
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 @@ fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationInde
| Rvalue::AddressOf(..)
| Rvalue::Len(..)
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::BinaryOp(..)
| Rvalue::CheckedBinaryOp(..)
| Rvalue::NullaryOp(..)
......
......@@ -701,6 +701,13 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
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 @@ pub fn codegen_rvalue_operand(
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 @@ pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) ->
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 @@ pub fn eval_rvalue_into_place(
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 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
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 @@ pub fn in_rvalue<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue
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 @@ fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
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 @@ 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>
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>
/// 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 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
});
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
}
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,
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) {
}
mir::Rvalue::Cast(..)
| mir::Rvalue::ShallowInitBox(..)
| mir::Rvalue::Use(..)
| mir::Rvalue::ThreadLocalRef(..)
| mir::Rvalue::Repeat(..)
......
......@@ -327,6 +327,7 @@ fn gather_rvalue(&mut self, rvalue: &Rvalue<'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 @@ fn const_prop(
| Rvalue::Repeat(..)
| Rvalue::Len(..)
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::Discriminant(..)
| Rvalue::NullaryOp(..) => {}
}
......
......@@ -967,6 +967,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
}
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() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册