1
Fork 0

Defer creating drop trees in MIR lowering until leaving that scope

This commit is contained in:
Matthew Jasper 2019-11-16 13:23:31 +00:00 committed by Aaron Hill
parent 0d37dca25a
commit fa3e2fcbe4
No known key found for this signature in database
GPG key ID: B4087E510E98B164
8 changed files with 766 additions and 728 deletions

View file

@ -345,11 +345,6 @@ struct Builder<'a, 'tcx> {
var_debug_info: Vec<VarDebugInfo<'tcx>>,
/// Cached block with the `RESUME` terminator; this is created
/// when first set of cleanups are built.
cached_resume_block: Option<BasicBlock>,
/// Cached block with the `RETURN` terminator.
cached_return_block: Option<BasicBlock>,
/// Cached block with the `UNREACHABLE` terminator.
cached_unreachable_block: Option<BasicBlock>,
}
@ -609,50 +604,34 @@ where
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
let arg_scope =
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments };
let mut block = START_BLOCK;
let source_info = builder.source_info(span);
let call_site_s = (call_site_scope, source_info);
unpack!(
block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
if should_abort_on_panic(tcx, fn_def_id, abi) {
builder.schedule_abort();
}
let arg_scope_s = (arg_scope, source_info);
// `return_block` is called when we evaluate a `return` expression, so
// we just use `START_BLOCK` here.
unpack!(
block = builder.in_breakable_scope(
None,
START_BLOCK,
Place::return_place(),
|builder| {
builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
builder.args_and_body(
block,
fn_def_id.to_def_id(),
&arguments,
arg_scope,
&body.value,
)
})
},
)
);
// Attribute epilogue to function's closing brace
let fn_end = span_with_body.shrink_to_hi();
let source_info = builder.source_info(fn_end);
let return_block = builder.return_block();
builder.cfg.goto(block, source_info, return_block);
builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
// Attribute any unreachable codepaths to the function's closing brace
if let Some(unreachable_block) = builder.cached_unreachable_block {
builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
}
return_block.unit()
})
);
assert_eq!(block, builder.return_block());
unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
let arg_scope_s = (arg_scope, source_info);
// Attribute epilogue to function's closing brace
let fn_end = span_with_body.shrink_to_hi();
let return_block =
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
builder.args_and_body(
START_BLOCK,
fn_def_id.to_def_id(),
&arguments,
arg_scope,
&body.value,
)
}))
}));
let source_info = builder.source_info(fn_end);
builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
let should_abort = should_abort_on_panic(tcx, fn_def_id, abi);
builder.build_drop_trees(should_abort);
// Attribute any unreachable codepaths to the function's closing brace
if let Some(unreachable_block) = builder.cached_unreachable_block {
builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
}
return_block.unit()
}));
let spread_arg = if abi == Abi::RustCall {
// RustCall pseudo-ABI untuples the last argument.
@ -686,8 +665,7 @@ fn construct_const<'a, 'tcx>(
let source_info = builder.source_info(span);
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
// Constants can't `return` so a return block should not be created.
assert_eq!(builder.cached_return_block, None);
builder.build_drop_trees(false);
// Constants may be match expressions in which case an unreachable block may
// be created, so terminate it properly.
@ -754,7 +732,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn_span: span,
arg_count,
generator_kind,
scopes: Default::default(),
scopes: scope::Scopes::new(),
block_context: BlockContext::new(),
source_scopes: IndexVec::new(),
source_scope: OUTERMOST_SOURCE_SCOPE,
@ -767,8 +745,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
var_indices: Default::default(),
unit_temp: None,
var_debug_info: vec![],
cached_resume_block: None,
cached_return_block: None,
cached_unreachable_block: None,
};
@ -1003,17 +979,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
}
fn return_block(&mut self) -> BasicBlock {
match self.cached_return_block {
Some(rb) => rb,
None => {
let rb = self.cfg.start_new_block();
self.cached_return_block = Some(rb);
rb
}
}
}
}
///////////////////////////////////////////////////////////////////////////