Defer creating drop trees in MIR lowering until leaving that scope
This commit is contained in:
parent
0d37dca25a
commit
fa3e2fcbe4
8 changed files with 766 additions and 728 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue