From ae33a9714e73dda15030894821b6819f781ed7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 7 Jul 2021 00:00:00 +0000 Subject: [PATCH 1/2] Set personality with LLVMSetPersonalityFn --- compiler/rustc_codegen_llvm/src/builder.rs | 6 +++++- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 582c9354041..981ea95f2e0 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -937,8 +937,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { 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, pers_fn, num_clauses as c_uint, UNNAMED) + llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED) } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 91923251018..b513e83bd19 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1165,7 +1165,7 @@ extern "C" { pub fn LLVMBuildLandingPad( B: &Builder<'a>, Ty: &'a Type, - PersFn: &'a Value, + PersFn: Option<&'a Value>, NumClauses: c_uint, Name: *const c_char, ) -> &'a Value; From f612ba1f846c0e9ee16b0f19dd7a3719d1dddd4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 7 Jul 2021 00:00:00 +0000 Subject: [PATCH 2/2] Use existing declaration of rust_eh_personality If crate declares `rust_eh_personality`, re-use existing declaration as otherwise attempts to set function attributes that follow the declaration will fail (unless it happens to have exactly the same type signature as the one predefined in the compiler). --- compiler/rustc_codegen_llvm/src/context.rs | 11 ++++++--- .../ui/panic-runtime/incompatible-type.rs | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/panic-runtime/incompatible-type.rs diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index d1aecd32e2f..cccf2f8498c 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -385,11 +385,16 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } else { "rust_eh_personality" }; - let fty = self.type_variadic_func(&[], self.type_i32()); - self.declare_cfn(name, llvm::UnnamedAddr::Global, fty) + if let Some(llfn) = self.get_declared_value(name) { + llfn + } else { + let fty = self.type_variadic_func(&[], self.type_i32()); + let llfn = self.declare_cfn(name, llvm::UnnamedAddr::Global, fty); + attributes::apply_target_cpu_attr(self, llfn); + llfn + } } }; - attributes::apply_target_cpu_attr(self, llfn); self.eh_personality.set(Some(llfn)); llfn } diff --git a/src/test/ui/panic-runtime/incompatible-type.rs b/src/test/ui/panic-runtime/incompatible-type.rs new file mode 100644 index 00000000000..026364a2058 --- /dev/null +++ b/src/test/ui/panic-runtime/incompatible-type.rs @@ -0,0 +1,24 @@ +// Check that rust_eh_personality can have a different type signature than the +// one hardcoded in the compiler. Regression test for #70117. Used to fail with: +// +// Assertion `isa(Val) && "cast() argument of incompatible type!"' failed. +// +// build-pass +// compile-flags: --crate-type=lib -Ccodegen-units=1 +#![no_std] +#![panic_runtime] +#![feature(panic_runtime)] +#![feature(rustc_attrs)] + +pub struct DropMe; + +impl Drop for DropMe { + fn drop(&mut self) {} +} + +pub fn test(_: DropMe) { + unreachable!(); +} + +#[rustc_std_internal_symbol] +pub unsafe extern "C" fn rust_eh_personality() {}