about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-12 08:25:26 +0000
committerbors <bors@rust-lang.org>2024-08-12 08:25:26 +0000
commita25ec22901e387d076eac487608a172d3b37390e (patch)
treef05489e27b891f15338149d09cd053f1eecc08a1 /compiler/rustc_codegen_ssa/src
parent3456432db1cb33322702b8a2585d5ffe13c4fd43 (diff)
parent14f9284ebecc4d7a6e68bf782720563a5e317888 (diff)
downloadrust-a25ec22901e387d076eac487608a172d3b37390e.tar.gz
rust-a25ec22901e387d076eac487608a172d3b37390e.zip
Auto merge of #3801 - RalfJung:rustup, r=RalfJung
Rustup
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs135
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs109
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs65
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs22
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs57
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs2
8 files changed, 313 insertions, 80 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 4f93b7b23c6..ce55d99f506 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -1,4 +1,6 @@
+use std::env;
 use std::error::Error;
+use std::ffi::OsString;
 use std::fs::{self, File};
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
@@ -9,7 +11,6 @@ use object::read::archive::ArchiveFile;
 use object::read::macho::FatArch;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::memmap::Mmap;
-use rustc_session::cstore::DllImport;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use tempfile::Builder as TempFileBuilder;
@@ -17,6 +18,7 @@ use tempfile::Builder as TempFileBuilder;
 use super::metadata::search_for_section;
 // Re-exporting for rustc_codegen_llvm::back::archive
 pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
+use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
 
 pub trait ArchiveBuilderBuilder {
     fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
@@ -30,10 +32,9 @@ pub trait ArchiveBuilderBuilder {
         &self,
         sess: &Session,
         lib_name: &str,
-        dll_imports: &[DllImport],
-        tmpdir: &Path,
-        is_direct_dependency: bool,
-    ) -> PathBuf;
+        import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+        output_path: &Path,
+    );
 
     fn extract_bundled_libs<'a>(
         &'a self,
@@ -72,6 +73,130 @@ pub trait ArchiveBuilderBuilder {
     }
 }
 
+pub fn create_mingw_dll_import_lib(
+    sess: &Session,
+    lib_name: &str,
+    import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+    output_path: &Path,
+) {
+    let def_file_path = output_path.with_extension("def");
+
+    let def_file_content = format!(
+        "EXPORTS\n{}",
+        import_name_and_ordinal_vector
+            .into_iter()
+            .map(|(name, ordinal)| {
+                match ordinal {
+                    Some(n) => format!("{name} @{n} NONAME"),
+                    None => name,
+                }
+            })
+            .collect::<Vec<String>>()
+            .join("\n")
+    );
+
+    match std::fs::write(&def_file_path, def_file_content) {
+        Ok(_) => {}
+        Err(e) => {
+            sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
+        }
+    };
+
+    // --no-leading-underscore: For the `import_name_type` feature to work, we need to be
+    // able to control the *exact* spelling of each of the symbols that are being imported:
+    // hence we don't want `dlltool` adding leading underscores automatically.
+    let dlltool = find_binutils_dlltool(sess);
+    let temp_prefix = {
+        let mut path = PathBuf::from(&output_path);
+        path.pop();
+        path.push(lib_name);
+        path
+    };
+    // dlltool target architecture args from:
+    // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
+    let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
+        "x86_64" => ("i386:x86-64", "--64"),
+        "x86" => ("i386", "--32"),
+        "aarch64" => ("arm64", "--64"),
+        "arm" => ("arm", "--32"),
+        _ => panic!("unsupported arch {}", sess.target.arch),
+    };
+    let mut dlltool_cmd = std::process::Command::new(&dlltool);
+    dlltool_cmd
+        .arg("-d")
+        .arg(def_file_path)
+        .arg("-D")
+        .arg(lib_name)
+        .arg("-l")
+        .arg(&output_path)
+        .arg("-m")
+        .arg(dlltool_target_arch)
+        .arg("-f")
+        .arg(dlltool_target_bitness)
+        .arg("--no-leading-underscore")
+        .arg("--temp-prefix")
+        .arg(temp_prefix);
+
+    match dlltool_cmd.output() {
+        Err(e) => {
+            sess.dcx().emit_fatal(ErrorCallingDllTool {
+                dlltool_path: dlltool.to_string_lossy(),
+                error: e,
+            });
+        }
+        // dlltool returns '0' on failure, so check for error output instead.
+        Ok(output) if !output.stderr.is_empty() => {
+            sess.dcx().emit_fatal(DlltoolFailImportLibrary {
+                dlltool_path: dlltool.to_string_lossy(),
+                dlltool_args: dlltool_cmd
+                    .get_args()
+                    .map(|arg| arg.to_string_lossy())
+                    .collect::<Vec<_>>()
+                    .join(" "),
+                stdout: String::from_utf8_lossy(&output.stdout),
+                stderr: String::from_utf8_lossy(&output.stderr),
+            })
+        }
+        _ => {}
+    }
+}
+
+fn find_binutils_dlltool(sess: &Session) -> OsString {
+    assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
+    if let Some(dlltool_path) = &sess.opts.cg.dlltool {
+        return dlltool_path.clone().into_os_string();
+    }
+
+    let tool_name: OsString = if sess.host.options.is_like_windows {
+        // If we're compiling on Windows, always use "dlltool.exe".
+        "dlltool.exe"
+    } else {
+        // On other platforms, use the architecture-specific name.
+        match sess.target.arch.as_ref() {
+            "x86_64" => "x86_64-w64-mingw32-dlltool",
+            "x86" => "i686-w64-mingw32-dlltool",
+            "aarch64" => "aarch64-w64-mingw32-dlltool",
+
+            // For non-standard architectures (e.g., aarch32) fallback to "dlltool".
+            _ => "dlltool",
+        }
+    }
+    .into();
+
+    // NOTE: it's not clear how useful it is to explicitly search PATH.
+    for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
+        let full_path = dir.join(&tool_name);
+        if full_path.is_file() {
+            return full_path.into_os_string();
+        }
+    }
+
+    // The user didn't specify the location of the dlltool binary, and we weren't able
+    // to find the appropriate one on the PATH. Just return the name of the tool
+    // and let the invocation fail with a hopefully useful error message.
+    tool_name
+}
+
 pub trait ArchiveBuilder {
     fn add_file(&mut self, path: &Path);
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 653895380be..7bad9d33e7d 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -51,7 +51,8 @@ use super::linker::{self, Linker};
 use super::metadata::{create_wrapper_file, MetadataPosition};
 use super::rpath::{self, RPathConfig};
 use crate::{
-    errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib,
+    common, errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo,
+    NativeLib,
 };
 
 pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
@@ -390,17 +391,13 @@ fn link_rlib<'a>(
         }
     }
 
-    for (raw_dylib_name, raw_dylib_imports) in
-        collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
-    {
-        let output_path = archive_builder_builder.create_dll_import_lib(
-            sess,
-            &raw_dylib_name,
-            &raw_dylib_imports,
-            tmpdir.as_ref(),
-            true,
-        );
-
+    for output_path in create_dll_import_libs(
+        sess,
+        archive_builder_builder,
+        codegen_results.crate_info.used_libraries.iter(),
+        tmpdir.as_ref(),
+        true,
+    )? {
         ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
             sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
         });
@@ -488,6 +485,47 @@ fn collate_raw_dylibs<'a>(
         .collect())
 }
 
+fn create_dll_import_libs<'a>(
+    sess: &Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
+    used_libraries: impl IntoIterator<Item = &'a NativeLib>,
+    tmpdir: &Path,
+    is_direct_dependency: bool,
+) -> Result<Vec<PathBuf>, ErrorGuaranteed> {
+    Ok(collate_raw_dylibs(sess, used_libraries)?
+        .into_iter()
+        .map(|(raw_dylib_name, raw_dylib_imports)| {
+            let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
+            let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib"));
+
+            let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
+
+            let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
+                .iter()
+                .map(|import: &DllImport| {
+                    if sess.target.arch == "x86" {
+                        (
+                            common::i686_decorated_name(import, mingw_gnu_toolchain, false),
+                            import.ordinal(),
+                        )
+                    } else {
+                        (import.name.to_string(), import.ordinal())
+                    }
+                })
+                .collect();
+
+            archive_builder_builder.create_dll_import_lib(
+                sess,
+                &raw_dylib_name,
+                import_name_and_ordinal_vector,
+                &output_path,
+            );
+
+            output_path
+        })
+        .collect())
+}
+
 /// Create a static archive.
 ///
 /// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
@@ -2305,16 +2343,14 @@ fn linker_with_args(
     );
 
     // Link with the import library generated for any raw-dylib functions.
-    for (raw_dylib_name, raw_dylib_imports) in
-        collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
-    {
-        cmd.add_object(&archive_builder_builder.create_dll_import_lib(
-            sess,
-            &raw_dylib_name,
-            &raw_dylib_imports,
-            tmpdir,
-            true,
-        ));
+    for output_path in create_dll_import_libs(
+        sess,
+        archive_builder_builder,
+        codegen_results.crate_info.used_libraries.iter(),
+        tmpdir,
+        true,
+    )? {
+        cmd.add_object(&output_path);
     }
     // As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
     // they are used within inlined functions or instantiated generic functions. We do this *after*
@@ -2339,16 +2375,14 @@ fn linker_with_args(
         .flatten()
         .collect::<Vec<_>>();
     native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
-    for (raw_dylib_name, raw_dylib_imports) in
-        collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
-    {
-        cmd.add_object(&archive_builder_builder.create_dll_import_lib(
-            sess,
-            &raw_dylib_name,
-            &raw_dylib_imports,
-            tmpdir,
-            false,
-        ));
+    for output_path in create_dll_import_libs(
+        sess,
+        archive_builder_builder,
+        native_libraries_from_nonstatics,
+        tmpdir,
+        false,
+    )? {
+        cmd.add_object(&output_path);
     }
 
     // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
@@ -2612,16 +2646,7 @@ fn add_native_libs_from_crate(
             NativeLibKind::Static { bundle, whole_archive } => {
                 if link_static {
                     let bundle = bundle.unwrap_or(true);
-                    let whole_archive = whole_archive == Some(true)
-                        // Backward compatibility case: this can be a rlib (so `+whole-archive`
-                        // cannot be added explicitly if necessary, see the error in `fn link_rlib`)
-                        // compiled as an executable due to `--test`. Use whole-archive implicitly,
-                        // like before the introduction of native lib modifiers.
-                        || (whole_archive == None
-                            && bundle
-                            && cnum == LOCAL_CRATE
-                            && sess.is_test_crate());
-
+                    let whole_archive = whole_archive == Some(true);
                     if bundle && cnum != LOCAL_CRATE {
                         if let Some(filename) = lib.filename {
                             // If rlib contains native libs as archives, they are unpacked to tmpdir.
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 19394029c94..9b5a797ad51 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -208,6 +208,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         "powerpc64" => (Architecture::PowerPc64, None),
         "riscv32" => (Architecture::Riscv32, None),
         "riscv64" => (Architecture::Riscv64, None),
+        "sparc" => (Architecture::Sparc32Plus, None),
         "sparc64" => (Architecture::Sparc64, None),
         "avr" => (Architecture::Avr, None),
         "msp430" => (Architecture::Msp430, None),
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index f4e44e63d73..f1e7f87f567 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -143,7 +143,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 ) -> Bx::Value {
     let cx = bx.cx();
     let (source, target) =
-        cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env());
+        cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env());
     match (source.kind(), target.kind()) {
         (&ty::Array(_, len), &ty::Slice(_)) => {
             cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index a972c0cd99d..bfb1d217eae 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -4,7 +4,9 @@ use rustc_hir::LangItem;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_middle::{bug, mir, span_bug};
+use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
 use rustc_span::Span;
+use rustc_target::spec::Target;
 
 use crate::traits::*;
 
@@ -176,3 +178,66 @@ pub fn asm_const_to_str<'tcx>(
         _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
     }
 }
+
+pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
+    target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
+}
+
+pub fn i686_decorated_name(
+    dll_import: &DllImport,
+    mingw: bool,
+    disable_name_mangling: bool,
+) -> String {
+    let name = dll_import.name.as_str();
+
+    let (add_prefix, add_suffix) = match dll_import.import_name_type {
+        Some(PeImportNameType::NoPrefix) => (false, true),
+        Some(PeImportNameType::Undecorated) => (false, false),
+        _ => (true, true),
+    };
+
+    // Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
+    let mut decorated_name = String::with_capacity(name.len() + 6);
+
+    if disable_name_mangling {
+        // LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled.
+        decorated_name.push('\x01');
+    }
+
+    let prefix = if add_prefix && dll_import.is_fn {
+        match dll_import.calling_convention {
+            DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
+            DllCallingConvention::Stdcall(_) => (!mingw
+                || dll_import.import_name_type == Some(PeImportNameType::Decorated))
+            .then_some('_'),
+            DllCallingConvention::Fastcall(_) => Some('@'),
+        }
+    } else if !dll_import.is_fn && !mingw {
+        // For static variables, prefix with '_' on MSVC.
+        Some('_')
+    } else {
+        None
+    };
+    if let Some(prefix) = prefix {
+        decorated_name.push(prefix);
+    }
+
+    decorated_name.push_str(name);
+
+    if add_suffix && dll_import.is_fn {
+        use std::fmt::Write;
+
+        match dll_import.calling_convention {
+            DllCallingConvention::C => {}
+            DllCallingConvention::Stdcall(arg_list_size)
+            | DllCallingConvention::Fastcall(arg_list_size) => {
+                write!(&mut decorated_name, "@{arg_list_size}").unwrap();
+            }
+            DllCallingConvention::Vectorcall(arg_list_size) => {
+                write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
+            }
+        }
+    }
+
+    decorated_name
+}
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 2d1eae630cf..94bf0ab34e2 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1027,6 +1027,28 @@ pub struct FailedToGetLayout<'tcx> {
 }
 
 #[derive(Diagnostic)]
+#[diag(codegen_ssa_dlltool_fail_import_library)]
+pub(crate) struct DlltoolFailImportLibrary<'a> {
+    pub dlltool_path: Cow<'a, str>,
+    pub dlltool_args: String,
+    pub stdout: Cow<'a, str>,
+    pub stderr: Cow<'a, str>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_error_writing_def_file)]
+pub(crate) struct ErrorWritingDEFFile {
+    pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_error_calling_dlltool)]
+pub(crate) struct ErrorCallingDllTool<'a> {
+    pub dlltool_path: Cow<'a, str>,
+    pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
 #[diag(codegen_ssa_error_creating_remark_dir)]
 pub struct ErrorCreatingRemarkDir {
     pub error: std::io::Error,
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 24b2c9c51c6..cf8f7fa25d8 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -1,11 +1,12 @@
 use rustc_ast::ast;
 use rustc_attr::InstructionSetAttr;
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::Applicability;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_middle::bug;
+use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
@@ -18,7 +19,7 @@ pub fn from_target_feature(
     tcx: TyCtxt<'_>,
     attr: &ast::Attribute,
     supported_target_features: &UnordMap<String, Option<Symbol>>,
-    target_features: &mut Vec<Symbol>,
+    target_features: &mut Vec<TargetFeature>,
 ) {
     let Some(list) = attr.meta_item_list() else { return };
     let bad_item = |span| {
@@ -99,14 +100,26 @@ pub fn from_target_feature(
         }));
     }
 
-    // Add both explicit and implied target features, using a set to deduplicate
-    let mut target_features_set = UnordSet::new();
+    // Add explicit features
+    target_features.extend(
+        added_target_features.iter().copied().map(|name| TargetFeature { name, implied: false }),
+    );
+
+    // Add implied features
+    let mut implied_target_features = UnordSet::new();
+    for feature in added_target_features.iter() {
+        implied_target_features.extend(tcx.implied_target_features(*feature).clone());
+    }
     for feature in added_target_features.iter() {
-        target_features_set
-            .extend_unord(tcx.implied_target_features(*feature).clone().into_items());
+        implied_target_features.remove(feature);
     }
-    target_features_set.extend(added_target_features);
-    target_features.extend(target_features_set.into_sorted_stable_ord())
+    target_features.extend(
+        implied_target_features
+            .into_sorted_stable_ord()
+            .iter()
+            .copied()
+            .map(|name| TargetFeature { name, implied: true }),
+    )
 }
 
 /// Computes the set of target features used in a function for the purposes of
@@ -115,7 +128,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
     let mut target_features = tcx.sess.unstable_target_features.clone();
     if tcx.def_kind(did).has_codegen_attrs() {
         let attrs = tcx.codegen_fn_attrs(did);
-        target_features.extend(&attrs.target_features);
+        target_features.extend(attrs.target_features.iter().map(|feature| feature.name));
         match attrs.instruction_set {
             None => {}
             Some(InstructionSetAttr::ArmA32) => {
@@ -160,31 +173,13 @@ pub(crate) fn provide(providers: &mut Providers) {
                     .target
                     .supported_target_features()
                     .iter()
-                    .map(|&(a, b)| (a.to_string(), b.as_feature_name()))
+                    .map(|&(a, b, _)| (a.to_string(), b.as_feature_name()))
                     .collect()
             }
         },
         implied_target_features: |tcx, feature| {
-            let implied_features = tcx
-                .sess
-                .target
-                .implied_target_features()
-                .iter()
-                .map(|(f, i)| (Symbol::intern(f), i))
-                .collect::<FxHashMap<_, _>>();
-
-            // implied target features have their own implied target features, so we traverse the
-            // map until there are no more features to add
-            let mut features = UnordSet::new();
-            let mut new_features = vec![feature];
-            while let Some(new_feature) = new_features.pop() {
-                if features.insert(new_feature) {
-                    if let Some(implied_features) = implied_features.get(&new_feature) {
-                        new_features.extend(implied_features.iter().copied().map(Symbol::intern))
-                    }
-                }
-            }
-            features
+            UnordSet::from(tcx.sess.target.implied_target_features(std::iter::once(feature)))
+                .into_sorted_stable_ord()
         },
         asm_target_features,
         ..*providers
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index 80dad79179a..7c042c0c621 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -91,7 +91,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
             return false;
         }
 
-        let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env);
+        let tail = self.tcx().struct_tail_for_codegen(ty, param_env);
         match tail.kind() {
             ty::Foreign(..) => false,
             ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,