Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export #[inline] fns with extern indicators #73034

Merged
merged 7 commits into from
Jun 19, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/librustc_codegen_ssa/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_middle/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
doctorn marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
43 changes: 43 additions & 0 deletions src/test/codegen/cdylib-external-inline-fns.rs
Original file line number Diff line number Diff line change
@@ -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() {}
20 changes: 15 additions & 5 deletions src/test/codegen/export-no-mangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
}
20 changes: 20 additions & 0 deletions src/test/codegen/external-no-mangle-fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
3 changes: 1 addition & 2 deletions src/test/codegen/sanitizer-no-sanitize-inlining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#![feature(no_sanitize)]

// ASAN-LABEL: define void @test
// ASAN: tail call fastcc void @random_inline
// ASAN: tail call fastcc
doctorn marked this conversation as resolved.
Show resolved Hide resolved
// ASAN: }
//
// LSAN-LABEL: define void @test
Expand All @@ -26,7 +26,6 @@ pub fn test(n: &mut u32) {

#[no_sanitize(address)]
#[inline]
#[no_mangle]
pub fn random_inline(n: &mut u32) {
*n = 42;
}
43 changes: 43 additions & 0 deletions src/test/codegen/staticlib-external-inline-fns.rs
Original file line number Diff line number Diff line change
@@ -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() {}