about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/back/archive.rs
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2024-04-16 18:31:43 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2024-07-07 16:56:35 +0000
commit58e551433d692579faf4ad59fb7f192aa9001677 (patch)
tree042cc5e2dc2c322c8bbee86518858d7979279acf /compiler/rustc_codegen_llvm/src/back/archive.rs
parent959a2eb275c732ccc9153f0503dd64896533e997 (diff)
downloadrust-58e551433d692579faf4ad59fb7f192aa9001677.tar.gz
rust-58e551433d692579faf4ad59fb7f192aa9001677.zip
Sync ar_archive_writer to LLVM 18.1.3
From LLVM 15.0.0-rc3. This adds support for COFF archives containing
Arm64EC object files and has various fixes for AIX big archive files.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/back/archive.rs')
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs109
1 files changed, 67 insertions, 42 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index a354f3d3536..f46c6b1c498 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -15,8 +15,8 @@ use crate::errors::{
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{
-    get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
-    ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
+    try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
+    ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
 };
 use tracing::trace;
 
@@ -115,7 +115,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
         if true {
             Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
         } else {
-            Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols))
+            Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
         }
     }
 
@@ -291,59 +291,84 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
 
 // The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files.
 // As such we need to use LLVM for them.
+
+static LLVM_OBJECT_READER: ObjectReader = ObjectReader {
+    get_symbols: get_llvm_object_symbols,
+    is_64_bit_object_file: llvm_is_64_bit_object_file,
+    is_ec_object_file: llvm_is_ec_object_file,
+    get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment,
+};
+
+fn should_use_llvm_reader(buf: &[u8]) -> bool {
+    let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) };
+
+    // COFF bigobj file, msvc LTO file or import library. See
+    // https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51
+    let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF");
+
+    is_bitcode || is_unsupported_windows_obj_file
+}
+
 #[deny(unsafe_op_in_unsafe_fn)]
 fn get_llvm_object_symbols(
     buf: &[u8],
     f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
 ) -> io::Result<bool> {
-    let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) };
+    if !should_use_llvm_reader(buf) {
+        return (DEFAULT_OBJECT_READER.get_symbols)(buf, f);
+    }
 
-    // COFF bigobj file, msvc LTO file or import library. See
-    // https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51
-    let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF");
+    let mut state = Box::new(f);
 
-    if is_bitcode || is_unsupported_windows_obj_file {
-        let mut state = Box::new(f);
-
-        let err = unsafe {
-            llvm::LLVMRustGetSymbols(
-                buf.as_ptr(),
-                buf.len(),
-                std::ptr::addr_of_mut!(*state) as *mut c_void,
-                callback,
-                error_callback,
-            )
-        };
+    let err = unsafe {
+        llvm::LLVMRustGetSymbols(
+            buf.as_ptr(),
+            buf.len(),
+            std::ptr::addr_of_mut!(*state) as *mut c_void,
+            callback,
+            error_callback,
+        )
+    };
 
-        if err.is_null() {
-            return Ok(true);
-        } else {
-            return Err(unsafe { *Box::from_raw(err as *mut io::Error) });
-        }
+    if err.is_null() {
+        return Ok(true);
+    } else {
+        return Err(unsafe { *Box::from_raw(err as *mut io::Error) });
+    }
 
-        unsafe extern "C" fn callback(
-            state: *mut c_void,
-            symbol_name: *const c_char,
-        ) -> *mut c_void {
-            let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
-            match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
-                Ok(()) => std::ptr::null_mut(),
-                Err(err) => Box::into_raw(Box::new(err)) as *mut c_void,
-            }
+    unsafe extern "C" fn callback(state: *mut c_void, symbol_name: *const c_char) -> *mut c_void {
+        let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
+        match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
+            Ok(()) => std::ptr::null_mut(),
+            Err(err) => Box::into_raw(Box::new(err)) as *mut c_void,
         }
+    }
 
-        unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
-            let error = unsafe { CStr::from_ptr(error) };
-            Box::into_raw(Box::new(io::Error::new(
-                io::ErrorKind::Other,
-                format!("LLVM error: {}", error.to_string_lossy()),
-            ))) as *mut c_void
-        }
-    } else {
-        get_native_object_symbols(buf, f)
+    unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
+        let error = unsafe { CStr::from_ptr(error) };
+        Box::into_raw(Box::new(io::Error::new(
+            io::ErrorKind::Other,
+            format!("LLVM error: {}", error.to_string_lossy()),
+        ))) as *mut c_void
     }
 }
 
+fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
+    if !should_use_llvm_reader(buf) {
+        return (DEFAULT_OBJECT_READER.is_64_bit_object_file)(buf);
+    }
+
+    unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }
+}
+
+fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
+    if !should_use_llvm_reader(buf) {
+        return (DEFAULT_OBJECT_READER.is_ec_object_file)(buf);
+    }
+
+    unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
+}
+
 impl<'a> LlvmArchiveBuilder<'a> {
     fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
         let kind = &*self.sess.target.archive_format;