about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorChris Denton <chris@chrisdenton.dev>2024-08-16 19:32:22 +0000
committerChris Denton <chris@chrisdenton.dev>2024-08-17 19:10:46 +0000
commit0156eb57a152003c0c82552229747b3d04e1fddc (patch)
tree249846c9486615f1e2434cfbf0ac0995260389f5 /compiler/rustc_codegen_ssa/src
parent27b93da8de2477b3a41811b0ee486cffa99fa00e (diff)
downloadrust-0156eb57a152003c0c82552229747b3d04e1fddc.tar.gz
rust-0156eb57a152003c0c82552229747b3d04e1fddc.zip
Always use ar_archive_writer for import libs
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs86
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs7
2 files changed, 90 insertions, 3 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 8eb44d12016..38a440a707a 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -5,7 +5,9 @@ use std::fs::{self, File};
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 
-use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember};
+use ar_archive_writer::{
+    write_archive_to_stream, ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember,
+};
 pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER};
 use object::read::archive::ArchiveFile;
 use object::read::macho::FatArch;
@@ -14,11 +16,15 @@ use rustc_data_structures::memmap::Mmap;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use tempfile::Builder as TempFileBuilder;
+use tracing::trace;
 
 use super::metadata::search_for_section;
+use crate::common;
 // Re-exporting for rustc_codegen_llvm::back::archive
 pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
-use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
+use crate::errors::{
+    DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
+};
 
 pub trait ArchiveBuilderBuilder {
     fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
@@ -34,7 +40,81 @@ pub trait ArchiveBuilderBuilder {
         lib_name: &str,
         import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
         output_path: &Path,
-    );
+    ) {
+        if common::is_mingw_gnu_toolchain(&sess.target) {
+            // The binutils linker used on -windows-gnu targets cannot read the import
+            // libraries generated by LLVM: in our attempts, the linker produced an .EXE
+            // that loaded but crashed with an AV upon calling one of the imported
+            // functions. Therefore, use binutils to create the import library instead,
+            // by writing a .DEF file to the temp dir and calling binutils's dlltool.
+            create_mingw_dll_import_lib(
+                sess,
+                lib_name,
+                import_name_and_ordinal_vector,
+                output_path,
+            );
+        } else {
+            trace!("creating import library");
+            trace!("  dll_name {:#?}", lib_name);
+            trace!("  output_path {}", output_path.display());
+            trace!(
+                "  import names: {}",
+                import_name_and_ordinal_vector
+                    .iter()
+                    .map(|(name, _ordinal)| name.clone())
+                    .collect::<Vec<_>>()
+                    .join(", "),
+            );
+
+            // All import names are Rust identifiers and therefore cannot contain \0 characters.
+            // FIXME: when support for #[link_name] is implemented, ensure that the import names
+            // still don't contain any \0 characters. Also need to check that the names don't
+            // contain substrings like " @" or "NONAME" that are keywords or otherwise reserved
+            // in definition files.
+
+            let mut file = match fs::File::create_new(&output_path) {
+                Ok(file) => file,
+                Err(error) => sess
+                    .dcx()
+                    .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
+            };
+
+            let exports = import_name_and_ordinal_vector
+                .iter()
+                .map(|(name, ordinal)| COFFShortExport {
+                    name: name.to_string(),
+                    ext_name: None,
+                    symbol_name: None,
+                    alias_target: None,
+                    ordinal: ordinal.unwrap_or(0),
+                    noname: ordinal.is_some(),
+                    data: false,
+                    private: false,
+                    constant: false,
+                })
+                .collect::<Vec<_>>();
+            let machine = match &*sess.target.arch {
+                "x86_64" => MachineTypes::AMD64,
+                "x86" => MachineTypes::I386,
+                "aarch64" => MachineTypes::ARM64,
+                "arm64ec" => MachineTypes::ARM64EC,
+                "arm" => MachineTypes::ARMNT,
+                cpu => panic!("unsupported cpu type {cpu}"),
+            };
+
+            if let Err(error) = ar_archive_writer::write_import_library(
+                &mut file,
+                lib_name,
+                &exports,
+                machine,
+                !sess.target.is_like_msvc,
+                /*comdat=*/ false,
+            ) {
+                sess.dcx()
+                    .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() });
+            }
+        }
+    }
 
     fn extract_bundled_libs<'a>(
         &'a self,
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 94bf0ab34e2..573a8cf7cbe 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1060,3 +1060,10 @@ pub struct CompilerBuiltinsCannotCall {
     pub caller: String,
     pub callee: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_error_creating_import_library)]
+pub(crate) struct ErrorCreatingImportLibrary<'a> {
+    pub lib_name: &'a str,
+    pub error: String,
+}