Skip to content

Commit c8a2f53

Browse files
committed
Rvalue::InitBox prototype
1 parent 8ceea01 commit c8a2f53

File tree

21 files changed

+127
-6
lines changed

21 files changed

+127
-6
lines changed

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+13
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
544544
OperandRef::new_zst(&mut bx, self.cx.layout_of(self.monomorphize(ty)));
545545
(bx, operand)
546546
}
547+
mir::Rvalue::InitBox(ref operand, content_ty) => {
548+
let operand = self.codegen_operand(&mut bx, operand);
549+
let lloperand = operand.immediate();
550+
551+
let content_ty = self.monomorphize(content_ty);
552+
let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty));
553+
let llty_ptr = bx.cx().backend_type(box_layout);
554+
555+
let val = bx.pointercast(lloperand, llty_ptr);
556+
let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
557+
(bx, operand)
558+
}
547559
}
548560
}
549561

@@ -757,6 +769,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
757769
mir::Rvalue::AddressOf(..) |
758770
mir::Rvalue::Len(..) |
759771
mir::Rvalue::Cast(..) | // (*)
772+
mir::Rvalue::InitBox(..) | // (*)
760773
mir::Rvalue::BinaryOp(..) |
761774
mir::Rvalue::CheckedBinaryOp(..) |
762775
mir::Rvalue::UnaryOp(..) |

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ language_item_table! {
294294
BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn, GenericRequirement::None;
295295

296296
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
297+
BoxNew, sym::box_new, box_new_fn, Target::Fn, GenericRequirement::Minimum(1);
297298
BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
298299
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
299300
Oom, sym::oom, oom, Target::Fn, GenericRequirement::None;

compiler/rustc_middle/src/mir/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,8 @@ pub enum Rvalue<'tcx> {
21702170
/// that `Foo` has a destructor. These rvalues can be optimized
21712171
/// away after type-checking and before lowering.
21722172
Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
2173+
2174+
InitBox(Operand<'tcx>, Ty<'tcx>),
21732175
}
21742176

21752177
#[cfg(target_arch = "x86_64")]
@@ -2418,6 +2420,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
24182420
}),
24192421
}
24202422
}
2423+
2424+
InitBox(ref place, ref ty) => {
2425+
write!(fmt, "{:?} as box {:?}", place, ty)
2426+
}
24212427
}
24222428
}
24232429
}

compiler/rustc_middle/src/mir/tcx.rs

+2
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ impl<'tcx> Rvalue<'tcx> {
206206
tcx.mk_generator(did, substs, movability)
207207
}
208208
},
209+
Rvalue::InitBox(_, ty) => tcx.mk_box(ty),
209210
}
210211
}
211212

@@ -215,6 +216,7 @@ impl<'tcx> Rvalue<'tcx> {
215216
pub fn initialization_state(&self) -> RvalueInitializationState {
216217
match *self {
217218
Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow,
219+
Rvalue::InitBox(_, _) => RvalueInitializationState::Shallow,
218220
_ => RvalueInitializationState::Deep,
219221
}
220222
}

compiler/rustc_middle/src/mir/type_foldable.rs

+5
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
210210
});
211211
Aggregate(kind, fields.fold_with(folder))
212212
}
213+
InitBox(op, ty) => InitBox(op.fold_with(folder), ty.fold_with(folder)),
213214
}
214215
}
215216

@@ -255,6 +256,10 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
255256
}
256257
fields.visit_with(visitor)
257258
}
259+
InitBox(ref op, ty) => {
260+
op.visit_with(visitor)?;
261+
ty.visit_with(visitor)
262+
}
258263
}
259264
}
260265
}

compiler/rustc_middle/src/mir/visit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,11 @@ macro_rules! make_mir_visitor {
753753
self.visit_operand(operand, location);
754754
}
755755
}
756+
757+
Rvalue::InitBox(operand, ty) => {
758+
self.visit_operand(operand, location);
759+
self.visit_ty(ty, TyContext::Location(location));
760+
}
756761
}
757762
}
758763

compiler/rustc_mir/src/borrow_check/invalidation.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
318318
Rvalue::Use(ref operand)
319319
| Rvalue::Repeat(ref operand, _)
320320
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
321-
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
322-
self.consume_operand(location, operand)
323-
}
321+
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
322+
| Rvalue::InitBox(ref operand, _ /*ty*/) => self.consume_operand(location, operand),
324323

325324
Rvalue::Len(place) | Rvalue::Discriminant(place) => {
326325
let af = match *rvalue {

compiler/rustc_mir/src/borrow_check/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1341,7 +1341,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13411341
Rvalue::Use(ref operand)
13421342
| Rvalue::Repeat(ref operand, _)
13431343
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
1344-
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
1344+
| Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
1345+
| Rvalue::InitBox(ref operand, _ /*ty*/) => {
13451346
self.consume_operand(location, (operand, span), flow_state)
13461347
}
13471348

compiler/rustc_mir/src/borrow_check/type_check/mod.rs

+20
Original file line numberDiff line numberDiff line change
@@ -2320,6 +2320,25 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23202320
}
23212321
}
23222322

2323+
Rvalue::InitBox(_, ty) => {
2324+
// Even with unsized locals cannot box an unsized value.
2325+
if self.unsized_feature_enabled() {
2326+
let span = body.source_info(location).span;
2327+
self.ensure_place_sized(ty, span);
2328+
}
2329+
2330+
let trait_ref = ty::TraitRef {
2331+
def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
2332+
substs: tcx.mk_substs_trait(ty, &[]),
2333+
};
2334+
2335+
self.prove_trait_ref(
2336+
trait_ref,
2337+
location.to_locations(),
2338+
ConstraintCategory::SizedBound,
2339+
);
2340+
}
2341+
23232342
Rvalue::AddressOf(..)
23242343
| Rvalue::ThreadLocalRef(..)
23252344
| Rvalue::Use(..)
@@ -2343,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23432362
| Rvalue::AddressOf(..)
23442363
| Rvalue::Len(..)
23452364
| Rvalue::Cast(..)
2365+
| Rvalue::InitBox(..)
23462366
| Rvalue::BinaryOp(..)
23472367
| Rvalue::CheckedBinaryOp(..)
23482368
| Rvalue::NullaryOp(..)

compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ where
169169
}
170170

171171
mir::Rvalue::Cast(..)
172+
| mir::Rvalue::InitBox(..)
172173
| mir::Rvalue::Use(..)
173174
| mir::Rvalue::ThreadLocalRef(..)
174175
| mir::Rvalue::Repeat(..)

compiler/rustc_mir/src/dataflow/move_paths/builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
327327
Rvalue::Use(ref operand)
328328
| Rvalue::Repeat(ref operand, _)
329329
| Rvalue::Cast(_, ref operand, _)
330+
| Rvalue::InitBox(ref operand, _)
330331
| Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
331332
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs))
332333
| Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => {

compiler/rustc_mir/src/interpret/step.rs

+6
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
284284
self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), &dest)?;
285285
}
286286

287+
InitBox(ref operand, _) => {
288+
let src = self.eval_operand(operand, None)?;
289+
let v = self.read_immediate(&src)?;
290+
self.write_immediate(*v, &dest)?;
291+
}
292+
287293
Cast(cast_kind, ref operand, cast_ty) => {
288294
let src = self.eval_operand(operand, None)?;
289295
let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);

compiler/rustc_mir/src/transform/check_consts/check.rs

+7
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
650650

651651
Rvalue::NullaryOp(NullOp::SizeOf, _) => {}
652652
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
653+
Rvalue::InitBox(_, _) => {}
653654

654655
Rvalue::UnaryOp(_, ref operand) => {
655656
let ty = operand.ty(self.body, self.tcx);
@@ -899,6 +900,12 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
899900
return;
900901
}
901902

903+
let is_box_new = Some(callee) == tcx.lang_items().box_new_fn();
904+
if is_box_new {
905+
self.check_op(ops::HeapAllocation);
906+
return;
907+
}
908+
902909
// `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
903910
let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
904911
if is_async_block {

compiler/rustc_mir/src/transform/check_consts/qualifs.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ where
166166
Rvalue::Use(operand)
167167
| Rvalue::Repeat(operand, _)
168168
| Rvalue::UnaryOp(_, operand)
169-
| Rvalue::Cast(_, operand, _) => in_operand::<Q, _>(cx, in_local, operand),
169+
| Rvalue::Cast(_, operand, _)
170+
| Rvalue::InitBox(operand, _) => in_operand::<Q, _>(cx, in_local, operand),
170171

171172
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
172173
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)

compiler/rustc_mir/src/transform/const_prop.rs

+1
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
723723
| Rvalue::Repeat(..)
724724
| Rvalue::Len(..)
725725
| Rvalue::Cast(..)
726+
| Rvalue::InitBox(..)
726727
| Rvalue::Discriminant(..)
727728
| Rvalue::NullaryOp(..) => {}
728729
}

compiler/rustc_mir/src/transform/dest_prop.rs

+1
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ impl<'tcx> Visitor<'tcx> for BorrowCollector {
969969
}
970970

971971
Rvalue::Cast(..)
972+
| Rvalue::InitBox(..)
972973
| Rvalue::Use(..)
973974
| Rvalue::Repeat(..)
974975
| Rvalue::Len(..)

compiler/rustc_mir/src/transform/promote_consts.rs

+2
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ impl<'tcx> Validator<'_, 'tcx> {
522522
NullOp::SizeOf => {}
523523
},
524524

525+
Rvalue::InitBox(_, _) => return Err(Unpromotable),
526+
525527
Rvalue::UnaryOp(op, operand) => {
526528
match op {
527529
// These operations can never fail.

compiler/rustc_mir/src/transform/separate_const_switch.rs

+2
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<
204204
| Rvalue::AddressOf(_, _)
205205
| Rvalue::Cast(_, Operand::Constant(_), _)
206206
| Rvalue::NullaryOp(_, _)
207+
| Rvalue::InitBox(_, _)
207208
| Rvalue::UnaryOp(_, Operand::Constant(_)) => return true,
208209

209210
// These rvalues make things ambiguous
@@ -301,6 +302,7 @@ fn find_determining_place<'tcx>(
301302
| Rvalue::ThreadLocalRef(_)
302303
| Rvalue::AddressOf(_, _)
303304
| Rvalue::NullaryOp(_, _)
305+
| Rvalue::InitBox(_, _)
304306
| Rvalue::UnaryOp(_, Operand::Constant(_))
305307
| Rvalue::Cast(_, Operand::Constant(_), _)
306308
=> return None,

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_index::vec::Idx;
55
use crate::build::expr::as_place::PlaceBase;
66
use crate::build::expr::category::{Category, RvalueFunc};
77
use crate::build::{BlockAnd, BlockAndExtension, Builder};
8+
use rustc_hir::lang_items::LangItem;
89
use rustc_middle::middle::region;
910
use rustc_middle::mir::AssertKind;
1011
use rustc_middle::mir::Place;
@@ -88,6 +89,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8889
}
8990
ExprKind::Box { value } => {
9091
let value = &this.thir[value];
92+
let tcx = this.tcx;
93+
94+
let u8_ptr = tcx.mk_mut_ptr(tcx.mk_mach_uint(ty::UintTy::U8));
95+
let storage = this.local_decls.push(LocalDecl::new(u8_ptr, expr_span).internal());
96+
this.cfg.push(
97+
block,
98+
Statement { source_info, kind: StatementKind::StorageLive(storage) },
99+
);
100+
101+
let box_new = tcx.require_lang_item(LangItem::BoxNew, Some(source_info.span));
102+
let box_new = Operand::function_handle(
103+
tcx,
104+
box_new,
105+
tcx.mk_substs([value.ty.into()].iter()),
106+
source_info.span,
107+
);
108+
109+
let success = this.cfg.start_new_block();
110+
this.cfg.terminate(
111+
block,
112+
source_info,
113+
TerminatorKind::Call {
114+
func: box_new,
115+
args: Vec::new(),
116+
destination: Some((Place::from(storage), success)),
117+
cleanup: None,
118+
from_hir_call: false,
119+
fn_span: source_info.span,
120+
},
121+
);
122+
this.diverge_from(block);
123+
block = success;
124+
91125
// The `Box<T>` temporary created here is not a part of the HIR,
92126
// and therefore is not considered during generator auto-trait
93127
// determination. See the comment about `box` at `yield_in_scope`.
@@ -102,7 +136,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
102136
}
103137

104138
// malloc some memory of suitable type (thus far, uninitialized):
105-
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
139+
let box_ = Rvalue::InitBox(Operand::Move(Place::from(storage)), value.ty);
106140
this.cfg.push_assign(block, source_info, Place::from(result), box_);
107141

108142
// initialize the box contents:

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ symbols! {
364364
borrowck_graphviz_postflow,
365365
borrowck_graphviz_preflow,
366366
box_free,
367+
box_new,
367368
box_patterns,
368369
box_syntax,
369370
bpf_target_feature,

library/alloc/src/alloc.rs

+12
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,18 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
319319
}
320320
}
321321

322+
#[cfg(not(bootstrap))]
323+
#[cfg(all(not(no_global_oom_handling), not(test)))]
324+
#[lang = "box_new"]
325+
#[inline]
326+
pub(crate) fn box_new<T>() -> *mut u8 {
327+
let layout = Layout::new::<T>();
328+
match Global.allocate(layout) {
329+
Ok(ptr) => ptr.as_mut_ptr(),
330+
Err(_) => handle_alloc_error(layout),
331+
}
332+
}
333+
322334
#[cfg_attr(not(test), lang = "box_free")]
323335
#[inline]
324336
// This signature has to be the same as `Box`, otherwise an ICE will happen.

0 commit comments

Comments
 (0)