summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_ssa/src/back
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/back')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs67
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs131
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs27
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs51
6 files changed, 207 insertions, 108 deletions
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"),
};