From 19dd2ecc2d49e2adfeb1211c038b0d35be42ec33 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 24 Jan 2022 13:45:34 +0100 Subject: [PATCH 1/4] Reorder unwinding related builder methods to differentiate between dwarf and msvc instructions --- compiler/rustc_codegen_gcc/src/builder.rs | 8 ++++---- compiler/rustc_codegen_llvm/src/builder.rs | 12 ++++++------ compiler/rustc_codegen_ssa/src/traits/builder.rs | 6 +++++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 379c88bbd40..1b9e13873b0 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1256,6 +1256,10 @@ fn insert_value(&mut self, aggregate_value: RValue<'gcc>, value: RValue<'gcc>, i aggregate_value } + fn set_personality_fn(&mut self, _personality: RValue<'gcc>) { + // TODO(antoyo) + } + fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: usize) -> RValue<'gcc> { let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1"); let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1"); @@ -1295,10 +1299,6 @@ fn add_handler(&mut self, _catch_switch: RValue<'gcc>, _handler: Block<'gcc>) { unimplemented!(); } - fn set_personality_fn(&mut self, _personality: RValue<'gcc>) { - // TODO(antoyo) - } - // Atomic Operations fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> { let expected = self.current_func().new_local(None, cmp.get_type(), "expected"); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 8a9450c20dd..efae50b37a8 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -956,6 +956,12 @@ fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value, idx: u64) -> &' unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, UNNAMED) } } + fn set_personality_fn(&mut self, personality: &'ll Value) { + unsafe { + llvm::LLVMSetPersonalityFn(self.llfn(), personality); + } + } + fn landing_pad( &mut self, ty: &'ll Type, @@ -1044,12 +1050,6 @@ fn add_handler(&mut self, catch_switch: &'ll Value, handler: &'ll BasicBlock) { } } - fn set_personality_fn(&mut self, personality: &'ll Value) { - unsafe { - llvm::LLVMSetPersonalityFn(self.llfn(), personality); - } - } - // Atomic Operations fn atomic_cmpxchg( &mut self, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 5a06fb46105..98c67154f9b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -421,6 +421,9 @@ fn select( fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value; fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value; + fn set_personality_fn(&mut self, personality: Self::Value); + + // These are used by everyone except msvc fn landing_pad( &mut self, ty: Self::Type, @@ -429,6 +432,8 @@ fn landing_pad( ) -> Self::Value; fn set_cleanup(&mut self, landing_pad: Self::Value); fn resume(&mut self, exn: Self::Value) -> Self::Value; + + // These are used only by msvc fn cleanup_pad(&mut self, parent: Option, args: &[Self::Value]) -> Self::Funclet; fn cleanup_ret( &mut self, @@ -443,7 +448,6 @@ fn catch_switch( num_handlers: usize, ) -> Self::Value; fn add_handler(&mut self, catch_switch: Self::Value, handler: Self::BasicBlock); - fn set_personality_fn(&mut self, personality: Self::Value); fn atomic_cmpxchg( &mut self, From e9646fa76b4876cbfe50fd89d3f179c27685f874 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 24 Jan 2022 13:48:09 +0100 Subject: [PATCH 2/4] Remove unused return values from resume and cleanup_ret Given that these instructions are diverging, not every codegen backend may be able to produce a return value for them. --- compiler/rustc_codegen_gcc/src/builder.rs | 4 ++-- compiler/rustc_codegen_llvm/src/builder.rs | 19 +++++++++---------- .../rustc_codegen_ssa/src/traits/builder.rs | 8 ++------ 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 1b9e13873b0..d3fdfccd8a5 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1275,7 +1275,7 @@ fn set_cleanup(&mut self, _landing_pad: RValue<'gcc>) { // TODO(antoyo) } - fn resume(&mut self, _exn: RValue<'gcc>) -> RValue<'gcc> { + fn resume(&mut self, _exn: RValue<'gcc>) { unimplemented!(); } @@ -1283,7 +1283,7 @@ fn cleanup_pad(&mut self, _parent: Option>, _args: &[RValue<'gcc>]) unimplemented!(); } - fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option>) -> RValue<'gcc> { + fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option>) { unimplemented!(); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index efae50b37a8..7d62e5e8d41 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -983,8 +983,10 @@ fn set_cleanup(&mut self, landing_pad: &'ll Value) { } } - fn resume(&mut self, exn: &'ll Value) -> &'ll Value { - unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) } + fn resume(&mut self, exn: &'ll Value) { + unsafe { + llvm::LLVMBuildResume(self.llbuilder, exn); + } } fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { @@ -1001,14 +1003,11 @@ fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Fu Funclet::new(ret.expect("LLVM does not have support for cleanuppad")) } - fn cleanup_ret( - &mut self, - funclet: &Funclet<'ll>, - unwind: Option<&'ll BasicBlock>, - ) -> &'ll Value { - let ret = - unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) }; - ret.expect("LLVM does not have support for cleanupret") + fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>) { + unsafe { + llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) + .expect("LLVM does not have support for cleanupret"); + } } fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 98c67154f9b..f10d7c01df0 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -431,15 +431,11 @@ fn landing_pad( num_clauses: usize, ) -> Self::Value; fn set_cleanup(&mut self, landing_pad: Self::Value); - fn resume(&mut self, exn: Self::Value) -> Self::Value; + fn resume(&mut self, exn: Self::Value); // These are used only by msvc fn cleanup_pad(&mut self, parent: Option, args: &[Self::Value]) -> Self::Funclet; - fn cleanup_ret( - &mut self, - funclet: &Self::Funclet, - unwind: Option, - ) -> Self::Value; + fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option); fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet; fn catch_switch( &mut self, From 7a164509d3ed0b7dfc5f79b2e0053a4abef5fb1b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 24 Jan 2022 13:50:12 +0100 Subject: [PATCH 3/4] Merge add_handler into catch_switch Some codegen backends may require all handlers to be immediately known --- compiler/rustc_codegen_gcc/src/builder.rs | 11 ++++++----- compiler/rustc_codegen_llvm/src/builder.rs | 16 ++++++++-------- compiler/rustc_codegen_llvm/src/intrinsic.rs | 5 ++--- compiler/rustc_codegen_ssa/src/mir/block.rs | 3 +-- compiler/rustc_codegen_ssa/src/traits/builder.rs | 3 +-- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index d3fdfccd8a5..185aa3a5b40 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1291,11 +1291,12 @@ fn catch_pad(&mut self, _parent: RValue<'gcc>, _args: &[RValue<'gcc>]) -> Funcle unimplemented!(); } - fn catch_switch(&mut self, _parent: Option>, _unwind: Option>, _num_handlers: usize) -> RValue<'gcc> { - unimplemented!(); - } - - fn add_handler(&mut self, _catch_switch: RValue<'gcc>, _handler: Block<'gcc>) { + fn catch_switch( + &mut self, + _parent: Option>, + _unwind: Option>, + _handlers: &[Block<'gcc>], + ) -> RValue<'gcc> { unimplemented!(); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 7d62e5e8d41..02b9f23c4d6 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1028,7 +1028,7 @@ fn catch_switch( &mut self, parent: Option<&'ll Value>, unwind: Option<&'ll BasicBlock>, - num_handlers: usize, + handlers: &[&'ll BasicBlock], ) -> &'ll Value { let name = cstr!("catchswitch"); let ret = unsafe { @@ -1036,17 +1036,17 @@ fn catch_switch( self.llbuilder, parent, unwind, - num_handlers as c_uint, + handlers.len() as c_uint, name.as_ptr(), ) }; - ret.expect("LLVM does not have support for catchswitch") - } - - fn add_handler(&mut self, catch_switch: &'ll Value, handler: &'ll BasicBlock) { - unsafe { - llvm::LLVMRustAddHandler(catch_switch, handler); + let ret = ret.expect("LLVM does not have support for catchswitch"); + for handler in handlers { + unsafe { + llvm::LLVMRustAddHandler(ret, handler); + } } + ret } // Atomic Operations diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 5adfa18035a..f51d014bfb3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -525,9 +525,8 @@ fn codegen_msvc_try<'ll>( normal.ret(bx.const_i32(0)); - let cs = catchswitch.catch_switch(None, None, 2); - catchswitch.add_handler(cs, catchpad_rust.llbb()); - catchswitch.add_handler(cs, catchpad_foreign.llbb()); + let cs = + catchswitch.catch_switch(None, None, &[catchpad_rust.llbb(), catchpad_foreign.llbb()]); // We can't use the TypeDescriptor defined in libpanic_unwind because it // might be in another DLL and the SEH encoding only supports specifying diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index b1a76b80002..ee7ca7f6e46 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1346,8 +1346,7 @@ fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { let mut cp_bx = self.new_block(&format!("cp_funclet{:?}", bb)); ret_llbb = cs_bx.llbb(); - let cs = cs_bx.catch_switch(None, None, 1); - cs_bx.add_handler(cs, cp_bx.llbb()); + let cs = cs_bx.catch_switch(None, None, &[cp_bx.llbb()]); // The "null" here is actually a RTTI type descriptor for the // C++ personality function, but `catch (...)` has no type so diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index f10d7c01df0..6c88241350f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -441,9 +441,8 @@ fn catch_switch( &mut self, parent: Option, unwind: Option, - num_handlers: usize, + handlers: &[Self::BasicBlock], ) -> Self::Value; - fn add_handler(&mut self, catch_switch: Self::Value, handler: Self::BasicBlock); fn atomic_cmpxchg( &mut self, From f6ce7711726c24025083aec429d6e30274d63476 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 24 Jan 2022 13:57:32 +0100 Subject: [PATCH 4/4] Merge landing_pad and set_cleanup into cleanup_landing_pad --- compiler/rustc_codegen_gcc/src/builder.rs | 6 +--- compiler/rustc_codegen_llvm/src/builder.rs | 34 ++++++++++--------- compiler/rustc_codegen_ssa/src/mir/block.rs | 3 +- .../rustc_codegen_ssa/src/traits/builder.rs | 8 +---- 4 files changed, 21 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 185aa3a5b40..ffb77e16a14 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1260,7 +1260,7 @@ fn set_personality_fn(&mut self, _personality: RValue<'gcc>) { // TODO(antoyo) } - fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: usize) -> RValue<'gcc> { + fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> { let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1"); let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1"); let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]); @@ -1271,10 +1271,6 @@ fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: // rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort. } - fn set_cleanup(&mut self, _landing_pad: RValue<'gcc>) { - // TODO(antoyo) - } - fn resume(&mut self, _exn: RValue<'gcc>) { unimplemented!(); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 02b9f23c4d6..c9a04e6280f 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -962,25 +962,12 @@ fn set_personality_fn(&mut self, personality: &'ll Value) { } } - fn landing_pad( - &mut self, - ty: &'ll Type, - pers_fn: &'ll Value, - num_clauses: usize, - ) -> &'ll Value { - // Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while, - // LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The - // personality lives on the parent function anyway. - self.set_personality_fn(pers_fn); - unsafe { - llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED) - } - } - - fn set_cleanup(&mut self, landing_pad: &'ll Value) { + fn cleanup_landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value) -> &'ll Value { + let landing_pad = self.landing_pad(ty, pers_fn, 1 /* FIXME should this be 0? */); unsafe { llvm::LLVMSetCleanup(landing_pad, llvm::True); } + landing_pad } fn resume(&mut self, exn: &'ll Value) { @@ -1477,4 +1464,19 @@ fn fptoint_sat( None } } + + pub(crate) fn landing_pad( + &mut self, + ty: &'ll Type, + pers_fn: &'ll Value, + num_clauses: usize, + ) -> &'ll Value { + // Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while, + // LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The + // personality lives on the parent function anyway. + self.set_personality_fn(pers_fn); + unsafe { + llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED) + } + } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index ee7ca7f6e46..4c7a09ca1e9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1373,8 +1373,7 @@ fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { let llpersonality = self.cx.eh_personality(); let llretty = self.landing_pad_type(); - let lp = bx.landing_pad(llretty, llpersonality, 1); - bx.set_cleanup(lp); + let lp = bx.cleanup_landing_pad(llretty, llpersonality); let slot = self.get_personality_slot(&mut bx); slot.storage_live(&mut bx); diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 6c88241350f..53fb21b269a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -424,13 +424,7 @@ fn select( fn set_personality_fn(&mut self, personality: Self::Value); // These are used by everyone except msvc - fn landing_pad( - &mut self, - ty: Self::Type, - pers_fn: Self::Value, - num_clauses: usize, - ) -> Self::Value; - fn set_cleanup(&mut self, landing_pad: Self::Value); + fn cleanup_landing_pad(&mut self, ty: Self::Type, pers_fn: Self::Value) -> Self::Value; fn resume(&mut self, exn: Self::Value); // These are used only by msvc