about summary refs log tree commit diff
path: root/compiler/rustc_metadata
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-06-06 03:59:17 +0000
committerbors <bors@rust-lang.org>2021-06-06 03:59:17 +0000
commit9a576175cc9a0aecb85d0764a4f66ee29e26e155 (patch)
treea154cec601fdf15e22d503c1b62f8111782d1677 /compiler/rustc_metadata
parentf434217aab9abf583ebc928b97ab4116921137aa (diff)
parent6aa45b71b11823a3140736536a93c5eac11ceecb (diff)
downloadrust-9a576175cc9a0aecb85d0764a4f66ee29e26e155.tar.gz
rust-9a576175cc9a0aecb85d0764a4f66ee29e26e155.zip
Auto merge of #84171 - ricobbe:raw-dylib-via-llvm, r=petrochenkov
Partial support for raw-dylib linkage

First cut of functionality for issue #58713: add support for `#[link(kind = "raw-dylib")]` on `extern` blocks in lib crates compiled to .rlib files.  Does not yet support `#[link_name]` attributes on functions, or the `#[link_ordinal]` attribute, or `#[link(kind = "raw-dylib")]` on `extern` blocks in bin crates; I intend to publish subsequent PRs to fill those gaps.  It's also not yet clear whether this works for functions in `extern "stdcall"` blocks; I also intend to investigate that shortly and make any necessary changes as a follow-on PR.

This implementation calls out to an LLVM function to construct the actual `.idata` sections as temporary `.lib` files on disk and then links those into the generated .rlib.
Diffstat (limited to 'compiler/rustc_metadata')
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs72
1 files changed, 61 insertions, 11 deletions
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index bc342119efb..cd4c394ae14 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_middle::middle::cstore::NativeLib;
+use rustc_middle::middle::cstore::{DllImport, NativeLib};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_session::utils::NativeLibKind;
@@ -33,8 +33,8 @@ struct Collector<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let abi = match it.kind {
-            hir::ItemKind::ForeignMod { abi, .. } => abi,
+        let (abi, foreign_mod_items) = match it.kind {
+            hir::ItemKind::ForeignMod { abi, items } => (abi, items),
             _ => return,
         };
 
@@ -57,6 +57,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
                 foreign_module: Some(it.def_id.to_def_id()),
                 wasm_import_module: None,
                 verbatim: None,
+                dll_imports: Vec::new(),
             };
             let mut kind_specified = false;
 
@@ -196,6 +197,27 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
                 .span_label(m.span, "missing `name` argument")
                 .emit();
             }
+
+            if lib.kind == NativeLibKind::RawDylib {
+                match abi {
+                    Abi::C { .. } => (),
+                    Abi::Cdecl => (),
+                    _ => {
+                        if sess.target.arch == "x86" {
+                            sess.span_fatal(
+                                it.span,
+                                r#"`#[link(kind = "raw-dylib")]` only supports C and Cdecl ABIs"#,
+                            );
+                        }
+                    }
+                };
+                lib.dll_imports.extend(
+                    foreign_mod_items
+                        .iter()
+                        .map(|child_item| DllImport { name: child_item.ident.name, ordinal: None }),
+                );
+            }
+
             self.register_native_lib(Some(m.span), lib);
         }
     }
@@ -253,15 +275,42 @@ impl Collector<'tcx> {
             )
             .emit();
         }
-        if lib.kind == NativeLibKind::RawDylib && !self.tcx.features().raw_dylib {
-            feature_err(
-                &self.tcx.sess.parse_sess,
-                sym::raw_dylib,
-                span.unwrap_or(rustc_span::DUMMY_SP),
-                "kind=\"raw-dylib\" is unstable",
-            )
-            .emit();
+        // this just unwraps lib.name; we already established that it isn't empty above.
+        if let (NativeLibKind::RawDylib, Some(lib_name)) = (lib.kind, lib.name) {
+            let span = match span {
+                Some(s) => s,
+                None => {
+                    bug!("raw-dylib libraries are not supported on the command line");
+                }
+            };
+
+            if !self.tcx.sess.target.options.is_like_windows {
+                self.tcx.sess.span_fatal(
+                    span,
+                    "`#[link(...)]` with `kind = \"raw-dylib\"` only supported on Windows",
+                );
+            } else if !self.tcx.sess.target.options.is_like_msvc {
+                self.tcx.sess.span_warn(
+                    span,
+                    "`#[link(...)]` with `kind = \"raw-dylib\"` not supported on windows-gnu",
+                );
+            }
+
+            if lib_name.as_str().contains('\0') {
+                self.tcx.sess.span_err(span, "library name may not contain NUL characters");
+            }
+
+            if !self.tcx.features().raw_dylib {
+                feature_err(
+                    &self.tcx.sess.parse_sess,
+                    sym::raw_dylib,
+                    span,
+                    "kind=\"raw-dylib\" is unstable",
+                )
+                .emit();
+            }
         }
+
         self.libs.push(lib);
     }
 
@@ -337,6 +386,7 @@ impl Collector<'tcx> {
                     foreign_module: None,
                     wasm_import_module: None,
                     verbatim: passed_lib.verbatim,
+                    dll_imports: Vec::new(),
                 };
                 self.register_native_lib(None, lib);
             } else {