Skip to content

Commit 0e332e9

Browse files
authored
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)
2 parents bf59152 + e8e0a0e commit 0e332e9

7 files changed

+132
-14
lines changed

src/librustc_codegen_ssa/back/symbol_export.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
8989
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
9090
let def_id = tcx.hir().local_def_id(hir_id);
9191
let generics = tcx.generics_of(def_id);
92-
if !generics.requires_monomorphization(tcx) &&
93-
// Functions marked with #[inline] are only ever codegened
94-
// with "internal" linkage and are never exported.
95-
!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
92+
if !generics.requires_monomorphization(tcx)
93+
// Functions marked with #[inline] are codegened with "internal"
94+
// linkage and are not exported unless marked with an extern
95+
// inidicator
96+
&& (!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
97+
|| tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator())
9698
{
9799
Some(def_id)
98100
} else {

src/librustc_middle/mir/mono.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ impl<'tcx> MonoItem<'tcx> {
9191
match *self {
9292
MonoItem::Fn(ref instance) => {
9393
let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
94-
// If this function isn't inlined or otherwise has explicit
95-
// linkage, then we'll be creating a globally shared version.
96-
if self.explicit_linkage(tcx).is_some()
94+
// If this function isn't inlined or otherwise has an extern
95+
// indicator, then we'll be creating a globally shared version.
96+
if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
9797
|| !instance.def.generates_cgu_internal_copy(tcx)
9898
|| Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id)
9999
{
@@ -102,7 +102,7 @@ impl<'tcx> MonoItem<'tcx> {
102102

103103
// At this point we don't have explicit linkage and we're an
104104
// inlined function. If we're inlining into all CGUs then we'll
105-
// be creating a local copy per CGU
105+
// be creating a local copy per CGU.
106106
if generate_cgu_internal_copies {
107107
return InstantiationMode::LocalCopy;
108108
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// compile-flags: -C no-prepopulate-passes
2+
3+
#![crate_type = "cdylib"]
4+
5+
// CHECK: define void @a()
6+
#[no_mangle]
7+
#[inline]
8+
pub extern "C" fn a() {}
9+
10+
// CHECK: define void @b()
11+
#[export_name = "b"]
12+
#[inline]
13+
pub extern "C" fn b() {}
14+
15+
// CHECK: define void @c()
16+
#[no_mangle]
17+
#[inline]
18+
extern "C" fn c() {}
19+
20+
// CHECK: define void @d()
21+
#[export_name = "d"]
22+
#[inline]
23+
extern "C" fn d() {}
24+
25+
// CHECK: define void @e()
26+
#[no_mangle]
27+
#[inline(always)]
28+
pub extern "C" fn e() {}
29+
30+
// CHECK: define void @f()
31+
#[export_name = "f"]
32+
#[inline(always)]
33+
pub extern "C" fn f() {}
34+
35+
// CHECK: define void @g()
36+
#[no_mangle]
37+
#[inline(always)]
38+
extern "C" fn g() {}
39+
40+
// CHECK: define void @h()
41+
#[export_name = "h"]
42+
#[inline(always)]
43+
extern "C" fn h() {}

src/test/codegen/export-no-mangle.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,21 @@ mod private {
1111
#[export_name = "BAR"]
1212
static BAR: u32 = 3;
1313

14-
// CHECK: void @foo()
14+
// CHECK: void @a()
1515
#[no_mangle]
16-
pub extern fn foo() {}
16+
pub extern fn a() {}
1717

18-
// CHECK: void @bar()
19-
#[export_name = "bar"]
20-
extern fn bar() {}
18+
// CHECK: void @b()
19+
#[export_name = "b"]
20+
extern fn b() {}
21+
22+
// CHECK: void @c()
23+
#[export_name = "c"]
24+
#[inline]
25+
extern fn c() {}
26+
27+
// CHECK: void @d()
28+
#[export_name = "d"]
29+
#[inline(always)]
30+
extern fn d() {}
2131
}

src/test/codegen/external-no-mangle-fns.rs

+20
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,23 @@ fn x() {
5353
core::ptr::read_volatile(&42);
5454
}
5555
}
56+
57+
// CHECK: define void @i()
58+
#[no_mangle]
59+
#[inline]
60+
fn i() {}
61+
62+
// CHECK: define void @j()
63+
#[no_mangle]
64+
#[inline]
65+
pub fn j() {}
66+
67+
// CHECK: define void @k()
68+
#[no_mangle]
69+
#[inline(always)]
70+
fn k() {}
71+
72+
// CHECK: define void @l()
73+
#[no_mangle]
74+
#[inline(always)]
75+
pub fn l() {}

src/test/codegen/sanitizer-no-sanitize-inlining.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#![feature(no_sanitize)]
1414

1515
// ASAN-LABEL: define void @test
16-
// ASAN: tail call fastcc void @random_inline
16+
// ASAN: call {{.*}} @random_inline
1717
// ASAN: }
1818
//
1919
// LSAN-LABEL: define void @test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// compile-flags: -C no-prepopulate-passes
2+
3+
#![crate_type = "staticlib"]
4+
5+
// CHECK: define void @a()
6+
#[no_mangle]
7+
#[inline]
8+
pub extern "C" fn a() {}
9+
10+
// CHECK: define void @b()
11+
#[export_name = "b"]
12+
#[inline]
13+
pub extern "C" fn b() {}
14+
15+
// CHECK: define void @c()
16+
#[no_mangle]
17+
#[inline]
18+
extern "C" fn c() {}
19+
20+
// CHECK: define void @d()
21+
#[export_name = "d"]
22+
#[inline]
23+
extern "C" fn d() {}
24+
25+
// CHECK: define void @e()
26+
#[no_mangle]
27+
#[inline(always)]
28+
pub extern "C" fn e() {}
29+
30+
// CHECK: define void @f()
31+
#[export_name = "f"]
32+
#[inline(always)]
33+
pub extern "C" fn f() {}
34+
35+
// CHECK: define void @g()
36+
#[no_mangle]
37+
#[inline(always)]
38+
extern "C" fn g() {}
39+
40+
// CHECK: define void @h()
41+
#[export_name = "h"]
42+
#[inline(always)]
43+
extern "C" fn h() {}

0 commit comments

Comments
 (0)