diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index bf8693f3547..98f7da8361c 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -90,10 +90,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap< let def_id = tcx.hir().local_def_id(hir_id); let generics = tcx.generics_of(def_id); if !generics.requires_monomorphization(tcx) - && (!Instance::mono(tcx, def_id.to_def_id()) - .def - .generates_cgu_internal_copy(tcx) - || tcx.inline_exportable(def_id.to_def_id())) + // 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 { diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs index d8dcf0dea8a..886690da212 100644 --- a/src/librustc_middle/mir/mono.rs +++ b/src/librustc_middle/mir/mono.rs @@ -92,10 +92,10 @@ impl<'tcx> MonoItem<'tcx> { 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. + // linkage or an extern indicator, then we'll be creating a + // globally shared version. if self.explicit_linkage(tcx).is_some() || !instance.def.generates_cgu_internal_copy(tcx) - || tcx.inline_exportable(instance.def_id()) || Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id) { return InstantiationMode::GloballyShared { may_conflict: false }; @@ -103,8 +103,12 @@ 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 - if generate_cgu_internal_copies { + // be creating a local copy per CGU. We need to watch out here + // for an extern indicator as we don't want to optimise away + // inlined functions that should be exported. + if generate_cgu_internal_copies + && !tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator() + { return InstantiationMode::LocalCopy; } diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 20487fdb669..be15e6c576f 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -697,10 +697,6 @@ rustc_queries! { storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { true } } - - query inline_exportable(def_id: DefId) -> bool { - desc { |tcx| "computing whether `{}` should be explicitly exported", tcx.def_path_str(def_id) } - } } Other { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 08a6330e718..1d59d749634 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -40,7 +40,6 @@ use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; -use rustc_session::config::CrateType; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -80,7 +79,6 @@ pub fn provide(providers: &mut Providers<'_>) { static_mutability, generator_kind, codegen_fn_attrs, - inline_exportable, collect_mod_item_types, ..*providers }; @@ -2601,16 +2599,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs } -fn inline_exportable(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - // Functions marked with #[inline] are only ever codegened - // with "internal" linkage and are never exported unless we're - // building a `staticlib` or `cdylib` and they are marked - // `#[no_mangle]`. - tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_MANGLE) - && (tcx.sess.crate_types().contains(&CrateType::Cdylib) - || tcx.sess.crate_types().contains(&CrateType::Staticlib)) -} - /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller /// applied to the method prototype. fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { diff --git a/src/test/codegen/cdylib-external-inline-fns.rs b/src/test/codegen/cdylib-external-inline-fns.rs new file mode 100644 index 00000000000..58f806b5a1f --- /dev/null +++ b/src/test/codegen/cdylib-external-inline-fns.rs @@ -0,0 +1,23 @@ +// 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() {} diff --git a/src/test/codegen/cdylib-external-no-mangle-fns.rs b/src/test/codegen/cdylib-external-no-mangle-fns.rs deleted file mode 100644 index 827de7e5c11..00000000000 --- a/src/test/codegen/cdylib-external-no-mangle-fns.rs +++ /dev/null @@ -1,13 +0,0 @@ -// compile-flags: -C no-prepopulate-passes - -#![crate_type = "cdylib"] - -// CHECK: define void @a() -#[no_mangle] -#[inline] -pub extern "C" fn a() { - // side effect to keep `a` around - unsafe { - core::ptr::read_volatile(&42); - } -} diff --git a/src/test/codegen/export-no-mangle.rs b/src/test/codegen/export-no-mangle.rs index 78d41e4be0a..793636bb1b0 100644 --- a/src/test/codegen/export-no-mangle.rs +++ b/src/test/codegen/export-no-mangle.rs @@ -18,4 +18,9 @@ mod private { // CHECK: void @bar() #[export_name = "bar"] extern fn bar() {} + + // CHECK: void @baz() + #[export_name = "baz"] + #[inline] + extern fn baz() {} } diff --git a/src/test/codegen/external-no-mangle-fns.rs b/src/test/codegen/external-no-mangle-fns.rs index 90288214499..aefa9ce21c3 100644 --- a/src/test/codegen/external-no-mangle-fns.rs +++ b/src/test/codegen/external-no-mangle-fns.rs @@ -53,3 +53,13 @@ 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() {} diff --git a/src/test/codegen/staticlib-external-inline-fns.rs b/src/test/codegen/staticlib-external-inline-fns.rs new file mode 100644 index 00000000000..8f55a530331 --- /dev/null +++ b/src/test/codegen/staticlib-external-inline-fns.rs @@ -0,0 +1,23 @@ +// 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() {} diff --git a/src/test/codegen/staticlib-external-no-mangle-fns.rs b/src/test/codegen/staticlib-external-no-mangle-fns.rs deleted file mode 100644 index 0b4a37febb2..00000000000 --- a/src/test/codegen/staticlib-external-no-mangle-fns.rs +++ /dev/null @@ -1,13 +0,0 @@ -// compile-flags: -C no-prepopulate-passes - -#![crate_type = "staticlib"] - -// CHECK: define void @a() -#[no_mangle] -#[inline] -pub extern "C" fn a() { - // side effect to keep `a` around - unsafe { - core::ptr::read_volatile(&42); - } -}