diff options
| author | bors <bors@rust-lang.org> | 2024-09-25 06:41:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-09-25 06:41:56 +0000 |
| commit | 34aff74fb06e78fb9cd1a66acafb6d150638de35 (patch) | |
| tree | 14533de260c2f1834994e58af1d210a6884625a9 /compiler/rustc_codegen_ssa/src | |
| parent | 938c7b1162a38dca257c7004ef7ecf86397a8634 (diff) | |
| parent | 8be19465ec14880160d294f2909202451a547740 (diff) | |
| download | rust-34aff74fb06e78fb9cd1a66acafb6d150638de35.tar.gz rust-34aff74fb06e78fb9cd1a66acafb6d150638de35.zip | |
Auto merge of #18183 - lnicola:sync-from-rust, r=lnicola
internal: Sync from downstream
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
45 files changed, 746 insertions, 1013 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 76a94de5433..2f48c1fbf0d 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -6,9 +6,9 @@ use std::io::{self, Write}; use std::path::{Path, PathBuf}; use ar_archive_writer::{ - write_archive_to_stream, ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember, + ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember, write_archive_to_stream, }; -pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER}; +pub use ar_archive_writer::{DEFAULT_OBJECT_READER, ObjectReader}; use object::read::archive::ArchiveFile; use object::read::macho::FatArch; use rustc_data_structures::fx::FxIndexSet; @@ -157,7 +157,7 @@ pub trait ArchiveBuilderBuilder { } } -pub fn create_mingw_dll_import_lib( +fn create_mingw_dll_import_lib( sess: &Session, lib_name: &str, import_name_and_ordinal_vector: Vec<(String, Option<u16>)>, @@ -395,10 +395,10 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let member_path = archive_path.parent().unwrap().join(Path::new(&file_name)); self.entries.push((file_name.into_bytes(), ArchiveEntry::File(member_path))); } else { - self.entries.push(( - file_name.into_bytes(), - ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, - )); + self.entries.push((file_name.into_bytes(), ArchiveEntry::FromArchive { + archive_index, + file_range: entry.file_range(), + })); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs index 95c4af2e59e..b3c5b86ccf4 100644 --- a/compiler/rustc_codegen_ssa/src/back/command.rs +++ b/compiler/rustc_codegen_ssa/src/back/command.rs @@ -8,7 +8,7 @@ use std::{fmt, io, mem}; use rustc_target::spec::LldFlavor; #[derive(Clone)] -pub struct Command { +pub(crate) struct Command { program: Program, args: Vec<OsString>, env: Vec<(OsString, OsString)>, @@ -23,15 +23,15 @@ enum Program { } impl Command { - pub fn new<P: AsRef<OsStr>>(program: P) -> Command { + pub(crate) fn new<P: AsRef<OsStr>>(program: P) -> Command { Command::_new(Program::Normal(program.as_ref().to_owned())) } - pub fn bat_script<P: AsRef<OsStr>>(program: P) -> Command { + pub(crate) fn bat_script<P: AsRef<OsStr>>(program: P) -> Command { Command::_new(Program::CmdBatScript(program.as_ref().to_owned())) } - pub fn lld<P: AsRef<OsStr>>(program: P, flavor: LldFlavor) -> Command { + pub(crate) fn lld<P: AsRef<OsStr>>(program: P, flavor: LldFlavor) -> Command { Command::_new(Program::Lld(program.as_ref().to_owned(), flavor)) } @@ -39,12 +39,12 @@ impl Command { Command { program, args: Vec::new(), env: Vec::new(), env_remove: Vec::new() } } - pub fn arg<P: AsRef<OsStr>>(&mut self, arg: P) -> &mut Command { + pub(crate) fn arg<P: AsRef<OsStr>>(&mut self, arg: P) -> &mut Command { self._arg(arg.as_ref()); self } - pub fn args<I>(&mut self, args: I) -> &mut Command + pub(crate) fn args<I>(&mut self, args: I) -> &mut Command where I: IntoIterator<Item: AsRef<OsStr>>, { @@ -58,7 +58,7 @@ impl Command { self.args.push(arg.to_owned()); } - pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Command + pub(crate) fn env<K, V>(&mut self, key: K, value: V) -> &mut Command where K: AsRef<OsStr>, V: AsRef<OsStr>, @@ -71,7 +71,7 @@ impl Command { self.env.push((key.to_owned(), value.to_owned())); } - pub fn env_remove<K>(&mut self, key: K) -> &mut Command + pub(crate) fn env_remove<K>(&mut self, key: K) -> &mut Command where K: AsRef<OsStr>, { @@ -83,11 +83,11 @@ impl Command { self.env_remove.push(key.to_owned()); } - pub fn output(&mut self) -> io::Result<Output> { + pub(crate) fn output(&mut self) -> io::Result<Output> { self.command().output() } - pub fn command(&self) -> process::Command { + pub(crate) fn command(&self) -> process::Command { let mut ret = match self.program { Program::Normal(ref p) => process::Command::new(p), Program::CmdBatScript(ref p) => { @@ -111,17 +111,17 @@ impl Command { // extensions - pub fn get_args(&self) -> &[OsString] { + pub(crate) fn get_args(&self) -> &[OsString] { &self.args } - pub fn take_args(&mut self) -> Vec<OsString> { + pub(crate) fn take_args(&mut self) -> Vec<OsString> { mem::take(&mut self.args) } /// Returns a `true` if we're pretty sure that this'll blow OS spawn limits, /// or `false` if we should attempt to spawn and see what the OS says. - pub fn very_likely_to_exceed_some_spawn_limit(&self) -> bool { + pub(crate) fn very_likely_to_exceed_some_spawn_limit(&self) -> bool { // We mostly only care about Windows in this method, on Unix the limits // can be gargantuan anyway so we're pretty unlikely to hit them if cfg!(unix) { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4d19425255f..892dfb91201 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,8 +1,8 @@ use std::collections::BTreeSet; use std::ffi::OsString; -use std::fs::{read, File, OpenOptions}; +use std::fs::{File, OpenOptions, read}; use std::io::{BufWriter, Write}; -use std::ops::Deref; +use std::ops::{ControlFlow, Deref}; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{env, fmt, fs, io, mem, str}; @@ -18,8 +18,8 @@ use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError}; use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; -use rustc_metadata::find_native_static_library; -use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME}; +use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; +use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs}; use rustc_middle::bug; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; @@ -34,7 +34,7 @@ use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. -use rustc_session::{filesearch, Session}; +use rustc_session::{Session, filesearch}; use rustc_span::symbol::Symbol; use rustc_target::spec::crt_objects::CrtObjects; use rustc_target::spec::{ @@ -48,11 +48,11 @@ use tracing::{debug, info, warn}; use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use super::command::Command; use super::linker::{self, Linker}; -use super::metadata::{create_wrapper_file, MetadataPosition}; +use super::metadata::{MetadataPosition, create_wrapper_file}; use super::rpath::{self, RPathConfig}; use crate::{ - common, errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, - NativeLib, + CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, + looks_like_rust_object_file, }; pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { @@ -281,12 +281,10 @@ pub fn each_linked_rlib( let used_crate_source = &info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.rlib { f(cnum, path); + } else if used_crate_source.rmeta.is_some() { + return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - if used_crate_source.rmeta.is_some() { - return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); - } else { - return Err(errors::LinkRlibError::NotFound { crate_name }); - } + return Err(errors::LinkRlibError::NotFound { crate_name }); } } Ok(()) @@ -438,7 +436,7 @@ fn link_rlib<'a>( ab.add_file(&lib) } - return Ok(ab); + Ok(ab) } /// Extract all symbols defined in raw-dylib libraries, collated by library name. @@ -628,12 +626,10 @@ fn link_staticlib( let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.dylib { all_rust_dylibs.push(&**path); + } else if used_crate_source.rmeta.is_some() { + sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - if used_crate_source.rmeta.is_some() { - sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); - } else { - sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name }); - } + sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name }); } } @@ -1201,8 +1197,8 @@ fn escape_linker_output(s: &[u8], flavour: LinkerFlavor) -> String { #[cfg(windows)] mod win { use windows::Win32::Globalization::{ - GetLocaleInfoEx, MultiByteToWideChar, CP_OEMCP, LOCALE_IUSEUTF8LEGACYOEMCP, - LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_RETURN_NUMBER, MB_ERR_INVALID_CHARS, + CP_OEMCP, GetLocaleInfoEx, LOCALE_IUSEUTF8LEGACYOEMCP, LOCALE_NAME_SYSTEM_DEFAULT, + LOCALE_RETURN_NUMBER, MB_ERR_INVALID_CHARS, MultiByteToWideChar, }; /// Get the Windows system OEM code page. This is most notably the code page @@ -1319,7 +1315,7 @@ fn link_sanitizer_runtime( fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf { let path = sess.target_tlib_path.dir.join(filename); if path.exists() { - return sess.target_tlib_path.dir.clone(); + sess.target_tlib_path.dir.clone() } else { let default_sysroot = filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); @@ -1327,7 +1323,7 @@ fn link_sanitizer_runtime( &default_sysroot, sess.opts.target_triple.triple(), ); - return default_tlib; + default_tlib } } @@ -1972,10 +1968,8 @@ fn add_late_link_args( if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) { cmd.verbatim_args(args.iter().map(Deref::deref)); } - } else { - if let Some(args) = sess.target.late_link_args_static.get(&flavor) { - cmd.verbatim_args(args.iter().map(Deref::deref)); - } + } else if let Some(args) = sess.target.late_link_args_static.get(&flavor) { + cmd.verbatim_args(args.iter().map(Deref::deref)); } if let Some(args) = sess.target.late_link_args.get(&flavor) { cmd.verbatim_args(args.iter().map(Deref::deref)); @@ -2110,50 +2104,19 @@ fn add_library_search_dirs( return; } - // Library search paths explicitly supplied by user (`-L` on the command line). - for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() { - cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)); - } - for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() { - // Contrary to the `-L` docs only framework-specific paths are considered here. - if search_path.kind != PathKind::All { - cmd.framework_path(&search_path.dir); - } - } - - // The toolchain ships some native library components and self-contained linking was enabled. - // Add the self-contained library directory to search paths. - if self_contained_components.intersects( - LinkSelfContainedComponents::LIBC - | LinkSelfContainedComponents::UNWIND - | LinkSelfContainedComponents::MINGW, - ) { - let lib_path = sess.target_tlib_path.dir.join("self-contained"); - cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); - } - - // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot - // library directory instead of the self-contained directories. - // Sanitizer libraries have the same issue and are also linked by name on Apple targets. - // The targets here should be in sync with `copy_third_party_objects` in bootstrap. - // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind - // and sanitizers to self-contained directory, and stop adding this search path. - if sess.target.vendor == "fortanix" - || sess.target.os == "linux" - || sess.target.os == "fuchsia" - || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() - { - cmd.include_path(&fix_windows_verbatim_for_gcc(&sess.target_tlib_path.dir)); - } - - // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks - // we must have the support library stubs in the library search path (#121430). - if let Some(sdk_root) = apple_sdk_root - && sess.target.llvm_target.contains("macabi") - { - cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib")); - cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks")); - } + walk_native_lib_search_dirs( + sess, + self_contained_components, + apple_sdk_root, + |dir, is_framework| { + if is_framework { + cmd.framework_path(dir); + } else { + cmd.include_path(&fix_windows_verbatim_for_gcc(dir)); + } + ControlFlow::<()>::Continue(()) + }, + ); } /// Add options making relocation sections in the produced ELF files read-only @@ -2666,10 +2629,8 @@ fn add_native_libs_from_crate( if link_static { cmd.link_staticlib_by_name(name, verbatim, false); } - } else { - if link_dynamic { - cmd.link_dylib_by_name(name, verbatim, true); - } + } else if link_dynamic { + cmd.link_dylib_by_name(name, verbatim, true); } } NativeLibKind::Framework { as_needed } => { @@ -3083,7 +3044,7 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro "iphonesimulator" if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => { } - "macosx10.15" + "macosx" if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") => {} "watchos" diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index fbab988a32b..84817e19844 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -7,14 +7,16 @@ use std::{env, iter, mem, str}; use cc::windows_registry; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; -use rustc_metadata::find_native_static_library; +use rustc_metadata::{ + find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library, +}; use rustc_middle::bug; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind}; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip}; use rustc_session::Session; +use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip}; use rustc_span::symbol::sym; use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld}; use tracing::{debug, warn}; @@ -28,7 +30,7 @@ use crate::errors; /// and prevent inspection of linker output in case of errors, which we occasionally do. /// This should be acceptable because other messages from rustc are in English anyway, /// and may also be desirable to improve searchability of the linker diagnostics. -pub fn disable_localization(linker: &mut Command) { +pub(crate) fn disable_localization(linker: &mut Command) { // No harm in setting both env vars simultaneously. // Unix-style linkers. linker.env("LC_ALL", "C"); @@ -39,7 +41,7 @@ pub fn disable_localization(linker: &mut Command) { /// The third parameter is for env vars, used on windows to set up the /// path for MSVC to find its DLLs, and gcc to find its bundled /// toolchain -pub fn get_linker<'a>( +pub(crate) fn get_linker<'a>( sess: &'a Session, linker: &Path, flavor: LinkerFlavor, @@ -213,28 +215,36 @@ fn link_or_cc_args<L: Linker + ?Sized>( macro_rules! generate_arg_methods { ($($ty:ty)*) => { $( impl $ty { - pub fn verbatim_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self { + #[allow(unused)] + pub(crate) fn verbatim_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self { verbatim_args(self, args) } - pub fn verbatim_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { + #[allow(unused)] + pub(crate) fn verbatim_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { verbatim_args(self, iter::once(arg)) } - pub fn link_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>, IntoIter: ExactSizeIterator>) -> &mut Self { + #[allow(unused)] + pub(crate) fn link_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>, IntoIter: ExactSizeIterator>) -> &mut Self { link_args(self, args) } - pub fn link_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { + #[allow(unused)] + pub(crate) fn link_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { link_args(self, iter::once(arg)) } - pub fn cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self { + #[allow(unused)] + pub(crate) fn cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self { cc_args(self, args) } - pub fn cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { + #[allow(unused)] + pub(crate) fn cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { cc_args(self, iter::once(arg)) } - pub fn link_or_cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self { + #[allow(unused)] + pub(crate) fn link_or_cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self { link_or_cc_args(self, args) } - pub fn link_or_cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { + #[allow(unused)] + pub(crate) fn link_or_cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { link_or_cc_args(self, iter::once(arg)) } } @@ -261,7 +271,7 @@ generate_arg_methods! { /// represents the meaning of each option being passed down. This trait is then /// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an /// MSVC linker (e.g., `link.exe`) is being used. -pub trait Linker { +pub(crate) trait Linker { fn cmd(&mut self) -> &mut Command; fn is_cc(&self) -> bool { false @@ -312,12 +322,12 @@ pub trait Linker { } impl dyn Linker + '_ { - pub fn take_cmd(&mut self) -> Command { + pub(crate) fn take_cmd(&mut self) -> Command { mem::replace(self.cmd(), Command::new("")) } } -pub struct GccLinker<'a> { +struct GccLinker<'a> { cmd: Command, sess: &'a Session, target_cpu: &'a str, @@ -791,14 +801,12 @@ impl<'a> Linker for GccLinker<'a> { self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_solaris { self.link_arg("-M").link_arg(path); + } else if is_windows { + self.link_arg(path); } else { - if is_windows { - self.link_arg(path); - } else { - let mut arg = OsString::from("--version-script="); - arg.push(path); - self.link_arg(arg).link_arg("--no-undefined-version"); - } + let mut arg = OsString::from("--version-script="); + arg.push(path); + self.link_arg(arg).link_arg("--no-undefined-version"); } } @@ -849,7 +857,7 @@ impl<'a> Linker for GccLinker<'a> { } } -pub struct MsvcLinker<'a> { +struct MsvcLinker<'a> { cmd: Command, sess: &'a Session, } @@ -878,7 +886,13 @@ impl<'a> Linker for MsvcLinker<'a> { } fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { - self.link_arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + // On MSVC-like targets rustc supports import libraries using alternative naming + // scheme (`libfoo.a`) unsupported by linker, search for such libraries manually. + if let Some(path) = try_find_native_dynamic_library(self.sess, name, verbatim) { + self.link_arg(path); + } else { + self.link_arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + } } fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) { @@ -891,9 +905,15 @@ impl<'a> Linker for MsvcLinker<'a> { } fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) { - let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; - let suffix = if verbatim { "" } else { ".lib" }; - self.link_arg(format!("{prefix}{name}{suffix}")); + // On MSVC-like targets rustc supports static libraries using alternative naming + // scheme (`libfoo.a`) unsupported by linker, search for such libraries manually. + if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) { + self.link_staticlib_by_path(&path, whole_archive); + } else { + let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; + let suffix = if verbatim { "" } else { ".lib" }; + self.link_arg(format!("{prefix}{name}{suffix}")); + } } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { @@ -1091,7 +1111,7 @@ impl<'a> Linker for MsvcLinker<'a> { } } -pub struct EmLinker<'a> { +struct EmLinker<'a> { cmd: Command, sess: &'a Session, } @@ -1208,7 +1228,7 @@ impl<'a> Linker for EmLinker<'a> { } } -pub struct WasmLd<'a> { +struct WasmLd<'a> { cmd: Command, sess: &'a Session, } @@ -1392,7 +1412,7 @@ impl<'a> WasmLd<'a> { } /// Linker shepherd script for L4Re (Fiasco) -pub struct L4Bender<'a> { +struct L4Bender<'a> { cmd: Command, sess: &'a Session, hinted_static: bool, @@ -1478,7 +1498,6 @@ impl<'a> Linker for L4Bender<'a> { fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { // ToDo, not implemented, copy from GCC self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented); - return; } fn subsystem(&mut self, subsystem: &str) { @@ -1499,7 +1518,7 @@ impl<'a> Linker for L4Bender<'a> { } impl<'a> L4Bender<'a> { - pub fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> { + fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> { L4Bender { cmd, sess, hinted_static: false } } @@ -1512,14 +1531,14 @@ impl<'a> L4Bender<'a> { } /// Linker for AIX. -pub struct AixLinker<'a> { +struct AixLinker<'a> { cmd: Command, sess: &'a Session, hinted_static: Option<bool>, } impl<'a> AixLinker<'a> { - pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> { + fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> { AixLinker { cmd, sess, hinted_static: None } } @@ -1747,7 +1766,7 @@ pub(crate) fn linked_symbols( /// Much simplified and explicit CLI for the NVPTX linker. The linker operates /// with bitcode and uses LLVM backend to generate a PTX assembly. -pub struct PtxLinker<'a> { +struct PtxLinker<'a> { cmd: Command, sess: &'a Session, } @@ -1813,7 +1832,7 @@ impl<'a> Linker for PtxLinker<'a> { } /// The `self-contained` LLVM bitcode linker -pub struct LlbcLinker<'a> { +struct LlbcLinker<'a> { cmd: Command, sess: &'a Session, } @@ -1884,7 +1903,7 @@ impl<'a> Linker for LlbcLinker<'a> { fn linker_plugin_lto(&mut self) {} } -pub struct BpfLinker<'a> { +struct BpfLinker<'a> { cmd: Command, sess: &'a Session, } diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index 8b6f6b5a220..ab8b06a05fc 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -5,8 +5,8 @@ use rustc_data_structures::memmap::Mmap; use rustc_errors::FatalError; use super::write::CodegenContext; -use crate::traits::*; use crate::ModuleCodegen; +use crate::traits::*; pub struct ThinModule<B: WriteBackendMethods> { pub shared: Arc<ThinShared<B>>, @@ -41,18 +41,14 @@ pub struct ThinShared<B: WriteBackendMethods> { } pub enum LtoModuleCodegen<B: WriteBackendMethods> { - Fat { - module: ModuleCodegen<B::Module>, - _serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>, - }, - + Fat(ModuleCodegen<B::Module>), Thin(ThinModule<B>), } impl<B: WriteBackendMethods> LtoModuleCodegen<B> { pub fn name(&self) -> &str { match *self { - LtoModuleCodegen::Fat { .. } => "everything", + LtoModuleCodegen::Fat(_) => "everything", LtoModuleCodegen::Thin(ref m) => m.name(), } } @@ -68,7 +64,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> { cgcx: &CodegenContext<B>, ) -> Result<ModuleCodegen<B::Module>, FatalError> { match self { - LtoModuleCodegen::Fat { mut module, .. } => { + LtoModuleCodegen::Fat(mut module) => { B::optimize_fat(cgcx, &mut module)?; Ok(module) } @@ -81,7 +77,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> { pub fn cost(&self) -> u64 { match *self { // Only one module with fat LTO, so the cost doesn't matter. - LtoModuleCodegen::Fat { .. } => 0, + LtoModuleCodegen::Fat(_) => 0, LtoModuleCodegen::Thin(ref m) => m.cost(), } } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 9b5a797ad51..06433484ea3 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -7,19 +7,20 @@ use std::path::Path; use object::write::{self, StandardSegment, Symbol, SymbolSection}; use object::{ - elf, pe, xcoff, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, - ObjectSymbol, SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, + Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, ObjectSymbol, + SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, elf, pe, + xcoff, }; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; +use rustc_data_structures::owned_slice::{OwnedSlice, try_slice_owned}; +use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::fs::METADATA_FILENAME; -use rustc_metadata::EncodedMetadata; use rustc_middle::bug; use rustc_session::Session; use rustc_span::sym; use rustc_target::abi::Endian; -use rustc_target::spec::{ef_avr_arch, RelocModel, Target}; +use rustc_target::spec::{RelocModel, Target, ef_avr_arch}; /// The default metadata loader. This is used by cg_llvm and cg_clif. /// @@ -32,7 +33,7 @@ use rustc_target::spec::{ef_avr_arch, RelocModel, Target}; /// <dd>The metadata can be found in the `.rustc` section of the shared library.</dd> /// </dl> #[derive(Debug)] -pub struct DefaultMetadataLoader; +pub(crate) struct DefaultMetadataLoader; static AIX_METADATA_SYMBOL_NAME: &'static str = "__aix_rust_metadata"; @@ -171,10 +172,10 @@ pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a "Metadata at offset {offset} with size {len} is beyond .info section" )); } - return Ok(&info_data[offset..(offset + len)]); + Ok(&info_data[offset..(offset + len)]) } else { - return Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}")); - }; + Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}")) + } } pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static>> { @@ -372,36 +373,51 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static Some(file) } -/// Since Xcode 15 Apple's LD requires object files to contain information about what they were -/// built for (LC_BUILD_VERSION): the platform (macOS/watchOS etc), minimum OS version, and SDK -/// version. This returns a `MachOBuildVersion` for the target. +/// Mach-O files contain information about: +/// - The platform/OS they were built for (macOS/watchOS/Mac Catalyst/iOS simulator etc). +/// - The minimum OS version / deployment target. +/// - The version of the SDK they were targetting. +/// +/// In the past, this was accomplished using the LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, +/// LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS load commands, which each contain information +/// about the deployment target and SDK version, and implicitly, by their presence, which OS they +/// target. Simulator targets were determined if the architecture was x86_64, but there was e.g. a +/// LC_VERSION_MIN_IPHONEOS present. +/// +/// This is of course brittle and limited, so modern tooling emit the LC_BUILD_VERSION load +/// command (which contains all three pieces of information in one) when the deployment target is +/// high enough, or the target is something that wouldn't be encodable with the old load commands +/// (such as Mac Catalyst, or Aarch64 iOS simulator). +/// +/// Since Xcode 15, Apple's LD apparently requires object files to use this load command, so this +/// returns the `MachOBuildVersion` for the target to do so. fn macho_object_build_version_for_target(target: &Target) -> object::write::MachOBuildVersion { /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz" /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200 - fn pack_version((major, minor): (u32, u32)) -> u32 { - (major << 16) | (minor << 8) + fn pack_version((major, minor, patch): (u16, u8, u8)) -> u32 { + let (major, minor, patch) = (major as u32, minor as u32, patch as u32); + (major << 16) | (minor << 8) | patch } let platform = rustc_target::spec::current_apple_platform(target).expect("unknown Apple target OS"); - let min_os = rustc_target::spec::current_apple_deployment_target(target) - .expect("unknown Apple target OS"); - let sdk = + let min_os = rustc_target::spec::current_apple_deployment_target(target); + let (sdk_major, sdk_minor) = rustc_target::spec::current_apple_sdk_version(platform).expect("unknown Apple target OS"); let mut build_version = object::write::MachOBuildVersion::default(); build_version.platform = platform; build_version.minos = pack_version(min_os); - build_version.sdk = pack_version(sdk); + build_version.sdk = pack_version((sdk_major, sdk_minor, 0)); build_version } /// Is Apple's CPU subtype `arm64e`s fn macho_is_arm64e(target: &Target) -> bool { - return target.llvm_target.starts_with("arm64e"); + target.llvm_target.starts_with("arm64e") } -pub enum MetadataPosition { +pub(crate) enum MetadataPosition { First, Last, } @@ -437,7 +453,7 @@ pub enum MetadataPosition { /// * ELF - All other targets are similar to Windows in that there's a /// `SHF_EXCLUDE` flag we can set on sections in an object file to get /// automatically removed from the final output. -pub fn create_wrapper_file( +pub(crate) fn create_wrapper_file( sess: &Session, section_name: String, data: &[u8], @@ -653,17 +669,13 @@ pub fn create_metadata_file_for_wasm(sess: &Session, data: &[u8], section_name: let mut imports = wasm_encoder::ImportSection::new(); if sess.target.pointer_width == 64 { - imports.import( - "env", - "__linear_memory", - wasm_encoder::MemoryType { - minimum: 0, - maximum: None, - memory64: true, - shared: false, - page_size_log2: None, - }, - ); + imports.import("env", "__linear_memory", wasm_encoder::MemoryType { + minimum: 0, + maximum: None, + memory64: true, + shared: false, + page_size_log2: None, + }); } if imports.len() > 0 { diff --git a/compiler/rustc_codegen_ssa/src/back/mod.rs b/compiler/rustc_codegen_ssa/src/back/mod.rs index d11ed54eb20..2b3a2e3a369 100644 --- a/compiler/rustc_codegen_ssa/src/back/mod.rs +++ b/compiler/rustc_codegen_ssa/src/back/mod.rs @@ -1,9 +1,9 @@ pub mod archive; -pub mod command; +pub(crate) mod command; pub mod link; -pub mod linker; +pub(crate) mod linker; pub mod lto; pub mod metadata; -pub mod rpath; +pub(crate) mod rpath; pub mod symbol_export; pub mod write; diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index 42f8c3114ff..56a808df6b0 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -6,14 +6,14 @@ use rustc_data_structures::fx::FxHashSet; use rustc_fs_util::try_canonicalize; use tracing::debug; -pub struct RPathConfig<'a> { +pub(super) struct RPathConfig<'a> { pub libs: &'a [&'a Path], pub out_filename: PathBuf, pub is_like_osx: bool, pub linker_is_gnu: bool, } -pub fn get_rpath_flags(config: &RPathConfig<'_>) -> Vec<OsString> { +pub(super) fn get_rpath_flags(config: &RPathConfig<'_>) -> Vec<OsString> { debug!("preparing the RPATH!"); let rpaths = get_rpaths(config); diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index 0de0b8a52b1..39034842d10 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -1,7 +1,7 @@ use std::ffi::OsString; use std::path::{Path, PathBuf}; -use super::{get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags, RPathConfig}; +use super::{RPathConfig, get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags}; #[test] fn test_rpaths_to_flags() { @@ -74,13 +74,10 @@ fn test_rpath_relative_issue_119571() { fn test_xlinker() { let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]); - assert_eq!( - args, - vec![ - OsString::from("-Wl,-rpath,a/normal/path"), - OsString::from("-Wl,-rpath"), - OsString::from("-Xlinker"), - OsString::from("a,comma,path") - ] - ); + assert_eq!(args, vec![ + OsString::from("-Wl,-rpath,a/normal/path"), + OsString::from("-Wl,-rpath"), + OsString::from("-Xlinker"), + OsString::from("a,comma,path") + ]); } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d2f11d48140..77c35a1fe79 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -3,11 +3,11 @@ use std::collections::hash_map::Entry::*; use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{ - metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, + ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, metadata_symbol_name, }; use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, TyCtxt}; @@ -18,7 +18,7 @@ use tracing::debug; use crate::base::allocator_kind_for_codegen; -pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { +fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(tcx.crate_types()) } @@ -140,14 +140,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S .into(); if let Some(id) = tcx.proc_macro_decls_static(()) { - reachable_non_generics.insert( - id.to_def_id(), - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Data, - used: false, - }, - ); + reachable_non_generics.insert(id.to_def_id(), SymbolExportInfo { + level: SymbolExportLevel::C, + kind: SymbolExportKind::Data, + used: false, + }); } reachable_non_generics @@ -188,14 +185,11 @@ fn exported_symbols_provider_local( if !tcx.sess.target.dll_tls_export { symbols.extend(sorted.iter().filter_map(|(&def_id, &info)| { tcx.needs_thread_local_shim(def_id).then(|| { - ( - ExportedSymbol::ThreadLocalShim(def_id), - SymbolExportInfo { - level: info.level, - kind: SymbolExportKind::Text, - used: info.used, - }, - ) + (ExportedSymbol::ThreadLocalShim(def_id), SymbolExportInfo { + level: info.level, + kind: SymbolExportKind::Text, + used: info.used, + }) }) })) } @@ -204,14 +198,11 @@ fn exported_symbols_provider_local( let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, tcx.sess.target.entry_name.as_ref())); - symbols.push(( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Text, - used: false, - }, - )); + symbols.push((exported_symbol, SymbolExportInfo { + level: SymbolExportLevel::C, + kind: SymbolExportKind::Text, + used: false, + })); } // Mark allocator shim symbols as exported only if they were generated. @@ -223,26 +214,20 @@ fn exported_symbols_provider_local( { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); - symbols.push(( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::Rust, - kind: SymbolExportKind::Text, - used: false, - }, - )); + symbols.push((exported_symbol, SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Text, + used: false, + })); } let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)); - symbols.push(( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::Rust, - kind: SymbolExportKind::Data, - used: false, - }, - )) + symbols.push((exported_symbol, SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Data, + used: false, + })) } if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { @@ -254,14 +239,11 @@ fn exported_symbols_provider_local( symbols.extend(PROFILER_WEAK_SYMBOLS.iter().map(|sym| { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym)); - ( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Data, - used: false, - }, - ) + (exported_symbol, SymbolExportInfo { + level: SymbolExportLevel::C, + kind: SymbolExportKind::Data, + used: false, + }) })); } @@ -279,14 +261,11 @@ fn exported_symbols_provider_local( symbols.extend(msan_weak_symbols.into_iter().map(|sym| { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym)); - ( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Data, - used: false, - }, - ) + (exported_symbol, SymbolExportInfo { + level: SymbolExportLevel::C, + kind: SymbolExportKind::Data, + used: false, + }) })); } @@ -296,14 +275,11 @@ fn exported_symbols_provider_local( let symbol_name = metadata_symbol_name(tcx); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); - symbols.push(( - exported_symbol, - SymbolExportInfo { - level: SymbolExportLevel::C, - kind: SymbolExportKind::Data, - used: true, - }, - )); + symbols.push((exported_symbol, SymbolExportInfo { + level: SymbolExportLevel::C, + kind: SymbolExportKind::Data, + used: true, + })); } if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() { @@ -338,14 +314,11 @@ fn exported_symbols_provider_local( MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => { if args.non_erasable_generics(tcx, def).next().is_some() { let symbol = ExportedSymbol::Generic(def, args); - symbols.push(( - symbol, - SymbolExportInfo { - level: SymbolExportLevel::Rust, - kind: SymbolExportKind::Text, - used: false, - }, - )); + symbols.push((symbol, SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Text, + used: false, + })); } } MonoItem::Fn(Instance { def: InstanceKind::DropGlue(def_id, Some(ty)), args }) => { @@ -354,14 +327,11 @@ fn exported_symbols_provider_local( args.non_erasable_generics(tcx, def_id).next(), Some(GenericArgKind::Type(ty)) ); - symbols.push(( - ExportedSymbol::DropGlue(ty), - SymbolExportInfo { - level: SymbolExportLevel::Rust, - kind: SymbolExportKind::Text, - used: false, - }, - )); + symbols.push((ExportedSymbol::DropGlue(ty), SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Text, + used: false, + })); } MonoItem::Fn(Instance { def: InstanceKind::AsyncDropGlueCtorShim(def_id, Some(ty)), @@ -372,14 +342,11 @@ fn exported_symbols_provider_local( args.non_erasable_generics(tcx, def_id).next(), Some(GenericArgKind::Type(ty)) ); - symbols.push(( - ExportedSymbol::AsyncDropGlueCtorShim(ty), - SymbolExportInfo { - level: SymbolExportLevel::Rust, - kind: SymbolExportKind::Text, - used: false, - }, - )); + symbols.push((ExportedSymbol::AsyncDropGlueCtorShim(ty), SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Text, + used: false, + })); } _ => { // Any other symbols don't qualify for sharing @@ -484,7 +451,7 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) !tcx.reachable_set(()).contains(&def_id) } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.reachable_non_generics = reachable_non_generics_provider; providers.is_reachable_non_generic = is_reachable_non_generic_provider_local; providers.exported_symbols = exported_symbols_provider_local; @@ -525,7 +492,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel } /// This is the symbol name of the given instance instantiated in a specific crate. -pub fn symbol_name_for_instance_in_crate<'tcx>( +pub(crate) fn symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, @@ -582,7 +549,7 @@ pub fn symbol_name_for_instance_in_crate<'tcx>( /// This is the symbol name of the given instance as seen by the linker. /// /// On 32-bit Windows symbols are decorated according to their calling conventions. -pub fn linking_symbol_name_for_instance_in_crate<'tcx>( +pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, @@ -661,7 +628,7 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( format!("{prefix}{undecorated}{suffix}{args_in_bytes}") } -pub fn exporting_symbol_name_for_instance_in_crate<'tcx>( +pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, cnum: CrateNum, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7ad31802454..4d81ff933dd 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2,8 +2,8 @@ use std::any::Any; use std::assert_matches::assert_matches; use std::marker::PhantomData; use std::path::{Path, PathBuf}; -use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::Arc; +use std::sync::mpsc::{Receiver, Sender, channel}; use std::{fs, io, mem, str, thread}; use jobserver::{Acquired, Client}; @@ -16,23 +16,23 @@ use rustc_errors::emitter::Emitter; use rustc_errors::translation::Translate; use rustc_errors::{ Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FluentBundle, Level, MultiSpan, - Style, + Style, Suggestions, }; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; -use rustc_metadata::fs::copy_to_stdout; use rustc_metadata::EncodedMetadata; +use rustc_metadata::fs::copy_to_stdout; use rustc_middle::bug; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::exported_symbols::SymbolExportInfo; use rustc_middle::ty::TyCtxt; +use rustc_session::Session; use rustc_session::config::{ self, CrateType, Lto, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath, }; -use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; @@ -45,8 +45,8 @@ use super::symbol_export::symbol_name_for_instance_in_crate; use crate::errors::ErrorCreatingRemarkDir; use crate::traits::*; use crate::{ - errors, CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, - ModuleKind, + CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, + errors, }; const PRE_LTO_BC_EXT: &str = "pre-lto.bc"; @@ -112,6 +112,7 @@ pub struct ModuleConfig { // Miscellaneous flags. These are mostly copied from command-line // options. pub verify_llvm_ir: bool, + pub lint_llvm_ir: bool, pub no_prepopulate_passes: bool, pub no_builtins: bool, pub time_module: bool, @@ -237,6 +238,7 @@ impl ModuleConfig { bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(), verify_llvm_ir: sess.verify_llvm_ir(), + lint_llvm_ir: sess.opts.unstable_opts.lint_llvm_ir, no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes, no_builtins: no_builtins || sess.target.no_builtins, @@ -333,7 +335,7 @@ pub type TargetMachineFactoryFn<B> = Arc< + Sync, >; -pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportInfo)>>>; +type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportInfo)>>>; /// Additional resources used by optimize_and_codegen (not module specific) #[derive(Clone)] @@ -435,9 +437,9 @@ fn generate_lto_work<B: ExtraBackendMethods>( } } -pub struct CompiledModules { - pub modules: Vec<CompiledModule>, - pub allocator_module: Option<CompiledModule>, +struct CompiledModules { + modules: Vec<CompiledModule>, + allocator_module: Option<CompiledModule>, } fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool { @@ -460,7 +462,7 @@ fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool { } } -pub fn start_async_codegen<B: ExtraBackendMethods>( +pub(crate) fn start_async_codegen<B: ExtraBackendMethods>( backend: B, tcx: TyCtxt<'_>, target_cpu: String, @@ -834,13 +836,13 @@ pub enum FatLtoInput<B: WriteBackendMethods> { } /// Actual LTO type we end up choosing based on multiple factors. -pub enum ComputedLtoType { +pub(crate) enum ComputedLtoType { No, Thin, Fat, } -pub fn compute_per_cgu_lto_type( +pub(crate) fn compute_per_cgu_lto_type( sess_lto: &Lto, opts: &config::Options, sess_crate_types: &[CrateType], @@ -1085,7 +1087,7 @@ struct Diagnostic { // A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's // missing the following fields from `rustc_errors::Subdiag`. // - `span`: it doesn't impl `Send`. -pub struct Subdiagnostic { +pub(crate) struct Subdiagnostic { level: Level, messages: Vec<(DiagMessage, Style)>, } @@ -1777,7 +1779,7 @@ fn start_executing_work<B: ExtraBackendMethods>( /// `FatalError` is explicitly not `Send`. #[must_use] -pub struct WorkerFatalError; +pub(crate) struct WorkerFatalError; fn spawn_work<'a, B: ExtraBackendMethods>( cgcx: &'a CodegenContext<B>, @@ -1865,7 +1867,7 @@ pub struct SharedEmitterMain { } impl SharedEmitter { - pub fn new() -> (SharedEmitter, SharedEmitterMain) { + fn new() -> (SharedEmitter, SharedEmitterMain) { let (sender, receiver) = channel(); (SharedEmitter { sender }, SharedEmitterMain { receiver }) @@ -1881,7 +1883,7 @@ impl SharedEmitter { drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source))); } - pub fn fatal(&self, msg: &str) { + fn fatal(&self, msg: &str) { drop(self.sender.send(SharedEmitterMessage::Fatal(msg.to_string()))); } } @@ -1901,7 +1903,7 @@ impl Emitter for SharedEmitter { // Check that we aren't missing anything interesting when converting to // the cut-down local `DiagInner`. assert_eq!(diag.span, MultiSpan::new()); - assert_eq!(diag.suggestions, Ok(vec![])); + assert_eq!(diag.suggestions, Suggestions::Enabled(vec![])); assert_eq!(diag.sort_span, rustc_span::DUMMY_SP); assert_eq!(diag.is_lint, None); // No sensible check for `diag.emitted_at`. @@ -1928,7 +1930,7 @@ impl Emitter for SharedEmitter { } impl SharedEmitterMain { - pub fn check(&self, sess: &Session, blocking: bool) { + fn check(&self, sess: &Session, blocking: bool) { loop { let message = if blocking { match self.receiver.recv() { @@ -2085,17 +2087,17 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> { ) } - pub fn codegen_finished(&self, tcx: TyCtxt<'_>) { + pub(crate) fn codegen_finished(&self, tcx: TyCtxt<'_>) { self.wait_for_signal_to_codegen_item(); self.check_for_errors(tcx.sess); drop(self.coordinator.sender.send(Box::new(Message::CodegenComplete::<B>))); } - pub fn check_for_errors(&self, sess: &Session) { + pub(crate) fn check_for_errors(&self, sess: &Session) { self.shared_emitter_main.check(sess, false); } - pub fn wait_for_signal_to_codegen_item(&self) { + pub(crate) fn wait_for_signal_to_codegen_item(&self) { match self.codegen_worker_receive.recv() { Ok(CguMessage) => { // Ok to proceed. @@ -2108,7 +2110,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> { } } -pub fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>( +pub(crate) fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>( _backend: &B, tx_to_llvm_workers: &Sender<Box<dyn Any + Send>>, module: ModuleCodegen<B::Module>, @@ -2118,7 +2120,7 @@ pub fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>( drop(tx_to_llvm_workers.send(Box::new(Message::CodegenDone::<B> { llvm_work_item, cost }))); } -pub fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>( +pub(crate) fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>( _backend: &B, tx_to_llvm_workers: &Sender<Box<dyn Any + Send>>, module: CachedModuleCodegen, @@ -2127,7 +2129,7 @@ pub fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>( drop(tx_to_llvm_workers.send(Box::new(Message::CodegenDone::<B> { llvm_work_item, cost: 0 }))); } -pub fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>( +pub(crate) fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>( _backend: &B, tcx: TyCtxt<'_>, tx_to_llvm_workers: &Sender<Box<dyn Any + Send>>, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f1e7f87f567..8e4385bee1a 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -3,7 +3,7 @@ use std::collections::BTreeSet; use std::time::{Duration, Instant}; use itertools::Itertools; -use rustc_ast::expand::allocator::{global_fn_name, AllocatorKind, ALLOCATOR_METHODS}; +use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; @@ -17,15 +17,15 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::middle::{exported_symbols, lang_items}; -use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::mir::BinOp; +use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; -use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_session::Session; +use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_span::symbol::sym; -use rustc_span::{Symbol, DUMMY_SP}; +use rustc_span::{DUMMY_SP, Symbol}; use rustc_target::abi::FIRST_VARIANT; use tracing::{debug, info}; @@ -33,58 +33,34 @@ use crate::assert_module_sources::CguReuse; use crate::back::link::are_upstream_rust_objects_already_included; use crate::back::metadata::create_compressed_metadata_file; use crate::back::write::{ - compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm, - submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, + ComputedLtoType, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen, + submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, }; use crate::common::{self, IntPredicate, RealPredicate, TypeKind}; use crate::mir::operand::OperandValue; use crate::mir::place::PlaceRef; use crate::traits::*; use crate::{ - errors, meth, mir, CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, + CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir, }; -pub fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate { - match op { - BinOp::Eq => IntPredicate::IntEQ, - BinOp::Ne => IntPredicate::IntNE, - BinOp::Lt => { - if signed { - IntPredicate::IntSLT - } else { - IntPredicate::IntULT - } - } - BinOp::Le => { - if signed { - IntPredicate::IntSLE - } else { - IntPredicate::IntULE - } - } - BinOp::Gt => { - if signed { - IntPredicate::IntSGT - } else { - IntPredicate::IntUGT - } - } - BinOp::Ge => { - if signed { - IntPredicate::IntSGE - } else { - IntPredicate::IntUGE - } - } - op => bug!( - "comparison_op_to_icmp_predicate: expected comparison operator, \ - found {:?}", - op - ), +pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate { + match (op, signed) { + (BinOp::Eq, _) => IntPredicate::IntEQ, + (BinOp::Ne, _) => IntPredicate::IntNE, + (BinOp::Lt, true) => IntPredicate::IntSLT, + (BinOp::Lt, false) => IntPredicate::IntULT, + (BinOp::Le, true) => IntPredicate::IntSLE, + (BinOp::Le, false) => IntPredicate::IntULE, + (BinOp::Gt, true) => IntPredicate::IntSGT, + (BinOp::Gt, false) => IntPredicate::IntUGT, + (BinOp::Ge, true) => IntPredicate::IntSGE, + (BinOp::Ge, false) => IntPredicate::IntUGE, + op => bug!("bin_op_to_icmp_predicate: expected comparison operator, found {:?}", op), } } -pub fn bin_op_to_fcmp_predicate(op: BinOp) -> RealPredicate { +pub(crate) fn bin_op_to_fcmp_predicate(op: BinOp) -> RealPredicate { match op { BinOp::Eq => RealPredicate::RealOEQ, BinOp::Ne => RealPredicate::RealUNE, @@ -92,13 +68,7 @@ pub fn bin_op_to_fcmp_predicate(op: BinOp) -> RealPredicate { BinOp::Le => RealPredicate::RealOLE, BinOp::Gt => RealPredicate::RealOGT, BinOp::Ge => RealPredicate::RealOGE, - op => { - bug!( - "comparison_op_to_fcmp_predicate: expected comparison operator, \ - found {:?}", - op - ); - } + op => bug!("bin_op_to_fcmp_predicate: expected comparison operator, found {:?}", op), } } @@ -135,7 +105,7 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// /// The `old_info` argument is a bit odd. It is intended for use in an upcast, /// where the new vtable for an object will be derived from the old one. -pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, source: Ty<'tcx>, target: Ty<'tcx>, @@ -145,16 +115,17 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let (source, target) = cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env()); match (source.kind(), target.kind()) { - (&ty::Array(_, len), &ty::Slice(_)) => { - cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all())) - } + (&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize( + len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"), + ), (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind)) if src_dyn_kind == target_dyn_kind => { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { - // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. + // A NOP cast that doesn't actually change anything, should be allowed even with + // invalid vtables. return old_info; } @@ -182,7 +153,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } /// Coerces `src` to `dst_ty`. `src_ty` must be a pointer. -pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, src: Bx::Value, src_ty: Ty<'tcx>, @@ -227,7 +198,7 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } /// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type. -pub fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, src: Bx::Value, src_ty_and_layout: TyAndLayout<'tcx>, @@ -250,7 +221,7 @@ pub fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// Coerces `src`, which is a reference to a value of type `src_ty`, /// to a value of type `dst_ty`, and stores the result in `dst`. -pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, src: PlaceRef<'tcx, Bx::Value>, dst: PlaceRef<'tcx, Bx::Value>, @@ -305,7 +276,7 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// /// If `is_unchecked` is true, this does no masking, and adds sufficient `assume` /// calls or operation flags to preserve as much freedom to optimize as possible. -pub fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, lhs: Bx::Value, mut rhs: Bx::Value, @@ -369,11 +340,11 @@ pub fn wants_msvc_seh(sess: &Session) -> bool { /// Returns `true` if this session's target requires the new exception /// handling LLVM IR instructions (catchpad / cleanuppad / ... instead /// of landingpad) -pub fn wants_new_eh_instructions(sess: &Session) -> bool { +pub(crate) fn wants_new_eh_instructions(sess: &Session) -> bool { wants_wasm_eh(sess) || wants_msvc_seh(sess) } -pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, ) { @@ -454,7 +425,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let isize_ty = cx.type_isize(); let ptr_ty = cx.type_ptr(); - let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx); + let (arg_argc, arg_argv) = get_argc_argv(&mut bx); let (start_fn, start_ty, args, instance) = if let EntryFnType::Main { sigpipe } = entry_type { @@ -497,33 +468,30 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } /// Obtain the `argc` and `argv` values to pass to the rust start function. -fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - cx: &'a Bx::CodegenCx, - bx: &mut Bx, -) -> (Bx::Value, Bx::Value) { - if cx.sess().target.os.contains("uefi") { +fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Value, Bx::Value) { + if bx.cx().sess().target.os.contains("uefi") { // Params for UEFI let param_handle = bx.get_param(0); let param_system_table = bx.get_param(1); let ptr_size = bx.tcx().data_layout.pointer_size; let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let arg_argc = bx.const_int(cx.type_isize(), 2); + let arg_argc = bx.const_int(bx.cx().type_isize(), 2); let arg_argv = bx.alloca(2 * ptr_size, ptr_align); bx.store(param_handle, arg_argv, ptr_align); let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes())); bx.store(param_system_table, arg_argv_el1, ptr_align); (arg_argc, arg_argv) - } else if cx.sess().target.main_needs_argc_argv { + } else if bx.cx().sess().target.main_needs_argc_argv { // Params from native `main()` used as args for rust start function let param_argc = bx.get_param(0); let param_argv = bx.get_param(1); - let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); + let arg_argc = bx.intcast(param_argc, bx.cx().type_isize(), true); let arg_argv = param_argv; (arg_argc, arg_argv) } else { // The Rust start function doesn't need `argc` and `argv`, so just pass zeros. - let arg_argc = bx.const_int(cx.type_int(), 0); - let arg_argv = bx.const_null(cx.type_ptr()); + let arg_argc = bx.const_int(bx.cx().type_int(), 0); + let arg_argv = bx.const_null(bx.cx().type_ptr()); (arg_argc, arg_argv) } } @@ -985,7 +953,8 @@ impl CrateInfo { false } CrateType::Staticlib | CrateType::Rlib => { - // We don't invoke the linker for these, so we don't need to collect the NatVis for them. + // We don't invoke the linker for these, so we don't need to collect the NatVis for + // them. false } }); @@ -999,7 +968,7 @@ impl CrateInfo { } } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.backend_optimization_level = |tcx, cratenum| { let for_speed = match tcx.sess.opts.optimize { // If globally no optimisation is done, #[optimize] has no effect. diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 209750d6ba6..e99c3a46271 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,15 +1,14 @@ -use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; -use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; -use rustc_data_structures::fx::FxHashSet; +use rustc_ast::{MetaItemKind, NestedMetaItem, ast, attr}; +use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_name}; use rustc_errors::codes::*; -use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage}; +use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; -use rustc_hir::{lang_items, LangItem}; +use rustc_hir::{LangItem, lang_items}; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, }; use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; @@ -17,9 +16,8 @@ use rustc_middle::ty::{self as ty, TyCtxt}; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span}; -use rustc_target::abi::VariantIdx; -use rustc_target::spec::{abi, SanitizerSet}; +use rustc_span::{Span, sym}; +use rustc_target::spec::{SanitizerSet, abi}; use crate::errors; use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature}; @@ -80,13 +78,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; - let fn_sig_outer = || { - use DefKind::*; - - let def_kind = tcx.def_kind(did); - if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None } - }; - for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` // pass that check that they aren't used anywhere else, rather this module. @@ -94,12 +85,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. let fn_sig = || { - let sig = fn_sig_outer(); - if sig.is_none() { + use DefKind::*; + + let def_kind = tcx.def_kind(did); + if let Fn | AssocFn | Variant | Ctor(..) = def_kind { + Some(tcx.fn_sig(did)) + } else { tcx.dcx() .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); + None } - sig }; let Some(Ident { name, .. }) = attr.ident() else { @@ -200,24 +195,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } } - sym::cmse_nonsecure_entry => { - if let Some(fn_sig) = fn_sig() - && !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. }) - { - struct_span_code_err!( - tcx.dcx(), - attr.span, - E0776, - "`#[cmse_nonsecure_entry]` requires C ABI" - ) - .emit(); - } - if !tcx.sess.target.llvm_target.contains("thumbv8m") { - struct_span_code_err!(tcx.dcx(), attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension") - .emit(); - } - codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY - } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::track_caller => { let is_closure = tcx.is_closure_like(did.to_def_id()); @@ -322,9 +299,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { "extern mutable statics are not allowed with `#[linkage]`", ); diag.note( - "marking the extern static mutable would allow changing which symbol \ - the static references rather than make the target of the symbol \ - mutable", + "marking the extern static mutable would allow changing which \ + symbol the static references rather than make the target of the \ + symbol mutable", ); diag.emit(); } @@ -618,122 +595,33 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - if let Some(sig) = fn_sig_outer() { - // Collect target features from types reachable from arguments. - // We define a type as "reachable" if: - // - it is a function argument - // - it is a field of a reachable struct - // - there is a reachable reference to it - // FIXME(struct_target_features): we may want to cache the result of this computation. - let mut visited_types = FxHashSet::default(); - let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned(); - let mut additional_tf = vec![]; - - while let Some(ty) = reachable_types.pop() { - if visited_types.contains(&ty) { - continue; - } - visited_types.insert(ty); - match ty.kind() { - ty::Alias(..) => { - if let Ok(t) = - tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty) - { - reachable_types.push(t) - } - } - - ty::Ref(_, inner, _) => reachable_types.push(*inner), - ty::Tuple(tys) => reachable_types.extend(tys.iter()), - ty::Adt(adt_def, args) => { - additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did())); - // This only recurses into structs as i.e. an Option<TargetFeature> is an ADT - // that doesn't actually always contain a TargetFeature. - if adt_def.is_struct() { - reachable_types.extend( - adt_def - .variant(VariantIdx::from_usize(0)) - .fields - .iter() - .map(|field| field.ty(tcx, args)), - ); - } - } - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Foreign(..) - | ty::Str - | ty::Array(..) - | ty::Pat(..) - | ty::Slice(..) - | ty::RawPtr(..) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::Dynamic(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Param(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Infer(..) - | ty::Error(..) => (), - } - } - - // FIXME(struct_target_features): is this really necessary? - if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust { - tcx.dcx().span_err( - tcx.hir().span(tcx.local_def_id_to_hir_id(did)), - "cannot use a struct with target features in a function with non-Rust ABI", - ); - } - if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { - tcx.dcx().span_err( - tcx.hir().span(tcx.local_def_id_to_hir_id(did)), - "cannot use a struct with target features in a #[inline(always)] function", - ); - } - codegen_fn_attrs - .target_features - .extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf })); - } - - // If a function uses non-default target_features it can't be inlined into general + // If a function uses #[target_feature] it can't be inlined into general // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. - if !codegen_fn_attrs.target_features.is_empty() { - if codegen_fn_attrs.inline == InlineAttr::Always { - if let Some(span) = inline_span { - tcx.dcx().span_err( - span, - "cannot use `#[inline(always)]` with \ + if !codegen_fn_attrs.target_features.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always + { + if let Some(span) = inline_span { + tcx.dcx().span_err( + span, + "cannot use `#[inline(always)]` with \ `#[target_feature]`", - ); - } + ); } } - if !codegen_fn_attrs.no_sanitize.is_empty() { - if codegen_fn_attrs.inline == InlineAttr::Always { - if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { - let hir_id = tcx.local_def_id_to_hir_id(did); - tcx.node_span_lint( - lint::builtin::INLINE_NO_SANITIZE, - hir_id, - no_sanitize_span, - |lint| { - lint.primary_message("`no_sanitize` will have no effect after inlining"); - lint.span_note(inline_span, "inlining requested here"); - }, - ) - } + if !codegen_fn_attrs.no_sanitize.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { + if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { + let hir_id = tcx.local_def_id_to_hir_id(did); + tcx.node_span_lint( + lint::builtin::INLINE_NO_SANITIZE, + hir_id, + no_sanitize_span, + |lint| { + lint.primary_message("`no_sanitize` will have no effect after inlining"); + lint.span_note(inline_span, "inlining requested here"); + }, + ) } } @@ -805,18 +693,19 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> { if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { - // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, - // the ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined - // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information - // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t. + // According to the table at + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, the + // ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined + // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import + // information to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t. // - // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for this: - // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies - // a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import library - // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import - // library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I don't know yet - // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment - // about LINK.EXE failing.) + // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for + // this: both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that + // specifies a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import + // library for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an + // import library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I + // don't know yet if the resulting EXE runs, as I haven't yet built the necessary DLL -- + // see earlier comment about LINK.EXE failing.) if *ordinal <= u16::MAX as u128 { Some(ordinal.get() as u16) } else { @@ -849,20 +738,6 @@ fn check_link_name_xor_ordinal( } } -fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] { - let mut features = vec![]; - let supported_features = tcx.supported_target_features(LOCAL_CRATE); - for attr in tcx.get_attrs(def_id, sym::target_feature) { - from_target_feature(tcx, attr, supported_features, &mut features); - } - tcx.arena.alloc_slice(&features) -} - -pub fn provide(providers: &mut Providers) { - *providers = Providers { - codegen_fn_attrs, - should_inherit_track_caller, - struct_target_features, - ..*providers - }; +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; } diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index bfb1d217eae..582a2a87e48 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -118,7 +118,7 @@ mod temp_stable_hash_impls { } } -pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &Bx, span: Option<Span>, li: LangItem, @@ -129,7 +129,7 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance), instance) } -pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, llty: Bx::Type, mask_llty: Bx::Type, @@ -200,7 +200,8 @@ pub fn i686_decorated_name( let mut decorated_name = String::with_capacity(name.len() + 6); if disable_name_mangling { - // LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled. + // LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be + // disabled. decorated_name.push('\x01'); } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs index 0918660e6be..bfd1b94c790 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs @@ -54,7 +54,7 @@ pub fn tag_base_type<'tcx>(tcx: TyCtxt<'tcx>, enum_type_and_layout: TyAndLayout< }) } -pub fn tag_base_type_opt<'tcx>( +fn tag_base_type_opt<'tcx>( tcx: TyCtxt<'tcx>, enum_type_and_layout: TyAndLayout<'tcx>, ) -> Option<Ty<'tcx>> { @@ -76,9 +76,9 @@ pub fn tag_base_type_opt<'tcx>( Primitive::Float(f) => Integer::from_size(f.size()).unwrap(), // FIXME(erikdesjardins): handle non-default addrspace ptr sizes Primitive::Pointer(_) => { - // If the niche is the NULL value of a reference, then `discr_enum_ty` will be - // a RawPtr. CodeView doesn't know what to do with enums whose base type is a - // pointer so we fix this up to just be `usize`. + // If the niche is the NULL value of a reference, then `discr_enum_ty` will + // be a RawPtr. CodeView doesn't know what to do with enums whose base type + // is a pointer so we fix this up to just be `usize`. // DWARF might be able to deal with this but with an integer type we are on // the safe side there too. tcx.data_layout.ptr_sized_integer() diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index f0bc4354f9a..369ab387bea 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -95,7 +95,8 @@ fn push_debuginfo_type_name<'tcx>( } Err(e) => { // Computing the layout can still fail here, e.g. if the target architecture - // cannot represent the type. See https://github.com/rust-lang/rust/issues/94961. + // cannot represent the type. See + // https://github.com/rust-lang/rust/issues/94961. tcx.dcx().emit_fatal(e.into_diagnostic()); } } @@ -187,7 +188,8 @@ fn push_debuginfo_type_name<'tcx>( _ => write!( output, ",{}>", - len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()) + len.try_to_target_usize(tcx) + .expect("expected monomorphic const in codegen") ) .unwrap(), } @@ -199,7 +201,8 @@ fn push_debuginfo_type_name<'tcx>( _ => write!( output, "; {}]", - len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()) + len.try_to_target_usize(tcx) + .expect("expected monomorphic const in codegen") ) .unwrap(), } @@ -236,15 +239,13 @@ fn push_debuginfo_type_name<'tcx>( let has_enclosing_parens = if cpp_like_debuginfo { output.push_str("dyn$<"); false + } else if trait_data.len() > 1 && auto_traits.len() != 0 { + // We need enclosing parens because there is more than one trait + output.push_str("(dyn "); + true } else { - if trait_data.len() > 1 && auto_traits.len() != 0 { - // We need enclosing parens because there is more than one trait - output.push_str("(dyn "); - true - } else { - output.push_str("dyn "); - false - } + output.push_str("dyn "); + false }; if let Some(principal) = trait_data.principal() { @@ -577,33 +578,20 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: & } fn coroutine_kind_label(coroutine_kind: Option<CoroutineKind>) -> &'static str { + use CoroutineDesugaring::*; + use CoroutineKind::*; + use CoroutineSource::*; match coroutine_kind { - Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Block)) => { - "gen_block" - } - Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Closure)) => { - "gen_closure" - } - Some(CoroutineKind::Desugared(CoroutineDesugaring::Gen, CoroutineSource::Fn)) => "gen_fn", - Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Block)) => { - "async_block" - } - Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)) => { - "async_closure" - } - Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn)) => { - "async_fn" - } - Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Block)) => { - "async_gen_block" - } - Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Closure)) => { - "async_gen_closure" - } - Some(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, CoroutineSource::Fn)) => { - "async_gen_fn" - } - Some(CoroutineKind::Coroutine(_)) => "coroutine", + Some(Desugared(Gen, Block)) => "gen_block", + Some(Desugared(Gen, Closure)) => "gen_closure", + Some(Desugared(Gen, Fn)) => "gen_fn", + Some(Desugared(Async, Block)) => "async_block", + Some(Desugared(Async, Closure)) => "async_closure", + Some(Desugared(Async, Fn)) => "async_fn", + Some(Desugared(AsyncGen, Block)) => "async_gen_block", + Some(Desugared(AsyncGen, Closure)) => "async_gen_closure", + Some(Desugared(AsyncGen, Fn)) => "async_gen_fn", + Some(Coroutine(_)) => "coroutine", None => "closure", } } @@ -701,7 +689,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S match ty.kind() { ty::Int(ity) => { // FIXME: directly extract the bits from a valtree instead of evaluating an - // alreay evaluated `Const` in order to get the bits. + // already evaluated `Const` in order to get the bits. let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; write!(output, "{val}") diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 573a8cf7cbe..08b326e3ac3 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -10,8 +10,8 @@ use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, }; use rustc_macros::Diagnostic; -use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::Ty; +use rustc_middle::ty::layout::LayoutError; use rustc_span::{Span, Symbol}; use rustc_type_ir::FloatTy; @@ -21,7 +21,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(codegen_ssa_incorrect_cgu_reuse_type)] -pub struct IncorrectCguReuseType<'a> { +pub(crate) struct IncorrectCguReuseType<'a> { #[primary_span] pub span: Span, pub cgu_user_name: &'a str, @@ -32,14 +32,14 @@ pub struct IncorrectCguReuseType<'a> { #[derive(Diagnostic)] #[diag(codegen_ssa_cgu_not_recorded)] -pub struct CguNotRecorded<'a> { +pub(crate) struct CguNotRecorded<'a> { pub cgu_user_name: &'a str, pub cgu_name: &'a str, } #[derive(Diagnostic)] #[diag(codegen_ssa_unknown_reuse_kind)] -pub struct UnknownReuseKind { +pub(crate) struct UnknownReuseKind { #[primary_span] pub span: Span, pub kind: Symbol, @@ -47,14 +47,14 @@ pub struct UnknownReuseKind { #[derive(Diagnostic)] #[diag(codegen_ssa_missing_query_depgraph)] -pub struct MissingQueryDepGraph { +pub(crate) struct MissingQueryDepGraph { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(codegen_ssa_malformed_cgu_name)] -pub struct MalformedCguName { +pub(crate) struct MalformedCguName { #[primary_span] pub span: Span, pub user_path: String, @@ -63,7 +63,7 @@ pub struct MalformedCguName { #[derive(Diagnostic)] #[diag(codegen_ssa_no_module_named)] -pub struct NoModuleNamed<'a> { +pub(crate) struct NoModuleNamed<'a> { #[primary_span] pub span: Span, pub user_path: &'a str, @@ -73,7 +73,7 @@ pub struct NoModuleNamed<'a> { #[derive(Diagnostic)] #[diag(codegen_ssa_field_associated_value_expected)] -pub struct FieldAssociatedValueExpected { +pub(crate) struct FieldAssociatedValueExpected { #[primary_span] pub span: Span, pub name: Symbol, @@ -81,7 +81,7 @@ pub struct FieldAssociatedValueExpected { #[derive(Diagnostic)] #[diag(codegen_ssa_no_field)] -pub struct NoField { +pub(crate) struct NoField { #[primary_span] pub span: Span, pub name: Symbol, @@ -89,49 +89,49 @@ pub struct NoField { #[derive(Diagnostic)] #[diag(codegen_ssa_lib_def_write_failure)] -pub struct LibDefWriteFailure { +pub(crate) struct LibDefWriteFailure { pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_version_script_write_failure)] -pub struct VersionScriptWriteFailure { +pub(crate) struct VersionScriptWriteFailure { pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_symbol_file_write_failure)] -pub struct SymbolFileWriteFailure { +pub(crate) struct SymbolFileWriteFailure { pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_ld64_unimplemented_modifier)] -pub struct Ld64UnimplementedModifier; +pub(crate) struct Ld64UnimplementedModifier; #[derive(Diagnostic)] #[diag(codegen_ssa_linker_unsupported_modifier)] -pub struct LinkerUnsupportedModifier; +pub(crate) struct LinkerUnsupportedModifier; #[derive(Diagnostic)] #[diag(codegen_ssa_L4Bender_exporting_symbols_unimplemented)] -pub struct L4BenderExportingSymbolsUnimplemented; +pub(crate) struct L4BenderExportingSymbolsUnimplemented; #[derive(Diagnostic)] #[diag(codegen_ssa_no_natvis_directory)] -pub struct NoNatvisDirectory { +pub(crate) struct NoNatvisDirectory { pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_no_saved_object_file)] -pub struct NoSavedObjectFile<'a> { +pub(crate) struct NoSavedObjectFile<'a> { pub cgu_name: &'a str, } #[derive(Diagnostic)] #[diag(codegen_ssa_copy_path_buf)] -pub struct CopyPathBuf { +pub(crate) struct CopyPathBuf { pub source_file: PathBuf, pub output_path: PathBuf, pub error: Error, @@ -180,20 +180,20 @@ pub struct IgnoringOutput { #[derive(Diagnostic)] #[diag(codegen_ssa_create_temp_dir)] -pub struct CreateTempDir { +pub(crate) struct CreateTempDir { pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_add_native_library)] -pub struct AddNativeLibrary { +pub(crate) struct AddNativeLibrary { pub library_path: PathBuf, pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_multiple_external_func_decl)] -pub struct MultipleExternalFuncDecl<'a> { +pub(crate) struct MultipleExternalFuncDecl<'a> { #[primary_span] pub span: Span, pub function: Symbol, @@ -215,7 +215,7 @@ pub enum LinkRlibError { IncompatibleDependencyFormats { ty1: String, ty2: String, list1: String, list2: String }, } -pub struct ThorinErrorWrapper(pub thorin::Error); +pub(crate) struct ThorinErrorWrapper(pub thorin::Error); impl<G: EmissionGuarantee> Diagnostic<'_, G> for ThorinErrorWrapper { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { @@ -343,7 +343,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ThorinErrorWrapper { } } -pub struct LinkingFailed<'a> { +pub(crate) struct LinkingFailed<'a> { pub linker_path: &'a PathBuf, pub exit_status: ExitStatus, pub command: &'a Command, @@ -376,28 +376,28 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { #[derive(Diagnostic)] #[diag(codegen_ssa_link_exe_unexpected_error)] -pub struct LinkExeUnexpectedError; +pub(crate) struct LinkExeUnexpectedError; #[derive(Diagnostic)] #[diag(codegen_ssa_repair_vs_build_tools)] -pub struct RepairVSBuildTools; +pub(crate) struct RepairVSBuildTools; #[derive(Diagnostic)] #[diag(codegen_ssa_missing_cpp_build_tool_component)] -pub struct MissingCppBuildToolComponent; +pub(crate) struct MissingCppBuildToolComponent; #[derive(Diagnostic)] #[diag(codegen_ssa_select_cpp_build_tool_workload)] -pub struct SelectCppBuildToolWorkload; +pub(crate) struct SelectCppBuildToolWorkload; #[derive(Diagnostic)] #[diag(codegen_ssa_visual_studio_not_installed)] -pub struct VisualStudioNotInstalled; +pub(crate) struct VisualStudioNotInstalled; #[derive(Diagnostic)] #[diag(codegen_ssa_linker_not_found)] #[note] -pub struct LinkerNotFound { +pub(crate) struct LinkerNotFound { pub linker_path: PathBuf, pub error: Error, } @@ -406,7 +406,7 @@ pub struct LinkerNotFound { #[diag(codegen_ssa_unable_to_exe_linker)] #[note] #[note(codegen_ssa_command_note)] -pub struct UnableToExeLinker { +pub(crate) struct UnableToExeLinker { pub linker_path: PathBuf, pub error: Error, pub command_formatted: String, @@ -414,38 +414,38 @@ pub struct UnableToExeLinker { #[derive(Diagnostic)] #[diag(codegen_ssa_msvc_missing_linker)] -pub struct MsvcMissingLinker; +pub(crate) struct MsvcMissingLinker; #[derive(Diagnostic)] #[diag(codegen_ssa_self_contained_linker_missing)] -pub struct SelfContainedLinkerMissing; +pub(crate) struct SelfContainedLinkerMissing; #[derive(Diagnostic)] #[diag(codegen_ssa_check_installed_visual_studio)] -pub struct CheckInstalledVisualStudio; +pub(crate) struct CheckInstalledVisualStudio; #[derive(Diagnostic)] #[diag(codegen_ssa_insufficient_vs_code_product)] -pub struct InsufficientVSCodeProduct; +pub(crate) struct InsufficientVSCodeProduct; #[derive(Diagnostic)] #[diag(codegen_ssa_processing_dymutil_failed)] #[note] -pub struct ProcessingDymutilFailed { +pub(crate) struct ProcessingDymutilFailed { pub status: ExitStatus, pub output: String, } #[derive(Diagnostic)] #[diag(codegen_ssa_unable_to_run_dsymutil)] -pub struct UnableToRunDsymutil { +pub(crate) struct UnableToRunDsymutil { pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_stripping_debug_info_failed)] #[note] -pub struct StrippingDebugInfoFailed<'a> { +pub(crate) struct StrippingDebugInfoFailed<'a> { pub util: &'a str, pub status: ExitStatus, pub output: String, @@ -453,58 +453,59 @@ pub struct StrippingDebugInfoFailed<'a> { #[derive(Diagnostic)] #[diag(codegen_ssa_unable_to_run)] -pub struct UnableToRun<'a> { +pub(crate) struct UnableToRun<'a> { pub util: &'a str, pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_linker_file_stem)] -pub struct LinkerFileStem; +pub(crate) struct LinkerFileStem; #[derive(Diagnostic)] #[diag(codegen_ssa_static_library_native_artifacts)] -pub struct StaticLibraryNativeArtifacts; +pub(crate) struct StaticLibraryNativeArtifacts; #[derive(Diagnostic)] #[diag(codegen_ssa_static_library_native_artifacts_to_file)] -pub struct StaticLibraryNativeArtifactsToFile<'a> { +pub(crate) struct StaticLibraryNativeArtifactsToFile<'a> { pub path: &'a Path, } #[derive(Diagnostic)] #[diag(codegen_ssa_link_script_unavailable)] -pub struct LinkScriptUnavailable; +pub(crate) struct LinkScriptUnavailable; #[derive(Diagnostic)] #[diag(codegen_ssa_link_script_write_failure)] -pub struct LinkScriptWriteFailure { +pub(crate) struct LinkScriptWriteFailure { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_failed_to_write)] -pub struct FailedToWrite { +pub(crate) struct FailedToWrite { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_unable_to_write_debugger_visualizer)] -pub struct UnableToWriteDebuggerVisualizer { +pub(crate) struct UnableToWriteDebuggerVisualizer { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_rlib_archive_build_failure)] -pub struct RlibArchiveBuildFailure { +pub(crate) struct RlibArchiveBuildFailure { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] +// Public for rustc_codegen_llvm::back::archive pub enum ExtractBundledLibsError<'a> { #[diag(codegen_ssa_extract_bundled_libs_open_file)] OpenFile { rlib: &'a Path, error: Box<dyn std::error::Error> }, @@ -533,26 +534,26 @@ pub enum ExtractBundledLibsError<'a> { #[derive(Diagnostic)] #[diag(codegen_ssa_unsupported_arch)] -pub struct UnsupportedArch<'a> { +pub(crate) struct UnsupportedArch<'a> { pub arch: &'a str, pub os: &'a str, } #[derive(Diagnostic)] -pub enum AppleSdkRootError<'a> { +pub(crate) enum AppleSdkRootError<'a> { #[diag(codegen_ssa_apple_sdk_error_sdk_path)] SdkPath { sdk_name: &'a str, error: Error }, } #[derive(Diagnostic)] #[diag(codegen_ssa_read_file)] -pub struct ReadFileError { +pub(crate) struct ReadFileError { pub message: std::io::Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_unsupported_link_self_contained)] -pub struct UnsupportedLinkSelfContained; +pub(crate) struct UnsupportedLinkSelfContained; #[derive(Diagnostic)] #[diag(codegen_ssa_archive_build_failure)] @@ -571,7 +572,7 @@ pub struct UnknownArchiveKind<'a> { #[derive(Diagnostic)] #[diag(codegen_ssa_expected_used_symbol)] -pub struct ExpectedUsedSymbol { +pub(crate) struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } @@ -579,45 +580,45 @@ pub struct ExpectedUsedSymbol { #[derive(Diagnostic)] #[diag(codegen_ssa_multiple_main_functions)] #[help] -pub struct MultipleMainFunctions { +pub(crate) struct MultipleMainFunctions { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(codegen_ssa_metadata_object_file_write)] -pub struct MetadataObjectFileWrite { +pub(crate) struct MetadataObjectFileWrite { pub error: Error, } #[derive(Diagnostic)] #[diag(codegen_ssa_invalid_windows_subsystem)] -pub struct InvalidWindowsSubsystem { +pub(crate) struct InvalidWindowsSubsystem { pub subsystem: Symbol, } #[derive(Diagnostic)] #[diag(codegen_ssa_shuffle_indices_evaluation)] -pub struct ShuffleIndicesEvaluation { +pub(crate) struct ShuffleIndicesEvaluation { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(codegen_ssa_missing_memory_ordering)] -pub struct MissingMemoryOrdering; +pub(crate) struct MissingMemoryOrdering; #[derive(Diagnostic)] #[diag(codegen_ssa_unknown_atomic_ordering)] -pub struct UnknownAtomicOrdering; +pub(crate) struct UnknownAtomicOrdering; #[derive(Diagnostic)] #[diag(codegen_ssa_atomic_compare_exchange)] -pub struct AtomicCompareExchange; +pub(crate) struct AtomicCompareExchange; #[derive(Diagnostic)] #[diag(codegen_ssa_unknown_atomic_operation)] -pub struct UnknownAtomicOperation; +pub(crate) struct UnknownAtomicOperation; #[derive(Diagnostic)] pub enum InvalidMonomorphization<'tcx> { @@ -986,7 +987,7 @@ impl IntoDiagArg for ExpectedPointerMutability { #[derive(Diagnostic)] #[diag(codegen_ssa_invalid_no_sanitize)] #[note] -pub struct InvalidNoSanitize { +pub(crate) struct InvalidNoSanitize { #[primary_span] pub span: Span, } @@ -994,7 +995,7 @@ pub struct InvalidNoSanitize { #[derive(Diagnostic)] #[diag(codegen_ssa_invalid_link_ordinal_nargs)] #[note] -pub struct InvalidLinkOrdinalNargs { +pub(crate) struct InvalidLinkOrdinalNargs { #[primary_span] pub span: Span, } @@ -1002,14 +1003,14 @@ pub struct InvalidLinkOrdinalNargs { #[derive(Diagnostic)] #[diag(codegen_ssa_illegal_link_ordinal_format)] #[note] -pub struct InvalidLinkOrdinalFormat { +pub(crate) struct InvalidLinkOrdinalFormat { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(codegen_ssa_target_feature_safe_trait)] -pub struct TargetFeatureSafeTrait { +pub(crate) struct TargetFeatureSafeTrait { #[primary_span] #[label] pub span: Span, @@ -1050,7 +1051,7 @@ pub(crate) struct ErrorCallingDllTool<'a> { #[derive(Diagnostic)] #[diag(codegen_ssa_error_creating_remark_dir)] -pub struct ErrorCreatingRemarkDir { +pub(crate) struct ErrorCreatingRemarkDir { pub error: std::io::Error, } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index c89bfca6687..ec0520fbb09 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -11,6 +11,7 @@ #![feature(negative_impls)] #![feature(rustdoc_internals)] #![feature(strict_provenance)] +#![feature(trait_alias)] #![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end @@ -36,10 +37,10 @@ use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::util::Providers; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use rustc_session::Session; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; use rustc_session::utils::NativeLibKind; -use rustc_session::Session; use rustc_span::symbol::Symbol; pub mod assert_module_sources; @@ -128,7 +129,7 @@ impl CompiledModule { } } -pub struct CachedModuleCodegen { +pub(crate) struct CachedModuleCodegen { pub name: String, pub source: WorkProduct, } diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index c9602d9cdae..ecc3b2b24f1 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -8,10 +8,10 @@ use tracing::{debug, instrument}; use crate::traits::*; #[derive(Copy, Clone, Debug)] -pub struct VirtualIndex(u64); +pub(crate) struct VirtualIndex(u64); impl<'a, 'tcx> VirtualIndex { - pub fn from_index(index: usize) -> Self { + pub(crate) fn from_index(index: usize) -> Self { VirtualIndex(index as u64) } @@ -51,7 +51,7 @@ impl<'a, 'tcx> VirtualIndex { } } - pub fn get_optional_fn<Bx: BuilderMethods<'a, 'tcx>>( + pub(crate) fn get_optional_fn<Bx: BuilderMethods<'a, 'tcx>>( self, bx: &mut Bx, llvtable: Bx::Value, @@ -61,7 +61,7 @@ impl<'a, 'tcx> VirtualIndex { self.get_fn_inner(bx, llvtable, ty, fn_abi, false) } - pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>( + pub(crate) fn get_fn<Bx: BuilderMethods<'a, 'tcx>>( self, bx: &mut Bx, llvtable: Bx::Value, @@ -71,7 +71,7 @@ impl<'a, 'tcx> VirtualIndex { self.get_fn_inner(bx, llvtable, ty, fn_abi, true) } - pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>( + pub(crate) fn get_usize<Bx: BuilderMethods<'a, 'tcx>>( self, bx: &mut Bx, llvtable: Bx::Value, @@ -115,7 +115,7 @@ fn expect_dyn_trait_in_self(ty: Ty<'_>) -> ty::PolyExistentialTraitRef<'_> { /// making an object `Foo<dyn Trait>` from a value of type `Foo<T>`, then /// `trait_ref` would map `T: Trait`. #[instrument(level = "debug", skip(cx))] -pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( +pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, ty: Ty<'tcx>, trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 386e1f91e7f..43b8230c679 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -5,7 +5,7 @@ use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::{self, traversal, DefLocation, Location, TerminatorKind}; +use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind, traversal}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::{bug, span_bug}; use tracing::debug; @@ -15,6 +15,7 @@ use crate::traits::*; pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, + traversal_order: &[mir::BasicBlock], ) -> BitSet<mir::Local> { let mir = fx.mir; let dominators = mir.basic_blocks.dominators(); @@ -24,13 +25,7 @@ pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( .map(|decl| { let ty = fx.monomorphize(decl.ty); let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span); - if layout.is_zst() { - LocalKind::ZST - } else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) { - LocalKind::Unused - } else { - LocalKind::Memory - } + if layout.is_zst() { LocalKind::ZST } else { LocalKind::Unused } }) .collect(); @@ -44,7 +39,8 @@ pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // If there exists a local definition that dominates all uses of that local, // the definition should be visited first. Traverse blocks in an order that // is a topological sort of dominance partial order. - for (bb, data) in traversal::reverse_postorder(mir) { + for bb in traversal_order.iter().copied() { + let data = &mir.basic_blocks[bb]; analyzer.visit_basic_block_data(bb, data); } @@ -69,19 +65,30 @@ enum LocalKind { SSA(DefLocation), } -struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { - fx: &'mir FunctionCx<'a, 'tcx, Bx>, - dominators: &'mir Dominators<mir::BasicBlock>, +struct LocalAnalyzer<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> { + fx: &'a FunctionCx<'b, 'tcx, Bx>, + dominators: &'a Dominators<mir::BasicBlock>, locals: IndexVec<mir::Local, LocalKind>, } -impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx> { fn define(&mut self, local: mir::Local, location: DefLocation) { + let fx = self.fx; let kind = &mut self.locals[local]; + let decl = &fx.mir.local_decls[local]; match *kind { LocalKind::ZST => {} LocalKind::Memory => {} - LocalKind::Unused => *kind = LocalKind::SSA(location), + LocalKind::Unused => { + let ty = fx.monomorphize(decl.ty); + let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span); + *kind = + if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) { + LocalKind::SSA(location) + } else { + LocalKind::Memory + }; + } LocalKind::SSA(_) => *kind = LocalKind::Memory, } } @@ -152,9 +159,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, } } -impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> - for LocalAnalyzer<'mir, 'a, 'tcx, Bx> -{ +impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> Visitor<'tcx> for LocalAnalyzer<'a, 'b, 'tcx, Bx> { fn visit_assign( &mut self, place: &mir::Place<'tcx>, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 817e2ca72ec..125d3b908c7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::source_map::Spanned; -use rustc_span::{sym, Span}; +use rustc_span::{Span, sym}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; @@ -24,7 +24,7 @@ use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphizat use crate::common::{self, IntPredicate}; use crate::errors::CompilerBuiltinsCannotCall; use crate::traits::*; -use crate::{meth, MemFlags}; +use crate::{MemFlags, meth}; // Indicates if we are in the middle of merging a BB's successor into it. This // can happen when BB jumps directly to its successor and the successor has no @@ -915,32 +915,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; - let args: Vec<_> = args - .iter() - .enumerate() - .map(|(i, arg)| { - // The indices passed to simd_shuffle in the - // third argument must be constant. This is - // checked by the type-checker. - if i == 2 && intrinsic.name == sym::simd_shuffle { - // FIXME: the simd_shuffle argument is actually an array, - // not a vector, so we need this special hack to make sure - // it is passed as an immediate. We should pass the - // shuffle indices as a vector instead to avoid this hack. - if let mir::Operand::Constant(constant) = &arg.node { - let (llval, ty) = self.immediate_const_vector(bx, constant); - return OperandRef { - val: Immediate(llval), - layout: bx.layout_of(ty), - }; - } else { - span_bug!(span, "shuffle indices must be constant"); - } - } - - self.codegen_operand(bx, &arg.node) - }) - .collect(); + let args: Vec<_> = + args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) { let location = self @@ -1020,7 +996,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until // we get a value of a built-in pointer type. // - // This is also relevant for `Pin<&mut Self>`, where we need to peel the `Pin`. + // This is also relevant for `Pin<&mut Self>`, where we need to peel the + // `Pin`. while !op.layout.ty.is_unsafe_ptr() && !op.layout.ty.is_ref() { let (idx, _) = op.layout.non_1zst_field(bx).expect( "not exactly one non-1-ZST field in a `DispatchFromDyn` type", @@ -1028,9 +1005,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { op = op.extract_field(bx, idx); } - // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its + // Now that we have `*dyn Trait` or `&dyn Trait`, split it up into its // data pointer and vtable. Look up the method in the vtable, and pass - // the data pointer as the first argument + // the data pointer as the first argument. llfn = Some(meth::VirtualIndex::from_index(idx).get_fn( bx, meta, @@ -1236,10 +1213,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mergeable_succ, ) } -} -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn codegen_block(&mut self, mut bb: mir::BasicBlock) { + pub(crate) fn codegen_block(&mut self, mut bb: mir::BasicBlock) { let llbb = match self.try_llbb(bb) { Some(llbb) => llbb, None => return, @@ -1279,7 +1254,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - pub fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) { + pub(crate) fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) { let llbb = match self.try_llbb(bb) { Some(llbb) => llbb, None => return, @@ -1464,8 +1439,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (mut llval, align, by_ref) = match op.val { Immediate(_) | Pair(..) => match arg.mode { PassMode::Indirect { attrs, .. } => { - // Indirect argument may have higher alignment requirements than the type's alignment. - // This can happen, e.g. when passing types with <4 byte alignment on the stack on x86. + // Indirect argument may have higher alignment requirements than the type's + // alignment. This can happen, e.g. when passing types with <4 byte alignment + // on the stack on x86. let required_align = match attrs.pointee_align { Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi), None => arg.layout.align.abi, @@ -1614,10 +1590,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some(slot) = self.personality_slot { slot } else { - let layout = cx.layout_of(Ty::new_tup( - cx.tcx(), - &[Ty::new_mut_ptr(cx.tcx(), cx.tcx().types.u8), cx.tcx().types.i32], - )); + let layout = cx.layout_of(Ty::new_tup(cx.tcx(), &[ + Ty::new_mut_ptr(cx.tcx(), cx.tcx().types.u8), + cx.tcx().types.i32, + ])); let slot = PlaceRef::alloca(bx, layout); self.personality_slot = Some(slot); slot @@ -1764,7 +1740,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } /// Like `llbb`, but may fail if the basic block should be skipped. - pub fn try_llbb(&mut self, bb: mir::BasicBlock) -> Option<Bx::BasicBlock> { + pub(crate) fn try_llbb(&mut self, bb: mir::BasicBlock) -> Option<Bx::BasicBlock> { match self.cached_llbbs[bb] { CachedLlbb::None => { let llbb = Bx::append_block(self.cx, self.llfn, &format!("{bb:?}")); diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 0aa85b82038..15f45b226f5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::HasTyCtxt; -use rustc_middle::ty::{self, Ty, ValTree}; +use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::abi::Abi; @@ -10,7 +10,7 @@ use crate::mir::operand::OperandRef; use crate::traits::*; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn eval_mir_constant_to_operand( + pub(crate) fn eval_mir_constant_to_operand( &self, bx: &mut Bx, constant: &mir::ConstOperand<'tcx>, @@ -32,27 +32,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// that the given `constant` is an `Const::Unevaluated` and must be convertible to /// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip. /// - /// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees! - pub fn eval_unevaluated_mir_constant_to_valtree( + /// Note that this function is cursed, since usually MIR consts should not be evaluated to + /// valtrees! + fn eval_unevaluated_mir_constant_to_valtree( &self, constant: &mir::ConstOperand<'tcx>, ) -> Result<Result<ty::ValTree<'tcx>, Ty<'tcx>>, ErrorHandled> { let uv = match self.monomorphize(constant.const_) { mir::Const::Unevaluated(uv, _) => uv.shrink(), mir::Const::Ty(_, c) => match c.kind() { - // A constant that came from a const generic but was then used as an argument to old-style - // simd_shuffle (passing as argument instead of as a generic param). + // A constant that came from a const generic but was then used as an argument to + // old-style simd_shuffle (passing as argument instead of as a generic param). rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Ok(valtree)), other => span_bug!(constant.span, "{other:#?}"), }, // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate - // a constant and write that value back into `Operand`s. This could happen, but is unlikely. - // Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care - // around intrinsics. For an issue to happen here, it would require a macro expanding to a - // `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but - // the user pass through arbitrary expressions. - // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real - // const generic, and get rid of this entire function. + // a constant and write that value back into `Operand`s. This could happen, but is + // unlikely. Also: all users of `simd_shuffle` are on unstable and already need to take + // a lot of care around intrinsics. For an issue to happen here, it would require a + // macro expanding to a `simd_shuffle` call without wrapping the constant argument in a + // `const {}` block, but the user pass through arbitrary expressions. + // FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a + // real const generic, and get rid of this entire function. other => span_bug!(constant.span, "{other:#?}"), }; let uv = self.monomorphize(uv); @@ -66,15 +67,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { constant: &mir::ConstOperand<'tcx>, ) -> (Bx::Value, Ty<'tcx>) { let ty = self.monomorphize(constant.ty()); - let ty_is_simd = ty.is_simd(); - // FIXME: ideally we'd assert that this is a SIMD type, but simd_shuffle - // in its current form relies on a regular array being passed as an - // immediate argument. This hack can be removed once that is fixed. - let field_ty = if ty_is_simd { - ty.simd_size_and_type(bx.tcx()).1 - } else { - ty.builtin_index().unwrap() - }; + assert!(ty.is_simd()); + let field_ty = ty.simd_size_and_type(bx.tcx()).1; let val = self .eval_unevaluated_mir_constant_to_valtree(constant) @@ -82,19 +76,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .map(|x| x.ok()) .flatten() .map(|val| { - // Depending on whether this is a SIMD type with an array field - // or a type with many fields (one for each elements), the valtree - // is either a single branch with N children, or a root node - // with exactly one child which then in turn has many children. - // So we look at the first child to determine whether it is a - // leaf or whether we have to go one more layer down. - let branch_or_leaf = val.unwrap_branch(); - let first = branch_or_leaf.get(0).unwrap(); - let field_iter = match first { - ValTree::Branch(_) => first.unwrap_branch().iter(), - ValTree::Leaf(_) => branch_or_leaf.iter(), - }; - let values: Vec<_> = field_iter + // A SIMD type has a single field, which is an array. + let fields = val.unwrap_branch(); + assert_eq!(fields.len(), 1); + let array = fields[0].unwrap_branch(); + // Iterate over the array elements to obtain the values in the vector. + let values: Vec<_> = array + .iter() .map(|field| { if let Some(prim) = field.try_to_scalar() { let layout = bx.layout_of(field_ty); @@ -107,7 +95,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }) .collect(); - if ty_is_simd { bx.const_vector(&values) } else { bx.const_struct(&values, false) } + bx.const_vector(&values) }) .unwrap_or_else(|| { bx.tcx().dcx().emit_err(errors::ShuffleIndicesEvaluation { span: constant.span }); diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index 67f1ef5d944..33a050ef280 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -1,11 +1,11 @@ -use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::SourceScope; +use rustc_middle::mir::coverage::CoverageKind; use super::FunctionCx; use crate::traits::*; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn codegen_coverage(&self, bx: &mut Bx, kind: &CoverageKind, scope: SourceScope) { + pub(crate) fn codegen_coverage(&self, bx: &mut Bx, kind: &CoverageKind, scope: SourceScope) { // Determine the instance that coverage data was originally generated for. let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) { self.monomorphize(inlined) diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 75692540c03..9874809ea2b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -8,8 +8,8 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{Instance, Ty}; use rustc_middle::{bug, mir, ty}; use rustc_session::config::DebugInfo; -use rustc_span::symbol::{kw, Symbol}; -use rustc_span::{hygiene, BytePos, Span}; +use rustc_span::symbol::{Symbol, kw}; +use rustc_span::{BytePos, Span, hygiene}; use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx}; use super::operand::{OperandRef, OperandValue}; @@ -24,6 +24,7 @@ pub struct FunctionDebugContext<'tcx, S, L> { /// Maps from an inlined function to its debug info declaration. pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>, } + #[derive(Copy, Clone)] pub enum VariableKind { ArgumentVariable(usize /*index*/), @@ -243,7 +244,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// Apply debuginfo and/or name, after creating the `alloca` for a local, /// or initializing the local with an operand (whichever applies). - pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) { + pub(crate) fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) { let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full; let vars = match &self.per_local_var_debug_info { @@ -426,7 +427,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - pub fn debug_introduce_locals(&self, bx: &mut Bx) { + pub(crate) fn debug_introduce_locals(&self, bx: &mut Bx) { if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() { for local in self.locals.indices() { self.debug_introduce_local(bx, local); @@ -435,7 +436,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } /// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`. - pub fn compute_per_local_var_debug_info( + pub(crate) fn compute_per_local_var_debug_info( &self, bx: &mut Bx, ) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> { @@ -547,6 +548,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(bx, var.source_info); let base = Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx); + bx.clear_dbg_loc(); bx.dbg_var_addr( dbg_var, diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 4acbc04c505..71541e6ab41 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,16 +1,16 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; -use rustc_span::{sym, Span}; -use rustc_target::abi::call::{FnAbi, PassMode}; +use rustc_span::{Span, sym}; use rustc_target::abi::WrappingRange; +use rustc_target::abi::call::{FnAbi, PassMode}; +use super::FunctionCx; use super::operand::OperandRef; use super::place::PlaceRef; -use super::FunctionCx; use crate::errors::InvalidMonomorphization; use crate::traits::*; -use crate::{errors, meth, size_of_val, MemFlags}; +use crate::{MemFlags, errors, meth, size_of_val}; fn copy_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index de94d87bcea..202baddec72 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -1,9 +1,9 @@ use std::iter; -use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; +use rustc_index::bit_set::BitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::{traversal, UnwindTerminateReason}; +use rustc_middle::mir::{UnwindTerminateReason, traversal}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::{bug, mir, span_bug}; @@ -15,8 +15,8 @@ use crate::traits::*; mod analyze; mod block; -pub mod constant; -pub mod coverageinfo; +mod constant; +mod coverageinfo; pub mod debuginfo; mod intrinsic; mod locals; @@ -218,7 +218,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx); - let memory_locals = analyze::non_ssa_locals(&fx); + let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance); + let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order); // Allocate variable and temp allocas let local_values = { @@ -277,17 +278,20 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); - let reachable_blocks = traversal::mono_reachable_as_bitset(mir, cx.tcx(), instance); + let mut unreached_blocks = BitSet::new_filled(mir.basic_blocks.len()); + // Codegen the body of each reachable block using our reverse postorder list. + for bb in traversal_order { + fx.codegen_block(bb); + unreached_blocks.remove(bb); + } - // Codegen the body of each block using reverse postorder - for (bb, _) in traversal::reverse_postorder(mir) { - if reachable_blocks.contains(bb) { - fx.codegen_block(bb); - } else { - // We want to skip this block, because it's not reachable. But we still create - // the block so terminators in other blocks can reference it. - fx.codegen_block_as_unreachable(bb); - } + // FIXME: These empty unreachable blocks are *mostly* a waste. They are occasionally + // targets for a SwitchInt terminator, but the reimplementation of the mono-reachable + // simplification in SwitchInt lowering sometimes misses cases that + // mono_reachable_reverse_postorder manages to figure out. + // The solution is to do something like post-mono GVN. But for now we have this hack. + for bb in unreached_blocks.iter() { + fx.codegen_block_as_unreachable(bb); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 1891de8c0eb..17f66c12a03 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -4,17 +4,17 @@ use std::fmt; use arrayvec::ArrayVec; use either::Either; use rustc_middle::bug; -use rustc_middle::mir::interpret::{alloc_range, Pointer, Scalar}; +use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range}; use rustc_middle::mir::{self, ConstValue}; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::Ty; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_target::abi::{self, Abi, Align, Size}; use tracing::debug; use super::place::{PlaceRef, PlaceValue}; use super::{FunctionCx, LocalRef}; use crate::traits::*; -use crate::{size_of_val, MemFlags}; +use crate::{MemFlags, size_of_val}; /// The representation of a Rust value. The enum variant is in fact /// uniquely determined by the value's type, but is kept as a @@ -27,32 +27,32 @@ pub enum OperandValue<V> { /// which indicates that it refers to an unsized rvalue. /// /// An `OperandValue` *must* be this variant for any type for which - /// [`LayoutTypeMethods::is_backend_ref`] returns `true`. + /// [`LayoutTypeCodegenMethods::is_backend_ref`] returns `true`. /// (That basically amounts to "isn't one of the other variants".) /// /// This holds a [`PlaceValue`] (like a [`PlaceRef`] does) with a pointer /// to the location holding the value. The type behind that pointer is the - /// one returned by [`LayoutTypeMethods::backend_type`]. + /// one returned by [`LayoutTypeCodegenMethods::backend_type`]. Ref(PlaceValue<V>), /// A single LLVM immediate value. /// /// An `OperandValue` *must* be this variant for any type for which - /// [`LayoutTypeMethods::is_backend_immediate`] returns `true`. + /// [`LayoutTypeCodegenMethods::is_backend_immediate`] returns `true`. /// The backend value in this variant must be the *immediate* backend type, - /// as returned by [`LayoutTypeMethods::immediate_backend_type`]. + /// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`]. Immediate(V), /// A pair of immediate LLVM values. Used by fat pointers too. /// /// An `OperandValue` *must* be this variant for any type for which - /// [`LayoutTypeMethods::is_backend_scalar_pair`] returns `true`. + /// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`. /// The backend values in this variant must be the *immediate* backend types, - /// as returned by [`LayoutTypeMethods::scalar_pair_element_backend_type`] + /// as returned by [`LayoutTypeCodegenMethods::scalar_pair_element_backend_type`] /// with `immediate: true`. Pair(V, V), /// A value taking no bytes, and which therefore needs no LLVM value at all. /// /// If you ever need a `V` to pass to something, get a fresh poison value - /// from [`ConstMethods::const_poison`]. + /// from [`ConstCodegenMethods::const_poison`]. /// /// An `OperandValue` *must* be this variant for any type for which /// `is_zst` on its `Layout` returns `true`. Note however that @@ -64,7 +64,7 @@ impl<V: CodegenObject> OperandValue<V> { /// If this is ZeroSized/Immediate/Pair, return an array of the 0/1/2 values. /// If this is Ref, return the place. #[inline] - pub fn immediates_or_place(self) -> Either<ArrayVec<V, 2>, PlaceValue<V>> { + pub(crate) fn immediates_or_place(self) -> Either<ArrayVec<V, 2>, PlaceValue<V>> { match self { OperandValue::ZeroSized => Either::Left(ArrayVec::new()), OperandValue::Immediate(a) => Either::Left(ArrayVec::from_iter([a])), @@ -75,7 +75,7 @@ impl<V: CodegenObject> OperandValue<V> { /// Given an array of 0/1/2 immediate values, return ZeroSized/Immediate/Pair. #[inline] - pub fn from_immediates(immediates: ArrayVec<V, 2>) -> Self { + pub(crate) fn from_immediates(immediates: ArrayVec<V, 2>) -> Self { let mut it = immediates.into_iter(); let Some(a) = it.next() else { return OperandValue::ZeroSized; @@ -90,7 +90,7 @@ impl<V: CodegenObject> OperandValue<V> { /// optional metadata as backend values. /// /// If you're making a place, use [`Self::deref`] instead. - pub fn pointer_parts(self) -> (V, Option<V>) { + pub(crate) fn pointer_parts(self) -> (V, Option<V>) { match self { OperandValue::Immediate(llptr) => (llptr, None), OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)), @@ -105,12 +105,12 @@ impl<V: CodegenObject> OperandValue<V> { /// alignment, then maybe you want [`OperandRef::deref`] instead. /// /// This is the inverse of [`PlaceValue::address`]. - pub fn deref(self, align: Align) -> PlaceValue<V> { + pub(crate) fn deref(self, align: Align) -> PlaceValue<V> { let (llval, llextra) = self.pointer_parts(); PlaceValue { llval, llextra, align } } - pub(crate) fn is_expected_variant_for_type<'tcx, Cx: LayoutTypeMethods<'tcx>>( + pub(crate) fn is_expected_variant_for_type<'tcx, Cx: LayoutTypeCodegenMethods<'tcx>>( &self, cx: &Cx, ty: TyAndLayout<'tcx>, @@ -153,7 +153,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { OperandRef { val: OperandValue::ZeroSized, layout } } - pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>( + pub(crate) fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>( bx: &mut Bx, val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, @@ -280,7 +280,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { /// /// If you don't need the type, see [`OperandValue::pointer_parts`] /// or [`OperandValue::deref`]. - pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> { + pub fn deref<Cx: CodegenMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> { if self.layout.ty.is_box() { // Derefer should have removed all Box derefs bug!("dereferencing {:?} in codegen", self.layout.ty); @@ -334,7 +334,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { OperandRef { val, layout } } - pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( + pub(crate) fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( &self, bx: &mut Bx, i: usize, @@ -478,8 +478,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest); match self { OperandValue::ZeroSized => { - // Avoid generating stores of zero-sized values, because the only way to have a zero-sized - // value is through `undef`/`poison`, and the store itself is useless. + // Avoid generating stores of zero-sized values, because the only way to have a + // zero-sized value is through `undef`/`poison`, and the store itself is useless. } OperandValue::Ref(val) => { assert!(dest.layout.is_sized(), "cannot directly store unsized values"); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 0fad4d169ed..0b764ae7747 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { Self::alloca(bx, ptr_layout) } - pub fn len<Cx: ConstMethods<'tcx, Value = V>>(&self, cx: &Cx) -> V { + pub fn len<Cx: ConstCodegenMethods<'tcx, Value = V>>(&self, cx: &Cx) -> V { if let FieldsShape::Array { count, .. } = self.layout.fields { if self.layout.is_unsized() { assert_eq!(count, 0); @@ -415,11 +415,10 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { layout.size }; - let llval = bx.inbounds_gep( - bx.cx().backend_type(self.layout), - self.val.llval, - &[bx.cx().const_usize(0), llindex], - ); + let llval = bx.inbounds_gep(bx.cx().backend_type(self.layout), self.val.llval, &[ + bx.cx().const_usize(0), + llindex, + ]); let align = self.val.align.restrict_for_offset(offset); PlaceValue::new_sized(llval, align).with_type(layout) } @@ -470,10 +469,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { LocalRef::Operand(..) => { if place_ref.is_indirect_first_projection() { base = 1; - let cg_base = self.codegen_consume( - bx, - mir::PlaceRef { projection: &place_ref.projection[..0], ..place_ref }, - ); + let cg_base = self.codegen_consume(bx, mir::PlaceRef { + projection: &place_ref.projection[..0], + ..place_ref + }); cg_base.deref(bx.cx()) } else { bug!("using operand local {:?} as place", place_ref); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d94c6f8ddce..f9c0f3ce941 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -6,8 +6,8 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug}; use rustc_session::config::OptLevel; -use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::{self, FieldIdx, FIRST_VARIANT}; +use rustc_span::{DUMMY_SP, Span}; +use rustc_target::abi::{self, FIRST_VARIANT, FieldIdx}; use tracing::{debug, instrument}; use super::operand::{OperandRef, OperandValue}; @@ -15,11 +15,11 @@ use super::place::PlaceRef; use super::{FunctionCx, LocalRef}; use crate::common::IntPredicate; use crate::traits::*; -use crate::{base, MemFlags}; +use crate::{MemFlags, base}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { #[instrument(level = "trace", skip(self, bx))] - pub fn codegen_rvalue( + pub(crate) fn codegen_rvalue( &mut self, bx: &mut Bx, dest: PlaceRef<'tcx, Bx::Value>, @@ -34,7 +34,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Cast( - mir::CastKind::PointerCoercion(PointerCoercion::Unsize), + mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _), ref source, _, ) => { @@ -114,7 +114,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let count = self .monomorphize(count) - .eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); + .try_to_target_usize(bx.tcx()) + .expect("expected monomorphic const in codegen"); bx.write_operand_repeatedly(cg_elem, count, dest); } @@ -382,7 +383,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { scalar: abi::Scalar, backend_ty: Bx::Type, ) { - if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less) + if matches!(self.cx.sess().opts.optimize, OptLevel::No) // For now, the critical niches are all over `Int`eger values. // Should floating-point values or pointers ever get more complex // niches, then this code will probably want to handle them too. @@ -419,7 +420,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - pub fn codegen_rvalue_unsized( + pub(crate) fn codegen_rvalue_unsized( &mut self, bx: &mut Bx, indirect_dest: PlaceRef<'tcx, Bx::Value>, @@ -440,7 +441,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - pub fn codegen_rvalue_operand( + pub(crate) fn codegen_rvalue_operand( &mut self, bx: &mut Bx, rvalue: &mir::Rvalue<'tcx>, @@ -464,7 +465,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let lladdr = bx.ptrtoint(llptr, llcast_ty); OperandValue::Immediate(lladdr) } - mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => { + mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => { match *operand.layout.ty.kind() { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( @@ -480,7 +481,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty), } } - mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => { + mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _) => { match *operand.layout.ty.kind() { ty::Closure(def_id, args) => { let instance = Instance::resolve_closure( @@ -495,11 +496,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty), } } - mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => { + mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => { // This is a no-op at the LLVM level. operand.val } - mir::CastKind::PointerCoercion(PointerCoercion::Unsize) => { + mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _) => { assert!(bx.cx().is_backend_scalar_pair(cast)); let (lldata, llextra) = operand.val.pointer_parts(); let (lldata, llextra) = @@ -507,7 +508,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Pair(lldata, llextra) } mir::CastKind::PointerCoercion( - PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, + PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _ ) => { bug!("{kind:?} is for borrowck, and should never appear in codegen"); } @@ -525,7 +526,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("unexpected non-pair operand"); } } - mir::CastKind::DynStar => { + mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _) => { let (lldata, llextra) = operand.val.pointer_parts(); let (lldata, llextra) = base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra); @@ -803,7 +804,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some(index) = place.as_local() { if let LocalRef::Operand(op) = self.locals[index] { if let ty::Array(_, n) = op.layout.ty.kind() { - let n = n.eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); + let n = n + .try_to_target_usize(bx.tcx()) + .expect("expected monomorphic const in codegen"); return bx.cx().const_usize(n); } } @@ -836,7 +839,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandRef { val, layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)) } } - pub fn codegen_scalar_binop( + fn codegen_scalar_binop( &mut self, bx: &mut Bx, op: mir::BinOp, @@ -981,7 +984,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - pub fn codegen_fat_ptr_binop( + fn codegen_fat_ptr_binop( &mut self, bx: &mut Bx, op: mir::BinOp, @@ -1023,7 +1026,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - pub fn codegen_scalar_checked_binop( + fn codegen_scalar_checked_binop( &mut self, bx: &mut Bx, op: mir::BinOp, @@ -1047,10 +1050,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Pair(val, of) } -} -impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { + pub(crate) fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { mir::Rvalue::Cast(mir::CastKind::Transmute, ref operand, cast_ty) => { let operand_ty = operand.ty(self.mir, self.cx.tcx()); diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 2ef860fc336..6338d16c897 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,6 +1,5 @@ use rustc_middle::mir::{self, NonDivergingIntrinsic}; use rustc_middle::span_bug; -use rustc_session::config::OptLevel; use tracing::instrument; use super::{FunctionCx, LocalRef}; @@ -8,7 +7,7 @@ use crate::traits::*; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { #[instrument(level = "debug", skip(self, bx))] - pub fn codegen_statement(&mut self, bx: &mut Bx, statement: &mir::Statement<'tcx>) { + pub(crate) fn codegen_statement(&mut self, bx: &mut Bx, statement: &mir::Statement<'tcx>) { self.set_debug_loc(bx, statement.source_info); match statement.kind { mir::StatementKind::Assign(box (ref place, ref rvalue)) => { @@ -68,10 +67,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_coverage(bx, kind, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { - if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) { - let op_val = self.codegen_operand(bx, op); - bx.assume(op_val.immediate()); - } + let op_val = self.codegen_operand(bx, op); + bx.assume(op_val.immediate()); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( mir::CopyNonOverlapping { ref count, ref src, ref dst }, diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 64fcefdc860..038c5857fac 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -1,8 +1,8 @@ use rustc_hir as hir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::Instance; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::{span_bug, ty}; use tracing::debug; diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index 933904f9845..3f3ae21035d 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -45,11 +45,13 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // The info in this case is the length of the str, so the size is that // times the unit size. ( - // All slice sizes must fit into `isize`, so this multiplication cannot (signed) wrap. + // All slice sizes must fit into `isize`, so this multiplication cannot (signed) + // wrap. // NOTE: ideally, we want the effects of both `unchecked_smul` and `unchecked_umul` // (resulting in `mul nsw nuw` in LLVM IR), since we know that the multiplication - // cannot signed wrap, and that both operands are non-negative. But at the time of writing, - // the `LLVM-C` binding can't do this, and it doesn't seem to enable any further optimizations. + // cannot signed wrap, and that both operands are non-negative. But at the time of + // writing, the `LLVM-C` binding can't do this, and it doesn't seem to enable any + // further optimizations. bx.unchecked_smul(info.unwrap(), bx.const_usize(unit.size.bytes())), bx.const_usize(unit.align.abi.bytes()), ) @@ -67,9 +69,9 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let (fn_abi, llfn, _instance) = common::build_langcall(bx, None, LangItem::PanicNounwind); - // Generate the call. - // Cannot use `do_call` since we don't have a MIR terminator so we can't create a `TerminationCodegenHelper`. - // (But we are in good company, this code is duplicated plenty of times.) + // Generate the call. Cannot use `do_call` since we don't have a MIR terminator so we + // can't create a `TerminationCodegenHelper`. (But we are in good company, this code is + // duplicated plenty of times.) let fn_ty = bx.fn_decl_backend_type(fn_abi); bx.call( @@ -148,9 +150,14 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // The full formula for the size would be: // let unsized_offset_adjusted = unsized_offset_unadjusted.align_to(unsized_align); // let full_size = (unsized_offset_adjusted + unsized_size).align_to(full_align); - // However, `unsized_size` is a multiple of `unsized_align`. - // Therefore, we can equivalently do the `align_to(unsized_align)` *after* adding `unsized_size`: - // let full_size = (unsized_offset_unadjusted + unsized_size).align_to(unsized_align).align_to(full_align); + // However, `unsized_size` is a multiple of `unsized_align`. Therefore, we can + // equivalently do the `align_to(unsized_align)` *after* adding `unsized_size`: + // + // let full_size = + // (unsized_offset_unadjusted + unsized_size) + // .align_to(unsized_align) + // .align_to(full_align); + // // Furthermore, `align >= unsized_align`, and therefore we only need to do: // let full_size = (unsized_offset_unadjusted + unsized_size).align_to(full_align); diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index cf8f7fa25d8..dfe8fd616e4 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -4,18 +4,18 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::Applicability; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::TargetFeature; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; +use rustc_span::symbol::{Symbol, sym}; use crate::errors; -pub fn from_target_feature( +pub(crate) fn from_target_feature( tcx: TyCtxt<'_>, attr: &ast::Attribute, supported_target_features: &UnordMap<String, Option<Symbol>>, @@ -146,7 +146,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> { /// Checks the function annotated with `#[target_feature]` is not a safe /// trait method implementation, reporting an error if it is. -pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) { +pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) { if let DefKind::AssocFn = tcx.def_kind(id) { let parent_id = tcx.local_parent(id); if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) { diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index 162141a106b..f4853da1156 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -60,7 +60,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { ); } -pub trait AsmMethods<'tcx> { +pub trait AsmCodegenMethods<'tcx> { fn codegen_global_asm( &self, template: &[InlineAsmTemplatePiece], diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index c5e2d55be83..676fb181d67 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -5,24 +5,23 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::ErrorGuaranteed; -use rustc_metadata::creader::MetadataLoaderDyn; use rustc_metadata::EncodedMetadata; +use rustc_metadata::creader::MetadataLoaderDyn; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; -use rustc_session::config::{self, OutputFilenames, PrintRequest}; use rustc_session::Session; +use rustc_session::config::{self, OutputFilenames, PrintRequest}; use rustc_span::symbol::Symbol; -use rustc_target::abi::call::FnAbi; -use super::write::WriteBackendMethods; use super::CodegenObject; +use super::write::WriteBackendMethods; use crate::back::write::TargetMachineFactoryFn; use crate::{CodegenResults, ModuleCodegen}; pub trait BackendTypes { type Value: CodegenObject; + type Metadata: CodegenObject; type Function: CodegenObject; type BasicBlock: Copy; @@ -36,34 +35,21 @@ pub trait BackendTypes { type DIVariable: Copy; } -pub trait Backend<'tcx>: - Sized - + BackendTypes - + HasTyCtxt<'tcx> - + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> - + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> -{ -} - -impl<'tcx, T> Backend<'tcx> for T where - Self: BackendTypes - + HasTyCtxt<'tcx> - + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> - + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> -{ -} - pub trait CodegenBackend { /// Locale resources for diagnostic messages - a string the content of the Fluent resource. /// Called before `init` so that all other functions are able to emit translatable diagnostics. fn locale_resource(&self) -> &'static str; fn init(&self, _sess: &Session) {} + fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {} + fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> { vec![] } + fn print_passes(&self) {} + fn print_version(&self) {} /// The metadata loader used to load rlib and dylib metadata. @@ -75,6 +61,7 @@ pub trait CodegenBackend { } fn provide(&self, _providers: &mut Providers) {} + fn codegen_crate<'tcx>( &self, tcx: TyCtxt<'tcx>, @@ -120,6 +107,7 @@ pub trait ExtraBackendMethods: kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind, ) -> Self::Module; + /// This generates the codegen unit and returns it along with /// a `u64` giving an estimate of the unit's processing cost. fn compile_codegen_unit( @@ -127,6 +115,7 @@ pub trait ExtraBackendMethods: tcx: TyCtxt<'_>, cgu_name: Symbol, ) -> (ModuleCodegen<Self::Module>, u64); + fn target_machine_factory( &self, sess: &Session, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 6cf84a012f0..c0c1085e949 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -1,29 +1,29 @@ use std::assert_matches::assert_matches; +use std::ops::Deref; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; -use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::{Instance, Ty}; use rustc_session::config::OptLevel; use rustc_span::Span; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange}; -use rustc_target::spec::HasTargetSpec; use super::abi::AbiBuilderMethods; use super::asm::AsmBuilderMethods; -use super::consts::ConstMethods; +use super::consts::ConstCodegenMethods; use super::coverageinfo::CoverageInfoBuilderMethods; use super::debuginfo::DebugInfoBuilderMethods; -use super::intrinsic::IntrinsicCallMethods; -use super::misc::MiscMethods; -use super::type_::{ArgAbiMethods, BaseTypeMethods, LayoutTypeMethods}; -use super::{HasCodegen, StaticBuilderMethods}; +use super::intrinsic::IntrinsicCallBuilderMethods; +use super::misc::MiscCodegenMethods; +use super::type_::{ArgAbiBuilderMethods, BaseTypeCodegenMethods, LayoutTypeCodegenMethods}; +use super::{CodegenMethods, StaticBuilderMethods}; +use crate::MemFlags; use crate::common::{ AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind, }; use crate::mir::operand::{OperandRef, OperandValue}; use crate::mir::place::{PlaceRef, PlaceValue}; -use crate::MemFlags; #[derive(Copy, Clone, Debug)] pub enum OverflowOp { @@ -33,17 +33,34 @@ pub enum OverflowOp { } pub trait BuilderMethods<'a, 'tcx>: - HasCodegen<'tcx> + Sized + + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> + + Deref<Target = Self::CodegenCx> + CoverageInfoBuilderMethods<'tcx> + DebugInfoBuilderMethods - + ArgAbiMethods<'tcx> + + ArgAbiBuilderMethods<'tcx> + AbiBuilderMethods<'tcx> - + IntrinsicCallMethods<'tcx> + + IntrinsicCallBuilderMethods<'tcx> + AsmBuilderMethods<'tcx> + StaticBuilderMethods - + HasParamEnv<'tcx> - + HasTargetSpec { + // `BackendTypes` is a supertrait of both `CodegenMethods` and + // `BuilderMethods`. This bound ensures all impls agree on the associated + // types within. + type CodegenCx: CodegenMethods< + 'tcx, + Value = Self::Value, + Metadata = Self::Metadata, + Function = Self::Function, + BasicBlock = Self::BasicBlock, + Type = Self::Type, + Funclet = Self::Funclet, + DIScope = Self::DIScope, + DILocation = Self::DILocation, + DIVariable = Self::DIVariable, + >; + fn build(cx: &'a Self::CodegenCx, llbb: Self::BasicBlock) -> Self; fn cx(&self) -> &Self::CodegenCx; diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index c15f1fa8e56..9af463a691a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -3,7 +3,7 @@ use rustc_target::abi; use super::BackendTypes; -pub trait ConstMethods<'tcx>: BackendTypes { +pub trait ConstCodegenMethods<'tcx>: BackendTypes { // Constant constructors fn const_null(&self, t: Self::Type) -> Self::Value; /// Generate an uninitialized value (matching uninitialized memory in MIR). @@ -14,18 +14,20 @@ pub trait ConstMethods<'tcx>: BackendTypes { /// (including code that e.g. copies uninit memory with `MaybeUninit`) can never encounter a /// poison value. fn const_poison(&self, t: Self::Type) -> Self::Value; - fn const_int(&self, t: Self::Type, i: i64) -> Self::Value; - fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value; - fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value; + fn const_bool(&self, val: bool) -> Self::Value; + + fn const_i8(&self, i: i8) -> Self::Value; fn const_i16(&self, i: i16) -> Self::Value; fn const_i32(&self, i: i32) -> Self::Value; - fn const_i8(&self, i: i8) -> Self::Value; + fn const_int(&self, t: Self::Type, i: i64) -> Self::Value; + fn const_u8(&self, i: u8) -> Self::Value; fn const_u32(&self, i: u32) -> Self::Value; fn const_u64(&self, i: u64) -> Self::Value; fn const_u128(&self, i: u128) -> Self::Value; fn const_usize(&self, i: u64) -> Self::Value; - fn const_u8(&self, i: u8) -> Self::Value; + fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value; + fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value; fn const_real(&self, t: Self::Type, val: f64) -> Self::Value; fn const_str(&self, s: &str) -> (Self::Value, Self::Value); diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index 0b1645c66ed..0b513dac503 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -1,9 +1,7 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; -use super::BackendTypes; - -pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { +pub trait CoverageInfoBuilderMethods<'tcx> { /// Performs any start-of-function codegen needed for coverage instrumentation. /// /// Can be a no-op in backends that don't support coverage instrumentation. diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index 31104e5749b..c26d4532d0f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -3,13 +3,13 @@ use std::ops::Range; use rustc_middle::mir; use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; use rustc_span::{SourceFile, Span, Symbol}; -use rustc_target::abi::call::FnAbi; use rustc_target::abi::Size; +use rustc_target::abi::call::FnAbi; use super::BackendTypes; use crate::mir::debuginfo::{FunctionDebugContext, VariableKind}; -pub trait DebugInfoMethods<'tcx>: BackendTypes { +pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes { fn create_vtable_debuginfo( &self, ty: Ty<'tcx>, @@ -80,6 +80,7 @@ pub trait DebugInfoBuilderMethods: BackendTypes { fragment: Option<Range<Size>>, ); fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation); + fn clear_dbg_loc(&mut self); fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); fn set_var_name(&mut self, value: Self::Value, name: &str); } diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs index 792d2b04ed6..c1edeac31b0 100644 --- a/compiler/rustc_codegen_ssa/src/traits/declare.rs +++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs @@ -2,9 +2,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::Instance; -use super::BackendTypes; - -pub trait PreDefineMethods<'tcx>: BackendTypes { +pub trait PreDefineCodegenMethods<'tcx> { fn predefine_static( &self, def_id: DefId, diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index 172004a9cc7..5b9274b4824 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -5,7 +5,7 @@ use rustc_target::abi::call::FnAbi; use super::BackendTypes; use crate::mir::operand::OperandRef; -pub trait IntrinsicCallMethods<'tcx>: BackendTypes { +pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes { /// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`, /// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics, /// add them to `compiler/rustc_codegen_llvm/src/context.rs`. @@ -24,14 +24,14 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; /// Trait method used to test whether a given pointer is associated with a type identifier. - fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value; + fn type_test(&mut self, pointer: Self::Value, typeid: Self::Metadata) -> Self::Value; /// Trait method used to load a function while testing if it is associated with a type /// identifier. fn type_checked_load( &mut self, llvtable: Self::Value, vtable_byte_offset: u64, - typeid: Self::Value, + typeid: Self::Metadata, ) -> Self::Value; /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in /// Rust defined C-variadic functions. diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index 40a49b3e1b5..5b33fd7ab10 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -7,7 +7,7 @@ use rustc_session::Session; use super::BackendTypes; -pub trait MiscMethods<'tcx>: BackendTypes { +pub trait MiscCodegenMethods<'tcx>: BackendTypes { fn vtables( &self, ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>; @@ -25,6 +25,7 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>; fn set_frame_pointer_type(&self, llfn: Self::Function); fn apply_target_cpu_attr(&self, llfn: Self::Function); - /// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists. + /// Declares the extern "C" main function for the entry point. Returns None if the symbol + /// already exists. fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function>; } diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs index 9ac923bef88..800470286bc 100644 --- a/compiler/rustc_codegen_ssa/src/traits/mod.rs +++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs @@ -8,9 +8,6 @@ //! actual codegen, while the builder stores the information about the function during codegen and //! is used to produce the instructions of the backend IR. //! -//! Finally, a third `Backend` structure has to implement methods related to how codegen information -//! is passed to the backend, especially for asynchronous compilation. -//! //! The traits contain associated types that are backend-specific, such as the backend's value or //! basic blocks. @@ -30,71 +27,36 @@ mod write; use std::fmt; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt}; -use rustc_target::spec::HasTargetSpec; +use rustc_middle::ty::Ty; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; +use rustc_target::abi::call::FnAbi; pub use self::abi::AbiBuilderMethods; -pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef}; -pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods}; +pub use self::asm::{ + AsmBuilderMethods, AsmCodegenMethods, GlobalAsmOperandRef, InlineAsmOperandRef, +}; +pub use self::backend::{BackendTypes, CodegenBackend, ExtraBackendMethods}; pub use self::builder::{BuilderMethods, OverflowOp}; -pub use self::consts::ConstMethods; +pub use self::consts::ConstCodegenMethods; pub use self::coverageinfo::CoverageInfoBuilderMethods; -pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; -pub use self::declare::PreDefineMethods; -pub use self::intrinsic::IntrinsicCallMethods; -pub use self::misc::MiscMethods; -pub use self::statics::{StaticBuilderMethods, StaticMethods}; +pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; +pub use self::declare::PreDefineCodegenMethods; +pub use self::intrinsic::IntrinsicCallBuilderMethods; +pub use self::misc::MiscCodegenMethods; +pub use self::statics::{StaticBuilderMethods, StaticCodegenMethods}; pub use self::type_::{ - ArgAbiMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMembershipMethods, - TypeMethods, + ArgAbiBuilderMethods, BaseTypeCodegenMethods, DerivedTypeCodegenMethods, + LayoutTypeCodegenMethods, TypeCodegenMethods, TypeMembershipCodegenMethods, }; pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods}; -pub trait CodegenObject: Copy + PartialEq + fmt::Debug {} -impl<T: Copy + PartialEq + fmt::Debug> CodegenObject for T {} - -pub trait CodegenMethods<'tcx>: - Backend<'tcx> - + TypeMethods<'tcx> - + MiscMethods<'tcx> - + ConstMethods<'tcx> - + StaticMethods - + DebugInfoMethods<'tcx> - + AsmMethods<'tcx> - + PreDefineMethods<'tcx> - + HasParamEnv<'tcx> - + HasTyCtxt<'tcx> - + HasTargetSpec -{ -} - -impl<'tcx, T> CodegenMethods<'tcx> for T where - Self: Backend<'tcx> - + TypeMethods<'tcx> - + MiscMethods<'tcx> - + ConstMethods<'tcx> - + StaticMethods - + DebugInfoMethods<'tcx> - + AsmMethods<'tcx> - + PreDefineMethods<'tcx> - + HasParamEnv<'tcx> - + HasTyCtxt<'tcx> - + HasTargetSpec -{ -} +pub trait CodegenObject = Copy + PartialEq + fmt::Debug; -pub trait HasCodegen<'tcx>: - Backend<'tcx> + std::ops::Deref<Target = <Self as HasCodegen<'tcx>>::CodegenCx> -{ - type CodegenCx: CodegenMethods<'tcx> - + BackendTypes< - Value = Self::Value, - Function = Self::Function, - BasicBlock = Self::BasicBlock, - Type = Self::Type, - Funclet = Self::Funclet, - DIScope = Self::DIScope, - DILocation = Self::DILocation, - DIVariable = Self::DIVariable, - >; -} +pub trait CodegenMethods<'tcx> = LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> + + TypeCodegenMethods<'tcx> + + ConstCodegenMethods<'tcx> + + StaticCodegenMethods + + DebugInfoCodegenMethods<'tcx> + + AsmCodegenMethods<'tcx> + + PreDefineCodegenMethods<'tcx>; diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs index b418199e616..c10733fb0ed 100644 --- a/compiler/rustc_codegen_ssa/src/traits/statics.rs +++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs @@ -3,7 +3,7 @@ use rustc_target::abi::Align; use super::BackendTypes; -pub trait StaticMethods: BackendTypes { +pub trait StaticCodegenMethods: BackendTypes { fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; fn codegen_static(&self, def_id: DefId); diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 7c042c0c621..f862434c8ef 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -1,17 +1,15 @@ use rustc_middle::bug; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; use rustc_target::abi::{AddressSpace, Float, Integer}; -use super::misc::MiscMethods; -use super::{Backend, HasCodegen}; +use super::BackendTypes; +use super::misc::MiscCodegenMethods; use crate::common::TypeKind; use crate::mir::place::PlaceRef; -// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use -// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves. -pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { +pub trait BaseTypeCodegenMethods<'tcx>: BackendTypes { fn type_i8(&self) -> Self::Type; fn type_i16(&self) -> Self::Type; fn type_i32(&self) -> Self::Type; @@ -42,7 +40,9 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn val_ty(&self, v: Self::Value) -> Self::Type; } -pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { +pub trait DerivedTypeCodegenMethods<'tcx>: + BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> +{ fn type_int(&self) -> Self::Type { match &self.sess().target.c_int_width[..] { "16" => self.type_i16(), @@ -100,9 +100,12 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } } -impl<'tcx, T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {} +impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where + Self: BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> +{ +} -pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { +pub trait LayoutTypeCodegenMethods<'tcx>: BackendTypes { /// The backend type used for a rust type when it's in memory, /// such as when it's stack-allocated or when it's being loaded or stored. fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type; @@ -114,7 +117,7 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { /// /// For nearly all types this is the same as the [`Self::backend_type`], however /// `bool` (and other `0`-or-`1` values) are kept as `i1` in registers but as - /// [`BaseTypeMethods::type_i8`] in memory. + /// [`BaseTypeCodegenMethods::type_i8`] in memory. /// /// Converting values between the two different backend types is done using /// [`from_immediate`](super::BuilderMethods::from_immediate) and @@ -146,17 +149,17 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { // For backends that support CFI using type membership (i.e., testing whether a given pointer is // associated with a type identifier). -pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> { +pub trait TypeMembershipCodegenMethods<'tcx>: BackendTypes { fn add_type_metadata(&self, _function: Self::Function, _typeid: String) {} fn set_type_metadata(&self, _function: Self::Function, _typeid: String) {} - fn typeid_metadata(&self, _typeid: String) -> Option<Self::Value> { + fn typeid_metadata(&self, _typeid: String) -> Option<Self::Metadata> { None } fn add_kcfi_type_metadata(&self, _function: Self::Function, _typeid: u32) {} fn set_kcfi_type_metadata(&self, _function: Self::Function, _typeid: u32) {} } -pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> { +pub trait ArgAbiBuilderMethods<'tcx>: BackendTypes { fn store_fn_arg( &mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, @@ -172,12 +175,6 @@ pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> { fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type; } -pub trait TypeMethods<'tcx>: - DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx> -{ -} - -impl<'tcx, T> TypeMethods<'tcx> for T where - Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx> -{ -} +pub trait TypeCodegenMethods<'tcx> = DerivedTypeCodegenMethods<'tcx> + + LayoutTypeCodegenMethods<'tcx> + + TypeMembershipCodegenMethods<'tcx>; |
