diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
commit | 9918693037dce8aa4bb6f08741b6812923486c18 (patch) | |
tree | 21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_codegen_ssa/src | |
parent | Releasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff) | |
download | rustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip |
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
27 files changed, 482 insertions, 729 deletions
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index 16bb7b12b..a5bd10ecb 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -149,7 +149,7 @@ impl<'tcx> AssertModuleSource<'tcx> { self.cgu_reuse_tracker.set_expectation( cgu_name, - &user_path, + user_path, attr.span, expected_reuse, comp_kind, @@ -199,8 +199,8 @@ impl fmt::Display for CguReuse { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { CguReuse::No => write!(f, "No"), - CguReuse::PreLto => write!(f, "PreLto "), - CguReuse::PostLto => write!(f, "PostLto "), + CguReuse::PreLto => write!(f, "PreLto"), + CguReuse::PostLto => write!(f, "PostLto"), } } } @@ -278,13 +278,13 @@ impl CguReuseTracker { if error { let at_least = if at_least { 1 } else { 0 }; - errors::IncorrectCguReuseType { + sess.emit_err(errors::IncorrectCguReuseType { span: *error_span, cgu_user_name, actual_reuse, expected_reuse, at_least, - }; + }); } } else { sess.emit_fatal(errors::CguNotRecorded { cgu_user_name, cgu_name }); diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 1c464b3ec..4dc28adf3 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -175,8 +175,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { ) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") { - if let Some(new_archive_path) = - try_extract_macho_fat_archive(&self.sess, &archive_path)? + if let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? { archive_path = new_archive_path } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index dd9d277fb..b0d22ad0a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{ErrorGuaranteed, Handler}; +use rustc_errors::{DiagCtxt, ErrorGuaranteed}; 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; @@ -44,7 +44,7 @@ use tempfile::Builder as TempFileBuilder; use itertools::Itertools; use std::cell::OnceCell; use std::collections::BTreeSet; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fs::{read, File, OpenOptions}; use std::io::{BufWriter, Write}; use std::ops::Deref; @@ -52,10 +52,10 @@ use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{env, fmt, fs, io, mem, str}; -pub fn ensure_removed(diag_handler: &Handler, path: &Path) { +pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) { if let Err(e) = fs::remove_file(path) { if e.kind() != io::ErrorKind::NotFound { - diag_handler.err(format!("failed to remove {}: {}", path.display(), e)); + dcx.err(format!("failed to remove {}: {}", path.display(), e)); } } } @@ -143,7 +143,7 @@ pub fn link_binary<'a>( } } if sess.opts.json_artifact_notifications { - sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link"); + sess.dcx().emit_artifact_notification(&out_filename, "link"); } if sess.prof.enabled() { @@ -183,13 +183,13 @@ pub fn link_binary<'a>( |preserve_objects: bool, preserve_dwarf_objects: bool, module: &CompiledModule| { if !preserve_objects { if let Some(ref obj) = module.object { - ensure_removed(sess.diagnostic(), obj); + ensure_removed(sess.dcx(), obj); } } if !preserve_dwarf_objects { if let Some(ref dwo_obj) = module.dwarf_object { - ensure_removed(sess.diagnostic(), dwo_obj); + ensure_removed(sess.dcx(), dwo_obj); } } }; @@ -208,7 +208,7 @@ pub fn link_binary<'a>( // Remove the temporary files if output goes to stdout for temp in tempfiles_for_stdout_output { - ensure_removed(sess.diagnostic(), &temp); + ensure_removed(sess.dcx(), &temp); } // If no requested outputs require linking, then the object temporaries should @@ -277,7 +277,7 @@ pub fn each_linked_rlib( let crate_name = info.crate_name[&cnum]; let used_crate_source = &info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.rlib { - f(cnum, &path); + f(cnum, path); } else { if used_crate_source.rmeta.is_some() { return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); @@ -524,7 +524,7 @@ fn link_staticlib<'a>( && !ignored_for_lto(sess, &codegen_results.crate_info, cnum); let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter(); - let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, &lib)); + let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib)); let relevant_libs: FxHashSet<_> = relevant.filter_map(|lib| lib.filename).collect(); let bundled_libs: FxHashSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); @@ -689,7 +689,7 @@ fn link_dwarf_object<'a>( // Adding an executable is primarily done to make `thorin` check that all the referenced // dwarf objects are found in the end. package.add_executable( - &executable_out_filename, + executable_out_filename, thorin::MissingReferencedObjectBehaviour::Skip, )?; @@ -928,7 +928,7 @@ fn link_natively<'a>( command: &cmd, escaped_output, }; - sess.diagnostic().emit_err(err); + sess.dcx().emit_err(err); // If MSVC's `link.exe` was expected but the return code // is not a Microsoft LNK error then suggest a way to fix or // install the Visual Studio build tools. @@ -945,7 +945,7 @@ fn link_natively<'a>( { let is_vs_installed = windows_registry::find_vs_version().is_ok(); let has_linker = windows_registry::find_tool( - &sess.opts.target_triple.triple(), + sess.opts.target_triple.triple(), "link.exe", ) .is_some(); @@ -1038,14 +1038,14 @@ fn link_natively<'a>( if sess.target.is_like_osx { match (strip, crate_type) { (Strip::Debuginfo, _) => { - strip_symbols_with_external_utility(sess, "strip", &out_filename, Some("-S")) + strip_symbols_with_external_utility(sess, "strip", out_filename, Some("-S")) } // Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988) (Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => { - strip_symbols_with_external_utility(sess, "strip", &out_filename, Some("-x")) + strip_symbols_with_external_utility(sess, "strip", out_filename, Some("-x")) } (Strip::Symbols, _) => { - strip_symbols_with_external_utility(sess, "strip", &out_filename, None) + strip_symbols_with_external_utility(sess, "strip", out_filename, None) } (Strip::None, _) => {} } @@ -1059,7 +1059,7 @@ fn link_natively<'a>( match strip { // Always preserve the symbol table (-x). Strip::Debuginfo => { - strip_symbols_with_external_utility(sess, stripcmd, &out_filename, Some("-x")) + strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-x")) } // Strip::Symbols is handled via the --strip-all linker option. Strip::Symbols => {} @@ -1245,13 +1245,13 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { // rpath to the library as well (the rpath should be absolute, see // PR #41352 for details). let filename = format!("rustc{channel}_rt.{name}"); - let path = find_sanitizer_runtime(&sess, &filename); + let path = find_sanitizer_runtime(sess, &filename); let rpath = path.to_str().expect("non-utf8 component in path"); linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); linker.link_dylib(&filename, false, true); } else { let filename = format!("librustc{channel}_rt.{name}.a"); - let path = find_sanitizer_runtime(&sess, &filename).join(&filename); + let path = find_sanitizer_runtime(sess, &filename).join(&filename); linker.link_whole_rlib(&path); } } @@ -1477,7 +1477,7 @@ fn print_native_static_libs( sess.emit_note(errors::StaticLibraryNativeArtifacts); // Prefix for greppability // Note: This must not be translated as tools are allowed to depend on this exact string. - sess.note_without_error(format!("native-static-libs: {}", &lib_args.join(" "))); + sess.note(format!("native-static-libs: {}", &lib_args.join(" "))); } } } @@ -1685,7 +1685,7 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { // Returns true if linker is located within sysroot fn detect_self_contained_mingw(sess: &Session) -> bool { - let (linker, _) = linker_and_flavor(&sess); + let (linker, _) = linker_and_flavor(sess); // Assume `-C linker=rust-lld` as self-contained mode if linker == Path::new("rust-lld") { return true; @@ -1737,7 +1737,7 @@ fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfC LinkSelfContainedDefault::InferredForMingw => { sess.host == sess.target && sess.target.vendor != "uwp" - && detect_self_contained_mingw(&sess) + && detect_self_contained_mingw(sess) } } }; @@ -2243,9 +2243,9 @@ fn linker_with_args<'a>( // ------------ Late order-dependent options ------------ // Doesn't really make sense. - // FIXME: In practice built-in target specs use this for arbitrary order-independent options, - // introduce a target spec option for order-independent linker options, migrate built-in specs - // to it and remove the option. + // FIXME: In practice built-in target specs use this for arbitrary order-independent options. + // Introduce a target spec option for order-independent linker options, migrate built-in specs + // to it and remove the option. Currently the last holdout is wasm32-unknown-emscripten. add_post_link_args(cmd, sess, flavor); Ok(cmd.take_cmd()) @@ -2378,6 +2378,11 @@ fn add_order_independent_options( cmd.control_flow_guard(); } + // OBJECT-FILES-NO, AUDIT-ORDER + if sess.opts.unstable_opts.ehcont_guard { + cmd.ehcont_guard(); + } + add_rpath_args(cmd, sess, codegen_results, out_filename); } @@ -2432,7 +2437,7 @@ fn add_native_libs_from_crate( // If rlib contains native libs as archives, unpack them to tmpdir. let rlib = &codegen_results.crate_info.used_crate_source[&cnum].rlib.as_ref().unwrap().0; archive_builder_builder - .extract_bundled_libs(rlib, tmpdir, &bundled_libs) + .extract_bundled_libs(rlib, tmpdir, bundled_libs) .unwrap_or_else(|e| sess.emit_fatal(e)); } @@ -2485,7 +2490,7 @@ fn add_native_libs_from_crate( cmd.link_whole_staticlib( name, verbatim, - &search_paths.get_or_init(|| archive_search_paths(sess)), + search_paths.get_or_init(|| archive_search_paths(sess)), ); } else { cmd.link_staticlib(name, verbatim) @@ -2522,7 +2527,7 @@ fn add_native_libs_from_crate( NativeLibKind::WasmImportModule => {} NativeLibKind::LinkArg => { if link_static { - cmd.arg(name); + cmd.linker_arg(OsStr::new(name), verbatim); } } } @@ -2719,7 +2724,7 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf { // already had `fix_windows_verbatim_for_gcc()` applied if needed. sysroot_lib_path } else { - fix_windows_verbatim_for_gcc(&lib_dir) + fix_windows_verbatim_for_gcc(lib_dir) } } @@ -2756,7 +2761,7 @@ fn add_static_crate<'a>( let mut link_upstream = |path: &Path| { let rlib_path = if let Some(dir) = path.parent() { let file_name = path.file_name().expect("rlib path has no file name path component"); - rehome_sysroot_lib_dir(sess, &dir).join(file_name) + rehome_sysroot_lib_dir(sess, dir).join(file_name) } else { fix_windows_verbatim_for_gcc(path) }; @@ -2793,7 +2798,7 @@ fn add_static_crate<'a>( let canonical = f.replace('-', "_"); let is_rust_object = - canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); + canonical.starts_with(&canonical_name) && looks_like_rust_object_file(f); // If we're performing LTO and this is a rust-generated object // file, then we don't need the object file as it's part of the diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 09434513e..eeb57d4d0 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -45,7 +45,7 @@ pub fn get_linker<'a>( self_contained: bool, target_cpu: &'a str, ) -> Box<dyn Linker + 'a> { - let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); + let msvc_tool = windows_registry::find_tool(sess.opts.target_triple.triple(), "link.exe"); // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle @@ -78,7 +78,7 @@ pub fn get_linker<'a>( if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" { if let Some(ref tool) = msvc_tool { let original_path = tool.path(); - if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { + if let Some(root_lib_path) = original_path.ancestors().nth(4) { let arch = match t.arch.as_ref() { "x86_64" => Some("x64"), "x86" => Some("x86"), @@ -185,6 +185,7 @@ pub trait Linker { fn optimize(&mut self); fn pgo_gen(&mut self); fn control_flow_guard(&mut self); + fn ehcont_guard(&mut self); fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]); fn no_crt_objects(&mut self); fn no_default_libraries(&mut self); @@ -195,6 +196,14 @@ pub trait Linker { fn add_no_exec(&mut self) {} fn add_as_needed(&mut self) {} fn reset_per_library_state(&mut self) {} + fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) { + self.linker_args(&[arg], verbatim); + } + fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) { + args.into_iter().for_each(|a| { + self.cmd().arg(a); + }); + } } impl dyn Linker + '_ { @@ -222,38 +231,12 @@ pub struct GccLinker<'a> { } impl<'a> GccLinker<'a> { - /// Passes an argument directly to the linker. - /// - /// When the linker is not ld-like such as when using a compiler as a linker, the argument is - /// prepended by `-Wl,`. - fn linker_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self { - self.linker_args(&[arg]); - self + fn linker_arg(&mut self, arg: impl AsRef<OsStr>) { + Linker::linker_arg(self, arg.as_ref(), false); } - - /// Passes a series of arguments directly to the linker. - /// - /// When the linker is ld-like, the arguments are simply appended to the command. When the - /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by - /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a - /// single argument is appended to the command to ensure that the order of the arguments is - /// preserved by the compiler. - fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) -> &mut Self { - if self.is_ld { - args.into_iter().for_each(|a| { - self.cmd.arg(a); - }); - } else { - if !args.is_empty() { - let mut s = OsString::from("-Wl"); - for a in args { - s.push(","); - s.push(a); - } - self.cmd.arg(s); - } - } - self + fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) { + let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect(); + Linker::linker_args(self, &args_vec, false); } fn takes_hints(&self) -> bool { @@ -360,6 +343,30 @@ impl<'a> GccLinker<'a> { } impl<'a> Linker for GccLinker<'a> { + /// Passes a series of arguments directly to the linker. + /// + /// When the linker is ld-like, the arguments are simply appended to the command. When the + /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by + /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a + /// single argument is appended to the command to ensure that the order of the arguments is + /// preserved by the compiler. + fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) { + if self.is_ld || verbatim { + args.into_iter().for_each(|a| { + self.cmd.arg(a); + }); + } else { + if !args.is_empty() { + let mut s = OsString::from("-Wl"); + for a in args { + s.push(","); + s.push(a); + } + self.cmd.arg(s); + } + } + } + fn cmd(&mut self) -> &mut Command { &mut self.cmd } @@ -519,7 +526,7 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = find_native_static_library(lib, verbatim, search_path, &self.sess); + let lib = find_native_static_library(lib, verbatim, search_path, self.sess); self.linker_arg(&lib); } } @@ -530,7 +537,7 @@ impl<'a> Linker for GccLinker<'a> { self.linker_arg("-force_load"); self.linker_arg(&lib); } else { - self.linker_arg("--whole-archive").cmd.arg(lib); + self.linker_args(&[OsString::from("--whole-archive"), lib.into()]); self.linker_arg("--no-whole-archive"); } } @@ -605,6 +612,8 @@ impl<'a> Linker for GccLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { // MacOS linker doesn't support stripping symbols directly anymore. if self.sess.target.is_like_osx { @@ -914,6 +923,12 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg("/guard:cf"); } + fn ehcont_guard(&mut self) { + if self.sess.target.pointer_width == 64 { + self.cmd.arg("/guard:ehcont"); + } + } + fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]) { match strip { Strip::None => { @@ -1127,6 +1142,8 @@ impl<'a> Linker for EmLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { // Preserve names or generate source maps depending on debug info // For more information see https://emscripten.org/docs/tools_reference/emcc.html#emcc-g @@ -1291,6 +1308,8 @@ impl<'a> Linker for WasmLd<'a> { } fn optimize(&mut self) { + // The -O flag is, as of late 2023, only used for merging of strings and debuginfo, and + // only differentiates -O0 and -O1. It does not apply to LTO. self.cmd.arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", @@ -1319,6 +1338,8 @@ impl<'a> Linker for WasmLd<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn no_crt_objects(&mut self) {} fn no_default_libraries(&mut self) {} @@ -1341,7 +1362,31 @@ impl<'a> Linker for WasmLd<'a> { fn subsystem(&mut self, _subsystem: &str) {} fn linker_plugin_lto(&mut self) { - // Do nothing for now + match self.sess.opts.cg.linker_plugin_lto { + LinkerPluginLto::Disabled => { + // Nothing to do + } + LinkerPluginLto::LinkerPluginAuto => { + self.push_linker_plugin_lto_args(); + } + LinkerPluginLto::LinkerPlugin(_) => { + self.push_linker_plugin_lto_args(); + } + } + } +} + +impl<'a> WasmLd<'a> { + fn push_linker_plugin_lto_args(&mut self) { + let opt_level = match self.sess.opts.optimize { + config::OptLevel::No => "O0", + config::OptLevel::Less => "O1", + config::OptLevel::Default => "O2", + config::OptLevel::Aggressive => "O3", + // wasm-ld only handles integer LTO opt levels. Use O2 + config::OptLevel::Size | config::OptLevel::SizeMin => "O2", + }; + self.cmd.arg(&format!("--lto-{opt_level}")); } } @@ -1472,6 +1517,8 @@ impl<'a> Linker for L4Bender<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn no_crt_objects(&mut self) {} } @@ -1590,7 +1637,7 @@ impl<'a> Linker for AixLinker<'a> { fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) { self.hint_static(); - let lib = find_native_static_library(lib, verbatim, search_path, &self.sess); + let lib = find_native_static_library(lib, verbatim, search_path, self.sess); self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); } @@ -1613,6 +1660,8 @@ impl<'a> Linker for AixLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { match strip { Strip::None => {} @@ -1699,7 +1748,9 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) - let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { if info.level.is_below_threshold(export_threshold) { - symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum)); + symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate( + tcx, symbol, cnum, + )); } }); @@ -1835,6 +1886,8 @@ impl<'a> Linker for PtxLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {} fn subsystem(&mut self, _subsystem: &str) {} @@ -1931,6 +1984,8 @@ impl<'a> Linker for BpfLinker<'a> { fn control_flow_guard(&mut self) {} + fn ehcont_guard(&mut self) {} + fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { let path = tmpdir.join("symbols"); let res: io::Result<()> = try { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index cb60ed729..b683e1b45 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -12,9 +12,9 @@ use object::{ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; +use rustc_metadata::creader::MetadataLoader; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; -use rustc_session::cstore::MetadataLoader; use rustc_session::Session; use rustc_span::sym; use rustc_target::abi::Endian; @@ -158,11 +158,12 @@ pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a file.symbols().find(|sym| sym.name() == Ok(AIX_METADATA_SYMBOL_NAME)) { let offset = metadata_symbol.address() as usize; + // The offset specifies the location of rustc metadata in the .info section of XCOFF. + // Each string stored in .info section of XCOFF is preceded by a 4-byte length field. if offset < 4 { return Err(format!("Invalid metadata symbol offset: {offset}")); } - // The offset specifies the location of rustc metadata in the comment section. - // The metadata is preceded by a 4-byte length field. + // XCOFF format uses big-endian byte order. let len = u32::from_be_bytes(info_data[(offset - 4)..offset].try_into().unwrap()) as usize; if offset + len > (info_data.len() as usize) { return Err(format!( @@ -226,6 +227,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static let mut file = write::Object::new(binary_format, architecture, endianness); if sess.target.is_like_osx { + if macho_is_arm64e(&sess.target) { + file.set_macho_cpu_subtype(object::macho::CPU_SUBTYPE_ARM64E); + } + file.set_macho_build_version(macho_object_build_version_for_target(&sess.target)) } if binary_format == BinaryFormat::Coff { @@ -385,6 +390,11 @@ fn macho_object_build_version_for_target(target: &Target) -> object::write::Mach build_version } +/// Is Apple's CPU subtype `arm64e`s +fn macho_is_arm64e(target: &Target) -> bool { + return target.llvm_target.starts_with("arm64e"); +} + pub enum MetadataPosition { First, Last, @@ -469,8 +479,11 @@ pub fn create_wrapper_file( file.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); file.section_mut(section).flags = SectionFlags::Xcoff { s_flags: xcoff::STYP_INFO as u32 }; - - let len = data.len() as u32; + // Encode string stored in .info section of XCOFF. + // FIXME: The length of data here is not guaranteed to fit in a u32. + // We may have to split the data into multiple pieces in order to + // store in .info section. + let len: u32 = data.len().try_into().unwrap(); let offset = file.append_section_data(section, &len.to_be_bytes(), 1); // Add a symbol referring to the data in .info section. file.add_symbol(Symbol { @@ -515,7 +528,7 @@ pub fn create_compressed_metadata_file( symbol_name: &str, ) -> Vec<u8> { let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec(); - packed_metadata.write_all(&(metadata.raw_data().len() as u32).to_be_bytes()).unwrap(); + packed_metadata.write_all(&(metadata.raw_data().len() as u64).to_le_bytes()).unwrap(); packed_metadata.extend(metadata.raw_data()); let Some(mut file) = create_object_file(sess) else { @@ -590,7 +603,7 @@ pub fn create_compressed_metadata_file_for_xcoff( section: SymbolSection::Section(data_section), flags: SymbolFlags::None, }); - let len = data.len() as u32; + let len: u32 = data.len().try_into().unwrap(); let offset = file.append_section_data(section, &len.to_be_bytes(), 1); // Add a symbol referring to the rustc metadata. file.add_symbol(Symbol { diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 9cd439410..ff667eecf 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{self, SymbolName, TyCtxt}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; -use rustc_target::spec::SanitizerSet; +use rustc_target::spec::{SanitizerSet, TlsModel}; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(tcx.crate_types()) @@ -548,6 +548,12 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); + // thread local will not be a function call, + // so it is safe to return before windows symbol decoration check. + if let Some(name) = maybe_emutls_symbol_name(tcx, symbol, &undecorated) { + return name; + } + let target = &tcx.sess.target; if !target.is_like_windows { // Mach-O has a global "_" suffix and `object` crate will handle it. @@ -608,6 +614,32 @@ 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>( + tcx: TyCtxt<'tcx>, + symbol: ExportedSymbol<'tcx>, + cnum: CrateNum, +) -> String { + let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, cnum); + maybe_emutls_symbol_name(tcx, symbol, &undecorated).unwrap_or(undecorated) +} + +fn maybe_emutls_symbol_name<'tcx>( + tcx: TyCtxt<'tcx>, + symbol: ExportedSymbol<'tcx>, + undecorated: &str, +) -> Option<String> { + if matches!(tcx.sess.tls_model(), TlsModel::Emulated) + && let ExportedSymbol::NonGeneric(def_id) = symbol + && tcx.is_thread_local_static(def_id) + { + // When using emutls, LLVM will add the `__emutls_v.` prefix to thread local symbols, + // and exported symbol name need to match this. + Some(format!("__emutls_v.{undecorated}")) + } else { + None + } +} + fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, String> { // Build up a map from DefId to a `NativeLib` structure, where // `NativeLib` internally contains information about @@ -621,7 +653,7 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, S let mut ret = FxHashMap::default(); for (def_id, lib) in tcx.foreign_modules(cnum).iter() { - let module = def_id_to_native_lib.get(&def_id).and_then(|s| s.wasm_import_module()); + let module = def_id_to_native_lib.get(def_id).and_then(|s| s.wasm_import_module()); let Some(module) = module else { continue }; ret.extend(lib.foreign_items.iter().map(|id| { assert_eq!(id.krate, cnum); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 3d6a21243..d80ef1eba 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -14,7 +14,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; -use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level}; +use rustc_errors::{translation::Translate, DiagCtxt, DiagnosticId, FatalError, Level}; use rustc_errors::{DiagnosticMessage, Style}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -355,7 +355,7 @@ pub struct CodegenContext<B: WriteBackendMethods> { /// how to call the compiler with the same arguments. pub expanded_args: Vec<String>, - /// Handler to use for diagnostics produced during codegen. + /// Emitter to use for diagnostics produced during codegen. pub diag_emitter: SharedEmitter, /// LLVM optimizations for which we want to print remarks. pub remark: Passes, @@ -370,8 +370,8 @@ pub struct CodegenContext<B: WriteBackendMethods> { } impl<B: WriteBackendMethods> CodegenContext<B> { - pub fn create_diag_handler(&self) -> Handler { - Handler::with_emitter(Box::new(self.diag_emitter.clone())) + pub fn create_dcx(&self) -> DiagCtxt { + DiagCtxt::with_emitter(Box::new(self.diag_emitter.clone())) } pub fn config(&self, kind: ModuleKind) -> &ModuleConfig { @@ -569,7 +569,7 @@ fn produce_final_output_artifacts( } if !sess.opts.cg.save_temps && !keep_numbered { // The user just wants `foo.x`, not `foo.#module-name#.x`. - ensure_removed(sess.diagnostic(), &path); + ensure_removed(sess.dcx(), &path); } } else { let extension = crate_output @@ -660,19 +660,19 @@ fn produce_final_output_artifacts( for module in compiled_modules.modules.iter() { if let Some(ref path) = module.object { if !keep_numbered_objects { - ensure_removed(sess.diagnostic(), path); + ensure_removed(sess.dcx(), path); } } if let Some(ref path) = module.dwarf_object { if !keep_numbered_objects { - ensure_removed(sess.diagnostic(), path); + ensure_removed(sess.dcx(), path); } } if let Some(ref path) = module.bytecode { if !keep_numbered_bitcode { - ensure_removed(sess.diagnostic(), path); + ensure_removed(sess.dcx(), path); } } } @@ -680,7 +680,7 @@ fn produce_final_output_artifacts( if !user_wants_bitcode { if let Some(ref allocator_module) = compiled_modules.allocator_module { if let Some(ref path) = allocator_module.bytecode { - ensure_removed(sess.diagnostic(), path); + ensure_removed(sess.dcx(), path); } } } @@ -836,10 +836,10 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>( module: ModuleCodegen<B::Module>, module_config: &ModuleConfig, ) -> Result<WorkItemResult<B>, FatalError> { - let diag_handler = cgcx.create_diag_handler(); + let dcx = cgcx.create_dcx(); unsafe { - B::optimize(cgcx, &diag_handler, &module, module_config)?; + B::optimize(cgcx, &dcx, &module, module_config)?; } // After we've done the initial round of optimizations we need to @@ -892,7 +892,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { - let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path); + let source_file = in_incr_comp_dir(incr_comp_session_dir, saved_path); debug!( "copying preexisting module `{}` from {:?} to {}", module.name, @@ -902,11 +902,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( match link_or_copy(&source_file, &output_path) { Ok(_) => Some(output_path), Err(error) => { - cgcx.create_diag_handler().emit_err(errors::CopyPathBuf { - source_file, - output_path, - error, - }); + cgcx.create_dcx().emit_err(errors::CopyPathBuf { source_file, output_path, error }); None } } @@ -914,7 +910,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( let object = load_from_incr_comp_dir( cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)), - &module.source.saved_files.get("o").expect("no saved object file in work product"), + module.source.saved_files.get("o").expect("no saved object file in work product"), ); let dwarf_object = module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| { @@ -924,7 +920,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( .expect( "saved dwarf object in work product but `split_dwarf_path` returned `None`", ); - load_from_incr_comp_dir(dwarf_obj_out, &saved_dwarf_object_file) + load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file) }); WorkItemResult::Finished(CompiledModule { @@ -950,13 +946,13 @@ fn finish_intra_module_work<B: ExtraBackendMethods>( module: ModuleCodegen<B::Module>, module_config: &ModuleConfig, ) -> Result<WorkItemResult<B>, FatalError> { - let diag_handler = cgcx.create_diag_handler(); + let dcx = cgcx.create_dcx(); if !cgcx.opts.unstable_opts.combine_cgu || module.kind == ModuleKind::Metadata || module.kind == ModuleKind::Allocator { - let module = unsafe { B::codegen(cgcx, &diag_handler, module, module_config)? }; + let module = unsafe { B::codegen(cgcx, &dcx, module, module_config)? }; Ok(WorkItemResult::Finished(module)) } else { Ok(WorkItemResult::NeedsLink(module)) @@ -1609,11 +1605,10 @@ fn start_executing_work<B: ExtraBackendMethods>( let needs_link = mem::take(&mut needs_link); if !needs_link.is_empty() { assert!(compiled_modules.is_empty()); - let diag_handler = cgcx.create_diag_handler(); - let module = B::run_link(&cgcx, &diag_handler, needs_link).map_err(|_| ())?; + let dcx = cgcx.create_dcx(); + let module = B::run_link(&cgcx, &dcx, needs_link).map_err(|_| ())?; let module = unsafe { - B::codegen(&cgcx, &diag_handler, module, cgcx.config(ModuleKind::Regular)) - .map_err(|_| ())? + B::codegen(&cgcx, &dcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())? }; compiled_modules.push(module); } @@ -1856,13 +1851,13 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { - let handler = sess.diagnostic(); + let dcx = sess.dcx(); let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg); if let Some(code) = diag.code { d.code(code); } d.replace_args(diag.args); - handler.emit_diagnostic(&mut d); + dcx.emit_diagnostic(d); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string(); @@ -1870,7 +1865,7 @@ impl SharedEmitterMain { let mut err = match level { Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(), Level::Warning(_) => sess.struct_warn(msg), - Level::Note => sess.struct_note_without_error(msg), + Level::Note => sess.struct_note(msg), _ => bug!("Invalid inline asm diagnostic level"), }; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 198e56963..1d5205ac6 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -148,10 +148,9 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( (&ty::Array(_, len), &ty::Slice(_)) => { cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all())) } - ( - &ty::Dynamic(ref data_a, _, src_dyn_kind), - &ty::Dynamic(ref data_b, _, target_dyn_kind), - ) if src_dyn_kind == target_dyn_kind => { + (&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() { @@ -322,8 +321,13 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if lhs_sz < rhs_sz { bx.trunc(rhs, lhs_llty) } else if lhs_sz > rhs_sz { - // FIXME (#1877: If in the future shifting by negative - // values is no longer undefined then this is wrong. + // We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the + // RHS to `255i32`. But then we mask the shift amount to be within the size of the LHS + // anyway so the result is `31` as it should be. All the extra bits introduced by zext + // are masked off so their value does not matter. + // FIXME: if we ever support 512bit integers, this will be wrong! For such large integers, + // the extra bits introduced by zext are *not* all masked away any more. + assert!(lhs_sz <= 256); bx.zext(rhs, lhs_llty) } else { rhs @@ -453,8 +457,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); - let llbb = Bx::append_block(&cx, llfn, "top"); - let mut bx = Bx::build(&cx, llbb); + let llbb = Bx::append_block(cx, llfn, "top"); + let mut bx = Bx::build(cx, llbb); bx.insert_reference_to_gdb_debug_scripts_section_global(); @@ -680,7 +684,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( // Calculate the CGU reuse let cgu_reuse = tcx.sess.time("find_cgu_reuse", || { - codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::<Vec<_>>() + codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, cgu)).collect::<Vec<_>>() }); crate::assert_module_sources::assert_module_sources(tcx, &|cgu_reuse_tracker| { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 2e0840f2d..e529956b1 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -57,7 +57,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { ); } - let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did)); + let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)); let mut codegen_fn_attrs = CodegenFnAttrs::new(); if tcx.should_inherit_track_caller(did) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; @@ -91,7 +91,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { Some(tcx.fn_sig(did)) } else { tcx.sess - .delay_span_bug(attr.span, "this attribute can only be applied to functions"); + .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); None } }; @@ -386,7 +386,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { [sym::arm, sym::a32] | [sym::arm, sym::t32] => { if !tcx.sess.target.has_thumb_interworking { struct_span_err!( - tcx.sess.diagnostic(), + tcx.sess.dcx(), attr.span, E0779, "target does not support `#[instruction_set]`" @@ -403,7 +403,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } _ => { struct_span_err!( - tcx.sess.diagnostic(), + tcx.sess.dcx(), attr.span, E0779, "invalid instruction set specified", @@ -415,7 +415,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } [] => { struct_span_err!( - tcx.sess.diagnostic(), + tcx.sess.dcx(), attr.span, E0778, "`#[instruction_set]` requires an argument" @@ -425,7 +425,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } _ => { struct_span_err!( - tcx.sess.diagnostic(), + tcx.sess.dcx(), attr.span, E0779, "cannot specify more than one instruction set" @@ -443,7 +443,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { rustc_attr::parse_alignment(&literal.kind) .map_err(|msg| { struct_span_err!( - tcx.sess.diagnostic(), + tcx.sess.dcx(), attr.span, E0589, "invalid `repr(align)` attribute: {}", @@ -469,27 +469,17 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { Some(MetaItemKind::List(ref items)) => { inline_span = Some(attr.span); if items.len() != 1 { - struct_span_err!( - tcx.sess.diagnostic(), - attr.span, - E0534, - "expected one argument" - ) - .emit(); + struct_span_err!(tcx.sess.dcx(), attr.span, E0534, "expected one argument") + .emit(); InlineAttr::None - } else if list_contains_name(&items, sym::always) { + } else if list_contains_name(items, sym::always) { InlineAttr::Always - } else if list_contains_name(&items, sym::never) { + } else if list_contains_name(items, sym::never) { InlineAttr::Never } else { - struct_span_err!( - tcx.sess.diagnostic(), - items[0].span(), - E0535, - "invalid argument" - ) - .help("valid inline arguments are `always` and `never`") - .emit(); + struct_span_err!(tcx.sess.dcx(), items[0].span(), E0535, "invalid argument") + .help("valid inline arguments are `always` and `never`") + .emit(); InlineAttr::None } @@ -503,7 +493,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if !attr.has_name(sym::optimize) { return ia; } - let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit(); + let err = |sp, s| struct_span_err!(tcx.sess.dcx(), sp, E0722, "{}", s).emit(); match attr.meta_kind() { Some(MetaItemKind::Word) => { err(attr.span, "expected one argument"); @@ -514,9 +504,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if items.len() != 1 { err(attr.span, "expected one argument"); OptimizeAttr::None - } else if list_contains_name(&items, sym::size) { + } else if list_contains_name(items, sym::size) { OptimizeAttr::Size - } else if list_contains_name(&items, sym::speed) { + } else if list_contains_name(items, sym::speed) { OptimizeAttr::Speed } else { err(items[0].span(), "invalid argument"); @@ -572,13 +562,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { 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.hir().local_def_id_to_hir_id(did); + let hir_id = tcx.local_def_id_to_hir_id(did); tcx.struct_span_lint_hir( lint::builtin::INLINE_NO_SANITIZE, hir_id, no_sanitize_span, "`no_sanitize` will have no effect after inlining", - |lint| lint.span_note(inline_span, "inlining requested here"), + |lint| { + lint.span_note(inline_span, "inlining requested here"); + }, ) } } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 1a85eb8dd..dda30046b 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -216,7 +216,7 @@ fn push_debuginfo_type_name<'tcx>( output.push(']'); } } - ty::Dynamic(ref trait_data, ..) => { + ty::Dynamic(trait_data, ..) => { let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect(); let has_enclosing_parens = if cpp_like_debuginfo { @@ -249,7 +249,7 @@ fn push_debuginfo_type_name<'tcx>( .projection_bounds() .map(|bound| { let ExistentialProjection { def_id: item_def_id, term, .. } = - tcx.erase_late_bound_regions(bound); + tcx.instantiate_bound_regions_with_erased(bound); // FIXME(associated_const_equality): allow for consts here (item_def_id, term.ty().unwrap()) }) @@ -566,6 +566,9 @@ fn coroutine_kind_label(coroutine_kind: Option<CoroutineKind>) -> &'static str { Some(CoroutineKind::Async(CoroutineSource::Block)) => "async_block", Some(CoroutineKind::Async(CoroutineSource::Closure)) => "async_closure", Some(CoroutineKind::Async(CoroutineSource::Fn)) => "async_fn", + Some(CoroutineKind::AsyncGen(CoroutineSource::Block)) => "async_gen_block", + Some(CoroutineKind::AsyncGen(CoroutineSource::Closure)) => "async_gen_closure", + Some(CoroutineKind::AsyncGen(CoroutineSource::Fn)) => "async_gen_fn", Some(CoroutineKind::Coroutine) => "coroutine", None => "closure", } @@ -594,7 +597,7 @@ fn push_unqualified_item_name( DefPathData::CrateRoot => { output.push_str(tcx.crate_name(def_id.krate).as_str()); } - DefPathData::ClosureExpr => { + DefPathData::Closure => { let label = coroutine_kind_label(tcx.coroutine_kind(def_id)); push_disambiguated_special_name( diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index ed6ac9f9c..668d39afb 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -4,7 +4,7 @@ use crate::assert_module_sources::CguReuse; use crate::back::command::Command; use crate::fluent_generated as fluent; use rustc_errors::{ - DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, IntoDiagnosticArg, }; use rustc_macros::Diagnostic; @@ -210,192 +210,191 @@ pub enum LinkRlibError { pub struct ThorinErrorWrapper(pub thorin::Error); impl IntoDiagnostic<'_> for ThorinErrorWrapper { - fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let mut diag; match self.0 { thorin::Error::ReadInput(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_read_input_failure); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_read_input_failure); diag } thorin::Error::ParseFileKind(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind); diag } thorin::Error::ParseObjectFile(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file); diag } thorin::Error::ParseArchiveFile(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file); diag } thorin::Error::ParseArchiveMember(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_archive_member); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_archive_member); diag } thorin::Error::InvalidInputKind => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind); diag } thorin::Error::DecompressData(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_decompress_data); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_decompress_data); diag } thorin::Error::NamelessSection(_, offset) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_section_without_name); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_without_name); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - diag = - handler.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MultipleRelocations(section, offset) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_relocations); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_relocations); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::UnsupportedRelocation(section, offset) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MissingDwoName(id) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name); diag.set_arg("id", format!("0x{id:08x}")); diag } thorin::Error::NoCompilationUnits => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_no_compilation_units); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_compilation_units); diag } thorin::Error::NoDie => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_no_die); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_die); diag } thorin::Error::TopLevelDieNotUnit => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit); diag } thorin::Error::MissingRequiredSection(section) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_required_section); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_required_section); diag.set_arg("section", section); diag } thorin::Error::ParseUnitAbbreviations(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations); diag } thorin::Error::ParseUnitAttribute(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute); diag } thorin::Error::ParseUnitHeader(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_header); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_header); diag } thorin::Error::ParseUnit(_) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit); diag } thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version); diag.set_arg("section", section); diag.set_arg("actual", actual); diag.set_arg("format", format); diag } thorin::Error::OffsetAtIndex(_, index) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_offset_at_index); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_offset_at_index); diag.set_arg("index", index); diag } thorin::Error::StrAtOffset(_, offset) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_str_at_offset); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_str_at_offset); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::ParseIndex(_, section) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_index); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_index); diag.set_arg("section", section); diag } thorin::Error::UnitNotInIndex(unit) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::RowNotInIndex(_, row) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_row_not_in_index); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_row_not_in_index); diag.set_arg("row", row); diag } thorin::Error::SectionNotInRow => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_section_not_in_row); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_not_in_row); diag } thorin::Error::EmptyUnit(unit) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_empty_unit); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_empty_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MultipleDebugInfoSection => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section); diag } thorin::Error::MultipleDebugTypesSection => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section); diag } thorin::Error::NotSplitUnit => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_not_split_unit); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_split_unit); diag } thorin::Error::DuplicateUnit(unit) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_duplicate_unit); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_duplicate_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MissingReferencedUnit(unit) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::NoOutputObjectCreated => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_not_output_object_created); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_output_object_created); diag } thorin::Error::MixedInputEncodings => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings); diag } thorin::Error::Io(e) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_io); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_io); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectRead(e) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_object_read); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectWrite(e) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_object_write); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_write); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliRead(e) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_read); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliWrite(e) => { - diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_write); + diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_write); diag.set_arg("error", format!("{e}")); diag } @@ -412,8 +411,8 @@ pub struct LinkingFailed<'a> { } impl IntoDiagnostic<'_> for LinkingFailed<'_> { - fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = handler.struct_err(fluent::codegen_ssa_linking_failed); + fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = dcx.struct_err(fluent::codegen_ssa_linking_failed); diag.set_arg("linker_path", format!("{}", self.linker_path.display())); diag.set_arg("exit_status", format!("{}", self.exit_status)); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 156c2904f..09fe138c6 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,7 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(if_let_guard)] @@ -27,8 +27,6 @@ extern crate rustc_middle; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_hir::def_id::CrateNum; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; @@ -53,14 +51,14 @@ pub mod codegen_attrs; pub mod common; pub mod debuginfo; pub mod errors; -pub mod glue; pub mod meth; pub mod mir; pub mod mono_item; +pub mod size_of_val; pub mod target_features; pub mod traits; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub struct ModuleCodegen<M> { /// The name of the module. When the crate may be saved between @@ -218,6 +216,7 @@ impl CodegenResults { sess: &Session, rlink_file: &Path, codegen_results: &CodegenResults, + outputs: &OutputFilenames, ) -> Result<usize, io::Error> { let mut encoder = FileEncoder::new(rlink_file)?; encoder.emit_raw_bytes(RLINK_MAGIC); @@ -226,10 +225,14 @@ impl CodegenResults { encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()); encoder.emit_str(sess.cfg_version); Encodable::encode(codegen_results, &mut encoder); - encoder.finish() + Encodable::encode(outputs, &mut encoder); + encoder.finish().map_err(|(_path, err)| err) } - pub fn deserialize_rlink(sess: &Session, data: Vec<u8>) -> Result<Self, CodegenErrors> { + pub fn deserialize_rlink( + sess: &Session, + data: Vec<u8>, + ) -> Result<(Self, OutputFilenames), CodegenErrors> { // The Decodable machinery is not used here because it panics if the input data is invalid // and because its internal representation may change. if !data.starts_with(RLINK_MAGIC) { @@ -258,6 +261,7 @@ impl CodegenResults { } let codegen_results = CodegenResults::decode(&mut decoder); - Ok(codegen_results) + let outputs = OutputFilenames::decode(&mut decoder); + Ok((codegen_results, outputs)) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 2285e7f4e..c1de9b76f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -36,13 +36,13 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Arguments get assigned to by means of the function being called for arg in mir.args_iter() { - analyzer.assign(arg, DefLocation::Argument); + analyzer.define(arg, DefLocation::Argument); } // 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, data) in traversal::reverse_postorder(mir) { analyzer.visit_basic_block_data(bb, data); } @@ -74,7 +74,7 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { } impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { - fn assign(&mut self, local: mir::Local, location: DefLocation) { + fn define(&mut self, local: mir::Local, location: DefLocation) { let kind = &mut self.locals[local]; match *kind { LocalKind::ZST => {} @@ -162,7 +162,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue); if let Some(local) = place.as_local() { - self.assign(local, DefLocation::Body(location)); + self.define(local, DefLocation::Assignment(location)); if self.locals[local] != LocalKind::Memory { let decl_span = self.fx.mir.local_decls[local].source_info.span; if !self.fx.rvalue_creates_operand(rvalue, decl_span) { @@ -183,9 +183,14 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> fn visit_local(&mut self, local: mir::Local, context: PlaceContext, location: Location) { match context { - PlaceContext::MutatingUse(MutatingUseContext::Call) - | PlaceContext::MutatingUse(MutatingUseContext::Yield) => { - self.assign(local, DefLocation::Body(location)); + PlaceContext::MutatingUse(MutatingUseContext::Call) => { + let call = location.block; + let TerminatorKind::Call { target, .. } = + self.fx.mir.basic_blocks[call].terminator().kind + else { + bug!() + }; + self.define(local, DefLocation::CallReturn { call, target }); } PlaceContext::NonUse(_) @@ -197,7 +202,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> ) => match &mut self.locals[local] { LocalKind::ZST => {} LocalKind::Memory => {} - LocalKind::SSA(def) if def.dominates(location, &self.dominators) => {} + LocalKind::SSA(def) if def.dominates(location, self.dominators) => {} // Reads from uninitialized variables (e.g., in dead code, after // optimizations) require locals to be in (uninitialized) memory. // N.B., there can be uninitialized reads of a local visited after @@ -237,6 +242,8 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } } } + + PlaceContext::MutatingUse(MutatingUseContext::Yield) => bug!(), } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 3d2d8f8b5..a1662f25e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { &self, fx: &'b mut FunctionCx<'a, 'tcx, Bx>, ) -> Option<&'b Bx::Funclet> { - let cleanup_kinds = (&fx.cleanup_kinds).as_ref()?; + let cleanup_kinds = fx.cleanup_kinds.as_ref()?; let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb)?; // If `landing_pad_for` hasn't been called yet to create the `Funclet`, // it has to be now. This may not seem necessary, as RPO should lead @@ -161,7 +161,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ) -> MergingSucc { // If there is a cleanup block and the function we're calling can unwind, then // do an invoke, otherwise do a call. - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let fn_ty = bx.fn_decl_backend_type(fn_abi); let fn_attrs = if bx.tcx().def_kind(fx.instance.def_id()).has_codegen_attrs() { Some(bx.tcx().codegen_fn_attrs(fx.instance.def_id())) @@ -204,9 +204,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { let invokeret = bx.invoke( fn_ty, fn_attrs, - Some(&fn_abi), + Some(fn_abi), fn_ptr, - &llargs, + llargs, ret_llbb, unwind_block, self.funclet(fx), @@ -225,7 +225,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } MergingSucc::False } else { - let llret = bx.call(fn_ty, fn_attrs, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx)); + let llret = bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, llargs, self.funclet(fx)); if fx.mir[self.bb].is_cleanup { bx.apply_attrs_to_cleanup_callsite(llret); } @@ -273,7 +273,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { bx.codegen_inline_asm( template, - &operands, + operands, options, line_spans, instance, @@ -281,7 +281,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ); MergingSucc::False } else { - bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None); + bx.codegen_inline_asm(template, operands, options, line_spans, instance, None); if let Some(target) = destination { self.funclet_br(fx, bx, target, mergeable_succ) @@ -318,7 +318,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { discr: &mir::Operand<'tcx>, targets: &SwitchTargets, ) { - let discr = self.codegen_operand(bx, &discr); + let discr = self.codegen_operand(bx, discr); let switch_ty = discr.layout.ty; let mut target_iter = targets.iter(); if target_iter.len() == 1 { @@ -498,7 +498,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args = &args[..1]; ( meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) - .get_fn(bx, vtable, ty, &fn_abi), + .get_fn(bx, vtable, ty, fn_abi), fn_abi, ) } @@ -540,7 +540,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { debug!("args' = {:?}", args); ( meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) - .get_fn(bx, meta.immediate(), ty, &fn_abi), + .get_fn(bx, meta.immediate(), ty, fn_abi), fn_abi, ) } @@ -864,7 +864,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // promotes any complex rvalues to constants. if i == 2 && intrinsic == sym::simd_shuffle { if let mir::Operand::Constant(constant) = arg { - let (llval, ty) = self.simd_shuffle_indices(&bx, constant); + let (llval, ty) = self.simd_shuffle_indices(bx, constant); return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty), @@ -881,7 +881,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Self::codegen_intrinsic_call( bx, *instance.as_ref().unwrap(), - &fn_abi, + fn_abi, &args, dest, span, @@ -937,7 +937,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, meta, op.layout.ty, - &fn_abi, + fn_abi, )); llargs.push(data_ptr); continue 'make_args; @@ -948,7 +948,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, meta, op.layout.ty, - &fn_abi, + fn_abi, )); llargs.push(data_ptr); continue; @@ -975,7 +975,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, meta.immediate(), op.layout.ty, - &fn_abi, + fn_abi, )); llargs.push(data_ptr.llval); continue; @@ -1587,9 +1587,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item()); - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let fn_ty = bx.fn_decl_backend_type(fn_abi); - let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); + let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref()); bx.apply_attrs_to_cleanup_callsite(llret); bx.unreachable(); @@ -1662,10 +1662,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } else { - self.codegen_place( - bx, - mir::PlaceRef { local: dest.local, projection: &dest.projection }, - ) + self.codegen_place(bx, mir::PlaceRef { local: dest.local, projection: dest.projection }) }; if fn_ret.is_indirect() { if dest.align < dest.layout.align.abi { @@ -1696,7 +1693,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match dest { Nothing => (), - Store(dst) => bx.store_arg(&ret_abi, llval, dst), + Store(dst) => bx.store_arg(ret_abi, llval, dst), IndirectOperand(tmp, index) => { let op = bx.load_operand(tmp); tmp.storage_dead(bx); @@ -1708,7 +1705,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let op = if let PassMode::Cast { .. } = ret_abi.mode { let tmp = PlaceRef::alloca(bx, ret_abi.layout); tmp.storage_live(bx); - bx.store_arg(&ret_abi, llval, tmp); + bx.store_arg(ret_abi, llval, tmp); let op = bx.load_operand(tmp); tmp.storage_dead(bx); op diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 0dc30d21c..14915e816 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -398,7 +398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return }; let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } = - calculate_debuginfo_offset(bx, &var.projection, base.layout); + calculate_debuginfo_offset(bx, var.projection, base.layout); // When targeting MSVC, create extra allocas for arguments instead of pointing multiple // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records @@ -416,7 +416,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if should_create_individual_allocas { let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } = - calculate_debuginfo_offset(bx, &var.projection, base); + calculate_debuginfo_offset(bx, var.projection, base); // Create a variable which will be a pointer to the actual value let ptr_ty = Ty::new_ptr( diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 136d06d56..a5bffc33d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -4,8 +4,8 @@ use super::FunctionCx; use crate::common::IntPredicate; use crate::errors; use crate::errors::InvalidMonomorphization; -use crate::glue; use crate::meth; +use crate::size_of_val; use crate::traits::*; use crate::MemFlags; @@ -88,21 +88,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { sym::va_end => bx.va_end(args[0].immediate()), sym::size_of_val => { let tp_ty = fn_args.type_at(0); - if let OperandValue::Pair(_, meta) = args[0].val { - let (llsize, _) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta)); - llsize - } else { - bx.const_usize(bx.layout_of(tp_ty).size.bytes()) - } + let meta = + if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None }; + let (llsize, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta); + llsize } sym::min_align_of_val => { let tp_ty = fn_args.type_at(0); - if let OperandValue::Pair(_, meta) = args[0].val { - let (_, llalign) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta)); - llalign - } else { - bx.const_usize(bx.layout_of(tp_ty).align.abi.bytes()) - } + let meta = + if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None }; + let (_, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta); + llalign } sym::vtable_size | sym::vtable_align => { let vtable = args[0].immediate(); diff --git a/compiler/rustc_codegen_ssa/src/mir/locals.rs b/compiler/rustc_codegen_ssa/src/mir/locals.rs index 378c54013..7db260c9f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/locals.rs +++ b/compiler/rustc_codegen_ssa/src/mir/locals.rs @@ -43,7 +43,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let local = mir::Local::from_usize(local); let expected_ty = self.monomorphize(self.mir.local_decls[local].ty); if expected_ty != op.layout.ty { - warn!("Unexpected initial operand type. See the issues/114858"); + warn!( + "Unexpected initial operand type: expected {expected_ty:?}, found {:?}.\ + See <https://github.com/rust-lang/rust/issues/114858>.", + op.layout.ty + ); } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index d0b799e08..a6fcf1fd3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -168,7 +168,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); - let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); + let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, mir); let start_llbb = Bx::append_block(cx, llfn, "start"); let mut start_bx = Bx::build(cx, start_llbb); @@ -180,7 +180,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let cleanup_kinds = - base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir)); + base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(mir)); let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> = mir.basic_blocks @@ -261,7 +261,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( drop(start_bx); // Codegen the body of each block using reverse postorder - for (bb, _) in traversal::reverse_postorder(&mir) { + for (bb, _) in traversal::reverse_postorder(mir) { fx.codegen_block(bb); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 0ab2b7ecd..794cbd315 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -2,7 +2,7 @@ use super::place::PlaceRef; use super::{FunctionCx, LocalRef}; use crate::base; -use crate::glue; +use crate::size_of_val; use crate::traits::*; use crate::MemFlags; @@ -105,7 +105,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { bug!("from_const: invalid ScalarPair layout: {:#?}", layout); }; let a = Scalar::from_pointer( - Pointer::new(bx.tcx().reserve_and_set_memory_alloc(data), Size::ZERO), + Pointer::new(bx.tcx().reserve_and_set_memory_alloc(data).into(), Size::ZERO), &bx.tcx(), ); let a_llval = bx.scalar_to_backend( @@ -132,7 +132,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { offset: Size, ) -> Self { let alloc_align = alloc.inner().align; - assert_eq!(alloc_align, layout.align.abi); + assert!(alloc_align >= layout.align.abi); let read_scalar = |start, size, s: abi::Scalar, ty| { match alloc.0.read_scalar( @@ -155,7 +155,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => { let size = s.size(bx); assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - let val = read_scalar(offset, size, s, bx.backend_type(layout)); + let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout)); OperandRef { val: OperandValue::Immediate(val), layout } } Abi::ScalarPair( @@ -414,6 +414,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { // value is through `undef`/`poison`, and the store itself is useless. } OperandValue::Ref(r, None, source_align) => { + assert!(dest.layout.is_sized(), "cannot directly store unsized values"); if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. let ty = bx.backend_type(dest.layout); @@ -465,13 +466,13 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { .ty; let OperandValue::Ref(llptr, Some(llextra), _) = self else { - bug!("store_unsized called with a sized value") + bug!("store_unsized called with a sized value (or with an extern type)") }; // Allocate an appropriate region on the stack, and copy the value into it. Since alloca // doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the // pointer manually. - let (size, align) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); + let (size, align) = size_of_val::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); let one = bx.const_usize(1); let align_minus_1 = bx.sub(align, one); let size_extra = bx.add(size, align_minus_1); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index eb590a45a..c0bb3ac56 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -2,7 +2,7 @@ use super::operand::OperandValue; use super::{FunctionCx, LocalRef}; use crate::common::IntPredicate; -use crate::glue; +use crate::size_of_val; use crate::traits::*; use rustc_middle::mir; @@ -99,6 +99,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let offset = self.layout.fields.offset(ix); let effective_field_align = self.align.restrict_for_offset(offset); + // `simple` is called when we don't need to adjust the offset to + // the dynamic alignment of the field. let mut simple = || { let llval = match self.layout.abi { _ if offset.bytes() == 0 => { @@ -141,35 +143,21 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { }; // Simple cases, which don't need DST adjustment: - // * no metadata available - just log the case - // * known alignment - sized types, `[T]`, `str` or a foreign type - // * packed struct - there is no alignment padding + // * known alignment - sized types, `[T]`, `str` + // * offset 0 -- rounding up to alignment cannot change the offset + // Note that looking at `field.align` is incorrect since that is not necessarily equal + // to the dynamic alignment of the type. match field.ty.kind() { - _ if self.llextra.is_none() => { - debug!( - "unsized field `{}`, of `{:?}` has no metadata for adjustment", - ix, self.llval - ); - return simple(); - } _ if field.is_sized() => return simple(), - ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(), - ty::Adt(def, _) => { - if def.repr().packed() { - // FIXME(eddyb) generalize the adjustment when we - // start supporting packing to larger alignments. - assert_eq!(self.layout.align.abi.bytes(), 1); - return simple(); - } - } + ty::Slice(..) | ty::Str => return simple(), + _ if offset.bytes() == 0 => return simple(), _ => {} } // We need to get the pointer manually now. // We do this by casting to a `*i8`, then offsetting it by the appropriate amount. // We do this instead of, say, simply adjusting the pointer from the result of a GEP - // because the field may have an arbitrary alignment in the LLVM representation - // anyway. + // because the field may have an arbitrary alignment in the LLVM representation. // // To demonstrate: // @@ -186,7 +174,16 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let unaligned_offset = bx.cx().const_usize(offset.bytes()); // Get the alignment of the field - let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta); + let (_, mut unsized_align) = size_of_val::size_and_align_of_dst(bx, field.ty, meta); + + // For packed types, we need to cap alignment. + if let ty::Adt(def, _) = self.layout.ty.kind() + && let Some(packed) = def.repr().pack + { + let packed = bx.const_usize(packed.bytes()); + let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed); + unsized_align = bx.select(cmp, unsized_align, packed) + } // Bump the unaligned offset up to the appropriate alignment let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align); @@ -474,27 +471,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_base.project_index(bx, llindex) } mir::ProjectionElem::ConstantIndex { offset, from_end: false, min_length: _ } => { - let lloffset = bx.cx().const_usize(offset as u64); + let lloffset = bx.cx().const_usize(offset); cg_base.project_index(bx, lloffset) } mir::ProjectionElem::ConstantIndex { offset, from_end: true, min_length: _ } => { - let lloffset = bx.cx().const_usize(offset as u64); + let lloffset = bx.cx().const_usize(offset); let lllen = cg_base.len(bx.cx()); let llindex = bx.sub(lllen, lloffset); cg_base.project_index(bx, llindex) } mir::ProjectionElem::Subslice { from, to, from_end } => { - let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from as u64)); + let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(from)); let projected_ty = PlaceTy::from_ty(cg_base.layout.ty).projection_ty(tcx, *elem).ty; subslice.layout = bx.cx().layout_of(self.monomorphize(projected_ty)); if subslice.layout.is_unsized() { assert!(from_end, "slice subslices should be `from_end`"); - subslice.llextra = Some(bx.sub( - cg_base.llextra.unwrap(), - bx.cx().const_usize((from as u64) + (to as u64)), - )); + subslice.llextra = + Some(bx.sub(cg_base.llextra.unwrap(), bx.cx().const_usize(from + to))); } subslice diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 8e5019967..02b51dfe5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -702,7 +702,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let fn_ptr = bx.get_fn_addr(instance); let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let fn_ty = bx.fn_decl_backend_type(fn_abi); let fn_attrs = if bx.tcx().def_kind(instance.def_id()).has_codegen_attrs() { Some(bx.tcx().codegen_fn_attrs(instance.def_id())) } else { diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 899e41265..a158fc6e2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -3,7 +3,6 @@ use rustc_middle::mir::NonDivergingIntrinsic; use super::FunctionCx; use super::LocalRef; -use crate::traits::BuilderMethods; use crate::traits::*; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 6fbf992ed..295e27691 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -34,7 +34,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir().item(item_id); - if let hir::ItemKind::GlobalAsm(ref asm) = item.kind { + if let hir::ItemKind::GlobalAsm(asm) = item.kind { let operands: Vec<_> = asm .operands .iter() @@ -88,7 +88,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } } MonoItem::Fn(instance) => { - base::codegen_instance::<Bx>(&cx, instance); + base::codegen_instance::<Bx>(cx, instance); } } @@ -119,10 +119,10 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { match *self { MonoItem::Static(def_id) => { - cx.predefine_static(def_id, linkage, visibility, &symbol_name); + cx.predefine_static(def_id, linkage, visibility, symbol_name); } MonoItem::Fn(instance) => { - cx.predefine_fn(instance, linkage, visibility, &symbol_name); + cx.predefine_fn(instance, linkage, visibility, symbol_name); } MonoItem::GlobalAsm(..) => {} } diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index c34f1dbf8..087836ca3 100644 --- a/compiler/rustc_codegen_ssa/src/glue.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -1,10 +1,11 @@ -//! -// -// Code relating to drop glue. +//! Computing the size and alignment of a value. +use crate::common; use crate::common::IntPredicate; use crate::meth; use crate::traits::*; +use rustc_hir::LangItem; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::WrappingRange; @@ -14,7 +15,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( info: Option<Bx::Value>, ) -> (Bx::Value, Bx::Value) { let layout = bx.layout_of(t); - debug!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", t, info, layout); + trace!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", t, info, layout); if layout.is_sized() { let size = bx.const_usize(layout.size.bytes()); let align = bx.const_usize(layout.align.abi.bytes()); @@ -51,7 +52,31 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx.const_usize(unit.align.abi.bytes()), ) } - _ => { + ty::Foreign(_) => { + // `extern` type. We cannot compute the size, so panic. + let msg_str = with_no_visible_paths!({ + with_no_trimmed_paths!({ + format!("attempted to compute the size or alignment of extern type `{t}`") + }) + }); + let msg = bx.const_str(&msg_str); + + // Obtain the panic entry point. + let (fn_abi, llfn) = 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.) + let fn_ty = bx.fn_decl_backend_type(fn_abi); + + bx.call(fn_ty, /* fn_attrs */ None, Some(fn_abi), llfn, &[msg.0, msg.1], None); + + // This function does not return so we can now return whatever we want. + let size = bx.const_usize(layout.size.bytes()); + let align = bx.const_usize(layout.align.abi.bytes()); + (size, align) + } + ty::Adt(..) | ty::Tuple(..) => { // First get the size of all statically known fields. // Don't use size_of because it also rounds up to alignment, which we // want to avoid, as the unsized field's alignment could be smaller. @@ -59,10 +84,13 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( debug!("DST {} layout: {:?}", t, layout); let i = layout.fields.count() - 1; - let sized_size = layout.fields.offset(i).bytes(); + let unsized_offset_unadjusted = layout.fields.offset(i).bytes(); let sized_align = layout.align.abi.bytes(); - debug!("DST {} statically sized prefix size: {} align: {}", t, sized_size, sized_align); - let sized_size = bx.const_usize(sized_size); + debug!( + "DST {} offset of dyn field: {}, statically sized align: {}", + t, unsized_offset_unadjusted, sized_align + ); + let unsized_offset_unadjusted = bx.const_usize(unsized_offset_unadjusted); let sized_align = bx.const_usize(sized_align); // Recurse to get the size of the dynamically sized field (must be @@ -70,26 +98,26 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let field_ty = layout.field(bx, i).ty; let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info); - // FIXME (#26403, #27023): We should be adding padding - // to `sized_size` (to accommodate the `unsized_align` - // required of the unsized field that follows) before - // summing it with `sized_size`. (Note that since #26403 - // is unfixed, we do not yet add the necessary padding - // here. But this is where the add would go.) + // # First compute the dynamic alignment - // Return the sum of sizes and max of aligns. - let size = bx.add(sized_size, unsized_size); - - // Packed types ignore the alignment of their fields. - if let ty::Adt(def, _) = t.kind() { - if def.repr().packed() { - unsized_align = sized_align; + // For packed types, we need to cap the alignment. + if let ty::Adt(def, _) = t.kind() + && let Some(packed) = def.repr().pack + { + if packed.bytes() == 1 { + // We know this will be capped to 1. + unsized_align = bx.const_usize(1); + } else { + // We have to dynamically compute `min(unsized_align, packed)`. + let packed = bx.const_usize(packed.bytes()); + let cmp = bx.icmp(IntPredicate::IntULT, unsized_align, packed); + unsized_align = bx.select(cmp, unsized_align, packed); } } // Choose max of two known alignments (combined value must // be aligned according to more restrictive of the two). - let align = match ( + let full_align = match ( bx.const_to_opt_u128(sized_align, false), bx.const_to_opt_u128(unsized_align, false), ) { @@ -104,6 +132,19 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } }; + // # Then compute the dynamic size + + // 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); + // Furthermore, `align >= unsized_align`, and therefore we only need to do: + // let full_size = (unsized_offset_unadjusted + unsized_size).align_to(full_align); + + let full_size = bx.add(unsized_offset_unadjusted, unsized_size); + // Issue #27023: must add any necessary padding to `size` // (to make it a multiple of `align`) before returning it. // @@ -115,12 +156,13 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // // `(size + (align-1)) & -align` let one = bx.const_usize(1); - let addend = bx.sub(align, one); - let add = bx.add(size, addend); - let neg = bx.neg(align); - let size = bx.and(add, neg); + let addend = bx.sub(full_align, one); + let add = bx.add(full_size, addend); + let neg = bx.neg(full_align); + let full_size = bx.and(add, neg); - (size, align) + (full_size, full_align) } + _ => bug!("size_and_align_of_dst: {t} not supported"), } } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 2936f1de3..0b9b08c6a 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -11,403 +11,10 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; -use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::symbol::Symbol; use rustc_span::Span; -/// Features that control behaviour of rustc, rather than the codegen. -pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; - -// When adding features to the below lists -// check whether they're named already elsewhere in rust -// e.g. in stdarch and whether the given name matches LLVM's -// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted -// -// When adding a new feature, be particularly mindful of features that affect function ABIs. Those -// need to be treated very carefully to avoid introducing unsoundness! This often affects features -// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an -// example of this going wrong), but features enabling new SIMD registers are also a concern (see -// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong). -// -// Stabilizing a target feature (setting the 2nd component of the pair to `None`) requires t-lang -// approval. - -const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("aclass", Some(sym::arm_target_feature)), - ("aes", Some(sym::arm_target_feature)), - ("crc", Some(sym::arm_target_feature)), - ("d32", Some(sym::arm_target_feature)), - ("dotprod", Some(sym::arm_target_feature)), - ("dsp", Some(sym::arm_target_feature)), - ("fp-armv8", Some(sym::arm_target_feature)), - ("i8mm", Some(sym::arm_target_feature)), - ("mclass", Some(sym::arm_target_feature)), - ("neon", Some(sym::arm_target_feature)), - ("rclass", Some(sym::arm_target_feature)), - ("sha2", Some(sym::arm_target_feature)), - // This is needed for inline assembly, but shouldn't be stabilized as-is - // since it should be enabled per-function using #[instruction_set], not - // #[target_feature]. - ("thumb-mode", Some(sym::arm_target_feature)), - ("thumb2", Some(sym::arm_target_feature)), - ("trustzone", Some(sym::arm_target_feature)), - ("v5te", Some(sym::arm_target_feature)), - ("v6", Some(sym::arm_target_feature)), - ("v6k", Some(sym::arm_target_feature)), - ("v6t2", Some(sym::arm_target_feature)), - ("v7", Some(sym::arm_target_feature)), - ("v8", Some(sym::arm_target_feature)), - ("vfp2", Some(sym::arm_target_feature)), - ("vfp3", Some(sym::arm_target_feature)), - ("vfp4", Some(sym::arm_target_feature)), - ("virtualization", Some(sym::arm_target_feature)), - // tidy-alphabetical-end -]; - -const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - // FEAT_AES - ("aes", None), - // FEAT_BF16 - ("bf16", None), - // FEAT_BTI - ("bti", None), - // FEAT_CRC - ("crc", None), - // FEAT_DIT - ("dit", None), - // FEAT_DotProd - ("dotprod", None), - // FEAT_DPB - ("dpb", None), - // FEAT_DPB2 - ("dpb2", None), - // FEAT_F32MM - ("f32mm", None), - // FEAT_F64MM - ("f64mm", None), - // FEAT_FCMA - ("fcma", None), - // FEAT_FHM - ("fhm", None), - // FEAT_FLAGM - ("flagm", None), - // FEAT_FP16 - ("fp16", None), - // FEAT_FRINTTS - ("frintts", None), - // FEAT_I8MM - ("i8mm", None), - // FEAT_JSCVT - ("jsconv", None), - // FEAT_LOR - ("lor", None), - // FEAT_LSE - ("lse", None), - // FEAT_MTE - ("mte", None), - // FEAT_AdvSimd & FEAT_FP - ("neon", None), - // FEAT_PAUTH (address authentication) - ("paca", None), - // FEAT_PAUTH (generic authentication) - ("pacg", None), - // FEAT_PAN - ("pan", None), - // FEAT_PMUv3 - ("pmuv3", None), - // FEAT_RAND - ("rand", None), - // FEAT_RAS - ("ras", None), - // FEAT_RCPC - ("rcpc", None), - // FEAT_RCPC2 - ("rcpc2", None), - // FEAT_RDM - ("rdm", None), - // FEAT_SB - ("sb", None), - // FEAT_SHA1 & FEAT_SHA256 - ("sha2", None), - // FEAT_SHA512 & FEAT_SHA3 - ("sha3", None), - // FEAT_SM3 & FEAT_SM4 - ("sm4", None), - // FEAT_SPE - ("spe", None), - // FEAT_SSBS - ("ssbs", None), - // FEAT_SVE - ("sve", None), - // FEAT_SVE2 - ("sve2", None), - // FEAT_SVE2_AES - ("sve2-aes", None), - // FEAT_SVE2_BitPerm - ("sve2-bitperm", None), - // FEAT_SVE2_SHA3 - ("sve2-sha3", None), - // FEAT_SVE2_SM4 - ("sve2-sm4", None), - // FEAT_TME - ("tme", None), - ("v8.1a", Some(sym::aarch64_ver_target_feature)), - ("v8.2a", Some(sym::aarch64_ver_target_feature)), - ("v8.3a", Some(sym::aarch64_ver_target_feature)), - ("v8.4a", Some(sym::aarch64_ver_target_feature)), - ("v8.5a", Some(sym::aarch64_ver_target_feature)), - ("v8.6a", Some(sym::aarch64_ver_target_feature)), - ("v8.7a", Some(sym::aarch64_ver_target_feature)), - // FEAT_VHE - ("vh", None), - // tidy-alphabetical-end -]; - -const AARCH64_TIED_FEATURES: &[&[&str]] = &[ - &["paca", "pacg"], // Together these represent `pauth` in LLVM -]; - -const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("adx", None), - ("aes", None), - ("avx", None), - ("avx2", None), - ("avx512bf16", Some(sym::avx512_target_feature)), - ("avx512bitalg", Some(sym::avx512_target_feature)), - ("avx512bw", Some(sym::avx512_target_feature)), - ("avx512cd", Some(sym::avx512_target_feature)), - ("avx512dq", Some(sym::avx512_target_feature)), - ("avx512er", Some(sym::avx512_target_feature)), - ("avx512f", Some(sym::avx512_target_feature)), - ("avx512ifma", Some(sym::avx512_target_feature)), - ("avx512pf", Some(sym::avx512_target_feature)), - ("avx512vbmi", Some(sym::avx512_target_feature)), - ("avx512vbmi2", Some(sym::avx512_target_feature)), - ("avx512vl", Some(sym::avx512_target_feature)), - ("avx512vnni", Some(sym::avx512_target_feature)), - ("avx512vp2intersect", Some(sym::avx512_target_feature)), - ("avx512vpopcntdq", Some(sym::avx512_target_feature)), - ("bmi1", None), - ("bmi2", None), - ("cmpxchg16b", None), - ("ermsb", Some(sym::ermsb_target_feature)), - ("f16c", None), - ("fma", None), - ("fxsr", None), - ("gfni", Some(sym::avx512_target_feature)), - ("lzcnt", None), - ("movbe", None), - ("pclmulqdq", None), - ("popcnt", None), - ("rdrand", None), - ("rdseed", None), - ("rtm", Some(sym::rtm_target_feature)), - ("sha", None), - ("sse", None), - ("sse2", None), - ("sse3", None), - ("sse4.1", None), - ("sse4.2", None), - ("sse4a", Some(sym::sse4a_target_feature)), - ("ssse3", None), - ("tbm", Some(sym::tbm_target_feature)), - ("vaes", Some(sym::avx512_target_feature)), - ("vpclmulqdq", Some(sym::avx512_target_feature)), - ("xsave", None), - ("xsavec", None), - ("xsaveopt", None), - ("xsaves", None), - // tidy-alphabetical-end -]; - -const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("hvx", Some(sym::hexagon_target_feature)), - ("hvx-length128b", Some(sym::hexagon_target_feature)), - // tidy-alphabetical-end -]; - -const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("altivec", Some(sym::powerpc_target_feature)), - ("power10-vector", Some(sym::powerpc_target_feature)), - ("power8-altivec", Some(sym::powerpc_target_feature)), - ("power8-vector", Some(sym::powerpc_target_feature)), - ("power9-altivec", Some(sym::powerpc_target_feature)), - ("power9-vector", Some(sym::powerpc_target_feature)), - ("vsx", Some(sym::powerpc_target_feature)), - // tidy-alphabetical-end -]; - -const MIPS_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("fp64", Some(sym::mips_target_feature)), - ("msa", Some(sym::mips_target_feature)), - ("virt", Some(sym::mips_target_feature)), - // tidy-alphabetical-end -]; - -const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("a", None), - ("c", None), - ("d", Some(sym::riscv_target_feature)), - ("e", Some(sym::riscv_target_feature)), - ("f", Some(sym::riscv_target_feature)), - ("m", None), - ("relax", Some(sym::riscv_target_feature)), - ("unaligned-scalar-mem", Some(sym::riscv_target_feature)), - ("v", Some(sym::riscv_target_feature)), - ("zba", None), - ("zbb", None), - ("zbc", None), - ("zbkb", None), - ("zbkc", None), - ("zbkx", None), - ("zbs", None), - ("zdinx", Some(sym::riscv_target_feature)), - ("zfh", Some(sym::riscv_target_feature)), - ("zfhmin", Some(sym::riscv_target_feature)), - ("zfinx", Some(sym::riscv_target_feature)), - ("zhinx", Some(sym::riscv_target_feature)), - ("zhinxmin", Some(sym::riscv_target_feature)), - ("zk", None), - ("zkn", None), - ("zknd", None), - ("zkne", None), - ("zknh", None), - ("zkr", None), - ("zks", None), - ("zksed", None), - ("zksh", None), - ("zkt", None), - // tidy-alphabetical-end -]; - -const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("atomics", Some(sym::wasm_target_feature)), - ("bulk-memory", Some(sym::wasm_target_feature)), - ("exception-handling", Some(sym::wasm_target_feature)), - ("multivalue", Some(sym::wasm_target_feature)), - ("mutable-globals", Some(sym::wasm_target_feature)), - ("nontrapping-fptoint", Some(sym::wasm_target_feature)), - ("reference-types", Some(sym::wasm_target_feature)), - ("relaxed-simd", Some(sym::wasm_target_feature)), - ("sign-ext", Some(sym::wasm_target_feature)), - ("simd128", None), - // tidy-alphabetical-end -]; - -const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))]; - -const CSKY_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("10e60", Some(sym::csky_target_feature)), - ("2e3", Some(sym::csky_target_feature)), - ("3e3r1", Some(sym::csky_target_feature)), - ("3e3r2", Some(sym::csky_target_feature)), - ("3e3r3", Some(sym::csky_target_feature)), - ("3e7", Some(sym::csky_target_feature)), - ("7e10", Some(sym::csky_target_feature)), - ("cache", Some(sym::csky_target_feature)), - ("doloop", Some(sym::csky_target_feature)), - ("dsp1e2", Some(sym::csky_target_feature)), - ("dspe60", Some(sym::csky_target_feature)), - ("e1", Some(sym::csky_target_feature)), - ("e2", Some(sym::csky_target_feature)), - ("edsp", Some(sym::csky_target_feature)), - ("elrw", Some(sym::csky_target_feature)), - ("float1e2", Some(sym::csky_target_feature)), - ("float1e3", Some(sym::csky_target_feature)), - ("float3e4", Some(sym::csky_target_feature)), - ("float7e60", Some(sym::csky_target_feature)), - ("floate1", Some(sym::csky_target_feature)), - ("hard-tp", Some(sym::csky_target_feature)), - ("high-registers", Some(sym::csky_target_feature)), - ("hwdiv", Some(sym::csky_target_feature)), - ("mp", Some(sym::csky_target_feature)), - ("mp1e2", Some(sym::csky_target_feature)), - ("nvic", Some(sym::csky_target_feature)), - ("trust", Some(sym::csky_target_feature)), - ("vdsp2e60f", Some(sym::csky_target_feature)), - ("vdspv1", Some(sym::csky_target_feature)), - ("vdspv2", Some(sym::csky_target_feature)), - // tidy-alphabetical-end - //fpu - // tidy-alphabetical-start - ("fdivdu", Some(sym::csky_target_feature)), - ("fpuv2_df", Some(sym::csky_target_feature)), - ("fpuv2_sf", Some(sym::csky_target_feature)), - ("fpuv3_df", Some(sym::csky_target_feature)), - ("fpuv3_hf", Some(sym::csky_target_feature)), - ("fpuv3_hi", Some(sym::csky_target_feature)), - ("fpuv3_sf", Some(sym::csky_target_feature)), - ("hard-float", Some(sym::csky_target_feature)), - ("hard-float-abi", Some(sym::csky_target_feature)), - // tidy-alphabetical-end -]; - -const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ - // tidy-alphabetical-start - ("d", Some(sym::loongarch_target_feature)), - ("f", Some(sym::loongarch_target_feature)), - ("lasx", Some(sym::loongarch_target_feature)), - ("lbt", Some(sym::loongarch_target_feature)), - ("lsx", Some(sym::loongarch_target_feature)), - ("lvz", Some(sym::loongarch_target_feature)), - ("ual", Some(sym::loongarch_target_feature)), - // tidy-alphabetical-end -]; - -/// When rustdoc is running, provide a list of all known features so that all their respective -/// primitives may be documented. -/// -/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! -pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> { - std::iter::empty() - .chain(ARM_ALLOWED_FEATURES.iter()) - .chain(AARCH64_ALLOWED_FEATURES.iter()) - .chain(X86_ALLOWED_FEATURES.iter()) - .chain(HEXAGON_ALLOWED_FEATURES.iter()) - .chain(POWERPC_ALLOWED_FEATURES.iter()) - .chain(MIPS_ALLOWED_FEATURES.iter()) - .chain(RISCV_ALLOWED_FEATURES.iter()) - .chain(WASM_ALLOWED_FEATURES.iter()) - .chain(BPF_ALLOWED_FEATURES.iter()) - .chain(CSKY_ALLOWED_FEATURES) - .chain(LOONGARCH_ALLOWED_FEATURES) - .cloned() -} - -pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] { - match &*sess.target.arch { - "arm" => ARM_ALLOWED_FEATURES, - "aarch64" => AARCH64_ALLOWED_FEATURES, - "x86" | "x86_64" => X86_ALLOWED_FEATURES, - "hexagon" => HEXAGON_ALLOWED_FEATURES, - "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES, - "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, - "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, - "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, - "bpf" => BPF_ALLOWED_FEATURES, - "csky" => CSKY_ALLOWED_FEATURES, - "loongarch64" => LOONGARCH_ALLOWED_FEATURES, - _ => &[], - } -} - -pub fn tied_target_features(sess: &Session) -> &'static [&'static [&'static str]] { - match &*sess.target.arch { - "aarch64" => AARCH64_TIED_FEATURES, - _ => &[], - } -} - pub fn from_target_feature( tcx: TyCtxt<'_>, attr: &ast::Attribute, @@ -529,11 +136,15 @@ pub(crate) fn provide(providers: &mut Providers) { if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all - all_known_features().map(|(a, b)| (a.to_string(), b)).collect() + rustc_target::target_features::all_known_features() + .map(|(a, b)| (a.to_string(), b.as_feature_name())) + .collect() } else { - supported_target_features(tcx.sess) + tcx.sess + .target + .supported_target_features() .iter() - .map(|&(a, b)| (a.to_string(), b)) + .map(|&(a, b)| (a.to_string(), b.as_feature_name())) .collect() } }, diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 35744d9a1..8e9907ed8 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -9,6 +9,7 @@ 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_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; @@ -16,7 +17,6 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, - cstore::MetadataLoaderDyn, Session, }; use rustc_span::symbol::Symbol; diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index ecf5095d8..048540894 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -2,7 +2,7 @@ use crate::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig}; use crate::{CompiledModule, ModuleCodegen}; -use rustc_errors::{FatalError, Handler}; +use rustc_errors::{DiagCtxt, FatalError}; use rustc_middle::dep_graph::WorkProduct; pub trait WriteBackendMethods: 'static + Sized + Clone { @@ -16,7 +16,7 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { /// Merge all modules into main_module and returning it fn run_link( cgcx: &CodegenContext<Self>, - diag_handler: &Handler, + dcx: &DiagCtxt, modules: Vec<ModuleCodegen<Self::Module>>, ) -> Result<ModuleCodegen<Self::Module>, FatalError>; /// Performs fat LTO by merging all modules into a single one and returning it @@ -38,7 +38,7 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { fn print_statistics(&self); unsafe fn optimize( cgcx: &CodegenContext<Self>, - diag_handler: &Handler, + dcx: &DiagCtxt, module: &ModuleCodegen<Self::Module>, config: &ModuleConfig, ) -> Result<(), FatalError>; @@ -52,7 +52,7 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { ) -> Result<ModuleCodegen<Self::Module>, FatalError>; unsafe fn codegen( cgcx: &CodegenContext<Self>, - diag_handler: &Handler, + dcx: &DiagCtxt, module: ModuleCodegen<Self::Module>, config: &ModuleConfig, ) -> Result<CompiledModule, FatalError>; |