Rollup merge of #73034 - doctorn:nomangle-inline-linkage, r=matthewjasper
Export `#[inline]` fns with extern indicators In ancient history (#36280) we stopped `#[inline]` fns being codegened if they weren't used. However, - #72944 - #72463 observe that when writing something like ```rust #![crate_type = "cdylib"] #[no_mangle] #[inline] pub extern "C" fn foo() { // ... } ``` we really _do_ want `foo` to be codegened. This change makes this the case. Resolves #72944, resolves #72463 (and maybe some more)
This commit is contained in:
commit
0e332e9e3c
@ -89,10 +89,12 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
|
||||
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
|
||||
let def_id = tcx.hir().local_def_id(hir_id);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
if !generics.requires_monomorphization(tcx) &&
|
||||
// Functions marked with #[inline] are only ever codegened
|
||||
// with "internal" linkage and are never exported.
|
||||
!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
|
||||
if !generics.requires_monomorphization(tcx)
|
||||
// Functions marked with #[inline] are codegened with "internal"
|
||||
// linkage and are not exported unless marked with an extern
|
||||
// inidicator
|
||||
&& (!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator())
|
||||
{
|
||||
Some(def_id)
|
||||
} else {
|
||||
|
@ -91,9 +91,9 @@ impl<'tcx> MonoItem<'tcx> {
|
||||
match *self {
|
||||
MonoItem::Fn(ref instance) => {
|
||||
let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
|
||||
// If this function isn't inlined or otherwise has explicit
|
||||
// linkage, then we'll be creating a globally shared version.
|
||||
if self.explicit_linkage(tcx).is_some()
|
||||
// If this function isn't inlined or otherwise has an extern
|
||||
// indicator, then we'll be creating a globally shared version.
|
||||
if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
|
||||
|| !instance.def.generates_cgu_internal_copy(tcx)
|
||||
|| Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id)
|
||||
{
|
||||
@ -102,7 +102,7 @@ impl<'tcx> MonoItem<'tcx> {
|
||||
|
||||
// At this point we don't have explicit linkage and we're an
|
||||
// inlined function. If we're inlining into all CGUs then we'll
|
||||
// be creating a local copy per CGU
|
||||
// be creating a local copy per CGU.
|
||||
if generate_cgu_internal_copies {
|
||||
return InstantiationMode::LocalCopy;
|
||||
}
|
||||
|
43
src/test/codegen/cdylib-external-inline-fns.rs
Normal file
43
src/test/codegen/cdylib-external-inline-fns.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type = "cdylib"]
|
||||
|
||||
// CHECK: define void @a()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
pub extern "C" fn a() {}
|
||||
|
||||
// CHECK: define void @b()
|
||||
#[export_name = "b"]
|
||||
#[inline]
|
||||
pub extern "C" fn b() {}
|
||||
|
||||
// CHECK: define void @c()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
extern "C" fn c() {}
|
||||
|
||||
// CHECK: define void @d()
|
||||
#[export_name = "d"]
|
||||
#[inline]
|
||||
extern "C" fn d() {}
|
||||
|
||||
// CHECK: define void @e()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn e() {}
|
||||
|
||||
// CHECK: define void @f()
|
||||
#[export_name = "f"]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn f() {}
|
||||
|
||||
// CHECK: define void @g()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
extern "C" fn g() {}
|
||||
|
||||
// CHECK: define void @h()
|
||||
#[export_name = "h"]
|
||||
#[inline(always)]
|
||||
extern "C" fn h() {}
|
@ -11,11 +11,21 @@ mod private {
|
||||
#[export_name = "BAR"]
|
||||
static BAR: u32 = 3;
|
||||
|
||||
// CHECK: void @foo()
|
||||
// CHECK: void @a()
|
||||
#[no_mangle]
|
||||
pub extern fn foo() {}
|
||||
pub extern fn a() {}
|
||||
|
||||
// CHECK: void @bar()
|
||||
#[export_name = "bar"]
|
||||
extern fn bar() {}
|
||||
// CHECK: void @b()
|
||||
#[export_name = "b"]
|
||||
extern fn b() {}
|
||||
|
||||
// CHECK: void @c()
|
||||
#[export_name = "c"]
|
||||
#[inline]
|
||||
extern fn c() {}
|
||||
|
||||
// CHECK: void @d()
|
||||
#[export_name = "d"]
|
||||
#[inline(always)]
|
||||
extern fn d() {}
|
||||
}
|
||||
|
@ -53,3 +53,23 @@ fn x() {
|
||||
core::ptr::read_volatile(&42);
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: define void @i()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
fn i() {}
|
||||
|
||||
// CHECK: define void @j()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
pub fn j() {}
|
||||
|
||||
// CHECK: define void @k()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
fn k() {}
|
||||
|
||||
// CHECK: define void @l()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
pub fn l() {}
|
||||
|
@ -13,7 +13,7 @@
|
||||
#![feature(no_sanitize)]
|
||||
|
||||
// ASAN-LABEL: define void @test
|
||||
// ASAN: tail call fastcc void @random_inline
|
||||
// ASAN: call {{.*}} @random_inline
|
||||
// ASAN: }
|
||||
//
|
||||
// LSAN-LABEL: define void @test
|
||||
|
43
src/test/codegen/staticlib-external-inline-fns.rs
Normal file
43
src/test/codegen/staticlib-external-inline-fns.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type = "staticlib"]
|
||||
|
||||
// CHECK: define void @a()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
pub extern "C" fn a() {}
|
||||
|
||||
// CHECK: define void @b()
|
||||
#[export_name = "b"]
|
||||
#[inline]
|
||||
pub extern "C" fn b() {}
|
||||
|
||||
// CHECK: define void @c()
|
||||
#[no_mangle]
|
||||
#[inline]
|
||||
extern "C" fn c() {}
|
||||
|
||||
// CHECK: define void @d()
|
||||
#[export_name = "d"]
|
||||
#[inline]
|
||||
extern "C" fn d() {}
|
||||
|
||||
// CHECK: define void @e()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn e() {}
|
||||
|
||||
// CHECK: define void @f()
|
||||
#[export_name = "f"]
|
||||
#[inline(always)]
|
||||
pub extern "C" fn f() {}
|
||||
|
||||
// CHECK: define void @g()
|
||||
#[no_mangle]
|
||||
#[inline(always)]
|
||||
extern "C" fn g() {}
|
||||
|
||||
// CHECK: define void @h()
|
||||
#[export_name = "h"]
|
||||
#[inline(always)]
|
||||
extern "C" fn h() {}
|
Loading…
Reference in New Issue
Block a user