Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #107946

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 39 additions & 96 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,9 @@ pub fn each_linked_rlib(

/// Create an 'rlib'.
///
/// An rlib in its current incarnation is essentially a renamed .a file. The rlib primarily contains
/// the object file of the crate, but it also contains all of the object files from native
/// libraries. This is done by unzipping native libraries and inserting all of the contents into
/// this archive.
/// An rlib in its current incarnation is essentially a renamed .a file (with "dummy" object files).
/// The rlib primarily contains the object file of the crate, but it also some of the object files
/// from native libraries.
fn link_rlib<'a>(
sess: &'a Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
Expand Down Expand Up @@ -347,44 +346,23 @@ fn link_rlib<'a>(
// loaded from the libraries found here and then encode that into the
// metadata of the rlib we're generating somehow.
for lib in codegen_results.crate_info.used_libraries.iter() {
match lib.kind {
NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) }
if flavor == RlibFlavor::Normal && sess.opts.unstable_opts.packed_bundled_libs => {}
NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) }
if flavor == RlibFlavor::Normal =>
{
// Don't allow mixing +bundle with +whole_archive since an rlib may contain
// multiple native libs, some of which are +whole-archive and some of which are
// -whole-archive and it isn't clear how we can currently handle such a
// situation correctly.
// See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897
sess.emit_err(errors::IncompatibleLinkingModifiers);
}
NativeLibKind::Static { bundle: None | Some(true), .. } => {}
NativeLibKind::Static { bundle: Some(false), .. }
| NativeLibKind::Dylib { .. }
| NativeLibKind::Framework { .. }
| NativeLibKind::RawDylib
| NativeLibKind::LinkArg
| NativeLibKind::Unspecified => continue,
}
if let Some(name) = lib.name {
let location =
let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else {
continue;
};
if whole_archive == Some(true) && !codegen_results.crate_info.feature_packed_bundled_libs {
sess.emit_err(errors::IncompatibleLinkingModifiers);
}
if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename {
let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess);
let src = read(path).map_err(|e| sess.emit_fatal(errors::ReadFileError {message: e }))?;
let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src);
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
packed_bundled_libs.push(wrapper_file);
} else if let Some(name) = lib.name {
let path =
find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess);
if sess.opts.unstable_opts.packed_bundled_libs && flavor == RlibFlavor::Normal {
let filename = lib.filename.unwrap();
let lib_path =
find_native_static_library(filename.as_str(), true, &lib_search_paths, sess);
let src = read(lib_path)
.map_err(|e| sess.emit_fatal(errors::ReadFileError { message: e }))?;
let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src);
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
packed_bundled_libs.push(wrapper_file);
continue;
}
ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|error| {
sess.emit_fatal(errors::AddNativeLibrary { library_path: location, error });
});
ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| {
sess.emit_fatal(errors::AddNativeLibrary { library_path: path, error })});
}
}

Expand Down Expand Up @@ -516,36 +494,14 @@ fn link_staticlib<'a>(
&codegen_results.crate_info,
Some(CrateType::Staticlib),
&mut |cnum, path| {
let name = codegen_results.crate_info.crate_name[&cnum];
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];

// Here when we include the rlib into our staticlib we need to make a
// decision whether to include the extra object files along the way.
// These extra object files come from statically included native
// libraries, but they may be cfg'd away with #[link(cfg(..))].
//
// This unstable feature, though, only needs liblibc to work. The only
// use case there is where musl is statically included in liblibc.rlib,
// so if we don't want the included version we just need to skip it. As
// a result the logic here is that if *any* linked library is cfg'd away
// we just skip all object files.
//
// Clearly this is not sufficient for a general purpose feature, and
// we'd want to read from the library's metadata to determine which
// object files come from where and selectively skip them.
let skip_object_files = native_libs.iter().any(|lib| {
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
&& !relevant_lib(sess, lib)
});

let lto = are_upstream_rust_objects_already_included(sess)
&& !ignored_for_lto(sess, &codegen_results.crate_info, cnum);

// Ignoring obj file starting with the crate name
// as simple comparison is not enough - there
// might be also an extra name suffix
let obj_start = name.as_str().to_owned();
let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter();
let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, &lib));
let relevant_libs: FxHashSet<_> = relevant.filter_map(|lib| lib.filename).collect();

let bundled_libs: FxHashSet<_> = native_libs.filter_map(|lib| lib.filename).collect();
ab.add_archive(
path,
Box::new(move |fname: &str| {
Expand All @@ -559,20 +515,25 @@ fn link_staticlib<'a>(
return true;
}

// Otherwise if this is *not* a rust object and we're skipping
// objects then skip this file
if skip_object_files
&& (!fname.starts_with(&obj_start) || !fname.ends_with(".o"))
{
// Skip objects for bundled libs.
if bundled_libs.contains(&Symbol::intern(fname)) {
return true;
}

// ok, don't skip this
false
}),
)
.unwrap();

archive_builder_builder
.extract_bundled_libs(path, tempdir.as_ref(), &relevant_libs)
.unwrap_or_else(|e| sess.emit_fatal(e));
for filename in relevant_libs {
let joined = tempdir.as_ref().join(filename.as_str());
let path = joined.as_path();
ab.add_archive(path, Box::new(|_| false)).unwrap();
}

all_native_libs
.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
},
Expand Down Expand Up @@ -2590,18 +2551,8 @@ fn add_static_crate<'a>(
cmd.link_rlib(&fix_windows_verbatim_for_gcc(path));
};

// See the comment above in `link_staticlib` and `link_rlib` for why if
// there's a static library that's not relevant we skip all object
// files.
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
let skip_native = native_libs.iter().any(|lib| {
matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
&& !relevant_lib(sess, lib)
});

if (!are_upstream_rust_objects_already_included(sess)
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum))
&& !skip_native
if !are_upstream_rust_objects_already_included(sess)
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum)
{
link_upstream(cratepath);
return;
Expand Down Expand Up @@ -2632,17 +2583,13 @@ fn add_static_crate<'a>(
let is_rust_object =
canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f);

// If we've been requested to skip all native object files
// (those not generated by the rust compiler) then we can skip
// this file. See above for why we may want to do this.
let skip_because_cfg_say_so = skip_native && !is_rust_object;

// 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.
let skip_because_lto =
upstream_rust_objects_already_included && is_rust_object && is_builtins;
if upstream_rust_objects_already_included && is_rust_object && is_builtins {
return true;
}

// We skip native libraries because:
// 1. This native libraries won't be used from the generated rlib,
Expand All @@ -2653,10 +2600,6 @@ fn add_static_crate<'a>(
return true;
}

if skip_because_cfg_say_so || skip_because_lto {
return true;
}

false
}),
) {
Expand Down
15 changes: 8 additions & 7 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::Symbol;
use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
use rustc_target::abi::{Align, Size, VariantIdx};
use rustc_target::abi::{Align, VariantIdx};

use std::collections::BTreeSet;
use std::time::{Duration, Instant};
Expand Down Expand Up @@ -273,12 +273,12 @@ pub fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
"destination type must be a dyn*"
);
// FIXME(dyn-star): this is probably not the best way to check if this is
// a pointer, and really we should ensure that the value is a suitable
// pointer earlier in the compilation process.
let src = match src_ty_and_layout.pointee_info_at(bx.cx(), Size::ZERO) {
Some(_) => bx.ptrtoint(src, bx.cx().type_isize()),
None => bx.bitcast(src, bx.type_isize()),
// FIXME(dyn-star): We can remove this when all supported LLVMs use opaque ptrs only.
let src = match bx.cx().type_kind(bx.cx().backend_type(src_ty_and_layout)) {
TypeKind::Pointer => bx.pointercast(src, bx.cx().type_i8p()),
TypeKind::Integer => bx.inttoptr(src, bx.cx().type_i8p()),
// FIXME(dyn-star): We probably have to do a bitcast first, then inttoptr.
kind => bug!("unexpected TypeKind for left-hand side of `dyn*` cast: {kind:?}"),
};
(src, unsized_info(bx, src_ty_and_layout.ty, dst_ty, old_info))
}
Expand Down Expand Up @@ -858,6 +858,7 @@ impl CrateInfo {
dependency_formats: tcx.dependency_formats(()).clone(),
windows_subsystem,
natvis_debugger_visualizers: Default::default(),
feature_packed_bundled_libs: tcx.features().packed_bundled_libs,
};
let crates = tcx.crates(());

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ pub struct CrateInfo {
pub dependency_formats: Lrc<Dependencies>,
pub windows_subsystem: Option<String>,
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
pub feature_packed_bundled_libs: bool, // unstable feature flag.
}

#[derive(Encodable, Decodable)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files w

codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}

codegen_ssa_incompatible_linking_modifiers = the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs

codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ declare_features! (
(active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None),
/// Allows using `#[omit_gdb_pretty_printer_section]`.
(active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
/// Allows using `+bundled,+whole-archive` native libs.
(active, packed_bundled_libs, "1.67.0", None, None),
/// Allows using `#[prelude_import]` on glob `use` items.
(active, prelude_import, "1.2.0", None, None),
/// Used to identify crates that contain the profiler runtime.
Expand Down
27 changes: 14 additions & 13 deletions compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,21 @@ fn find_bundled_library(
name: Option<Symbol>,
verbatim: Option<bool>,
kind: NativeLibKind,
has_cfg: bool,
sess: &Session,
) -> Option<Symbol> {
if sess.opts.unstable_opts.packed_bundled_libs &&
sess.crate_types().iter().any(|ct| ct == &CrateType::Rlib || ct == &CrateType::Staticlib) &&
let NativeLibKind::Static { bundle: Some(true) | None, .. } = kind {
find_native_static_library(
name.unwrap().as_str(),
verbatim.unwrap_or(false),
&sess.target_filesearch(PathKind::Native).search_path_dirs(),
sess,
).file_name().and_then(|s| s.to_str()).map(Symbol::intern)
} else {
None
if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind
&& sess.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib))
&& (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
{
let verbatim = verbatim.unwrap_or(false);
let search_paths = &sess.target_filesearch(PathKind::Native).search_path_dirs();
return find_native_static_library(name.unwrap().as_str(), verbatim, search_paths, sess)
.file_name()
.and_then(|s| s.to_str())
.map(Symbol::intern);
}
None
}

pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
Expand Down Expand Up @@ -385,7 +386,7 @@ impl<'tcx> Collector<'tcx> {

let name = name.map(|(name, _)| name);
let kind = kind.unwrap_or(NativeLibKind::Unspecified);
let filename = find_bundled_library(name, verbatim, kind, sess);
let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess);
self.libs.push(NativeLib {
name,
filename,
Expand Down Expand Up @@ -475,7 +476,7 @@ impl<'tcx> Collector<'tcx> {
let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name)));
let sess = self.tcx.sess;
let filename =
find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, sess);
find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess);
self.libs.push(NativeLib {
name,
filename,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ where

ty::Dynamic(_, _, ty::DynStar) => {
if i == 0 {
TyMaybeWithLayout::Ty(tcx.types.usize)
TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit))
} else if i == 1 {
// FIXME(dyn-star) same FIXME as above applies here too
TyMaybeWithLayout::Ty(
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;

use std::cell::Cell;
use std::char;
use std::collections::BTreeMap;
use std::fmt::{self, Write as _};
use std::iter;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub struct Session {
/// `-C metadata` arguments passed to the compiler. Its value forms a unique
/// global identifier for the crate. It is used to allow multiple crates
/// with the same name to coexist. See the
/// `rustc_codegen_llvm::back::symbol_names` module for more information.
/// `rustc_symbol_mangling` crate for more information.
pub stable_crate_id: OnceCell<StableCrateId>,

features: OnceCell<rustc_feature::Features>,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_span/src/lev_distance/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use super::*;

#[test]
fn test_lev_distance() {
use std::char::{from_u32, MAX};
// Test bytelength agnosticity
for c in (0..MAX as u32).filter_map(from_u32).map(|i| i.to_string()) {
for c in (0..char::MAX as u32).filter_map(char::from_u32).map(|i| i.to_string()) {
assert_eq!(lev_distance(&c[..], &c[..], usize::MAX), Some(0));
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,7 @@ symbols! {
overlapping_marker_traits,
owned_box,
packed,
packed_bundled_libs,
panic,
panic_2015,
panic_2021,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ty_utils/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ fn layout_of_uncached<'tcx>(
}

ty::Dynamic(_, _, ty::DynStar) => {
let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false));
let mut data = scalar_unit(Pointer(AddressSpace::DATA));
data.valid_range_mut().start = 0;
let mut vtable = scalar_unit(Pointer(AddressSpace::DATA));
vtable.valid_range_mut().start = 1;
Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_type_ir/src/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ pub enum DynKind {
Dyn,
/// A sized `dyn* Trait` object
///
/// These objects are represented as a `(data, vtable)` pair where `data` is a ptr-sized value
/// (often a pointer to the real object, but not necessarily) and `vtable` is a pointer to
/// the vtable for `dyn* Trait`. The representation is essentially the same as `&dyn Trait`
/// or similar, but the drop function included in the vtable is responsible for freeing the
/// underlying storage if needed. This allows a `dyn*` object to be treated agnostically with
/// These objects are represented as a `(data, vtable)` pair where `data` is a value of some
/// ptr-sized and ptr-aligned dynamically determined type `T` and `vtable` is a pointer to the
/// vtable of `impl T for Trait`. This allows a `dyn*` object to be treated agnostically with
/// respect to whether it points to a `Box<T>`, `Rc<T>`, etc.
DynStar,
}
Expand Down
Loading