about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNathan Corbyn <me@nathancorbyn.com>2020-06-05 16:47:37 +0100
committerNathan Corbyn <me@nathancorbyn.com>2020-06-15 09:40:56 +0100
commitf62903b74a8630fa62e721f69e6621d1d441e7f1 (patch)
treea054cf5352766f8084835cc3f9326a316f83cd96 /src
parentce6d3a73b514e9649e57cee812ad129bb2112016 (diff)
downloadrust-f62903b74a8630fa62e721f69e6621d1d441e7f1.tar.gz
rust-f62903b74a8630fa62e721f69e6621d1d441e7f1.zip
Export `#[inline] #[no_mangle]` fns in cdylibs and staticlibs
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs9
-rw-r--r--src/librustc_middle/mir/mono.rs1
-rw-r--r--src/librustc_middle/query/mod.rs4
-rw-r--r--src/librustc_typeck/collect.rs12
-rw-r--r--src/test/codegen/cdylib-external-no-mangle-fns.rs13
-rw-r--r--src/test/codegen/staticlib-external-no-mangle-fns.rs13
6 files changed, 48 insertions, 4 deletions
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 970d13b30c0..bf8693f3547 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -89,10 +89,11 @@ 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)
+                        && (!Instance::mono(tcx, def_id.to_def_id())
+                            .def
+                            .generates_cgu_internal_copy(tcx)
+                            || tcx.inline_exportable(def_id.to_def_id()))
                     {
                         Some(def_id)
                     } else {
diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs
index c889dbc0a44..d8dcf0dea8a 100644
--- a/src/librustc_middle/mir/mono.rs
+++ b/src/librustc_middle/mir/mono.rs
@@ -95,6 +95,7 @@ impl<'tcx> MonoItem<'tcx> {
                 // linkage, 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 };
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index be15e6c576f..20487fdb669 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -697,6 +697,10 @@ 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 1d59d749634..08a6330e718 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -40,6 +40,7 @@ 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};
@@ -79,6 +80,7 @@ pub fn provide(providers: &mut Providers<'_>) {
         static_mutability,
         generator_kind,
         codegen_fn_attrs,
+        inline_exportable,
         collect_mod_item_types,
         ..*providers
     };
@@ -2599,6 +2601,16 @@ 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-no-mangle-fns.rs b/src/test/codegen/cdylib-external-no-mangle-fns.rs
new file mode 100644
index 00000000000..827de7e5c11
--- /dev/null
+++ b/src/test/codegen/cdylib-external-no-mangle-fns.rs
@@ -0,0 +1,13 @@
+// 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/staticlib-external-no-mangle-fns.rs b/src/test/codegen/staticlib-external-no-mangle-fns.rs
new file mode 100644
index 00000000000..0b4a37febb2
--- /dev/null
+++ b/src/test/codegen/staticlib-external-no-mangle-fns.rs
@@ -0,0 +1,13 @@
+// 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);
+    }
+}