From 20431706a863f92cb37dc512fef6e48d192aaf2c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:11:38 +0200 Subject: Merging upstream version 1.66.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_codegen_ssa/src/back/link.rs | 241 ++++++++------ compiler/rustc_codegen_ssa/src/back/linker.rs | 151 ++++----- .../rustc_codegen_ssa/src/back/symbol_export.rs | 13 +- compiler/rustc_codegen_ssa/src/back/write.rs | 63 ++-- compiler/rustc_codegen_ssa/src/base.rs | 112 ++++--- compiler/rustc_codegen_ssa/src/common.rs | 5 +- .../rustc_codegen_ssa/src/debuginfo/type_names.rs | 6 +- compiler/rustc_codegen_ssa/src/errors.rs | 356 +++++++++++++++++++++ compiler/rustc_codegen_ssa/src/lib.rs | 3 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 104 +++--- compiler/rustc_codegen_ssa/src/mir/mod.rs | 20 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 16 + compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 28 +- compiler/rustc_codegen_ssa/src/target_features.rs | 208 ++++++------ compiler/rustc_codegen_ssa/src/traits/abi.rs | 3 - compiler/rustc_codegen_ssa/src/traits/backend.rs | 2 - compiler/rustc_codegen_ssa/src/traits/builder.rs | 6 +- compiler/rustc_codegen_ssa/src/traits/intrinsic.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/misc.rs | 4 - compiler/rustc_codegen_ssa/src/traits/type_.rs | 7 +- compiler/rustc_codegen_ssa/src/traits/write.rs | 1 - 22 files changed, 906 insertions(+), 447 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/errors.rs (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 6cce95427..0dc0dee86 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; -use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; +use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip}; use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind}; use rustc_session::cstore::DllImport; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; @@ -23,20 +23,23 @@ use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; use rustc_span::DebuggerVisualizerFile; use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; -use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; -use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; +use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy}; +use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, Target}; use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{create_rmeta_file, MetadataPosition}; use super::rpath::{self, RPathConfig}; -use crate::{looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib}; +use crate::{ + errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib, +}; use cc::windows_registry; use regex::Regex; use tempfile::Builder as TempFileBuilder; +use itertools::Itertools; use std::borrow::Borrow; use std::cell::OnceCell; use std::collections::BTreeSet; @@ -93,7 +96,7 @@ pub fn link_binary<'a>( let tmpdir = TempFileBuilder::new() .prefix("rustc") .tempdir() - .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err))); + .unwrap_or_else(|error| sess.emit_fatal(errors::CreateTempDir { error })); let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps); let out_filename = out_filename( sess, @@ -206,11 +209,29 @@ pub fn link_binary<'a>( } pub fn each_linked_rlib( + sess: &Session, info: &CrateInfo, f: &mut dyn FnMut(CrateNum, &Path), -) -> Result<(), String> { +) -> Result<(), errors::LinkRlibError> { let crates = info.used_crates.iter(); let mut fmts = None; + + let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin); + if lto_active { + for combination in info.dependency_formats.iter().combinations(2) { + let (ty1, list1) = &combination[0]; + let (ty2, list2) = &combination[1]; + if list1 != list2 { + return Err(errors::LinkRlibError::IncompatibleDependencyFormats { + ty1: format!("{ty1:?}"), + ty2: format!("{ty2:?}"), + list1: format!("{list1:?}"), + list2: format!("{list2:?}"), + }); + } + } + } + for (ty, list) in info.dependency_formats.iter() { match ty { CrateType::Executable @@ -220,30 +241,31 @@ pub fn each_linked_rlib( fmts = Some(list); break; } + CrateType::Dylib if lto_active => { + fmts = Some(list); + break; + } _ => {} } } let Some(fmts) = fmts else { - return Err("could not find formats for rlibs".to_string()); + return Err(errors::LinkRlibError::MissingFormat); }; for &cnum in crates { match fmts.get(cnum.as_usize() - 1) { Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue, Some(_) => {} - None => return Err("could not find formats for rlibs".to_string()), + None => return Err(errors::LinkRlibError::MissingFormat), } - let name = info.crate_name[&cnum]; + 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); } else { if used_crate_source.rmeta.is_some() { - return Err(format!( - "could not find rlib for: `{}`, found rmeta (metadata) file", - name - )); + return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - return Err(format!("could not find rlib for: `{}`", name)); + return Err(errors::LinkRlibError::NotFound { crate_name }); } } } @@ -340,10 +362,7 @@ fn link_rlib<'a>( // -whole-archive and it isn't clear how we can currently handle such a // situation correctly. // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897 - sess.err( - "the linking modifiers `+bundle` and `+whole-archive` are not compatible \ - with each other when generating rlibs", - ); + sess.emit_err(errors::IncompatibleLinkingModifiers); } NativeLibKind::Static { bundle: None | Some(true), .. } => {} NativeLibKind::Static { bundle: Some(false), .. } @@ -365,12 +384,8 @@ fn link_rlib<'a>( )); continue; } - ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|e| { - sess.fatal(&format!( - "failed to add native library {}: {}", - location.to_string_lossy(), - e - )); + ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|error| { + sess.emit_fatal(errors::AddNativeLibrary { library_path: location, error }); }); } } @@ -386,8 +401,8 @@ fn link_rlib<'a>( true, ); - ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| { - sess.fatal(&format!("failed to add native library {}: {}", output_path.display(), e)); + ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| { + sess.emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); }); } @@ -452,14 +467,11 @@ fn collate_raw_dylibs<'a, 'b>( // FIXME: when we add support for ordinals, figure out if we need to do anything // if we have two DllImport values with the same name but different ordinals. if import.calling_convention != old_import.calling_convention { - sess.span_err( - import.span, - &format!( - "multiple declarations of external function `{}` from \ - library `{}` have different calling conventions", - import.name, name, - ), - ); + sess.emit_err(errors::MultipleExternalFuncDecl { + span: import.span, + function: import.name, + library_name: &name, + }); } } } @@ -502,7 +514,7 @@ fn link_staticlib<'a>( )?; let mut all_native_libs = vec![]; - let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { + let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| { let name = codegen_results.crate_info.crate_name[&cnum]; let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; @@ -561,7 +573,7 @@ fn link_staticlib<'a>( all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); }); if let Err(e) = res { - sess.fatal(&e); + sess.emit_fatal(e); } ab.build(out_filename); @@ -674,9 +686,7 @@ fn link_dwarf_object<'a>( }) { Ok(()) => {} Err(e) => { - sess.struct_err("linking dwarf objects with thorin failed") - .note(&format!("{:?}", e)) - .emit(); + sess.emit_err(errors::ThorinErrorWrapper(e)); sess.abort_if_errors(); } } @@ -749,8 +759,7 @@ fn link_natively<'a>( // then it should not default to linking executables as pie. Different // versions of gcc seem to use different quotes in the error message so // don't check for them. - if sess.target.linker_is_gnu - && flavor != LinkerFlavor::Ld + if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) && unknown_arg_regex.is_match(&out) && out.contains("-no-pie") && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie") @@ -768,8 +777,7 @@ fn link_natively<'a>( // Detect '-static-pie' used with an older version of gcc or clang not supporting it. // Fallback from '-static-pie' to '-static' in that case. - if sess.target.linker_is_gnu - && flavor != LinkerFlavor::Ld + if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) && unknown_arg_regex.is_match(&out) && (out.contains("-static-pie") || out.contains("--no-dynamic-linker")) && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-static-pie") @@ -882,29 +890,20 @@ fn link_natively<'a>( let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); let escaped_output = escape_string(&output); - let mut err = sess.struct_err(&format!( - "linking with `{}` failed: {}", - linker_path.display(), - prog.status - )); - err.note(&format!("{:?}", &cmd)).note(&escaped_output); - if escaped_output.contains("undefined reference to") { - err.help( - "some `extern` functions couldn't be found; some native libraries may \ - need to be installed or have their path specified", - ); - err.note("use the `-l` flag to specify native libraries to link"); - err.note("use the `cargo:rustc-link-lib` directive to specify the native \ - libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)"); - } - err.emit(); - + // FIXME: Add UI tests for this error. + let err = errors::LinkingFailed { + linker_path: &linker_path, + exit_status: prog.status, + command: &cmd, + escaped_output: &escaped_output, + }; + sess.diagnostic().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. if let Some(code) = prog.status.code() { if sess.target.is_like_msvc - && flavor == LinkerFlavor::Msvc + && flavor == LinkerFlavor::Msvc(Lld::No) // Respect the command line override && sess.opts.cg.linker.is_none() // Match exactly "link.exe" @@ -980,9 +979,10 @@ fn link_natively<'a>( but `link.exe` was not found", ); sess.note_without_error( - "please ensure that VS 2013, VS 2015, VS 2017, VS 2019 or VS 2022 \ - was installed with the Visual C++ option", + "please ensure that Visual Studio 2017 or later, or Build Tools \ + for Visual Studio were installed with the Visual C++ option.", ); + sess.note_without_error("VS Code is a different product, and is not sufficient."); } sess.abort_if_errors(); } @@ -1035,16 +1035,36 @@ fn link_natively<'a>( if sess.target.is_like_osx { match (strip, crate_type) { - (Strip::Debuginfo, _) => strip_symbols_in_osx(sess, &out_filename, Some("-S")), + (Strip::Debuginfo, _) => { + 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_in_osx(sess, &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, _) => strip_symbols_in_osx(sess, &out_filename, None), (Strip::None, _) => {} } } + if sess.target.os == "illumos" { + // Many illumos systems will have both the native 'strip' utility and + // the GNU one. Use the native version explicitly and do not rely on + // what's in the path. + let stripcmd = "/usr/bin/strip"; + match strip { + // Always preserve the symbol table (-x). + Strip::Debuginfo => { + strip_symbols_with_external_utility(sess, stripcmd, &out_filename, Some("-x")) + } + // Strip::Symbols is handled via the --strip-all linker option. + Strip::Symbols => {} + Strip::None => {} + } + } + Ok(()) } @@ -1056,8 +1076,13 @@ fn strip_value(sess: &Session) -> Strip { } } -fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: Option<&str>) { - let mut cmd = Command::new("strip"); +fn strip_symbols_with_external_utility<'a>( + sess: &'a Session, + util: &str, + out_filename: &Path, + option: Option<&str>, +) { + let mut cmd = Command::new(util); if let Some(option) = option { cmd.arg(option); } @@ -1068,14 +1093,14 @@ fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: Opti let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); sess.struct_warn(&format!( - "stripping debug info with `strip` failed: {}", - prog.status + "stripping debug info with `{}` failed: {}", + util, prog.status )) .note(&escape_string(&output)) .emit(); } } - Err(e) => sess.fatal(&format!("unable to run `strip`: {}", e)), + Err(e) => sess.fatal(&format!("unable to run `{}`: {}", util, e)), } } @@ -1091,11 +1116,12 @@ fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut d // both executables and dynamic shared objects. Everywhere else the runtimes // are currently distributed as static libraries which should be linked to // executables only. - let needs_runtime = match crate_type { - CrateType::Executable => true, - CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => sess.target.is_like_osx, - CrateType::Rlib | CrateType::Staticlib => false, - }; + let needs_runtime = !sess.target.is_like_android + && match crate_type { + CrateType::Executable => true, + CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => sess.target.is_like_osx, + CrateType::Rlib | CrateType::Staticlib => false, + }; if !needs_runtime { return; @@ -1187,7 +1213,10 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { // only the linker flavor is known; use the default linker for the selected flavor (None, Some(flavor)) => Some(( PathBuf::from(match flavor { - LinkerFlavor::Gcc => { + LinkerFlavor::Gnu(Cc::Yes, _) + | LinkerFlavor::Darwin(Cc::Yes, _) + | LinkerFlavor::WasmLld(Cc::Yes) + | LinkerFlavor::Unix(Cc::Yes) => { if cfg!(any(target_os = "solaris", target_os = "illumos")) { // On historical Solaris systems, "cc" may have // been Sun Studio, which is not flag-compatible @@ -1200,9 +1229,14 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { "cc" } } - LinkerFlavor::Ld => "ld", - LinkerFlavor::Lld(_) => "lld", - LinkerFlavor::Msvc => "link.exe", + LinkerFlavor::Gnu(_, Lld::Yes) + | LinkerFlavor::Darwin(_, Lld::Yes) + | LinkerFlavor::WasmLld(..) + | LinkerFlavor::Msvc(Lld::Yes) => "lld", + LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => { + "ld" + } + LinkerFlavor::Msvc(..) => "link.exe", LinkerFlavor::EmCc => { if cfg!(windows) { "emcc.bat" @@ -1227,15 +1261,20 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { || stem == "clang" || stem.ends_with("-clang") { - LinkerFlavor::Gcc + LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target) } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") { - LinkerFlavor::Lld(LldFlavor::Wasm) - } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") { - LinkerFlavor::Ld - } else if stem == "link" || stem == "lld-link" { - LinkerFlavor::Msvc + LinkerFlavor::WasmLld(Cc::No) + } else if stem == "ld" || stem.ends_with("-ld") { + LinkerFlavor::from_cli(LinkerFlavorCli::Ld, &sess.target) + } else if stem == "ld.lld" { + LinkerFlavor::Gnu(Cc::No, Lld::Yes) + } else if stem == "link" { + LinkerFlavor::Msvc(Lld::No) + } else if stem == "lld-link" { + LinkerFlavor::Msvc(Lld::Yes) } else if stem == "lld" || stem == "rust-lld" { - LinkerFlavor::Lld(sess.target.lld_flavor) + let lld_flavor = sess.target.linker_flavor.lld_flavor(); + LinkerFlavor::from_cli(LinkerFlavorCli::Lld(lld_flavor), &sess.target) } else { // fall back to the value in the target spec sess.target.linker_flavor @@ -1249,7 +1288,8 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { // linker and linker flavor specified via command line have precedence over what the target // specification specifies - let linker_flavor = sess.opts.cg.linker_flavor.map(LinkerFlavor::from_cli); + let linker_flavor = + sess.opts.cg.linker_flavor.map(|flavor| LinkerFlavor::from_cli(flavor, &sess.target)); if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) { return ret; } @@ -1320,7 +1360,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { let verbatim = lib.verbatim.unwrap_or(false); if sess.target.is_like_msvc { Some(format!("{}{}", name, if verbatim { "" } else { ".lib" })) - } else if sess.target.linker_is_gnu { + } else if sess.target.linker_flavor.is_gnu() { Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name)) } else { Some(format!("-l{}", name)) @@ -1607,7 +1647,7 @@ fn add_pre_link_objects( let empty = Default::default(); let objects = if self_contained { &opts.pre_link_objects_self_contained - } else if !(sess.target.os == "fuchsia" && flavor == LinkerFlavor::Gcc) { + } else if !(sess.target.os == "fuchsia" && matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))) { &opts.pre_link_objects } else { &empty @@ -1647,7 +1687,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) { match (crate_type, &sess.target.link_script) { (CrateType::Cdylib | CrateType::Executable, Some(script)) => { - if !sess.target.linker_is_gnu { + if !sess.target.linker_flavor.is_gnu() { sess.fatal("can only use link script when linking with GNU-like linker"); } @@ -1890,7 +1930,7 @@ fn add_rpath_args( out_filename: out_filename.to_path_buf(), has_rpath: sess.target.has_rpath, is_like_osx: sess.target.is_like_osx, - linker_is_gnu: sess.target.linker_is_gnu, + linker_is_gnu: sess.target.linker_flavor.is_gnu(), }; cmd.args(&rpath::get_rpath_flags(&mut rpath_config)); } @@ -2134,7 +2174,7 @@ fn add_order_independent_options( if sess.target.os == "fuchsia" && crate_type == CrateType::Executable - && flavor != LinkerFlavor::Gcc + && !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) { let prefix = if sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::ADDRESS) { "asan/" @@ -2747,12 +2787,12 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { let llvm_target = &sess.target.llvm_target; if sess.target.vendor != "apple" || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "macos") - || (flavor != LinkerFlavor::Gcc && flavor != LinkerFlavor::Lld(LldFlavor::Ld64)) + || !matches!(flavor, LinkerFlavor::Darwin(..)) { return; } - if os == "macos" && flavor != LinkerFlavor::Lld(LldFlavor::Ld64) { + if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) { return; } @@ -2786,10 +2826,10 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { }; match flavor { - LinkerFlavor::Gcc => { + LinkerFlavor::Darwin(Cc::Yes, _) => { cmd.args(&["-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]); } - LinkerFlavor::Lld(LldFlavor::Ld64) => { + LinkerFlavor::Darwin(Cc::No, _) => { cmd.args(&["-syslibroot", &sdk_root]); } _ => unreachable!(), @@ -2852,7 +2892,10 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result { fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if let Some(ld_impl) = sess.opts.unstable_opts.gcc_ld { - if let LinkerFlavor::Gcc = flavor { + if let LinkerFlavor::Gnu(Cc::Yes, _) + | LinkerFlavor::Darwin(Cc::Yes, _) + | LinkerFlavor::WasmLld(Cc::Yes) = flavor + { match ld_impl { LdImpl::Lld => { // Implement the "self-contained" part of -Zgcc-ld @@ -2867,7 +2910,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { // Implement the "linker flavor" part of -Zgcc-ld // by asking cc to use some kind of lld. cmd.arg("-fuse-ld=lld"); - if sess.target.lld_flavor != LldFlavor::Ld { + if !flavor.is_gnu() { // Tell clang to use a non-default LLD flavor. // Gcc doesn't understand the target option, but we currently assume // that gcc is not used for Apple and Wasm targets (#97402). diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e505543b2..c49b19bdf 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1,5 +1,6 @@ use super::command::Command; use super::symbol_export; +use crate::errors; use rustc_span::symbol::sym; use std::ffi::{OsStr, OsString}; @@ -16,7 +17,7 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, S use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip}; use rustc_session::Session; -use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor}; +use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld}; use cc::windows_registry; @@ -56,8 +57,13 @@ pub fn get_linker<'a>( let mut cmd = match linker.to_str() { Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker), _ => match flavor { - LinkerFlavor::Lld(f) => Command::lld(linker, f), - LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => { + LinkerFlavor::Gnu(Cc::No, Lld::Yes) + | LinkerFlavor::Darwin(Cc::No, Lld::Yes) + | LinkerFlavor::WasmLld(Cc::No) + | LinkerFlavor::Msvc(Lld::Yes) => Command::lld(linker, flavor.lld_flavor()), + LinkerFlavor::Msvc(Lld::No) + if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => + { Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path())) } _ => Command::new(linker), @@ -68,9 +74,7 @@ pub fn get_linker<'a>( // To comply with the Windows App Certification Kit, // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). let t = &sess.target; - if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link)) - && t.vendor == "uwp" - { + 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) { @@ -126,23 +130,22 @@ pub fn get_linker<'a>( // to the linker args construction. assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp"); match flavor { - LinkerFlavor::Gcc => { - Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false }) - as Box - } - LinkerFlavor::Ld if sess.target.os == "l4re" => { + LinkerFlavor::Unix(Cc::No) if sess.target.os == "l4re" => { Box::new(L4Bender::new(cmd, sess)) as Box } - LinkerFlavor::Lld(LldFlavor::Ld) - | LinkerFlavor::Lld(LldFlavor::Ld64) - | LinkerFlavor::Ld => { - Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true }) - as Box - } - LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { - Box::new(MsvcLinker { cmd, sess }) as Box - } - LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box, + LinkerFlavor::WasmLld(Cc::No) => Box::new(WasmLd::new(cmd, sess)) as Box, + LinkerFlavor::Gnu(cc, _) + | LinkerFlavor::Darwin(cc, _) + | LinkerFlavor::WasmLld(cc) + | LinkerFlavor::Unix(cc) => Box::new(GccLinker { + cmd, + sess, + target_cpu, + hinted_static: false, + is_ld: cc == Cc::No, + is_gnu: flavor.is_gnu(), + }) as Box, + LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box, LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box, LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box, LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box, @@ -211,6 +214,7 @@ pub struct GccLinker<'a> { hinted_static: bool, // Keeps track of the current hinting mode. // Link as ld is_ld: bool, + is_gnu: bool, } impl<'a> GccLinker<'a> { @@ -359,7 +363,7 @@ impl<'a> Linker for GccLinker<'a> { fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { match output_kind { LinkOutputKind::DynamicNoPicExe => { - if !self.is_ld && self.sess.target.linker_is_gnu { + if !self.is_ld && self.is_gnu { self.cmd.arg("-no-pie"); } } @@ -373,7 +377,7 @@ impl<'a> Linker for GccLinker<'a> { LinkOutputKind::StaticNoPicExe => { // `-static` works for both gcc wrapper and ld. self.cmd.arg("-static"); - if !self.is_ld && self.sess.target.linker_is_gnu { + if !self.is_ld && self.is_gnu { self.cmd.arg("-no-pie"); } } @@ -431,26 +435,26 @@ impl<'a> Linker for GccLinker<'a> { // FIXME(81490): ld64 doesn't support these flags but macOS 11 // has -needed-l{} / -needed_library {} // but we have no way to detect that here. - self.sess.warn("`as-needed` modifier not implemented yet for ld64"); - } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { + self.sess.emit_warning(errors::Ld64UnimplementedModifier); + } else if self.is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--no-as-needed"); } else { - self.sess.warn("`as-needed` modifier not supported for current linker"); + self.sess.emit_warning(errors::LinkerUnsupportedModifier); } } self.hint_dynamic(); - self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib)); + self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },)); if !as_needed { if self.sess.target.is_like_osx { // See above FIXME comment - } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { + } else if self.is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--as-needed"); } } } fn link_staticlib(&mut self, lib: &str, verbatim: bool) { self.hint_static(); - self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib)); + self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },)); } fn link_rlib(&mut self, lib: &Path) { self.hint_static(); @@ -489,7 +493,7 @@ impl<'a> Linker for GccLinker<'a> { // FIXME(81490): ld64 as of macOS 11 supports the -needed_framework // flag but we have no way to detect that here. // self.cmd.arg("-needed_framework").arg(framework); - self.sess.warn("`as-needed` modifier not implemented yet for ld64"); + self.sess.emit_warning(errors::Ld64UnimplementedModifier); } self.cmd.arg("-framework").arg(framework); } @@ -504,11 +508,8 @@ impl<'a> Linker for GccLinker<'a> { self.hint_static(); let target = &self.sess.target; if !target.is_like_osx { - self.linker_arg("--whole-archive").cmd.arg(format!( - "-l{}{}", - if verbatim { ":" } else { "" }, - lib - )); + self.linker_arg("--whole-archive"); + self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },)); self.linker_arg("--no-whole-archive"); } else { // -force_load is the macOS equivalent of --whole-archive, but it @@ -553,21 +554,19 @@ impl<'a> Linker for GccLinker<'a> { // eliminate the metadata. If we're building an executable, however, // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67% // reduction. - } else if (self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm) - && !keep_metadata - { + } else if (self.is_gnu || self.sess.target.is_like_wasm) && !keep_metadata { self.linker_arg("--gc-sections"); } } fn no_gc_sections(&mut self) { - if self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm { + if self.is_gnu || self.sess.target.is_like_wasm { self.linker_arg("--no-gc-sections"); } } fn optimize(&mut self) { - if !self.sess.target.linker_is_gnu && !self.sess.target.is_like_wasm { + if !self.is_gnu && !self.sess.target.is_like_wasm { return; } @@ -581,7 +580,7 @@ impl<'a> Linker for GccLinker<'a> { } fn pgo_gen(&mut self) { - if !self.sess.target.linker_is_gnu { + if !self.is_gnu { return; } @@ -611,7 +610,13 @@ impl<'a> Linker for GccLinker<'a> { match strip { Strip::None => {} Strip::Debuginfo => { - self.linker_arg("--strip-debug"); + // The illumos linker does not support --strip-debug although + // it does support --strip-all as a compatibility alias for -s. + // The --strip-debug case is handled by running an external + // `strip` utility as a separate step after linking. + if self.sess.target.os != "illumos" { + self.linker_arg("--strip-debug"); + } } Strip::Symbols => { self.linker_arg("--strip-all"); @@ -667,8 +672,8 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, "_{}", sym)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write lib.def file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::LibDefWriteFailure { error }); } } else if is_windows { let res: io::Result<()> = try { @@ -682,8 +687,8 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, " {}", symbol)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write list.def file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::LibDefWriteFailure { error }); } } else { // Write an LD version script @@ -699,8 +704,8 @@ impl<'a> Linker for GccLinker<'a> { } writeln!(f, "\n local:\n *;\n}};")?; }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write version script: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::VersionScriptWriteFailure { error }); } } @@ -752,13 +757,13 @@ impl<'a> Linker for GccLinker<'a> { fn add_no_exec(&mut self) { if self.sess.target.is_like_windows { self.linker_arg("--nxcompat"); - } else if self.sess.target.linker_is_gnu { + } else if self.is_gnu { self.linker_arg("-znoexecstack"); } } fn add_as_needed(&mut self) { - if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { + if self.is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--as-needed"); } else if self.sess.target.is_like_solaris { // -z ignore is the Solaris equivalent to the GNU ld --as-needed option @@ -917,9 +922,8 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg(arg); } } - Err(err) => { - self.sess - .warn(&format!("error enumerating natvis directory: {}", err)); + Err(error) => { + self.sess.emit_warning(errors::NoNatvisDirectory { error }); } } } @@ -973,8 +977,8 @@ impl<'a> Linker for MsvcLinker<'a> { writeln!(f, " {}", symbol)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write lib.def file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::LibDefWriteFailure { error }); } let mut arg = OsString::from("/DEF:"); arg.push(path); @@ -1174,22 +1178,19 @@ impl<'a> WasmLd<'a> { // sharing memory and instantiating the module multiple times. As a // result if it were exported then we'd just have no sharing. // - // * `--export=__wasm_init_memory` - when using `--passive-segments` the - // linker will synthesize this function, and so we need to make sure - // that our usage of `--export` below won't accidentally cause this - // function to get deleted. - // - // * `--export=*tls*` - when `#[thread_local]` symbols are used these - // symbols are how the TLS segments are initialized and configured. + // On wasm32-unknown-unknown, we also export symbols for glue code to use: + // * `--export=*tls*` - when `#[thread_local]` symbols are used these + // symbols are how the TLS segments are initialized and configured. if sess.target_features.contains(&sym::atomics) { cmd.arg("--shared-memory"); cmd.arg("--max-memory=1073741824"); cmd.arg("--import-memory"); - cmd.arg("--export=__wasm_init_memory"); - cmd.arg("--export=__wasm_init_tls"); - cmd.arg("--export=__tls_size"); - cmd.arg("--export=__tls_align"); - cmd.arg("--export=__tls_base"); + if sess.target.os == "unknown" { + cmd.arg("--export=__wasm_init_tls"); + cmd.arg("--export=__tls_size"); + cmd.arg("--export=__tls_align"); + cmd.arg("--export=__tls_base"); + } } WasmLd { cmd, sess } } @@ -1314,10 +1315,12 @@ impl<'a> Linker for WasmLd<'a> { // LLD will hide these otherwise-internal symbols since it only exports // symbols explicitly passed via the `--export` flags above and hides all - // others. Various bits and pieces of tooling use this, so be sure these - // symbols make their way out of the linker as well. - self.cmd.arg("--export=__heap_base"); - self.cmd.arg("--export=__data_end"); + // others. Various bits and pieces of wasm32-unknown-unknown tooling use + // this, so be sure these symbols make their way out of the linker as well. + if self.sess.target.os == "unknown" { + self.cmd.arg("--export=__heap_base"); + self.cmd.arg("--export=__data_end"); + } } fn subsystem(&mut self, _subsystem: &str) {} @@ -1438,7 +1441,7 @@ impl<'a> Linker for L4Bender<'a> { fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { // ToDo, not implemented, copy from GCC - self.sess.warn("exporting symbols not implemented yet for L4Bender"); + self.sess.emit_warning(errors::L4BenderExportingSymbolsUnimplemented); return; } @@ -1730,8 +1733,8 @@ impl<'a> Linker for BpfLinker<'a> { writeln!(f, "{}", sym)?; } }; - if let Err(e) = res { - self.sess.fatal(&format!("failed to write symbols file: {}", e)); + if let Err(error) = res { + self.sess.emit_fatal(errors::SymbolFileWriteFailure { error }); } else { self.cmd.arg("--export-symbols").arg(&path); } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 8d7e2c5cf..c2ecc4160 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, SymbolName, TyCtxt}; -use rustc_session::config::CrateType; +use rustc_session::config::{CrateType, OomStrategy}; use rustc_target::spec::SanitizerSet; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { @@ -76,7 +76,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap< // let it through if it's included statically. match tcx.hir().get_by_def_id(def_id) { Node::ForeignItem(..) => { - tcx.is_statically_included_foreign_item(def_id).then_some(def_id) + tcx.native_library(def_id).map_or(false, |library| library.kind.is_statically_included()).then_some(def_id) } // Only consider nodes that actually have exported symbols. @@ -206,6 +206,15 @@ fn exported_symbols_provider_local<'tcx>( }, )); } + + symbols.push(( + ExportedSymbol::NoDefId(SymbolName::new(tcx, OomStrategy::SYMBOL)), + SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Text, + used: false, + }, + )); } if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 68f3b19b7..d0ac016b0 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2,11 +2,11 @@ use super::link::{self, ensure_removed}; use super::lto::{self, SerializedModule}; use super::symbol_export::symbol_name_for_instance_in_crate; +use crate::errors; +use crate::traits::*; use crate::{ CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, }; - -use crate::traits::*; use jobserver::{Acquired, Client}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; @@ -15,7 +15,10 @@ use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::profiling::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::{to_fluent_args, Translate}, + DiagnosticId, FatalError, Handler, Level, +}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ @@ -113,7 +116,6 @@ pub struct ModuleConfig { pub vectorize_slp: bool, pub merge_functions: bool, pub inline_threshold: Option, - pub new_llvm_pass_manager: Option, pub emit_lifetime_markers: bool, pub llvm_plugins: Vec, } @@ -265,7 +267,6 @@ impl ModuleConfig { }, inline_threshold: sess.opts.cg.inline_threshold, - new_llvm_pass_manager: sess.opts.unstable_opts.new_llvm_pass_manager, emit_lifetime_markers: sess.emit_lifetime_markers(), llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]), } @@ -532,7 +533,7 @@ fn produce_final_output_artifacts( // Produce final compile outputs. let copy_gracefully = |from: &Path, to: &Path| { if let Err(e) = fs::copy(from, to) { - sess.err(&format!("could not copy {:?} to {:?}: {}", from, to, e)); + sess.emit_err(errors::CopyPath::new(from, to, e)); } }; @@ -548,7 +549,7 @@ fn produce_final_output_artifacts( ensure_removed(sess.diagnostic(), &path); } } else { - let ext = crate_output + let extension = crate_output .temp_path(output_type, None) .extension() .unwrap() @@ -559,19 +560,11 @@ fn produce_final_output_artifacts( if crate_output.outputs.contains_key(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.warn(&format!( - "ignoring emit path because multiple .{} files \ - were produced", - ext - )); + sess.emit_warning(errors::IgnoringEmitPath { extension }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.warn(&format!( - "ignoring -o because multiple .{} files \ - were produced", - ext - )); + sess.emit_warning(errors::IgnoringOutput { extension }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -882,14 +875,12 @@ fn execute_copy_from_cache_work_item( ); match link_or_copy(&source_file, &output_path) { Ok(_) => Some(output_path), - Err(err) => { - let diag_handler = cgcx.create_diag_handler(); - diag_handler.err(&format!( - "unable to copy {} to {}: {}", - source_file.display(), - output_path.display(), - err - )); + Err(error) => { + cgcx.create_diag_handler().emit_err(errors::CopyPathBuf { + source_file, + output_path, + error, + }); None } } @@ -1008,6 +999,14 @@ fn start_executing_work( let coordinator_send = tx_to_llvm_workers; let sess = tcx.sess; + let mut each_linked_rlib_for_lto = Vec::new(); + drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| { + if link::ignored_for_lto(sess, crate_info, cnum) { + return; + } + each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); + })); + // Compute the set of symbols we need to retain when doing LTO (if we need to) let exported_symbols = { let mut exported_symbols = FxHashMap::default(); @@ -1029,7 +1028,7 @@ fn start_executing_work( } Lto::Fat | Lto::Thin => { exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); - for &cnum in tcx.crates(()).iter() { + for &(cnum, ref _path) in &each_linked_rlib_for_lto { exported_symbols.insert(cnum, copy_symbols(cnum)); } Some(Arc::new(exported_symbols)) @@ -1049,14 +1048,6 @@ fn start_executing_work( }) .expect("failed to spawn helper thread"); - let mut each_linked_rlib_for_lto = Vec::new(); - drop(link::each_linked_rlib(crate_info, &mut |cnum, path| { - if link::ignored_for_lto(sess, crate_info, cnum) { - return; - } - each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); - })); - let ol = if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { // If we know that we won’t be doing codegen, create target machines without optimisation. @@ -1639,7 +1630,7 @@ fn start_executing_work( llvm_start_time: &mut Option>, ) { if config.time_module && llvm_start_time.is_none() { - *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes", "crate")); + *llvm_start_time = Some(prof.verbose_generic_activity("LLVM_passes")); } } } @@ -1752,7 +1743,7 @@ impl Translate for SharedEmitter { impl Emitter for SharedEmitter { fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { - let fluent_args = self.to_fluent_args(diag.args()); + let fluent_args = to_fluent_args(diag.args()); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { msg: self.translate_messages(&diag.message, &fluent_args).to_string(), code: diag.code.clone(), diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index b98ff4957..84b89cd71 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -39,7 +39,7 @@ use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Symbol; use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType}; -use rustc_target::abi::{Align, VariantIdx}; +use rustc_target::abi::{Align, Size, VariantIdx}; use std::collections::BTreeSet; use std::convert::TryFrom; @@ -151,7 +151,12 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( (&ty::Array(_, len), &ty::Slice(_)) => { cx.const_usize(len.eval_usize(cx.tcx(), ty::ParamEnv::reveal_all())) } - (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { + ( + &ty::Dynamic(ref data_a, _, src_dyn_kind), + &ty::Dynamic(ref data_b, _, target_dyn_kind), + ) => { + assert_eq!(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() { @@ -167,11 +172,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if let Some(entry_idx) = vptr_entry_idx { let ptr_ty = cx.type_i8p(); let ptr_align = cx.tcx().data_layout.pointer_align.abi; - let vtable_ptr_ty = cx.scalar_pair_element_backend_type( - cx.layout_of(cx.tcx().mk_mut_ptr(target)), - 1, - true, - ); + let vtable_ptr_ty = vtable_ptr_ty(cx, target, target_dyn_kind); let llvtable = bx.pointercast(old_info, bx.type_ptr_to(ptr_ty)); let gep = bx.inbounds_gep( ptr_ty, @@ -187,18 +188,32 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( old_info } } - (_, &ty::Dynamic(ref data, ..)) => { - let vtable_ptr_ty = cx.scalar_pair_element_backend_type( - cx.layout_of(cx.tcx().mk_mut_ptr(target)), - 1, - true, - ); + (_, &ty::Dynamic(ref data, _, target_dyn_kind)) => { + let vtable_ptr_ty = vtable_ptr_ty(cx, target, target_dyn_kind); cx.const_ptrcast(meth::get_vtable(cx, source, data.principal()), vtable_ptr_ty) } _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } +// Returns the vtable pointer type of a `dyn` or `dyn*` type +fn vtable_ptr_ty<'tcx, Cx: CodegenMethods<'tcx>>( + cx: &Cx, + target: Ty<'tcx>, + kind: ty::DynKind, +) -> ::Type { + cx.scalar_pair_element_backend_type( + cx.layout_of(match kind { + // vtable is the second field of `*mut dyn Trait` + ty::Dyn => cx.tcx().mk_mut_ptr(target), + // vtable is the second field of `dyn* Trait` + ty::DynStar => target, + }), + 1, + true, + ) +} + /// Coerces `src` to `dst_ty`. `src_ty` must be a pointer. pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, @@ -248,6 +263,29 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } +/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type. +pub fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + bx: &mut Bx, + src: Bx::Value, + src_ty_and_layout: TyAndLayout<'tcx>, + dst_ty: Ty<'tcx>, + old_info: Option, +) -> (Bx::Value, Bx::Value) { + debug!("cast_to_dyn_star: {:?} => {:?}", src_ty_and_layout.ty, dst_ty); + assert!( + matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)), + "destination type must be a dyn*" + ); + // FIXME(dyn-star): this is probably not the best way to check if this is + // a pointer, and really we should ensure that the value is a suitable + // pointer earlier in the compilation process. + let src = match src_ty_and_layout.pointee_info_at(bx.cx(), Size::ZERO) { + Some(_) => bx.ptrtoint(src, bx.cx().type_isize()), + None => bx.bitcast(src, bx.type_isize()), + }; + (src, unsized_info(bx, src_ty_and_layout.ty, dst_ty, old_info)) +} + /// Coerces `src`, which is a reference to a value of type `src_ty`, /// to a value of type `dst_ty`, and stores the result in `dst`. pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( @@ -299,40 +337,26 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, - op: hir::BinOpKind, - lhs: Bx::Value, - rhs: Bx::Value, -) -> Bx::Value { - cast_shift_rhs(bx, op, lhs, rhs) -} - -fn cast_shift_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - bx: &mut Bx, - op: hir::BinOpKind, lhs: Bx::Value, rhs: Bx::Value, ) -> Bx::Value { // Shifts may have any size int on the rhs - if op.is_shift() { - let mut rhs_llty = bx.cx().val_ty(rhs); - let mut lhs_llty = bx.cx().val_ty(lhs); - if bx.cx().type_kind(rhs_llty) == TypeKind::Vector { - rhs_llty = bx.cx().element_type(rhs_llty) - } - if bx.cx().type_kind(lhs_llty) == TypeKind::Vector { - lhs_llty = bx.cx().element_type(lhs_llty) - } - let rhs_sz = bx.cx().int_width(rhs_llty); - let lhs_sz = bx.cx().int_width(lhs_llty); - 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. - bx.zext(rhs, lhs_llty) - } else { - rhs - } + let mut rhs_llty = bx.cx().val_ty(rhs); + let mut lhs_llty = bx.cx().val_ty(lhs); + if bx.cx().type_kind(rhs_llty) == TypeKind::Vector { + rhs_llty = bx.cx().element_type(rhs_llty) + } + if bx.cx().type_kind(lhs_llty) == TypeKind::Vector { + lhs_llty = bx.cx().element_type(lhs_llty) + } + let rhs_sz = bx.cx().int_width(rhs_llty); + let lhs_sz = bx.cx().int_width(lhs_llty); + 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. + bx.zext(rhs, lhs_llty) } else { rhs } @@ -475,7 +499,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( (rust_main, start_ty, vec![arg_argc, arg_argv]) }; - let result = bx.call(start_ty, start_fn, &args, None); + let result = bx.call(start_ty, None, start_fn, &args, None); let cast = bx.intcast(result, cx.type_int(), true); bx.ret(cast); diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 8ca1a6084..71f9179d0 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -1,7 +1,6 @@ #![allow(non_camel_case_types)] use rustc_errors::struct_span_err; -use rustc_hir as hir; use rustc_hir::LangItem; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt}; @@ -140,7 +139,7 @@ pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( lhs: Bx::Value, rhs: Bx::Value, ) -> Bx::Value { - let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs); + let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs); // #1877, #10183: Ensure that input is always valid let rhs = shift_mask_rhs(bx, rhs); bx.shl(lhs, rhs) @@ -152,7 +151,7 @@ pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( lhs: Bx::Value, rhs: Bx::Value, ) -> Bx::Value { - let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs); + let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs); // #1877, #10183: Ensure that input is always valid let rhs = shift_mask_rhs(bx, rhs); let is_signed = lhs_t.is_signed(); diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 135ed680d..e05646e1e 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -666,10 +666,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S hcx.while_hashing_spans(false, |hcx| { ct.to_valtree().hash_stable(hcx, &mut hasher) }); - // Note: Don't use `StableHashResult` impl of `u64` here directly, since that - // would lead to endianness problems. - let hash: u128 = hasher.finish(); - (hash.to_le() as u64).to_le() + let hash: u64 = hasher.finish(); + hash }); if cpp_like_debuginfo(tcx) { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs new file mode 100644 index 000000000..ebb531f1c --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -0,0 +1,356 @@ +//! Errors emitted by codegen_ssa + +use crate::back::command::Command; +use rustc_errors::{ + fluent, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, + IntoDiagnosticArg, +}; +use rustc_macros::Diagnostic; +use rustc_span::{Span, Symbol}; +use std::borrow::Cow; +use std::io::Error; +use std::path::{Path, PathBuf}; +use std::process::ExitStatus; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_lib_def_write_failure)] +pub struct LibDefWriteFailure { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_version_script_write_failure)] +pub struct VersionScriptWriteFailure { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_symbol_file_write_failure)] +pub struct SymbolFileWriteFailure { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_ld64_unimplemented_modifier)] +pub struct Ld64UnimplementedModifier; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_linker_unsupported_modifier)] +pub struct LinkerUnsupportedModifier; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_L4Bender_exporting_symbols_unimplemented)] +pub struct L4BenderExportingSymbolsUnimplemented; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_no_natvis_directory)] +pub struct NoNatvisDirectory { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_copy_path_buf)] +pub struct CopyPathBuf { + pub source_file: PathBuf, + pub output_path: PathBuf, + pub error: Error, +} + +// Reports Paths using `Debug` implementation rather than Path's `Display` implementation. +#[derive(Diagnostic)] +#[diag(codegen_ssa_copy_path)] +pub struct CopyPath<'a> { + from: DebugArgPath<'a>, + to: DebugArgPath<'a>, + error: Error, +} + +impl<'a> CopyPath<'a> { + pub fn new(from: &'a Path, to: &'a Path, error: Error) -> CopyPath<'a> { + CopyPath { from: DebugArgPath(from), to: DebugArgPath(to), error } + } +} + +struct DebugArgPath<'a>(pub &'a Path); + +impl IntoDiagnosticArg for DebugArgPath<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self.0))) + } +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_ignoring_emit_path)] +pub struct IgnoringEmitPath { + pub extension: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_ignoring_output)] +pub struct IgnoringOutput { + pub extension: String, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_create_temp_dir)] +pub struct CreateTempDir { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_incompatible_linking_modifiers)] +pub struct IncompatibleLinkingModifiers; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_add_native_library)] +pub struct AddNativeLibrary { + pub library_path: PathBuf, + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_multiple_external_func_decl)] +pub struct MultipleExternalFuncDecl<'a> { + #[primary_span] + pub span: Span, + pub function: Symbol, + pub library_name: &'a str, +} + +#[derive(Diagnostic)] +pub enum LinkRlibError { + #[diag(codegen_ssa_rlib_missing_format)] + MissingFormat, + + #[diag(codegen_ssa_rlib_only_rmeta_found)] + OnlyRmetaFound { crate_name: Symbol }, + + #[diag(codegen_ssa_rlib_not_found)] + NotFound { crate_name: Symbol }, + + #[diag(codegen_ssa_rlib_incompatible_dependency_formats)] + IncompatibleDependencyFormats { ty1: String, ty2: String, list1: String, list2: String }, +} + +pub struct ThorinErrorWrapper(pub thorin::Error); + +impl IntoDiagnostic<'_> for ThorinErrorWrapper { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag; + match self.0 { + thorin::Error::ReadInput(_) => { + diag = handler.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 + } + thorin::Error::ParseObjectFile(_) => { + diag = handler.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 + } + thorin::Error::ParseArchiveMember(_) => { + diag = handler.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 + } + thorin::Error::DecompressData(_) => { + diag = handler.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.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::RelocationWithInvalidSymbol(section, offset) => { + diag = + handler.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); + diag.set_arg("section", section); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::MultipleRelocations(section, offset) => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_relocations); + diag.set_arg("section", section); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::UnsupportedRelocation(section, offset) => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation); + diag.set_arg("section", section); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::MissingDwoName(id) => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name); + diag.set_arg("id", format!("0x{:08x}", id)); + diag + } + thorin::Error::NoCompilationUnits => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_no_compilation_units); + diag + } + thorin::Error::NoDie => { + diag = handler.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 + } + thorin::Error::MissingRequiredSection(section) => { + diag = handler.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 + } + thorin::Error::ParseUnitAttribute(_) => { + diag = handler.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 + } + thorin::Error::ParseUnit(_) => { + diag = handler.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.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.set_arg("index", index); + diag + } + thorin::Error::StrAtOffset(_, offset) => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_str_at_offset); + diag.set_arg("offset", format!("0x{:08x}", offset)); + diag + } + thorin::Error::ParseIndex(_, section) => { + diag = handler.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.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::RowNotInIndex(_, row) => { + diag = handler.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 + } + thorin::Error::EmptyUnit(unit) => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_empty_unit); + diag.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::MultipleDebugInfoSection => { + diag = handler.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 + } + thorin::Error::NotSplitUnit => { + diag = handler.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.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::MissingReferencedUnit(unit) => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit); + diag.set_arg("unit", format!("0x{:08x}", unit)); + diag + } + thorin::Error::NoOutputObjectCreated => { + diag = handler.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 + } + thorin::Error::Io(e) => { + diag = handler.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.set_arg("error", format!("{e}")); + diag + } + thorin::Error::ObjectWrite(e) => { + diag = handler.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.set_arg("error", format!("{e}")); + diag + } + thorin::Error::GimliWrite(e) => { + diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_write); + diag.set_arg("error", format!("{e}")); + diag + } + _ => unimplemented!("Untranslated thorin error"), + } + } +} + +pub struct LinkingFailed<'a> { + pub linker_path: &'a PathBuf, + pub exit_status: ExitStatus, + pub command: &'a Command, + pub escaped_output: &'a str, +} + +impl IntoDiagnostic<'_> for LinkingFailed<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.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)); + + diag.note(format!("{:?}", self.command)).note(self.escaped_output); + + // Trying to match an error from OS linkers + // which by now we have no way to translate. + if self.escaped_output.contains("undefined reference to") { + diag.note(fluent::codegen_ssa_extern_funcs_not_found) + .note(fluent::codegen_ssa_specify_libraries_to_link) + .note(fluent::codegen_ssa_use_cargo_directive); + } + diag + } +} diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index e736b2aba..ceebe4d41 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,12 +1,12 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] #![feature(try_blocks)] -#![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(associated_type_bounds)] #![feature(strict_provenance)] #![feature(int_roundings)] #![feature(if_let_guard)] +#![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] @@ -44,6 +44,7 @@ pub mod base; pub mod common; pub mod coverageinfo; pub mod debuginfo; +pub mod errors; pub mod glue; pub mod meth; pub mod mir; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a6b226ef7..29b7c9b0a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -63,7 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } } - fn lltarget>( + /// Get a basic block (creating it if necessary), possibly with a landing + /// pad next to it. + fn llbb_with_landing_pad>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, @@ -73,32 +75,36 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { let target_funclet = fx.cleanup_kinds[target].funclet_bb(target); match (self.funclet_bb, target_funclet) { (None, None) => (lltarget, false), - (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => { - (lltarget, false) - } // jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC (None, Some(_)) => (fx.landing_pad_for(target), false), (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator), - (Some(_), Some(_)) => (fx.landing_pad_for(target), true), + (Some(f), Some(t_f)) => { + if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) { + (lltarget, false) + } else { + (fx.landing_pad_for(target), true) + } + } } } - /// Create a basic block. - fn llblock>( + /// Get a basic block (creating it if necessary), possibly with cleanup + /// stuff in it or next to it. + fn llbb_with_cleanup>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, ) -> Bx::BasicBlock { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); + let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target); if is_cleanupret { // MSVC cross-funclet jump - need a trampoline - - debug!("llblock: creating cleanup trampoline for {:?}", target); + debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess)); + debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target); let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target); - let trampoline = Bx::append_block(fx.cx, fx.llfn, name); - let mut trampoline_bx = Bx::build(fx.cx, trampoline); + let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name); + let mut trampoline_bx = Bx::build(fx.cx, trampoline_llbb); trampoline_bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); - trampoline + trampoline_llbb } else { lltarget } @@ -110,10 +116,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { bx: &mut Bx, target: mir::BasicBlock, ) { - let (lltarget, is_cleanupret) = self.lltarget(fx, target); + let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target); if is_cleanupret { - // micro-optimization: generate a `ret` rather than a jump + // MSVC micro-optimization: generate a `ret` rather than a jump // to a trampoline. + debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess)); bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); } else { bx.br(lltarget); @@ -138,7 +145,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { let fn_ty = bx.fn_decl_backend_type(&fn_abi); let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) { - Some(self.llblock(fx, cleanup)) + Some(self.llbb_with_cleanup(fx, cleanup)) } else if fx.mir[self.bb].is_cleanup && fn_abi.can_unwind && !base::wants_msvc_seh(fx.cx.tcx().sess) @@ -162,9 +169,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } else { fx.unreachable_block() }; - let invokeret = - bx.invoke(fn_ty, fn_ptr, &llargs, ret_llbb, unwind_block, self.funclet(fx)); - bx.apply_attrs_callsite(&fn_abi, invokeret); + let invokeret = bx.invoke( + fn_ty, + Some(&fn_abi), + fn_ptr, + &llargs, + ret_llbb, + unwind_block, + self.funclet(fx), + ); if fx.mir[self.bb].is_cleanup { bx.do_not_inline(invokeret); } @@ -178,8 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret); } } else { - let llret = bx.call(fn_ty, fn_ptr, &llargs, self.funclet(fx)); - bx.apply_attrs_callsite(&fn_abi, llret); + let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx)); if fx.mir[self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested @@ -226,7 +238,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { options, line_spans, instance, - Some((ret_llbb, self.llblock(fx, cleanup), self.funclet(fx))), + Some((ret_llbb, self.llbb_with_cleanup(fx, cleanup), self.funclet(fx))), ); } else { bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None); @@ -276,8 +288,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if target_iter.len() == 1 { // If there are two targets (one conditional, one fallback), emit br instead of switch let (test_value, target) = target_iter.next().unwrap(); - let lltrue = helper.llblock(self, target); - let llfalse = helper.llblock(self, targets.otherwise()); + let lltrue = helper.llbb_with_cleanup(self, target); + let llfalse = helper.llbb_with_cleanup(self, targets.otherwise()); if switch_ty == bx.tcx().types.bool { // Don't generate trivial icmps when switching on bool match test_value { @@ -294,8 +306,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { bx.switch( discr.immediate(), - helper.llblock(self, targets.otherwise()), - target_iter.map(|(value, target)| (value, helper.llblock(self, target))), + helper.llbb_with_cleanup(self, targets.otherwise()), + target_iter.map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))), ); } } @@ -525,7 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cond = bx.expect(cond, expected); // Create the failure block and the conditional branch to it. - let lltarget = helper.llblock(self, target); + let lltarget = helper.llbb_with_cleanup(self, target); let panic_block = bx.append_sibling_block("panic"); if expected { bx.cond_br(cond, lltarget, panic_block); @@ -1454,20 +1466,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // bar(); // } Some(&mir::TerminatorKind::Abort) => { - let cs_bb = + let cs_llbb = Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb)); - let cp_bb = + let cp_llbb = Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb)); - ret_llbb = cs_bb; + ret_llbb = cs_llbb; - let mut cs_bx = Bx::build(self.cx, cs_bb); - let cs = cs_bx.catch_switch(None, None, &[cp_bb]); + let mut cs_bx = Bx::build(self.cx, cs_llbb); + let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); // The "null" here is actually a RTTI type descriptor for the // C++ personality function, but `catch (...)` has no type so // it's null. The 64 here is actually a bitfield which // represents that this is a catch-all block. - let mut cp_bx = Bx::build(self.cx, cp_bb); + let mut cp_bx = Bx::build(self.cx, cp_llbb); let null = cp_bx.const_null( cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space), ); @@ -1476,10 +1488,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cp_bx.br(llbb); } _ => { - let cleanup_bb = + let cleanup_llbb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb)); - ret_llbb = cleanup_bb; - let mut cleanup_bx = Bx::build(self.cx, cleanup_bb); + ret_llbb = cleanup_llbb; + let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb); funclet = cleanup_bx.cleanup_pad(None, &[]); cleanup_bx.br(llbb); } @@ -1487,19 +1499,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.funclets[bb] = Some(funclet); ret_llbb } else { - let bb = Bx::append_block(self.cx, self.llfn, "cleanup"); - let mut bx = Bx::build(self.cx, bb); + let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup"); + let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb); let llpersonality = self.cx.eh_personality(); let llretty = self.landing_pad_type(); - let lp = bx.cleanup_landing_pad(llretty, llpersonality); + let lp = cleanup_bx.cleanup_landing_pad(llretty, llpersonality); - let slot = self.get_personality_slot(&mut bx); - slot.storage_live(&mut bx); - Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot); + let slot = self.get_personality_slot(&mut cleanup_bx); + slot.storage_live(&mut cleanup_bx); + Pair(cleanup_bx.extract_value(lp, 0), cleanup_bx.extract_value(lp, 1)) + .store(&mut cleanup_bx, slot); - bx.br(llbb); - bx.llbb() + cleanup_bx.br(llbb); + cleanup_llbb } } @@ -1533,8 +1546,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind); let fn_ty = bx.fn_decl_backend_type(&fn_abi); - let llret = bx.call(fn_ty, fn_ptr, &[], None); - bx.apply_attrs_callsite(&fn_abi, llret); + let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None); bx.do_not_inline(llret); bx.unreachable(); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 2b931bfc9..da9aaf00e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -148,10 +148,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); let start_llbb = Bx::append_block(cx, llfn, "start"); - let mut bx = Bx::build(cx, start_llbb); + let mut start_bx = Bx::build(cx, start_llbb); if mir.basic_blocks.iter().any(|bb| bb.is_cleanup) { - bx.set_personality_fn(cx.eh_personality()); + start_bx.set_personality_fn(cx.eh_personality()); } let cleanup_kinds = analyze::cleanup_kinds(&mir); @@ -180,7 +180,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( caller_location: None, }; - fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx); + fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx); // Evaluate all required consts; codegen later assumes that CTFE will never fail. let mut all_consts_ok = true; @@ -206,29 +206,29 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Allocate variable and temp allocas fx.locals = { - let args = arg_local_refs(&mut bx, &mut fx, &memory_locals); + let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals); let mut allocate_local = |local| { let decl = &mir.local_decls[local]; - let layout = bx.layout_of(fx.monomorphize(decl.ty)); + let layout = start_bx.layout_of(fx.monomorphize(decl.ty)); assert!(!layout.ty.has_erasable_regions()); if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() { debug!("alloc: {:?} (return place) -> place", local); - let llretptr = bx.get_param(0); + let llretptr = start_bx.get_param(0); return LocalRef::Place(PlaceRef::new_sized(llretptr, layout)); } if memory_locals.contains(local) { debug!("alloc: {:?} -> place", local); if layout.is_unsized() { - LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut bx, layout)) + LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut start_bx, layout)) } else { - LocalRef::Place(PlaceRef::alloca(&mut bx, layout)) + LocalRef::Place(PlaceRef::alloca(&mut start_bx, layout)) } } else { debug!("alloc: {:?} -> operand", local); - LocalRef::new_operand(&mut bx, layout) + LocalRef::new_operand(&mut start_bx, layout) } }; @@ -240,7 +240,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }; // Apply debuginfo to the newly allocated locals. - fx.debug_introduce_locals(&mut bx); + fx.debug_introduce_locals(&mut start_bx); // Codegen the body of each block using reverse postorder for (bb, _) in traversal::reverse_postorder(&mir) { diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 37b1e0362..e6ba642a7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -352,7 +352,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { // Allocate an appropriate region on the stack, and copy the value into it let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); - let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, max_align); + let lldst = bx.byte_array_alloca(llsize, max_align); bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags); // Store the allocated region and the extra to the indirect place. diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 13d8f6edd..9c18df564 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -400,6 +400,21 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { downcast } + pub fn project_type>( + &self, + bx: &mut Bx, + ty: Ty<'tcx>, + ) -> Self { + let mut downcast = *self; + downcast.layout = bx.cx().layout_of(ty); + + // Cast to the appropriate type. + let variant_ty = bx.cx().backend_type(downcast.layout); + downcast.llval = bx.pointercast(downcast.llval, bx.cx().type_ptr_to(variant_ty)); + + downcast + } + pub fn storage_live>(&self, bx: &mut Bx) { bx.lifetime_start(self.llval, self.layout.size); } @@ -442,6 +457,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ProjectionElem::Field(ref field, _) => { cg_base.project_field(bx, field.index()) } + mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty), mir::ProjectionElem::Index(index) => { let index = &mir::Operand::Copy(mir::Place::from(index)); let index = self.codegen_operand(bx, index); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 56852b0fc..4aab31fbf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -4,7 +4,6 @@ use super::{FunctionCx, LocalRef}; use crate::base; use crate::common::{self, IntPredicate}; -use crate::meth::get_vtable; use crate::traits::*; use crate::MemFlags; @@ -250,7 +249,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Pair(lldata, llextra) } mir::CastKind::Pointer(PointerCast::MutToConstPointer) - | mir::CastKind::Misc + | mir::CastKind::PtrToPtr if bx.cx().is_backend_scalar_pair(operand.layout) => { if let OperandValue::Pair(data_ptr, meta) = operand.val { @@ -273,24 +272,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } mir::CastKind::DynStar => { - let data = match operand.val { + let (lldata, llextra) = match operand.val { OperandValue::Ref(_, _, _) => todo!(), - OperandValue::Immediate(v) => v, - OperandValue::Pair(_, _) => todo!(), + OperandValue::Immediate(v) => (v, None), + OperandValue::Pair(v, l) => (v, Some(l)), }; - let trait_ref = - if let ty::Dynamic(data, _, ty::DynStar) = cast.ty.kind() { - data.principal() - } else { - bug!("Only valid to do a DynStar cast into a DynStar type") - }; - let vtable = get_vtable(bx.cx(), source.ty(self.mir, bx.tcx()), trait_ref); - OperandValue::Pair(data, vtable) + let (lldata, llextra) = + base::cast_to_dyn_star(&mut bx, lldata, operand.layout, cast.ty, llextra); + OperandValue::Pair(lldata, llextra) } mir::CastKind::Pointer( PointerCast::MutToConstPointer | PointerCast::ArrayToPointer, ) - | mir::CastKind::Misc + | mir::CastKind::IntToInt + | mir::CastKind::FloatToInt + | mir::CastKind::FloatToFloat + | mir::CastKind::IntToFloat + | mir::CastKind::PtrToPtr + | mir::CastKind::FnPtrToPtr + // Since int2ptr can have arbitrary integer types as input (so we have to do // sign extension and all that), it is currently best handled in the same code // path as the other integer-to-X casts. diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 0e259bcd1..83407ee8f 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -13,17 +13,25 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; // if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ + // tidy-alphabetical-start ("aclass", Some(sym::arm_target_feature)), - ("mclass", Some(sym::arm_target_feature)), - ("rclass", Some(sym::arm_target_feature)), - ("dsp", Some(sym::arm_target_feature)), - ("neon", Some(sym::arm_target_feature)), + ("aes", Some(sym::arm_target_feature)), ("crc", Some(sym::arm_target_feature)), ("crypto", Some(sym::arm_target_feature)), - ("aes", Some(sym::arm_target_feature)), - ("sha2", Some(sym::arm_target_feature)), - ("i8mm", 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)), ("v5te", Some(sym::arm_target_feature)), ("v6", Some(sym::arm_target_feature)), ("v6k", Some(sym::arm_target_feature)), @@ -33,104 +41,97 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("vfp2", Some(sym::arm_target_feature)), ("vfp3", Some(sym::arm_target_feature)), ("vfp4", Some(sym::arm_target_feature)), - ("fp-armv8", 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)), - ("d32", Some(sym::arm_target_feature)), + // tidy-alphabetical-end ]; const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ - // FEAT_AdvSimd & FEAT_FP - ("neon", None), - // FEAT_FP16 - ("fp16", None), - // FEAT_SVE - ("sve", None), + // tidy-alphabetical-start + // FEAT_AES + ("aes", None), + // FEAT_BF16 + ("bf16", None), + // FEAT_BTI + ("bti", None), // FEAT_CRC ("crc", None), - // FEAT_RAS - ("ras", None), - // FEAT_LSE - ("lse", None), - // FEAT_RDM - ("rdm", None), - // FEAT_RCPC - ("rcpc", None), - // FEAT_RCPC2 - ("rcpc2", None), - // FEAT_DotProd - ("dotprod", None), - // FEAT_TME - ("tme", None), - // FEAT_FHM - ("fhm", None), // FEAT_DIT ("dit", None), - // FEAT_FLAGM - ("flagm", None), - // FEAT_SSBS - ("ssbs", None), - // FEAT_SB - ("sb", None), - // FEAT_PAUTH (address authentication) - ("paca", None), - // FEAT_PAUTH (generic authentication) - ("pacg", None), + // FEAT_DotProd + ("dotprod", None), // FEAT_DPB ("dpb", None), // FEAT_DPB2 ("dpb2", None), - // FEAT_SVE2 - ("sve2", None), - // FEAT_SVE2_AES - ("sve2-aes", None), - // FEAT_SVE2_SM4 - ("sve2-sm4", None), - // FEAT_SVE2_SHA3 - ("sve2-sha3", None), - // FEAT_SVE2_BitPerm - ("sve2-bitperm", None), - // FEAT_FRINTTS - ("frintts", None), - // FEAT_I8MM - ("i8mm", None), // FEAT_F32MM ("f32mm", None), // FEAT_F64MM ("f64mm", None), - // FEAT_BF16 - ("bf16", None), - // FEAT_RAND - ("rand", None), - // FEAT_BTI - ("bti", None), - // FEAT_MTE - ("mte", None), - // FEAT_JSCVT - ("jsconv", None), // FEAT_FCMA ("fcma", None), - // FEAT_AES - ("aes", 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_PAN - ("pan", None), - // FEAT_LOR - ("lor", None), - // FEAT_VHE - ("vh", None), - // FEAT_PMUv3 - ("pmuv3", 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)), @@ -138,6 +139,9 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("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]] = &[ @@ -145,6 +149,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[ ]; const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ + // tidy-alphabetical-start ("adx", None), ("aes", None), ("avx", None), @@ -194,69 +199,80 @@ const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("xsavec", None), ("xsaveopt", None), ("xsaves", None), + // tidy-alphabetical-end ]; const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ + // 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)] = &[ + // tidy-alphabetical-start ("altivec", Some(sym::powerpc_target_feature)), ("power8-altivec", Some(sym::powerpc_target_feature)), - ("power9-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)] = &[ + // 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)] = &[ - ("m", Some(sym::riscv_target_feature)), + // tidy-alphabetical-start ("a", Some(sym::riscv_target_feature)), ("c", Some(sym::riscv_target_feature)), - ("f", Some(sym::riscv_target_feature)), ("d", Some(sym::riscv_target_feature)), ("e", Some(sym::riscv_target_feature)), + ("f", Some(sym::riscv_target_feature)), + ("m", Some(sym::riscv_target_feature)), ("v", Some(sym::riscv_target_feature)), - ("zfinx", Some(sym::riscv_target_feature)), - ("zdinx", Some(sym::riscv_target_feature)), - ("zhinx", Some(sym::riscv_target_feature)), - ("zhinxmin", Some(sym::riscv_target_feature)), - ("zfh", Some(sym::riscv_target_feature)), - ("zfhmin", Some(sym::riscv_target_feature)), ("zba", Some(sym::riscv_target_feature)), ("zbb", Some(sym::riscv_target_feature)), ("zbc", Some(sym::riscv_target_feature)), - ("zbs", Some(sym::riscv_target_feature)), ("zbkb", Some(sym::riscv_target_feature)), ("zbkc", Some(sym::riscv_target_feature)), ("zbkx", Some(sym::riscv_target_feature)), + ("zbs", Some(sym::riscv_target_feature)), + ("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", Some(sym::riscv_target_feature)), + ("zkn", Some(sym::riscv_target_feature)), ("zknd", Some(sym::riscv_target_feature)), ("zkne", Some(sym::riscv_target_feature)), ("zknh", Some(sym::riscv_target_feature)), - ("zksed", Some(sym::riscv_target_feature)), - ("zksh", Some(sym::riscv_target_feature)), ("zkr", Some(sym::riscv_target_feature)), - ("zkn", Some(sym::riscv_target_feature)), ("zks", Some(sym::riscv_target_feature)), - ("zk", Some(sym::riscv_target_feature)), + ("zksed", Some(sym::riscv_target_feature)), + ("zksh", Some(sym::riscv_target_feature)), ("zkt", Some(sym::riscv_target_feature)), + // tidy-alphabetical-end ]; const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ - ("simd128", None), + // tidy-alphabetical-start ("atomics", Some(sym::wasm_target_feature)), - ("nontrapping-fptoint", Some(sym::wasm_target_feature)), ("bulk-memory", 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)), ("sign-ext", Some(sym::wasm_target_feature)), + ("simd128", None), + // tidy-alphabetical-end ]; const BPF_ALLOWED_FEATURES: &[(&str, Option)] = &[("alu32", Some(sym::bpf_target_feature))]; diff --git a/compiler/rustc_codegen_ssa/src/traits/abi.rs b/compiler/rustc_codegen_ssa/src/traits/abi.rs index a00d78daf..60d8f2a9e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/abi.rs +++ b/compiler/rustc_codegen_ssa/src/traits/abi.rs @@ -1,8 +1,5 @@ use super::BackendTypes; -use rustc_middle::ty::Ty; -use rustc_target::abi::call::FnAbi; pub trait AbiBuilderMethods<'tcx>: BackendTypes { - fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value); fn get_param(&mut self, index: usize) -> Self::Value; } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 779bd3ea2..87e347c61 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -134,8 +134,6 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se opt_level: config::OptLevel, target_features: &[String], ) -> TargetMachineFactoryFn; - fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str; - fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str>; fn spawn_thread(_time_trace: bool, f: F) -> std::thread::JoinHandle where diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 10cf8948b..01408f39f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -17,6 +17,7 @@ use crate::MemFlags; use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout}; use rustc_middle::ty::Ty; use rustc_span::Span; +use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange}; use rustc_target::spec::HasTargetSpec; @@ -71,6 +72,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn invoke( &mut self, llty: Self::Type, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: Self::Value, args: &[Self::Value], then: Self::BasicBlock, @@ -133,8 +135,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value; fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; - fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; - fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value; + fn byte_array_alloca(&mut self, len: Self::Value, align: Align) -> Self::Value; fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value; fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value; @@ -320,6 +321,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn call( &mut self, llty: Self::Type, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: Self::Value, args: &[Self::Value], funclet: Option<&Self::Funclet>, diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index 7755e6793..450672fb9 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -5,7 +5,7 @@ use rustc_span::Span; use rustc_target::abi::call::FnAbi; pub trait IntrinsicCallMethods<'tcx>: BackendTypes { - /// Remember to add all intrinsics here, in `compiler/rustc_typeck/src/check/mod.rs`, + /// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`, /// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics, /// add them to `compiler/rustc_codegen_llvm/src/context.rs`. fn codegen_intrinsic_call( diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index 4266e42ec..04e2b8796 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -15,12 +15,8 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn eh_personality(&self) -> Self::Value; fn sess(&self) -> &Session; fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>; - fn used_statics(&self) -> &RefCell>; - fn compiler_used_statics(&self) -> &RefCell>; fn set_frame_pointer_type(&self, llfn: Self::Function); fn apply_target_cpu_attr(&self, llfn: Self::Function); - fn create_used_variable(&self); - fn create_compiler_used_variable(&self); /// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists. fn declare_c_main(&self, fn_type: Self::Type) -> Option; } diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 8158e8dd0..bdc6a91cf 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -5,7 +5,6 @@ use crate::common::TypeKind; use crate::mir::place::PlaceRef; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty}; -use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; use rustc_target::abi::{AddressSpace, Integer}; @@ -75,16 +74,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) + ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all()) } fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) + ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all()) } fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { let param_env = ty::ParamEnv::reveal_all(); - if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) { + if ty.is_sized(self.tcx(), param_env) { return false; } diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index e54ec34f1..e0e8ffa89 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -9,7 +9,6 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { type Module: Send + Sync; type TargetMachine; type ModuleBuffer: ModuleBufferMethods; - type Context: ?Sized; type ThinData: Send + Sync; type ThinBuffer: ThinBufferMethods; -- cgit v1.2.3