Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,13 +829,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
fx.bcx.ins().nop();
}
}
Rvalue::ShallowInitBox(ref operand, content_ty) => {
let content_ty = fx.monomorphize(content_ty);
let box_layout = fx.layout_of(Ty::new_box(fx.tcx, 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(ref null_op, ty) => {
assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env()));
let layout = fx.layout_of(fx.monomorphize(ty));
Expand Down Expand Up @@ -924,6 +917,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
lval.write_cvalue_transmute(fx, operand);
}
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in codegen"),
}
}
StatementKind::StorageLive(_)
Expand Down
10 changes: 1 addition & 9 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,22 +724,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
}
mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
let operand = self.codegen_operand(bx, operand);
let val = operand.immediate();

let content_ty = self.monomorphize(content_ty);
let box_layout = bx.cx().layout_of(Ty::new_box(bx.tcx(), content_ty));

OperandRef { val: OperandValue::Immediate(val), layout: box_layout }
}
mir::Rvalue::WrapUnsafeBinder(ref operand, binder_ty) => {
let operand = self.codegen_operand(bx, operand);
let binder_ty = self.monomorphize(binder_ty);
let layout = bx.cx().layout_of(binder_ty);
OperandRef { val: operand.val, layout }
}
mir::Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
mir::Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in codegen"),
}
}

Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,13 @@ macro_rules! static_assert_size {
const _: (usize, usize) = ($size, ::std::mem::size_of::<$ty>());
};
}

#[macro_export]
macro_rules! indexvec {
($expr:expr; $n:expr) => {
IndexVec::from_raw(vec![$expr; $n])
};
($($expr:expr),* $(,)?) => {
IndexVec::from_raw(vec![$($expr),*])
};
}
15 changes: 5 additions & 10 deletions compiler/rustc_mir_transform/src/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{CoroutineDesugaring, CoroutineKind};
use rustc_index::bit_set::{BitMatrix, DenseBitSet, GrowableBitSet};
use rustc_index::{Idx, IndexVec};
use rustc_index::{Idx, IndexVec, indexvec};
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::util::Discr;
Expand Down Expand Up @@ -289,7 +289,7 @@ impl<'tcx> TransformVisitor<'tcx> {
let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, source_info.span);
let args = self.tcx.mk_args(&[self.old_ret_ty.into()]);
let (variant_idx, operands) = if is_return {
(ZERO, IndexVec::from_raw(vec![val])) // Poll::Ready(val)
(ZERO, indexvec![val]) // Poll::Ready(val)
} else {
(ONE, IndexVec::new()) // Poll::Pending
};
Expand All @@ -301,7 +301,7 @@ impl<'tcx> TransformVisitor<'tcx> {
let (variant_idx, operands) = if is_return {
(ZERO, IndexVec::new()) // None
} else {
(ONE, IndexVec::from_raw(vec![val])) // Some(val)
(ONE, indexvec![val]) // Some(val)
};
make_aggregate_adt(option_def_id, variant_idx, args, operands)
}
Expand Down Expand Up @@ -337,12 +337,7 @@ impl<'tcx> TransformVisitor<'tcx> {
} else {
ZERO // CoroutineState::Yielded(val)
};
make_aggregate_adt(
coroutine_state_def_id,
variant_idx,
args,
IndexVec::from_raw(vec![val]),
)
make_aggregate_adt(coroutine_state_def_id, variant_idx, args, indexvec![val])
}
};

Expand Down Expand Up @@ -1122,7 +1117,7 @@ fn return_poll_ready_assign<'tcx>(tcx: TyCtxt<'tcx>, source_info: SourceInfo) ->
}));
let ready_val = Rvalue::Aggregate(
Box::new(AggregateKind::Adt(poll_def_id, VariantIdx::from_usize(0), args, None, None)),
IndexVec::from_raw(vec![val]),
indexvec![val],
);
Statement::new(source_info, StatementKind::Assign(Box::new((Place::return_place(), ready_val))))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/dataflow_const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map),
Rvalue::Use(operand) => return self.handle_operand(operand, state),
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in runtime MIR"),
Rvalue::Ref(..) | Rvalue::RawPtr(..) => {
// We don't track such places.
return ValueOrPlace::TOP;
Expand All @@ -489,7 +490,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
| Rvalue::Cast(..)
| Rvalue::BinaryOp(..)
| Rvalue::Aggregate(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::WrapUnsafeBinder(..) => {
// No modification is possible through these r-values.
return ValueOrPlace::TOP;
Expand Down
94 changes: 80 additions & 14 deletions compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
//!
//! Box is not actually a pointer so it is incorrect to dereference it directly.

use rustc_abi::FieldIdx;
use rustc_hir::def_id::DefId;
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_index::{IndexVec, indexvec};
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};

use crate::patch::MirPatch;

/// Constructs the types used when accessing a Box's pointer
fn build_ptr_tys<'tcx>(
tcx: TyCtxt<'tcx>,
pointee: Ty<'tcx>,
unique_did: DefId,
nonnull_did: DefId,
unique_def: ty::AdtDef<'tcx>,
nonnull_def: ty::AdtDef<'tcx>,
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
let args = tcx.mk_args(&[pointee.into()]);
let unique_ty = tcx.type_of(unique_did).instantiate(tcx, args);
let nonnull_ty = tcx.type_of(nonnull_did).instantiate(tcx, args);
let unique_ty = Ty::new_adt(tcx, unique_def, args);
let nonnull_ty = Ty::new_adt(tcx, nonnull_def, args);
let ptr_ty = Ty::new_imm_ptr(tcx, pointee);

(unique_ty, nonnull_ty, ptr_ty)
Expand All @@ -36,8 +36,8 @@ pub(super) fn build_projection<'tcx>(

struct ElaborateBoxDerefVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
unique_did: DefId,
nonnull_did: DefId,
unique_def: ty::AdtDef<'tcx>,
nonnull_def: ty::AdtDef<'tcx>,
local_decls: &'a mut LocalDecls<'tcx>,
patch: MirPatch<'tcx>,
}
Expand All @@ -64,7 +64,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
let source_info = self.local_decls[place.local].source_info;

let (unique_ty, nonnull_ty, ptr_ty) =
build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did);
build_ptr_tys(tcx, boxed_ty, self.unique_def, self.nonnull_def);

let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);

Expand All @@ -86,6 +86,68 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {

self.super_place(place, context, location);
}

fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) {
self.super_statement(stmt, location);

let tcx = self.tcx;
let source_info = stmt.source_info;

if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind
&& let Rvalue::ShallowInitBox(ref mut mutptr_to_u8, pointee) = *rvalue
&& let ty::Adt(box_adt, box_args) = Ty::new_box(tcx, pointee).kind()
{
let args = tcx.mk_args(&[pointee.into()]);
let (unique_ty, nonnull_ty, ptr_ty) =
build_ptr_tys(tcx, pointee, self.unique_def, self.nonnull_def);
let adt_kind = |def: ty::AdtDef<'tcx>, args| {
Box::new(AggregateKind::Adt(def.did(), VariantIdx::ZERO, args, None, None))
};
let zst = |ty| {
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::zero_sized(ty),
}))
};

let constptr = self.patch.new_temp(ptr_ty, source_info.span);
self.patch.add_assign(
location,
constptr.into(),
Rvalue::Cast(CastKind::Transmute, mutptr_to_u8.clone(), ptr_ty),
);

let nonnull = self.patch.new_temp(nonnull_ty, source_info.span);
self.patch.add_assign(
location,
nonnull.into(),
Rvalue::Aggregate(
adt_kind(self.nonnull_def, args),
indexvec![Operand::Move(constptr.into())],
),
);

let unique = self.patch.new_temp(unique_ty, source_info.span);
let phantomdata_ty =
self.unique_def.non_enum_variant().fields[FieldIdx::ONE].ty(tcx, args);
self.patch.add_assign(
location,
unique.into(),
Rvalue::Aggregate(
adt_kind(self.unique_def, args),
indexvec![Operand::Move(nonnull.into()), zst(phantomdata_ty)],
),
);

let global_alloc_ty =
box_adt.non_enum_variant().fields[FieldIdx::ONE].ty(tcx, box_args);
*rvalue = Rvalue::Aggregate(
adt_kind(*box_adt, box_args),
indexvec![Operand::Move(unique.into()), zst(global_alloc_ty)],
);
}
}
}

pub(super) struct ElaborateBoxDerefs;
Expand All @@ -97,18 +159,22 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {

let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did;

let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else {
let Some(unique_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else {
span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
};

let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did;
let nonnull_did = unique_def.non_enum_variant().fields[FieldIdx::ZERO].did;

let Some(nonnull_def) = tcx.type_of(nonnull_did).instantiate_identity().ty_adt_def() else {
span_bug!(tcx.def_span(nonnull_did), "expected Unique to contain Nonnull")
};

let patch = MirPatch::new(body);

let local_decls = &mut body.local_decls;

let mut visitor =
ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
ElaborateBoxDerefVisitor { tcx, unique_def, nonnull_def, local_decls, patch };

for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
visitor.visit_basic_block_data(block, data);
Expand All @@ -131,7 +197,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
new_projections.get_or_insert_with(|| base.projection.to_vec());

let (unique_ty, nonnull_ty, ptr_ty) =
build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did);
build_ptr_tys(tcx, boxed_ty, unique_def, nonnull_def);

new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty));
// While we can't project into `NonNull<_>` in a basic block
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1067,8 +1067,10 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
}

// Unsupported values.
Rvalue::ThreadLocalRef(..) | Rvalue::ShallowInitBox(..) => return None,
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
Rvalue::ThreadLocalRef(..) => return None,
Rvalue::CopyForDeref(_) | Rvalue::ShallowInitBox(..) => {
bug!("forbidden in runtime MIR: {rvalue:?}")
}
};
let ty = rvalue.ty(self.local_decls, self.tcx);
Some(self.insert(ty, value))
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_mir_transform/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
ProjectionElem::Deref
if self.body.phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) =>
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) =>
{
let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;

Expand Down Expand Up @@ -970,7 +970,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
assert!(!adt_def.is_union());
let variant = &adt_def.variants()[idx];
if variant.fields.len() != fields.len() {
self.fail(location, "adt has the wrong number of initialized fields");
self.fail(location, format!(
"adt {def_id:?} has the wrong number of initialized fields, expected {}, found {}",
fields.len(),
variant.fields.len(),
));
}
for (src, dest) in std::iter::zip(fields, &variant.fields) {
let dest_ty = self
Expand Down Expand Up @@ -1175,6 +1179,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
Rvalue::ShallowInitBox(operand, _) => {
let a = operand.ty(&self.body.local_decls, self.tcx);
check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..));
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location, format!("ShallowInitBox after ElaborateBoxDerefs"))
}
}
Rvalue::Cast(kind, operand, target_type) => {
let op_ty = operand.ty(self.body, self.tcx);
Expand Down
5 changes: 4 additions & 1 deletion tests/mir-opt/box_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// EMIT_MIR box_expr.main.ElaborateDrops.diff
fn main() {
// CHECK-LABEL: fn main(
// CHECK: [[box:_.*]] = ShallowInitBox(
// CHECK: [[ptr:_.*]] = move {{_.*}} as *const S (Transmute);
// CHECK: [[nonnull:_.*]] = NonNull::<S> { pointer: move [[ptr]] };
// CHECK: [[unique:_.*]] = Unique::<S> { pointer: move [[nonnull]], _marker: const PhantomData::<S> };
// CHECK: [[box:_.*]] = Box::<S>(move [[unique]], const std::alloc::Global);
// CHECK: [[ptr:_.*]] = copy (([[box]].0: std::ptr::Unique<S>).0: std::ptr::NonNull<S>) as *const S (Transmute);
// CHECK: (*[[ptr]]) = S::new() -> [return: [[ret:bb.*]], unwind: [[unwind:bb.*]]];
// CHECK: [[ret]]: {
Expand Down
23 changes: 17 additions & 6 deletions tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
let mut _6: *mut u8;
let mut _7: std::boxed::Box<i32>;
let mut _8: *const i32;
let mut _9: *const i32;
let mut _9: std::ptr::NonNull<i32>;
let mut _10: std::ptr::Unique<i32>;
let mut _11: *const i32;
let mut _12: *const i32;
scope 1 {
debug x => _1;
}
Expand All @@ -31,13 +34,21 @@

bb1: {
StorageLive(_7);
_7 = ShallowInitBox(move _6, i32);
_8 = copy ((_7.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
(*_8) = const 42_i32;
- _8 = move _6 as *const i32 (Transmute);
- _9 = NonNull::<i32> { pointer: move _8 };
- _10 = Unique::<i32> { pointer: move _9, _marker: const PhantomData::<i32> };
+ _8 = copy _6 as *const i32 (PtrToPtr);
+ _9 = NonNull::<i32> { pointer: copy _8 };
+ _10 = Unique::<i32> { pointer: copy _9, _marker: const PhantomData::<i32> };
_7 = Box::<i32>(move _10, const std::alloc::Global);
- _11 = copy ((_7.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
- (*_11) = const 42_i32;
+ _11 = copy _8;
+ (*_8) = const 42_i32;
_3 = move _7;
StorageDead(_7);
_9 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
_2 = copy (*_9);
_12 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
_2 = copy (*_12);
- _1 = Add(move _2, const 0_i32);
- StorageDead(_2);
+ _1 = copy _2;
Expand Down
Loading
Loading