From adb065a781fb063556137a1a21fcef581985d6d0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 1 Jun 2026 18:54:29 +0300 Subject: [PATCH] rustc_codegen_ssa: Refactor `ArchiveEntry` to include entry kind --- .../rustc_codegen_ssa/src/back/archive.rs | 62 ++++++++++++------- compiler/rustc_codegen_ssa/src/back/link.rs | 40 ++++++------ 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index ba811825dce23..e4bfbdccba4a0 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -21,7 +21,7 @@ use rustc_target::spec::Arch; use tracing::trace; use super::metadata::{create_compressed_metadata_file, search_for_section}; -use super::rmeta_link::{self, RmetaLink}; +use super::rmeta_link; use crate::common; // Public for ArchiveBuilderBuilder::extract_bundled_libs pub use crate::errors::ExtractBundledLibsError; @@ -309,12 +309,12 @@ fn find_binutils_dlltool(sess: &Session) -> OsString { } pub trait ArchiveBuilder { - fn add_file(&mut self, path: &Path); + fn add_file(&mut self, path: &Path, kind: ArchiveEntryKind); fn add_archive( &mut self, archive: &Path, - skip: Option) -> bool + 'static>>, + skip: Option bool + 'static>>, ) -> io::Result<()>; fn build(self: Box, output: &Path) -> bool; @@ -383,12 +383,27 @@ pub struct ArArchiveBuilder<'a> { entries: Vec<(Vec, ArchiveEntry)>, } +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum ArchiveEntryKind { + /// Object file produced from Rust code. + RustObj, + /// Anything else, introduce new variants as needed. + Other, +} + #[derive(Debug)] -enum ArchiveEntry { - FromArchive { archive_index: usize, file_range: (u64, u64) }, +enum ArchiveEntrySource { + Archive { archive_index: usize, file_range: (u64, u64) }, File(PathBuf), } +#[derive(Debug)] +struct ArchiveEntry { + source: ArchiveEntrySource, + #[expect(dead_code)] // used in #155338 + kind: ArchiveEntryKind, +} + impl<'a> ArArchiveBuilder<'a> { pub fn new(sess: &'a Session, object_reader: &'static ObjectReader) -> ArArchiveBuilder<'a> { ArArchiveBuilder { sess, object_reader, src_archives: vec![], entries: vec![] } @@ -446,7 +461,7 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { fn add_archive( &mut self, archive_path: &Path, - mut skip: Option) -> bool + 'static>>, + mut skip: Option bool + 'static>>, ) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") @@ -462,8 +477,7 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; let archive = ArchiveFile::parse(&*archive_map) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let metadata_link = - skip.as_ref().and_then(|_| rmeta_link::read(&archive, &archive_map, &archive_path)); + let metadata_link = rmeta_link::read(&archive, &archive_map, &archive_path); let archive_index = self.src_archives.len(); if let Some(expected_kind) = @@ -483,17 +497,23 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; let file_name = String::from_utf8(entry.name().to_vec()) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let drop = skip.as_mut().is_some_and(|f| f(&file_name, metadata_link.as_ref())); + let kind = if metadata_link + .as_ref() + .is_some_and(|m| m.rust_object_files.iter().any(|f| f == &file_name)) + { + ArchiveEntryKind::RustObj + } else { + ArchiveEntryKind::Other + }; + let drop = skip.as_mut().is_some_and(|f| f(&file_name, kind)); if !drop { - if entry.is_thin() { + let source = if entry.is_thin() { let member_path = archive_path.parent().unwrap().join(Path::new(&file_name)); - self.entries.push((file_name.into_bytes(), ArchiveEntry::File(member_path))); + ArchiveEntrySource::File(member_path) } else { - self.entries.push(( - file_name.into_bytes(), - ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, - )); - } + ArchiveEntrySource::Archive { archive_index, file_range: entry.file_range() } + }; + self.entries.push((file_name.into_bytes(), ArchiveEntry { source, kind })); } } @@ -502,10 +522,10 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { } /// Adds an arbitrary file to this archive - fn add_file(&mut self, file: &Path) { + fn add_file(&mut self, file: &Path, kind: ArchiveEntryKind) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), - ArchiveEntry::File(file.to_owned()), + ArchiveEntry { source: ArchiveEntrySource::File(file.to_owned()), kind }, )); } @@ -539,8 +559,8 @@ impl<'a> ArArchiveBuilder<'a> { for (entry_name, entry) in self.entries { let data = - match entry { - ArchiveEntry::FromArchive { archive_index, file_range } => { + match entry.source { + ArchiveEntrySource::Archive { archive_index, file_range } => { let src_archive = &self.src_archives[archive_index]; let archive_data = &src_archive.1; let start = file_range.0 as usize; @@ -563,7 +583,7 @@ impl<'a> ArArchiveBuilder<'a> { Box::new(data) as Box> } - ArchiveEntry::File(file) => unsafe { + ArchiveEntrySource::File(file) => unsafe { Box::new( Mmap::map(File::open(file).map_err(|err| { io_error_context("failed to open object file", err) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d54f9141d8225..955616b04c1c1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -53,7 +53,7 @@ use rustc_target::spec::{ }; use tracing::{debug, info, warn}; -use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; +use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ArchiveEntryKind}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; @@ -342,11 +342,11 @@ fn link_rlib<'a>( // normal linkers for the platform. Sometimes this is not possible however. // If it is possible however, placing the metadata object first improves // performance of getting metadata from rlibs. - ab.add_file(&metadata); + ab.add_file(&metadata, ArchiveEntryKind::Other); // Place the rmeta-link member immediately after metadata so consumers // can find it without iterating the whole archive. if let Some(file) = &metadata_link_file { - ab.add_file(file); + ab.add_file(file, ArchiveEntryKind::Other); } None } @@ -359,15 +359,15 @@ fn link_rlib<'a>( for m in &compiled_modules.modules { if let Some(obj) = m.object.as_ref() { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } if let Some(obj) = m.global_asm_object.as_ref() { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } if let Some(dwarf_obj) = m.dwarf_object.as_ref() { - ab.add_file(dwarf_obj); + ab.add_file(dwarf_obj, ArchiveEntryKind::Other); } } @@ -376,10 +376,10 @@ fn link_rlib<'a>( RlibFlavor::StaticlibBase => { if let Some(m) = &compiled_modules.allocator_module { if let Some(obj) = &m.object { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } if let Some(obj) = &m.global_asm_object { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } } } @@ -469,18 +469,18 @@ fn link_rlib<'a>( // // Basically, all this means is that this code should not move above the // code above. - ab.add_file(&trailing_metadata); + ab.add_file(&trailing_metadata, ArchiveEntryKind::Other); // Place the rmeta-link member immediately after metadata so consumers can // find it without iterating the whole archive. if let Some(file) = &metadata_link_file { - ab.add_file(file); + ab.add_file(file, ArchiveEntryKind::Other); } } // Add all bundled static native library dependencies. // Archives added to the end of .rlib archive, see comment above for the reason. for lib in packed_bundled_libs { - ab.add_file(&lib) + ab.add_file(&lib, ArchiveEntryKind::Other) } ab @@ -529,16 +529,14 @@ fn link_staticlib( let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); ab.add_archive( path, - Some(Box::new(move |fname: &str, metadata_link| { + Some(Box::new(move |fname: &str, entry_kind| { // Ignore metadata and rmeta-link files. if fname == METADATA_FILENAME || fname == rmeta_link::FILENAME { return true; } // Don't include Rust objects if LTO is enabled. - if lto - && metadata_link.is_some_and(|m| m.rust_object_files.iter().any(|f| f == fname)) - { + if lto && entry_kind == ArchiveEntryKind::RustObj { return true; } @@ -1266,7 +1264,7 @@ fn link_natively( if should_archive { let mut ab = archive_builder_builder.new_archive_builder(sess); - ab.add_file(temp_filename); + ab.add_file(temp_filename, ArchiveEntryKind::Other); ab.build(out_filename); } } @@ -3242,19 +3240,19 @@ fn add_static_crate( let mut archive = archive_builder_builder.new_archive_builder(sess); if let Err(error) = archive.add_archive( cratepath, - Some(Box::new(move |f, metadata_link| { + Some(Box::new(move |f, entry_kind| { if f == METADATA_FILENAME || f == rmeta_link::FILENAME { return true; } - let is_rust_object = - metadata_link.is_some_and(|m| m.rust_object_files.iter().any(|rf| rf == f)); - // If we're performing LTO and this is a rust-generated object // file, then we don't need the object file as it's part of the // LTO module. Note that `#![no_builtins]` is excluded from LTO, // though, so we let that object file slide. - if upstream_rust_objects_already_included && is_rust_object && is_builtins { + if upstream_rust_objects_already_included + && entry_kind == ArchiveEntryKind::RustObj + && is_builtins + { return true; }