diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:13:23 +0000 |
commit | 20431706a863f92cb37dc512fef6e48d192aaf2c (patch) | |
tree | 2867f13f5fd5437ba628c67d7f87309ccadcd286 /compiler/rustc_codegen_ssa/src/mir/block.rs | |
parent | Releasing progress-linux version 1.65.0+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.tar.xz rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.zip |
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir/block.rs')
-rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a6b226ef7..29b7c9b0a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -63,7 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } } - fn lltarget<Bx: BuilderMethods<'a, 'tcx>>( + /// Get a basic block (creating it if necessary), possibly with a landing + /// pad next to it. + fn llbb_with_landing_pad<Bx: BuilderMethods<'a, 'tcx>>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, @@ -73,32 +75,36 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { let target_funclet = fx.cleanup_kinds[target].funclet_bb(target); match (self.funclet_bb, target_funclet) { (None, None) => (lltarget, false), - (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => { - (lltarget, false) - } // jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC (None, Some(_)) => (fx.landing_pad_for(target), false), (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator), - (Some(_), Some(_)) => (fx.landing_pad_for(target), true), + (Some(f), Some(t_f)) => { + if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) { + (lltarget, false) + } else { + (fx.landing_pad_for(target), true) + } + } } } - /// Create a basic block. - fn llblock<Bx: BuilderMethods<'a, 'tcx>>( + /// Get a basic block (creating it if necessary), possibly with cleanup + /// stuff in it or next to it. + fn llbb_with_cleanup<Bx: BuilderMethods<'a, 'tcx>>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, ) -> Bx::BasicBlock { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); + let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target); if is_cleanupret { // MSVC cross-funclet jump - need a trampoline - - debug!("llblock: creating cleanup trampoline for {:?}", target); + debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess)); + debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target); let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target); - let trampoline = Bx::append_block(fx.cx, fx.llfn, name); - let mut trampoline_bx = Bx::build(fx.cx, trampoline); + let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name); + let mut trampoline_bx = Bx::build(fx.cx, trampoline_llbb); trampoline_bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); - trampoline + trampoline_llbb } else { lltarget } @@ -110,10 +116,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { bx: &mut Bx, target: mir::BasicBlock, ) { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); + let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target); if is_cleanupret { - // micro-optimization: generate a `ret` rather than a jump + // MSVC micro-optimization: generate a `ret` rather than a jump // to a trampoline. + debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess)); bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); } else { bx.br(lltarget); @@ -138,7 +145,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { let fn_ty = bx.fn_decl_backend_type(&fn_abi); let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) { - Some(self.llblock(fx, cleanup)) + Some(self.llbb_with_cleanup(fx, cleanup)) } else if fx.mir[self.bb].is_cleanup && fn_abi.can_unwind && !base::wants_msvc_seh(fx.cx.tcx().sess) @@ -162,9 +169,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } else { fx.unreachable_block() }; - let invokeret = - bx.invoke(fn_ty, fn_ptr, &llargs, ret_llbb, unwind_block, self.funclet(fx)); - bx.apply_attrs_callsite(&fn_abi, invokeret); + let invokeret = bx.invoke( + fn_ty, + Some(&fn_abi), + fn_ptr, + &llargs, + ret_llbb, + unwind_block, + self.funclet(fx), + ); if fx.mir[self.bb].is_cleanup { bx.do_not_inline(invokeret); } @@ -178,8 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret); } } else { - let llret = bx.call(fn_ty, fn_ptr, &llargs, self.funclet(fx)); - bx.apply_attrs_callsite(&fn_abi, llret); + let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx)); if fx.mir[self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested @@ -226,7 +238,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { options, line_spans, instance, - Some((ret_llbb, self.llblock(fx, cleanup), self.funclet(fx))), + Some((ret_llbb, self.llbb_with_cleanup(fx, cleanup), self.funclet(fx))), ); } else { bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None); @@ -276,8 +288,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if target_iter.len() == 1 { // If there are two targets (one conditional, one fallback), emit br instead of switch let (test_value, target) = target_iter.next().unwrap(); - let lltrue = helper.llblock(self, target); - let llfalse = helper.llblock(self, targets.otherwise()); + let lltrue = helper.llbb_with_cleanup(self, target); + let llfalse = helper.llbb_with_cleanup(self, targets.otherwise()); if switch_ty == bx.tcx().types.bool { // Don't generate trivial icmps when switching on bool match test_value { @@ -294,8 +306,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { bx.switch( discr.immediate(), - helper.llblock(self, targets.otherwise()), - target_iter.map(|(value, target)| (value, helper.llblock(self, target))), + helper.llbb_with_cleanup(self, targets.otherwise()), + target_iter.map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))), ); } } @@ -525,7 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cond = bx.expect(cond, expected); // Create the failure block and the conditional branch to it. - let lltarget = helper.llblock(self, target); + let lltarget = helper.llbb_with_cleanup(self, target); let panic_block = bx.append_sibling_block("panic"); if expected { bx.cond_br(cond, lltarget, panic_block); @@ -1454,20 +1466,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // bar(); // } Some(&mir::TerminatorKind::Abort) => { - let cs_bb = + let cs_llbb = Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb)); - let cp_bb = + let cp_llbb = Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb)); - ret_llbb = cs_bb; + ret_llbb = cs_llbb; - let mut cs_bx = Bx::build(self.cx, cs_bb); - let cs = cs_bx.catch_switch(None, None, &[cp_bb]); + let mut cs_bx = Bx::build(self.cx, cs_llbb); + let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); // The "null" here is actually a RTTI type descriptor for the // C++ personality function, but `catch (...)` has no type so // it's null. The 64 here is actually a bitfield which // represents that this is a catch-all block. - let mut cp_bx = Bx::build(self.cx, cp_bb); + let mut cp_bx = Bx::build(self.cx, cp_llbb); let null = cp_bx.const_null( cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space), ); @@ -1476,10 +1488,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cp_bx.br(llbb); } _ => { - let cleanup_bb = + let cleanup_llbb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb)); - ret_llbb = cleanup_bb; - let mut cleanup_bx = Bx::build(self.cx, cleanup_bb); + ret_llbb = cleanup_llbb; + let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb); funclet = cleanup_bx.cleanup_pad(None, &[]); cleanup_bx.br(llbb); } @@ -1487,19 +1499,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.funclets[bb] = Some(funclet); ret_llbb } else { - let bb = Bx::append_block(self.cx, self.llfn, "cleanup"); - let mut bx = Bx::build(self.cx, bb); + let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup"); + let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb); let llpersonality = self.cx.eh_personality(); let llretty = self.landing_pad_type(); - let lp = bx.cleanup_landing_pad(llretty, llpersonality); + let lp = cleanup_bx.cleanup_landing_pad(llretty, llpersonality); - let slot = self.get_personality_slot(&mut bx); - slot.storage_live(&mut bx); - Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot); + let slot = self.get_personality_slot(&mut cleanup_bx); + slot.storage_live(&mut cleanup_bx); + Pair(cleanup_bx.extract_value(lp, 0), cleanup_bx.extract_value(lp, 1)) + .store(&mut cleanup_bx, slot); - bx.br(llbb); - bx.llbb() + cleanup_bx.br(llbb); + cleanup_llbb } } @@ -1533,8 +1546,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind); let fn_ty = bx.fn_decl_backend_type(&fn_abi); - let llret = bx.call(fn_ty, fn_ptr, &[], None); - bx.apply_attrs_callsite(&fn_abi, llret); + let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None); bx.do_not_inline(llret); bx.unreachable(); |