Skip to content

Commit 339a409

Browse files
committed
Auto merge of #31430 - nagisa:mir-dyndrop, r=nikomatsakis
Zeroing on-drop seems to work fine. Still thinking about the best way to approach zeroing on-move. (based on top of the other drop PR; only the last 2 commits are relevant)
2 parents 84d8fec + d1a1239 commit 339a409

File tree

22 files changed

+405
-221
lines changed

22 files changed

+405
-221
lines changed

src/librustc/dep_graph/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ pub fn visit_all_items_in_krate<'tcx,V,F>(tcx: &ty::ctxt<'tcx>,
198198
fn visit_item(&mut self, i: &'tcx hir::Item) {
199199
let item_def_id = self.tcx.map.local_def_id(i.id);
200200
let task_id = (self.dep_node_fn)(item_def_id);
201-
debug!("About to start task {:?}", task_id);
202201
let _task = self.tcx.dep_graph.in_task(task_id);
202+
debug!("Started task {:?}", task_id);
203203
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
204204
self.visitor.visit_item(i)
205205
}

src/librustc_llvm/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2165,6 +2165,8 @@ extern {
21652165
NumInputs: c_uint)
21662166
-> OperandBundleDefRef;
21672167
pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
2168+
2169+
pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
21682170
}
21692171

21702172
// LLVM requires symbols from this library, but apparently they're not printed

src/librustc_mir/build/block.rs

+56-6
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,64 @@ impl<'a,'tcx> Builder<'a,'tcx> {
2121
-> BlockAnd<()> {
2222
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
2323
self.in_scope(extent, block, move |this| {
24-
unpack!(block = this.stmts(block, stmts));
25-
match expr {
26-
Some(expr) => this.into(destination, block, expr),
27-
None => {
28-
this.cfg.push_assign_unit(block, span, destination);
29-
block.unit()
24+
// This convoluted structure is to avoid using recursion as we walk down a list
25+
// of statements. Basically, the structure we get back is something like:
26+
//
27+
// let x = <init> in {
28+
// expr1;
29+
// let y = <init> in {
30+
// expr2;
31+
// expr3;
32+
// ...
33+
// }
34+
// }
35+
//
36+
// The let bindings are valid till the end of block so all we have to do is to pop all
37+
// the let-scopes at the end.
38+
//
39+
// First we build all the statements in the block.
40+
let mut let_extent_stack = Vec::with_capacity(8);
41+
for stmt in stmts {
42+
let Stmt { span: _, kind } = this.hir.mirror(stmt);
43+
match kind {
44+
StmtKind::Expr { scope, expr } => {
45+
unpack!(block = this.in_scope(scope, block, |this| {
46+
let expr = this.hir.mirror(expr);
47+
let temp = this.temp(expr.ty.clone());
48+
unpack!(block = this.into(&temp, block, expr));
49+
unpack!(block = this.build_drop(block, temp));
50+
block.unit()
51+
}));
52+
}
53+
StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
54+
this.push_scope(remainder_scope);
55+
let_extent_stack.push(remainder_scope);
56+
unpack!(block = this.in_scope(init_scope, block, move |this| {
57+
// FIXME #30046 ^~~~
58+
if let Some(init) = initializer {
59+
this.expr_into_pattern(block, remainder_scope, pattern, init)
60+
} else {
61+
this.declare_bindings(remainder_scope, &pattern);
62+
block.unit()
63+
}
64+
}));
65+
}
3066
}
3167
}
68+
// Then, the block may have an optional trailing expression which is a “return” value
69+
// of the block.
70+
if let Some(expr) = expr {
71+
unpack!(block = this.into(destination, block, expr));
72+
} else {
73+
// FIXME(#31472)
74+
this.cfg.push_assign_unit(block, span, destination);
75+
}
76+
// Finally, we pop all the let scopes before exiting out from the scope of block
77+
// itself.
78+
for extent in let_extent_stack.into_iter().rev() {
79+
unpack!(block = this.pop_scope(extent, block));
80+
}
81+
block.unit()
3282
})
3383
}
3484
}

src/librustc_mir/build/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,3 @@ mod into;
185185
mod matches;
186186
mod misc;
187187
mod scope;
188-
mod stmt;

src/librustc_mir/build/scope.rs

+1
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
249249
extent: CodeExtent,
250250
mut block: BasicBlock,
251251
target: BasicBlock) {
252+
debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
252253
let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent)
253254
.unwrap_or_else(||{
254255
self.hir.span_bug(span, &format!("extent {:?} does not enclose", extent))

src/librustc_mir/build/stmt.rs

-83
This file was deleted.

src/librustc_mir/hair/cx/block.rs

+33-43
Original file line numberDiff line numberDiff line change
@@ -21,62 +21,52 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
2121
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
2222
// We have to eagerly translate the "spine" of the statements
2323
// in order to get the lexical scoping correctly.
24-
let stmts = mirror_stmts(cx, self.id, self.stmts.iter().enumerate());
24+
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
2525
Block {
2626
extent: cx.tcx.region_maps.node_extent(self.id),
2727
span: self.span,
2828
stmts: stmts,
29-
expr: self.expr.to_ref(),
29+
expr: self.expr.to_ref()
3030
}
3131
}
3232
}
3333

34-
fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
35-
block_id: ast::NodeId,
36-
mut stmts: STMTS)
37-
-> Vec<StmtRef<'tcx>>
38-
where STMTS: Iterator<Item=(usize, &'tcx hir::Stmt)>
34+
fn mirror_stmts<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
35+
block_id: ast::NodeId,
36+
stmts: &'tcx [hir::Stmt])
37+
-> Vec<StmtRef<'tcx>>
3938
{
4039
let mut result = vec![];
41-
while let Some((index, stmt)) = stmts.next() {
40+
for (index, stmt) in stmts.iter().enumerate() {
4241
match stmt.node {
4342
hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) =>
44-
result.push(
45-
StmtRef::Mirror(
46-
Box::new(Stmt { span: stmt.span,
47-
kind: StmtKind::Expr {
48-
scope: cx.tcx.region_maps.node_extent(id),
49-
expr: expr.to_ref() } }))),
50-
51-
hir::StmtDecl(ref decl, id) => {
52-
match decl.node {
53-
hir::DeclItem(..) => { /* ignore for purposes of the MIR */ }
54-
hir::DeclLocal(ref local) => {
55-
let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
56-
block: block_id,
57-
first_statement_index: index as u32,
58-
});
59-
let remainder_extent =
60-
cx.tcx.region_maps.lookup_code_extent(remainder_extent);
61-
62-
// pull in all following statements, since
63-
// they are within the scope of this let:
64-
let following_stmts = mirror_stmts(cx, block_id, stmts);
65-
66-
let pattern = cx.irrefutable_pat(&local.pat);
67-
result.push(StmtRef::Mirror(Box::new(Stmt {
68-
span: stmt.span,
69-
kind: StmtKind::Let {
70-
remainder_scope: remainder_extent,
71-
init_scope: cx.tcx.region_maps.node_extent(id),
72-
pattern: pattern,
73-
initializer: local.init.to_ref(),
74-
stmts: following_stmts,
75-
},
76-
})));
77-
78-
return result;
43+
result.push(StmtRef::Mirror(Box::new(Stmt {
44+
span: stmt.span,
45+
kind: StmtKind::Expr {
46+
scope: cx.tcx.region_maps.node_extent(id),
47+
expr: expr.to_ref()
7948
}
49+
}))),
50+
hir::StmtDecl(ref decl, id) => match decl.node {
51+
hir::DeclItem(..) => { /* ignore for purposes of the MIR */ }
52+
hir::DeclLocal(ref local) => {
53+
let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
54+
block: block_id,
55+
first_statement_index: index as u32,
56+
});
57+
let remainder_extent =
58+
cx.tcx.region_maps.lookup_code_extent(remainder_extent);
59+
60+
let pattern = cx.irrefutable_pat(&local.pat);
61+
result.push(StmtRef::Mirror(Box::new(Stmt {
62+
span: stmt.span,
63+
kind: StmtKind::Let {
64+
remainder_scope: remainder_extent,
65+
init_scope: cx.tcx.region_maps.node_extent(id),
66+
pattern: pattern,
67+
initializer: local.init.to_ref(),
68+
},
69+
})));
8070
}
8171
}
8272
}

src/librustc_mir/hair/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,7 @@ pub enum StmtKind<'tcx> {
7878
pattern: Pattern<'tcx>,
7979

8080
/// let pat = <INIT> ...
81-
initializer: Option<ExprRef<'tcx>>,
82-
83-
/// let pat = init; <STMTS>
84-
stmts: Vec<StmtRef<'tcx>>,
81+
initializer: Option<ExprRef<'tcx>>
8582
},
8683
}
8784

src/librustc_trans/trans/base.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -1295,22 +1295,29 @@ pub fn init_zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'
12951295
fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte: u8) {
12961296
let _icx = push_ctxt("memfill");
12971297
let ccx = b.ccx;
1298-
12991298
let llty = type_of::type_of(ccx, ty);
1300-
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
1301-
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
1302-
1303-
let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
13041299
let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to());
13051300
let llzeroval = C_u8(ccx, byte);
13061301
let size = machine::llsize_of(ccx, llty);
13071302
let align = C_i32(ccx, type_of::align_of(ccx, ty) as i32);
1308-
let volatile = C_bool(ccx, false);
1309-
b.call(llintrinsicfn,
1310-
&[llptr, llzeroval, size, align, volatile],
1311-
None, None);
1303+
call_memset(b, llptr, llzeroval, size, align, false);
13121304
}
13131305

1306+
pub fn call_memset<'bcx, 'tcx>(b: &Builder<'bcx, 'tcx>,
1307+
ptr: ValueRef,
1308+
fill_byte: ValueRef,
1309+
size: ValueRef,
1310+
align: ValueRef,
1311+
volatile: bool) {
1312+
let ccx = b.ccx;
1313+
let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
1314+
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
1315+
let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
1316+
let volatile = C_bool(ccx, volatile);
1317+
b.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None, None);
1318+
}
1319+
1320+
13141321
/// In general, when we create an scratch value in an alloca, the
13151322
/// creator may not know if the block (that initializes the scratch
13161323
/// with the desired value) actually dominates the cleanup associated

src/librustc_trans/trans/builder.rs

+6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
104104
}
105105
}
106106

107+
pub fn position_at_start(&self, llbb: BasicBlockRef) {
108+
unsafe {
109+
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
110+
}
111+
}
112+
107113
pub fn ret_void(&self) {
108114
self.count_insn("retvoid");
109115
unsafe {

src/librustc_trans/trans/common.rs

+9
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,15 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
735735
BlockAndBuilder::new(bcx, owned_builder)
736736
}
737737

738+
pub fn at_start<F, R>(&self, f: F) -> R
739+
where F: FnOnce(&BlockAndBuilder<'blk, 'tcx>) -> R
740+
{
741+
self.position_at_start(self.bcx.llbb);
742+
let r = f(self);
743+
self.position_at_end(self.bcx.llbb);
744+
r
745+
}
746+
738747
// Methods delegated to bcx
739748

740749
pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {

0 commit comments

Comments
 (0)