mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Defer creating drop trees in MIR lowering until leaving that scope
This commit is contained in:
parent
0d37dca25a
commit
fa3e2fcbe4
@ -111,13 +111,24 @@ where
|
|||||||
write!(w, r#"<table border="0" cellborder="1" cellspacing="0">"#)?;
|
write!(w, r#"<table border="0" cellborder="1" cellspacing="0">"#)?;
|
||||||
|
|
||||||
// Basic block number at the top.
|
// Basic block number at the top.
|
||||||
|
let (blk, bgcolor) = if data.is_cleanup {
|
||||||
|
(format!("{} (cleanup)", block.index()), "lightblue")
|
||||||
|
} else {
|
||||||
|
let color = if dark_mode {
|
||||||
|
"dimgray"
|
||||||
|
} else {
|
||||||
|
"gray"
|
||||||
|
};
|
||||||
|
(format!("{}", block.index()), "gray")
|
||||||
|
};
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
r#"<tr><td bgcolor="{bgcolor}" {attrs} colspan="{colspan}">{blk}</td></tr>"#,
|
r#"<tr><td bgcolor="{bgcolor}" {attrs} colspan="{colspan}">{blk}</td></tr>"#,
|
||||||
bgcolor = if dark_mode { "dimgray" } else { "gray" },
|
bgcolor = if dark_mode { "dimgray" } else { "gray" },
|
||||||
attrs = r#"align="center""#,
|
attrs = r#"align="center""#,
|
||||||
colspan = num_cols,
|
colspan = num_cols,
|
||||||
blk = block.index()
|
blk = blk,
|
||||||
|
color = color
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
init(w)?;
|
init(w)?;
|
||||||
|
@ -28,14 +28,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
|
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
|
||||||
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
|
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
|
||||||
if targeted_by_break {
|
if targeted_by_break {
|
||||||
// This is a `break`-able block
|
this.in_breakable_scope(None, destination, span, |this| {
|
||||||
let exit_block = this.cfg.start_new_block();
|
Some(this.ast_block_stmts(
|
||||||
let block_exit =
|
destination,
|
||||||
this.in_breakable_scope(None, exit_block, destination, |this| {
|
block,
|
||||||
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
|
span,
|
||||||
});
|
stmts,
|
||||||
this.cfg.goto(unpack!(block_exit), source_info, exit_block);
|
expr,
|
||||||
exit_block.unit()
|
safety_mode,
|
||||||
|
))
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
|
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
|
||||||
}
|
}
|
||||||
|
@ -140,23 +140,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// body, even when the exact code in the body cannot unwind
|
// body, even when the exact code in the body cannot unwind
|
||||||
|
|
||||||
let loop_block = this.cfg.start_new_block();
|
let loop_block = this.cfg.start_new_block();
|
||||||
let exit_block = this.cfg.start_new_block();
|
|
||||||
|
|
||||||
// Start the loop.
|
// Start the loop.
|
||||||
this.cfg.goto(block, source_info, loop_block);
|
this.cfg.goto(block, source_info, loop_block);
|
||||||
|
|
||||||
this.in_breakable_scope(Some(loop_block), exit_block, destination, move |this| {
|
this.in_breakable_scope(Some(loop_block), destination, expr_span, move |this| {
|
||||||
// conduct the test, if necessary
|
// conduct the test, if necessary
|
||||||
let body_block = this.cfg.start_new_block();
|
let body_block = this.cfg.start_new_block();
|
||||||
let diverge_cleanup = this.diverge_cleanup();
|
|
||||||
this.cfg.terminate(
|
this.cfg.terminate(
|
||||||
loop_block,
|
loop_block,
|
||||||
source_info,
|
source_info,
|
||||||
TerminatorKind::FalseUnwind {
|
TerminatorKind::FalseUnwind { real_target: body_block, unwind: None },
|
||||||
real_target: body_block,
|
|
||||||
unwind: Some(diverge_cleanup),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
this.diverge_from(loop_block);
|
||||||
|
|
||||||
// The “return” value of the loop body must always be an unit. We therefore
|
// The “return” value of the loop body must always be an unit. We therefore
|
||||||
// introduce a unit temporary as the destination for the loop body.
|
// introduce a unit temporary as the destination for the loop body.
|
||||||
@ -164,8 +160,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// Execute the body, branching back to the test.
|
// Execute the body, branching back to the test.
|
||||||
let body_block_end = unpack!(this.into(tmp, body_block, body));
|
let body_block_end = unpack!(this.into(tmp, body_block, body));
|
||||||
this.cfg.goto(body_block_end, source_info, loop_block);
|
this.cfg.goto(body_block_end, source_info, loop_block);
|
||||||
});
|
|
||||||
exit_block.unit()
|
// Loops are only exited by `break` expressions.
|
||||||
|
None
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => {
|
ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => {
|
||||||
let intrinsic = match *ty.kind() {
|
let intrinsic = match *ty.kind() {
|
||||||
@ -206,7 +204,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let success = this.cfg.start_new_block();
|
let success = this.cfg.start_new_block();
|
||||||
let cleanup = this.diverge_cleanup();
|
|
||||||
|
|
||||||
this.record_operands_moved(&args);
|
this.record_operands_moved(&args);
|
||||||
|
|
||||||
@ -218,7 +215,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
TerminatorKind::Call {
|
TerminatorKind::Call {
|
||||||
func: fun,
|
func: fun,
|
||||||
args,
|
args,
|
||||||
cleanup: Some(cleanup),
|
cleanup: None,
|
||||||
// FIXME(varkor): replace this with an uninhabitedness-based check.
|
// FIXME(varkor): replace this with an uninhabitedness-based check.
|
||||||
// This requires getting access to the current module to call
|
// This requires getting access to the current module to call
|
||||||
// `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
|
// `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
|
||||||
@ -231,6 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
fn_span,
|
fn_span,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
this.diverge_from(block);
|
||||||
success.unit()
|
success.unit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,12 +435,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let scope = this.local_scope();
|
let scope = this.local_scope();
|
||||||
let value = unpack!(block = this.as_operand(block, scope, value));
|
let value = unpack!(block = this.as_operand(block, scope, value));
|
||||||
let resume = this.cfg.start_new_block();
|
let resume = this.cfg.start_new_block();
|
||||||
let cleanup = this.generator_drop_cleanup();
|
|
||||||
this.cfg.terminate(
|
this.cfg.terminate(
|
||||||
block,
|
block,
|
||||||
source_info,
|
source_info,
|
||||||
TerminatorKind::Yield { value, resume, resume_arg: destination, drop: cleanup },
|
TerminatorKind::Yield { value, resume, resume_arg: destination, drop: None },
|
||||||
);
|
);
|
||||||
|
this.generator_drop_cleanup(block);
|
||||||
resume.unit()
|
resume.unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +228,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
outer_source_info: SourceInfo,
|
outer_source_info: SourceInfo,
|
||||||
fake_borrow_temps: Vec<(Place<'tcx>, Local)>,
|
fake_borrow_temps: Vec<(Place<'tcx>, Local)>,
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
let match_scope = self.scopes.topmost();
|
|
||||||
|
|
||||||
let arm_end_blocks: Vec<_> = arm_candidates
|
let arm_end_blocks: Vec<_> = arm_candidates
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(arm, candidate)| {
|
.map(|(arm, candidate)| {
|
||||||
@ -250,7 +248,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let arm_block = this.bind_pattern(
|
let arm_block = this.bind_pattern(
|
||||||
outer_source_info,
|
outer_source_info,
|
||||||
candidate,
|
candidate,
|
||||||
arm.guard.as_ref().map(|g| (g, match_scope)),
|
arm.guard.as_ref(),
|
||||||
&fake_borrow_temps,
|
&fake_borrow_temps,
|
||||||
scrutinee_span,
|
scrutinee_span,
|
||||||
Some(arm.scope),
|
Some(arm.scope),
|
||||||
@ -287,7 +285,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
outer_source_info: SourceInfo,
|
outer_source_info: SourceInfo,
|
||||||
candidate: Candidate<'_, 'tcx>,
|
candidate: Candidate<'_, 'tcx>,
|
||||||
guard: Option<(&Guard<'tcx>, region::Scope)>,
|
guard: Option<&Guard<'tcx>>,
|
||||||
fake_borrow_temps: &Vec<(Place<'tcx>, Local)>,
|
fake_borrow_temps: &Vec<(Place<'tcx>, Local)>,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
arm_scope: Option<region::Scope>,
|
arm_scope: Option<region::Scope>,
|
||||||
@ -1592,7 +1590,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
candidate: Candidate<'pat, 'tcx>,
|
candidate: Candidate<'pat, 'tcx>,
|
||||||
parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
|
parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
|
||||||
guard: Option<(&Guard<'tcx>, region::Scope)>,
|
guard: Option<&Guard<'tcx>>,
|
||||||
fake_borrows: &Vec<(Place<'tcx>, Local)>,
|
fake_borrows: &Vec<(Place<'tcx>, Local)>,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
schedule_drops: bool,
|
schedule_drops: bool,
|
||||||
@ -1704,7 +1702,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// the reference that we create for the arm.
|
// the reference that we create for the arm.
|
||||||
// * So we eagerly create the reference for the arm and then take a
|
// * So we eagerly create the reference for the arm and then take a
|
||||||
// reference to that.
|
// reference to that.
|
||||||
if let Some((guard, region_scope)) = guard {
|
if let Some(guard) = guard {
|
||||||
let tcx = self.hir.tcx();
|
let tcx = self.hir.tcx();
|
||||||
let bindings = parent_bindings
|
let bindings = parent_bindings
|
||||||
.iter()
|
.iter()
|
||||||
@ -1748,12 +1746,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
unreachable
|
unreachable
|
||||||
});
|
});
|
||||||
let outside_scope = self.cfg.start_new_block();
|
let outside_scope = self.cfg.start_new_block();
|
||||||
self.exit_scope(
|
self.exit_top_scope(otherwise_post_guard_block, outside_scope, source_info);
|
||||||
source_info.span,
|
|
||||||
region_scope,
|
|
||||||
otherwise_post_guard_block,
|
|
||||||
outside_scope,
|
|
||||||
);
|
|
||||||
self.false_edges(
|
self.false_edges(
|
||||||
outside_scope,
|
outside_scope,
|
||||||
otherwise_block,
|
otherwise_block,
|
||||||
|
@ -418,7 +418,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let bool_ty = self.hir.bool_ty();
|
let bool_ty = self.hir.bool_ty();
|
||||||
let eq_result = self.temp(bool_ty, source_info.span);
|
let eq_result = self.temp(bool_ty, source_info.span);
|
||||||
let eq_block = self.cfg.start_new_block();
|
let eq_block = self.cfg.start_new_block();
|
||||||
let cleanup = self.diverge_cleanup();
|
|
||||||
self.cfg.terminate(
|
self.cfg.terminate(
|
||||||
block,
|
block,
|
||||||
source_info,
|
source_info,
|
||||||
@ -435,12 +434,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
literal: method,
|
literal: method,
|
||||||
}),
|
}),
|
||||||
args: vec![val, expect],
|
args: vec![val, expect],
|
||||||
destination: Some((eq_result, eq_block)),
|
destination: Some((eq_result.clone(), eq_block)),
|
||||||
cleanup: Some(cleanup),
|
cleanup: None,
|
||||||
from_hir_call: false,
|
from_hir_call: false,
|
||||||
fn_span: source_info.span,
|
fn_span: source_info.span,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
self.diverge_from(block);
|
||||||
|
|
||||||
if let [success_block, fail_block] = *make_target_blocks(self) {
|
if let [success_block, fail_block] = *make_target_blocks(self) {
|
||||||
// check the result
|
// check the result
|
||||||
|
@ -345,11 +345,6 @@ struct Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
var_debug_info: Vec<VarDebugInfo<'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 block with the `UNREACHABLE` terminator.
|
||||||
cached_unreachable_block: Option<BasicBlock>,
|
cached_unreachable_block: Option<BasicBlock>,
|
||||||
}
|
}
|
||||||
@ -609,50 +604,34 @@ where
|
|||||||
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
|
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
|
||||||
let arg_scope =
|
let arg_scope =
|
||||||
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments };
|
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 source_info = builder.source_info(span);
|
||||||
let call_site_s = (call_site_scope, source_info);
|
let call_site_s = (call_site_scope, source_info);
|
||||||
unpack!(
|
unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
|
||||||
block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
|
let arg_scope_s = (arg_scope, source_info);
|
||||||
if should_abort_on_panic(tcx, fn_def_id, abi) {
|
// Attribute epilogue to function's closing brace
|
||||||
builder.schedule_abort();
|
let fn_end = span_with_body.shrink_to_hi();
|
||||||
}
|
let return_block =
|
||||||
|
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
|
||||||
let arg_scope_s = (arg_scope, source_info);
|
Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
|
||||||
// `return_block` is called when we evaluate a `return` expression, so
|
builder.args_and_body(
|
||||||
// we just use `START_BLOCK` here.
|
START_BLOCK,
|
||||||
unpack!(
|
fn_def_id.to_def_id(),
|
||||||
block = builder.in_breakable_scope(
|
&arguments,
|
||||||
None,
|
arg_scope,
|
||||||
START_BLOCK,
|
&body.value,
|
||||||
Place::return_place(),
|
)
|
||||||
|builder| {
|
}))
|
||||||
builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
|
}));
|
||||||
builder.args_and_body(
|
let source_info = builder.source_info(fn_end);
|
||||||
block,
|
builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
|
||||||
fn_def_id.to_def_id(),
|
let should_abort = should_abort_on_panic(tcx, fn_def_id, abi);
|
||||||
&arguments,
|
builder.build_drop_trees(should_abort);
|
||||||
arg_scope,
|
// Attribute any unreachable codepaths to the function's closing brace
|
||||||
&body.value,
|
if let Some(unreachable_block) = builder.cached_unreachable_block {
|
||||||
)
|
builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable);
|
||||||
})
|
}
|
||||||
},
|
return_block.unit()
|
||||||
)
|
}));
|
||||||
);
|
|
||||||
// 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());
|
|
||||||
|
|
||||||
let spread_arg = if abi == Abi::RustCall {
|
let spread_arg = if abi == Abi::RustCall {
|
||||||
// RustCall pseudo-ABI untuples the last argument.
|
// RustCall pseudo-ABI untuples the last argument.
|
||||||
@ -686,8 +665,7 @@ fn construct_const<'a, 'tcx>(
|
|||||||
let source_info = builder.source_info(span);
|
let source_info = builder.source_info(span);
|
||||||
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
||||||
|
|
||||||
// Constants can't `return` so a return block should not be created.
|
builder.build_drop_trees(false);
|
||||||
assert_eq!(builder.cached_return_block, None);
|
|
||||||
|
|
||||||
// Constants may be match expressions in which case an unreachable block may
|
// Constants may be match expressions in which case an unreachable block may
|
||||||
// be created, so terminate it properly.
|
// be created, so terminate it properly.
|
||||||
@ -754,7 +732,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
fn_span: span,
|
fn_span: span,
|
||||||
arg_count,
|
arg_count,
|
||||||
generator_kind,
|
generator_kind,
|
||||||
scopes: Default::default(),
|
scopes: scope::Scopes::new(),
|
||||||
block_context: BlockContext::new(),
|
block_context: BlockContext::new(),
|
||||||
source_scopes: IndexVec::new(),
|
source_scopes: IndexVec::new(),
|
||||||
source_scope: OUTERMOST_SOURCE_SCOPE,
|
source_scope: OUTERMOST_SOURCE_SCOPE,
|
||||||
@ -767,8 +745,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
var_indices: Default::default(),
|
var_indices: Default::default(),
|
||||||
unit_temp: None,
|
unit_temp: None,
|
||||||
var_debug_info: vec![],
|
var_debug_info: vec![],
|
||||||
cached_resume_block: None,
|
|
||||||
cached_return_block: None,
|
|
||||||
cached_unreachable_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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -23,13 +23,13 @@ pub fn droppy() {
|
|||||||
// FIXME(eddyb) the `void @` forces a match on the instruction, instead of the
|
// FIXME(eddyb) the `void @` forces a match on the instruction, instead of the
|
||||||
// comment, that's `; call core::intrinsics::drop_in_place::<drop::SomeUniqueName>`
|
// comment, that's `; call core::intrinsics::drop_in_place::<drop::SomeUniqueName>`
|
||||||
// for the `v0` mangling, should switch to matching on that once `legacy` is gone.
|
// for the `v0` mangling, should switch to matching on that once `legacy` is gone.
|
||||||
|
// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
|
// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
|
// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
// CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
// CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
|
||||||
// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
|
||||||
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
|
||||||
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
// CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName
|
// CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName
|
||||||
// The next line checks for the } that ends the function definition
|
// The next line checks for the } that ends the function definition
|
||||||
|
Loading…
Reference in New Issue
Block a user