about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2025-03-03 08:38:46 +0200
committerLaurențiu Nicola <lnicola@dend.ro>2025-03-03 08:38:46 +0200
commitdd3a5f9a64f97fd02e1d254236cb1612ed119e82 (patch)
tree3f99fe82095b8a0ec0b3d1cfa541983a0eaa728e /compiler/rustc_codegen_ssa/src
parent969868ba30b41af0cece305cd68d133369b492a4 (diff)
parentdaf59857d6d2b87af4b846316bf1561a6083ed51 (diff)
downloadrust-dd3a5f9a64f97fd02e1d254236cb1612ed119e82.tar.gz
rust-dd3a5f9a64f97fd02e1d254236cb1612ed119e82.zip
Merge from rust-lang/rust
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/assert_module_sources.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/back/apple.rs84
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs67
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs125
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/naked_asm.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/write.rs2
18 files changed, 278 insertions, 116 deletions
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index 27331ce4ca6..32f689608f8 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -94,7 +94,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
                 other => {
                     self.tcx
                         .dcx()
-                        .emit_fatal(errors::UnknownReuseKind { span: attr.span, kind: other });
+                        .emit_fatal(errors::UnknownReuseKind { span: attr.span(), kind: other });
                 }
             }
         } else {
@@ -102,7 +102,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
         };
 
         if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
-            self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span: attr.span });
+            self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span: attr.span() });
         }
 
         if !self.check_config(attr) {
@@ -115,7 +115,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
 
         if !user_path.starts_with(&crate_name) {
             self.tcx.dcx().emit_fatal(errors::MalformedCguName {
-                span: attr.span,
+                span: attr.span(),
                 user_path,
                 crate_name,
             });
@@ -145,7 +145,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
             let cgu_names: Vec<&str> =
                 self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord();
             self.tcx.dcx().emit_err(errors::NoModuleNamed {
-                span: attr.span,
+                span: attr.span(),
                 user_path,
                 cgu_name,
                 cgu_names: cgu_names.join(", "),
@@ -155,7 +155,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
         self.cgu_reuse_tracker.set_expectation(
             cgu_name,
             user_path,
-            attr.span,
+            attr.span(),
             expected_reuse,
             comp_kind,
         );
@@ -175,7 +175,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
             }
         }
 
-        self.tcx.dcx().emit_fatal(errors::NoField { span: attr.span, name });
+        self.tcx.dcx().emit_fatal(errors::NoField { span: attr.span(), name });
     }
 
     /// Scan for a `cfg="foo"` attribute and check whether we have a
@@ -211,7 +211,7 @@ impl fmt::Display for CguReuse {
 }
 
 impl IntoDiagArg for CguReuse {
-    fn into_diag_arg(self) -> DiagArgValue {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.to_string()))
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index d9c5c3e5af9..bfa7635a869 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -2,6 +2,7 @@ use std::env;
 use std::fmt::{Display, from_fn};
 use std::num::ParseIntError;
 
+use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_session::Session;
 use rustc_target::spec::Target;
 
@@ -26,6 +27,89 @@ pub(super) fn macho_platform(target: &Target) -> u32 {
     }
 }
 
+/// Add relocation and section data needed for a symbol to be considered
+/// undefined by ld64.
+///
+/// The relocation must be valid, and hence must point to a valid piece of
+/// machine code, and hence this is unfortunately very architecture-specific.
+///
+///
+/// # New architectures
+///
+/// The values here are basically the same as emitted by the following program:
+///
+/// ```c
+/// // clang -c foo.c -target $CLANG_TARGET
+/// void foo(void);
+///
+/// extern int bar;
+///
+/// void* foobar[2] = {
+///     (void*)foo,
+///     (void*)&bar,
+///     // ...
+/// };
+/// ```
+///
+/// Can be inspected with:
+/// ```console
+/// objdump --macho --reloc foo.o
+/// objdump --macho --full-contents foo.o
+/// ```
+pub(super) fn add_data_and_relocation(
+    file: &mut object::write::Object<'_>,
+    section: object::write::SectionId,
+    symbol: object::write::SymbolId,
+    target: &Target,
+    kind: SymbolExportKind,
+) -> object::write::Result<()> {
+    let authenticated_pointer =
+        kind == SymbolExportKind::Text && target.llvm_target.starts_with("arm64e");
+
+    let data: &[u8] = match target.pointer_width {
+        _ if authenticated_pointer => &[0, 0, 0, 0, 0, 0, 0, 0x80],
+        32 => &[0; 4],
+        64 => &[0; 8],
+        pointer_width => unimplemented!("unsupported Apple pointer width {pointer_width:?}"),
+    };
+
+    if target.arch == "x86_64" {
+        // Force alignment for the entire section to be 16 on x86_64.
+        file.section_mut(section).append_data(&[], 16);
+    } else {
+        // Elsewhere, the section alignment is the same as the pointer width.
+        file.section_mut(section).append_data(&[], target.pointer_width as u64);
+    }
+
+    let offset = file.section_mut(section).append_data(data, data.len() as u64);
+
+    let flags = if authenticated_pointer {
+        object::write::RelocationFlags::MachO {
+            r_type: object::macho::ARM64_RELOC_AUTHENTICATED_POINTER,
+            r_pcrel: false,
+            r_length: 3,
+        }
+    } else if target.arch == "arm" {
+        // FIXME(madsmtm): Remove once `object` supports 32-bit ARM relocations:
+        // https://github.com/gimli-rs/object/pull/757
+        object::write::RelocationFlags::MachO {
+            r_type: object::macho::ARM_RELOC_VANILLA,
+            r_pcrel: false,
+            r_length: 2,
+        }
+    } else {
+        object::write::RelocationFlags::Generic {
+            kind: object::RelocationKind::Absolute,
+            encoding: object::RelocationEncoding::Generic,
+            size: target.pointer_width as u8,
+        }
+    };
+
+    file.add_relocation(section, object::write::Relocation { offset, addend: 0, symbol, flags })?;
+
+    Ok(())
+}
+
 /// Deployment target or SDK version.
 ///
 /// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`.
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 4c076450269..5054ae561c0 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1726,8 +1726,12 @@ fn exec_linker(
         args.push_str(
             &Escape {
                 arg: arg.to_str().unwrap(),
-                // LLD also uses MSVC-like parsing for @-files by default when running on windows hosts
-                is_like_msvc: sess.target.is_like_msvc || (cfg!(windows) && flavor.uses_lld()),
+                // Windows-style escaping for @-files is used by
+                // - all linkers targeting MSVC-like targets, including LLD
+                // - all LLD flavors running on Windows hosts
+                // С/С++ compilers use Posix-style escaping (except clang-cl, which we do not use).
+                is_like_msvc: sess.target.is_like_msvc
+                    || (cfg!(windows) && flavor.uses_lld() && !flavor.uses_cc()),
             }
             .to_string(),
         );
@@ -2058,8 +2062,8 @@ fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor
 /// linker, and since they never participate in the linking, using `KEEP` in the linker scripts
 /// can't keep them either. This causes #47384.
 ///
-/// To keep them around, we could use `--whole-archive` and equivalents to force rlib to
-/// participate in linking like object files, but this proves to be expensive (#93791). Therefore
+/// To keep them around, we could use `--whole-archive`, `-force_load` and equivalents to force rlib
+/// to participate in linking like object files, but this proves to be expensive (#93791). Therefore
 /// we instead just introduce an undefined reference to them. This could be done by `-u` command
 /// line option to the linker or `EXTERN(...)` in linker scripts, however they does not only
 /// introduce an undefined reference, but also make them the GC roots, preventing `--gc-sections`
@@ -2101,8 +2105,20 @@ fn add_linked_symbol_object(
         file.set_mangling(object::write::Mangling::None);
     }
 
+    // ld64 requires a relocation to load undefined symbols, see below.
+    // Not strictly needed if linking with lld, but might as well do it there too.
+    let ld64_section_helper = if file.format() == object::BinaryFormat::MachO {
+        Some(file.add_section(
+            file.segment_name(object::write::StandardSegment::Data).to_vec(),
+            "__data".into(),
+            object::SectionKind::Data,
+        ))
+    } else {
+        None
+    };
+
     for (sym, kind) in symbols.iter() {
-        file.add_symbol(object::write::Symbol {
+        let symbol = file.add_symbol(object::write::Symbol {
             name: sym.clone().into(),
             value: 0,
             size: 0,
@@ -2116,6 +2132,47 @@ fn add_linked_symbol_object(
             section: object::write::SymbolSection::Undefined,
             flags: object::SymbolFlags::None,
         });
+
+        // The linker shipped with Apple's Xcode, ld64, works a bit differently from other linkers.
+        //
+        // Code-wise, the relevant parts of ld64 are roughly:
+        // 1. Find the `ArchiveLoadMode` based on commandline options, default to `parseObjects`.
+        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/Options.cpp#L924-L932
+        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/Options.h#L55
+        //
+        // 2. Read the archive table of contents (__.SYMDEF file).
+        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L294-L325
+        //
+        // 3. Begin linking by loading "atoms" from input files.
+        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/doc/design/linker.html
+        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/InputFiles.cpp#L1349
+        //
+        //   a. Directly specified object files (`.o`) are parsed immediately.
+        //      https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/macho_relocatable_file.cpp#L4611-L4627
+        //
+        //     - Undefined symbols are not atoms (`n_value > 0` denotes a common symbol).
+        //       https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/macho_relocatable_file.cpp#L2455-L2468
+        //       https://maskray.me/blog/2022-02-06-all-about-common-symbols
+        //
+        //     - Relocations/fixups are atoms.
+        //       https://github.com/apple-oss-distributions/ld64/blob/ce6341ae966b3451aa54eeb049f2be865afbd578/src/ld/parsers/macho_relocatable_file.cpp#L2088-L2114
+        //
+        //   b. Archives are not parsed yet.
+        //      https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L467-L577
+        //
+        // 4. When a symbol is needed by an atom, parse the object file that contains the symbol.
+        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/InputFiles.cpp#L1417-L1491
+        //    https://github.com/apple-oss-distributions/ld64/blob/ld64-954.16/src/ld/parsers/archive_file.cpp#L579-L597
+        //
+        // All of the steps above are fairly similar to other linkers, except that **it completely
+        // ignores undefined symbols**.
+        //
+        // So to make this trick work on ld64, we need to do something else to load the relevant
+        // object files. We do this by inserting a relocation (fixup) for each symbol.
+        if let Some(section) = ld64_section_helper {
+            apple::add_data_and_relocation(&mut file, section, symbol, &sess.target, *kind)
+                .expect("failed adding relocation");
+        }
     }
 
     let path = tmpdir.join("symbols.o");
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 8900405c1b8..818edaf6603 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1939,14 +1939,14 @@ impl<'a> Linker for LlbcLinker<'a> {
     }
 
     fn optimize(&mut self) {
-        match self.sess.opts.optimize {
+        self.link_arg(match self.sess.opts.optimize {
             OptLevel::No => "-O0",
             OptLevel::Less => "-O1",
             OptLevel::More => "-O2",
             OptLevel::Aggressive => "-O3",
             OptLevel::Size => "-Os",
             OptLevel::SizeMin => "-Oz",
-        };
+        });
     }
 
     fn full_relro(&mut self) {}
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 236507ac0cd..3aacbcde1a7 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -373,7 +373,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         Architecture::Avr => {
             // Resolve the ISA revision and set
             // the appropriate EF_AVR_ARCH flag.
-            ef_avr_arch(&sess.target.options.cpu)
+            if let Some(ref cpu) = sess.opts.cg.target_cpu {
+                ef_avr_arch(cpu)
+            } else {
+                bug!("AVR CPU not explicitly specified")
+            }
         }
         Architecture::Csky => {
             let e_flags = match sess.target.options.abi.as_ref() {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index f008bd12ed8..c8bb229998e 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -278,6 +278,10 @@ impl ModuleConfig {
             || self.emit_obj == EmitObj::Bitcode
             || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
     }
+
+    pub fn embed_bitcode(&self) -> bool {
+        self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
+    }
 }
 
 /// Configuration passed to the function returned by the `target_machine_factory`.
@@ -877,14 +881,14 @@ pub(crate) fn compute_per_cgu_lto_type(
 
 fn execute_optimize_work_item<B: ExtraBackendMethods>(
     cgcx: &CodegenContext<B>,
-    module: ModuleCodegen<B::Module>,
+    mut module: ModuleCodegen<B::Module>,
     module_config: &ModuleConfig,
 ) -> Result<WorkItemResult<B>, FatalError> {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
 
     unsafe {
-        B::optimize(cgcx, dcx, &module, module_config)?;
+        B::optimize(cgcx, dcx, &mut module, module_config)?;
     }
 
     // After we've done the initial round of optimizations we need to
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 40238f4b491..63f2f8fa3d1 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -5,7 +5,9 @@ use std::time::{Duration, Instant};
 
 use itertools::Itertools;
 use rustc_abi::FIRST_VARIANT;
+use rustc_ast as ast;
 use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name};
+use rustc_attr_parsing::OptimizeAttr;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
 use rustc_data_structures::sync::par_map;
@@ -29,7 +31,6 @@ use rustc_span::{DUMMY_SP, Symbol, sym};
 use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
 use tracing::{debug, info};
-use {rustc_ast as ast, rustc_attr_parsing as attr};
 
 use crate::assert_module_sources::CguReuse;
 use crate::back::link::are_upstream_rust_objects_already_included;
@@ -686,7 +687,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         submit_codegened_module_to_llvm(
             &backend,
             &ongoing_codegen.coordinator.sender,
-            ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator },
+            ModuleCodegen::new_allocator(llmod_id, module_llvm),
             cost,
         );
     }
@@ -1061,7 +1062,7 @@ pub(crate) fn provide(providers: &mut Providers) {
 
         let any_for_speed = defids.items().any(|id| {
             let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id);
-            matches!(optimize, attr::OptimizeAttr::Speed)
+            matches!(optimize, OptimizeAttr::Speed)
         });
 
         if any_for_speed {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 97bc84c0b69..673740b4aab 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -5,7 +5,8 @@ use rustc_ast::expand::autodiff_attrs::{
     AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
 };
 use rustc_ast::{MetaItem, MetaItemInner, attr};
-use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_attr_parsing::ReprAttr::ReprAlign;
+use rustc_attr_parsing::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::codes::*;
 use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
@@ -104,12 +105,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
             if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
                 Some(tcx.fn_sig(did))
             } else {
-                tcx.dcx()
-                    .span_delayed_bug(attr.span, "this attribute can only be applied to functions");
+                tcx.dcx().span_delayed_bug(
+                    attr.span(),
+                    "this attribute can only be applied to functions",
+                );
                 None
             }
         };
 
+        if let hir::Attribute::Parsed(p) = attr {
+            match p {
+                AttributeKind::Repr(reprs) => {
+                    codegen_fn_attrs.alignment = reprs
+                        .iter()
+                        .find_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None });
+                }
+
+                _ => {}
+            }
+        }
+
         let Some(Ident { name, .. }) = attr.ident() else {
             continue;
         };
@@ -130,14 +145,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                 if tcx.opt_item_name(did.to_def_id()).is_some() {
                     codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
                     mixed_export_name_no_mangle_lint_state.track_no_mangle(
-                        attr.span,
+                        attr.span(),
                         tcx.local_def_id_to_hir_id(did),
                         attr,
                     );
                 } else {
                     tcx.dcx()
                         .struct_span_err(
-                            attr.span,
+                            attr.span(),
                             format!(
                                 "`#[no_mangle]` cannot be used on {} {} as it has no name",
                                 tcx.def_descr_article(did.to_def_id()),
@@ -158,7 +173,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                             feature_err(
                                 &tcx.sess,
                                 sym::used_with_arg,
-                                attr.span,
+                                attr.span(),
                                 "`#[used(linker)]` is currently unstable",
                             )
                             .emit();
@@ -170,7 +185,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                             feature_err(
                                 &tcx.sess,
                                 sym::used_with_arg,
-                                attr.span,
+                                attr.span(),
                                 "`#[used(compiler)]` is currently unstable",
                             )
                             .emit();
@@ -178,7 +193,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
                     }
                     Some(_) => {
-                        tcx.dcx().emit_err(errors::ExpectedUsedSymbol { span: attr.span });
+                        tcx.dcx().emit_err(errors::ExpectedUsedSymbol { span: attr.span() });
                     }
                     None => {
                         // Unfortunately, unconditionally using `llvm.used` causes
@@ -223,7 +238,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                 {
                     struct_span_code_err!(
                         tcx.dcx(),
-                        attr.span,
+                        attr.span(),
                         E0737,
                         "`#[track_caller]` requires Rust ABI"
                     )
@@ -231,12 +246,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                 }
                 if is_closure
                     && !tcx.features().closure_track_caller()
-                    && !attr.span.allows_unstable(sym::closure_track_caller)
+                    && !attr.span().allows_unstable(sym::closure_track_caller)
                 {
                     feature_err(
                         &tcx.sess,
                         sym::closure_track_caller,
-                        attr.span,
+                        attr.span(),
                         "`#[track_caller]` on closures is currently unstable",
                     )
                     .emit();
@@ -250,19 +265,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         // so it may not contain any null characters.
                         struct_span_code_err!(
                             tcx.dcx(),
-                            attr.span,
+                            attr.span(),
                             E0648,
                             "`export_name` may not contain null characters"
                         )
                         .emit();
                     }
                     codegen_fn_attrs.export_name = Some(s);
-                    mixed_export_name_no_mangle_lint_state.track_export_name(attr.span);
+                    mixed_export_name_no_mangle_lint_state.track_export_name(attr.span());
                 }
             }
             sym::target_feature => {
                 let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else {
-                    tcx.dcx().span_delayed_bug(attr.span, "target_feature applied to non-fn");
+                    tcx.dcx().span_delayed_bug(attr.span(), "target_feature applied to non-fn");
                     continue;
                 };
                 let safe_target_features =
@@ -292,7 +307,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         // `main`, `start`, and other functions that are not usually
                         // allowed.
                     } else {
-                        check_target_feature_trait_unsafe(tcx, did, attr.span);
+                        check_target_feature_trait_unsafe(tcx, did, attr.span());
                     }
                 }
                 from_target_feature_attr(
@@ -310,7 +325,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
 
                         if tcx.is_mutable_static(did.into()) {
                             let mut diag = tcx.dcx().struct_span_err(
-                                attr.span,
+                                attr.span(),
                                 "extern mutable statics are not allowed with `#[linkage]`",
                             );
                             diag.note(
@@ -329,7 +344,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                 if let Some(val) = attr.value_str() {
                     if val.as_str().bytes().any(|b| b == 0) {
                         let msg = format!("illegal null byte in link_section value: `{val}`");
-                        tcx.dcx().span_err(attr.span, msg);
+                        tcx.dcx().span_err(attr.span(), msg);
                     } else {
                         codegen_fn_attrs.link_section = Some(val);
                     }
@@ -337,13 +352,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
             }
             sym::link_name => codegen_fn_attrs.link_name = attr.value_str(),
             sym::link_ordinal => {
-                link_ordinal_span = Some(attr.span);
+                link_ordinal_span = Some(attr.span());
                 if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
                     codegen_fn_attrs.link_ordinal = ordinal;
                 }
             }
             sym::no_sanitize => {
-                no_sanitize_span = Some(attr.span);
+                no_sanitize_span = Some(attr.span());
                 if let Some(list) = attr.meta_item_list() {
                     for item in list.iter() {
                         match item.name_or_empty() {
@@ -381,7 +396,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                                 {
                                     struct_span_code_err!(
                                         tcx.dcx(),
-                                        attr.span,
+                                        attr.span(),
                                         E0779,
                                         "target does not support `#[instruction_set]`"
                                     )
@@ -393,7 +408,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                                 _ => {
                                     struct_span_code_err!(
                                         tcx.dcx(),
-                                        attr.span,
+                                        attr.span(),
                                         E0779,
                                         "invalid instruction set specified",
                                     )
@@ -405,7 +420,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         [] => {
                             struct_span_code_err!(
                                 tcx.dcx(),
-                                attr.span,
+                                attr.span(),
                                 E0778,
                                 "`#[instruction_set]` requires an argument"
                             )
@@ -415,7 +430,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         _ => {
                             struct_span_code_err!(
                                 tcx.dcx(),
-                                attr.span,
+                                attr.span(),
                                 E0779,
                                 "cannot specify more than one instruction set"
                             )
@@ -424,27 +439,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         }
                     })
             }
-            sym::repr => {
-                codegen_fn_attrs.alignment = if let Some(items) = attr.meta_item_list()
-                    && let [item] = items.as_slice()
-                    && let Some((sym::align, literal)) = item.singleton_lit_list()
-                {
-                    rustc_attr_parsing::parse_alignment(&literal.kind)
-                        .inspect_err(|msg| {
-                            struct_span_code_err!(
-                                tcx.dcx(),
-                                literal.span,
-                                E0589,
-                                "invalid `repr(align)` attribute: {}",
-                                msg
-                            )
-                            .emit();
-                        })
-                        .ok()
-                } else {
-                    None
-                };
-            }
             sym::patchable_function_entry => {
                 codegen_fn_attrs.patchable_function_entry = attr.meta_item_list().and_then(|l| {
                     let mut prefix = None;
@@ -510,7 +504,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     }
 
                     if let (None, None) = (prefix, entry) {
-                        tcx.dcx().span_err(attr.span, "must specify at least one parameter");
+                        tcx.dcx().span_err(attr.span(), "must specify at least one parameter");
                     }
 
                     Some(PatchableFunctionEntry::from_prefix_and_entry(
@@ -536,18 +530,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         let Some(ref items) = attr.meta_item_list() else {
             return ia;
         };
+        inline_span = Some(attr.span());
 
-        inline_span = Some(attr.span);
         let [item] = &items[..] else {
-            struct_span_code_err!(tcx.dcx(), attr.span, E0534, "expected one argument").emit();
+            struct_span_code_err!(tcx.dcx(), attr.span(), E0534, "expected one argument").emit();
             return InlineAttr::None;
         };
+
         if item.has_name(sym::always) {
             InlineAttr::Always
         } else if item.has_name(sym::never) {
             InlineAttr::Never
         } else {
-            struct_span_code_err!(tcx.dcx(), item.span(), E0535, "invalid argument")
+            struct_span_code_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
                 .with_help("valid inline arguments are `always` and `never`")
                 .emit();
 
@@ -560,9 +555,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         }
 
         if attr.is_word() {
-            InlineAttr::Force { attr_span: attr.span, reason: None }
+            InlineAttr::Force { attr_span: attr.span(), reason: None }
         } else if let Some(val) = attr.value_str() {
-            InlineAttr::Force { attr_span: attr.span, reason: Some(val) }
+            InlineAttr::Force { attr_span: attr.span(), reason: Some(val) }
         } else {
             debug!("`rustc_force_inline` not checked by attribute validation");
             ia
@@ -582,16 +577,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         }
         let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
         if attr.is_word() {
-            err(attr.span, "expected one argument");
+            err(attr.span(), "expected one argument");
             return ia;
         }
         let Some(ref items) = attr.meta_item_list() else {
             return OptimizeAttr::Default;
         };
 
-        inline_span = Some(attr.span);
+        inline_span = Some(attr.span());
         let [item] = &items[..] else {
-            err(attr.span, "expected one argument");
+            err(attr.span(), "expected one argument");
             return OptimizeAttr::Default;
         };
         if item.has_name(sym::size) {
@@ -703,7 +698,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         let span = tcx
             .get_attrs(did, sym::target_feature)
             .next()
-            .map_or_else(|| tcx.def_span(did), |a| a.span);
+            .map_or_else(|| tcx.def_span(did), |a| a.span());
         tcx.dcx()
             .create_err(errors::TargetFeatureDisableOrEnable {
                 features,
@@ -752,7 +747,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option<u16> {
     use rustc_ast::{LitIntType, LitKind, MetaItemLit};
     let meta_item_list = attr.meta_item_list()?;
     let [sole_meta_list] = &meta_item_list[..] else {
-        tcx.dcx().emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span });
+        tcx.dcx().emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span() });
         return None;
     };
     if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
@@ -776,13 +771,13 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option<u16> {
         } else {
             let msg = format!("ordinal value in `link_ordinal` is too large: `{ordinal}`");
             tcx.dcx()
-                .struct_span_err(attr.span, msg)
+                .struct_span_err(attr.span(), msg)
                 .with_note("the value may not exceed `u16::MAX`")
                 .emit();
             None
         }
     } else {
-        tcx.dcx().emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span });
+        tcx.dcx().emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span() });
         None
     }
 }
@@ -828,7 +823,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
             export_name: Some(export_name),
             no_mangle: Some(no_mangle),
             hir_id: Some(hir_id),
-            no_mangle_attr: Some(no_mangle_attr),
+            no_mangle_attr: Some(_),
         } = self
         {
             tcx.emit_node_span_lint(
@@ -837,7 +832,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
                 no_mangle,
                 errors::MixedExportNameAndNoMangle {
                     no_mangle,
-                    no_mangle_attr: rustc_hir_pretty::attribute_to_string(&tcx, no_mangle_attr),
+                    no_mangle_attr: "#[unsafe(no_mangle)]".to_string(),
                     export_name,
                     removal_span: no_mangle,
                 },
@@ -869,7 +864,7 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
         _ => {
             //FIXME(ZuseZ4): Once we fixed our parser, we should also prohibit the two-attribute
             //branch above.
-            span_bug!(attrs[1].span, "cg_ssa: rustc_autodiff should only exist once per source");
+            span_bug!(attrs[1].span(), "cg_ssa: rustc_autodiff should only exist once per source");
         }
     };
 
@@ -881,12 +876,12 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
     }
 
     let [mode, input_activities @ .., ret_activity] = &list[..] else {
-        span_bug!(attr.span, "rustc_autodiff attribute must contain mode and activities");
+        span_bug!(attr.span(), "rustc_autodiff attribute must contain mode and activities");
     };
     let mode = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = mode {
         p1.segments.first().unwrap().ident
     } else {
-        span_bug!(attr.span, "rustc_autodiff attribute must contain mode");
+        span_bug!(attr.span(), "rustc_autodiff attribute must contain mode");
     };
 
     // parse mode
@@ -902,7 +897,7 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
     let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity {
         p1.segments.first().unwrap().ident
     } else {
-        span_bug!(attr.span, "rustc_autodiff attribute must contain the return activity");
+        span_bug!(attr.span(), "rustc_autodiff attribute must contain the return activity");
     };
 
     // Then parse it into an actual DiffActivity
@@ -937,11 +932,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
 
     for &input in &arg_activities {
         if !valid_input_activity(mode, input) {
-            span_bug!(attr.span, "Invalid input activity {} for {} mode", input, mode);
+            span_bug!(attr.span(), "Invalid input activity {} for {} mode", input, mode);
         }
     }
     if !valid_ret_activity(mode, ret_activity) {
-        span_bug!(attr.span, "Invalid return activity {} for {} mode", ret_activity, mode);
+        span_bug!(attr.span(), "Invalid return activity {} for {} mode", ret_activity, mode);
     }
 
     Some(AutoDiffAttrs { mode, ret_activity, input_activity: arg_activities })
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 3ddbe4aeeec..7e28961599f 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -161,7 +161,7 @@ impl<'a> CopyPath<'a> {
 struct DebugArgPath<'a>(pub &'a Path);
 
 impl IntoDiagArg for DebugArgPath<'_> {
-    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
         DiagArgValue::Str(Cow::Owned(format!("{:?}", self.0)))
     }
 }
@@ -1087,7 +1087,7 @@ pub enum ExpectedPointerMutability {
 }
 
 impl IntoDiagArg for ExpectedPointerMutability {
-    fn into_diag_arg(self) -> DiagArgValue {
+    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
         match self {
             ExpectedPointerMutability::Mut => DiagArgValue::Str(Cow::Borrowed("*mut")),
             ExpectedPointerMutability::Not => DiagArgValue::Str(Cow::Borrowed("*_")),
@@ -1180,6 +1180,8 @@ pub(crate) struct ErrorCreatingRemarkDir {
 pub struct CompilerBuiltinsCannotCall {
     pub caller: String,
     pub callee: String,
+    #[primary_span]
+    pub span: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 9d2ac219d59..4e758bfdec3 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -75,9 +75,29 @@ pub struct ModuleCodegen<M> {
     pub name: String,
     pub module_llvm: M,
     pub kind: ModuleKind,
+    /// Saving the ThinLTO buffer for embedding in the object file.
+    pub thin_lto_buffer: Option<Vec<u8>>,
 }
 
 impl<M> ModuleCodegen<M> {
+    pub fn new_regular(name: impl Into<String>, module: M) -> Self {
+        Self {
+            name: name.into(),
+            module_llvm: module,
+            kind: ModuleKind::Regular,
+            thin_lto_buffer: None,
+        }
+    }
+
+    pub fn new_allocator(name: impl Into<String>, module: M) -> Self {
+        Self {
+            name: name.into(),
+            module_llvm: module,
+            kind: ModuleKind::Allocator,
+            thin_lto_buffer: None,
+        }
+    }
+
     pub fn into_compiled_module(
         self,
         emit_obj: bool,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 1e52c639463..e2a9b540d30 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -165,9 +165,13 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         if let Some(instance) = instance {
             if is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance) {
                 if destination.is_some() {
-                    let caller = with_no_trimmed_paths!(tcx.def_path_str(fx.instance.def_id()));
-                    let callee = with_no_trimmed_paths!(tcx.def_path_str(instance.def_id()));
-                    tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee });
+                    let caller_def = fx.instance.def_id();
+                    let e = CompilerBuiltinsCannotCall {
+                        span: tcx.def_span(caller_def),
+                        caller: with_no_trimmed_paths!(tcx.def_path_str(caller_def)),
+                        callee: with_no_trimmed_paths!(tcx.def_path_str(instance.def_id())),
+                    };
+                    tcx.dcx().emit_err(e);
                 } else {
                     info!(
                         "compiler_builtins call to diverging function {:?} replaced with abort",
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index ba28720afec..0758e5d0456 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -3,7 +3,7 @@ use std::iter;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::{UnwindTerminateReason, traversal};
+use rustc_middle::mir::{Local, UnwindTerminateReason, traversal};
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::{bug, mir, span_bug};
@@ -240,7 +240,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let local_values = {
         let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals);
 
-        let mut allocate_local = |local| {
+        let mut allocate_local = |local: Local| {
             let decl = &mir.local_decls[local];
             let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
             assert!(!layout.ty.has_erasable_regions());
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index 0593fb420c3..96d1ab018f6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -349,7 +349,7 @@ fn wasm_type<'tcx>(
         PassMode::Direct(_) => {
             let direct_type = match arg_abi.layout.backend_repr {
                 BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type),
-                BackendRepr::Vector { .. } => "v128",
+                BackendRepr::SimdVector { .. } => "v128",
                 BackendRepr::Memory { .. } => {
                     // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
                     let _ = WasmCAbi::Legacy;
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 461cf1b8acd..4b33bdeadba 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -359,7 +359,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         let offset = self.layout.fields.offset(i);
 
         if !bx.is_backend_ref(self.layout) && bx.is_backend_ref(field) {
-            if let BackendRepr::Vector { count, .. } = self.layout.backend_repr
+            if let BackendRepr::SimdVector { count, .. } = self.layout.backend_repr
                 && let BackendRepr::Memory { sized: true } = field.backend_repr
                 && count.is_power_of_two()
             {
@@ -404,7 +404,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 }
             };
             OperandValue::Immediate(match field.backend_repr {
-                BackendRepr::Vector { .. } => imm,
+                BackendRepr::SimdVector { .. } => imm,
                 BackendRepr::Scalar(out_scalar) => {
                     let Some(in_scalar) = in_scalar else {
                         span_bug!(
@@ -666,7 +666,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     // However, some SIMD types do not actually use the vector ABI
                     // (in particular, packed SIMD types do not). Ensure we exclude those.
                     let layout = bx.layout_of(constant_ty);
-                    if let BackendRepr::Vector { .. } = layout.backend_repr {
+                    if let BackendRepr::SimdVector { .. } = layout.backend_repr {
                         let (llval, ty) = self.immediate_const_vector(bx, constant);
                         return OperandRef {
                             val: OperandValue::Immediate(llval),
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index edd09b9c3c5..00e01e47fee 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -2,7 +2,7 @@ use rustc_abi::Primitive::{Int, Pointer};
 use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants};
 use rustc_middle::mir::PlaceTy;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, mir};
 use tracing::{debug, instrument};
@@ -168,7 +168,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
             };
             let val = PlaceValue {
                 llval,
-                llextra: if bx.cx().type_has_metadata(field.ty) { self.val.llextra } else { None },
+                llextra: if bx.cx().tcx().type_has_metadata(field.ty, bx.cx().typing_env()) {
+                    self.val.llextra
+                } else {
+                    None
+                },
                 align: effective_field_align,
             };
             val.with_type(field)
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 1eebe04225b..67555d40332 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -3,7 +3,7 @@ use std::assert_matches::assert_matches;
 use arrayvec::ArrayVec;
 use rustc_abi::{self as abi, FIRST_VARIANT, FieldIdx};
 use rustc_middle::ty::adjustment::PointerCoercion;
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_session::config::OptLevel;
@@ -878,7 +878,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         let ty = cg_place.layout.ty;
         assert!(
-            if bx.cx().type_has_metadata(ty) {
+            if bx.cx().tcx().type_has_metadata(ty, bx.cx().typing_env()) {
                 matches!(val, OperandValue::Pair(..))
             } else {
                 matches!(val, OperandValue::Immediate(..))
@@ -1190,7 +1190,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             assert!(!self.cx.is_backend_scalar_pair(layout));
             OperandValueKind::Immediate(match layout.backend_repr {
                 abi::BackendRepr::Scalar(s) => s,
-                abi::BackendRepr::Vector { element, .. } => element,
+                abi::BackendRepr::SimdVector { element, .. } => element,
                 x => span_bug!(self.mir.span, "Couldn't translate {x:?} as backend immediate"),
             })
         } else if self.cx.is_backend_scalar_pair(layout) {
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index c178ebc596e..fbd927d0d66 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -1,7 +1,7 @@
 use rustc_abi::{AddressSpace, Float, Integer, Reg};
 use rustc_middle::bug;
+use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
-use rustc_middle::ty::{self, Ty};
 use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi};
 
 use super::BackendTypes;
@@ -84,19 +84,6 @@ pub trait DerivedTypeCodegenMethods<'tcx>:
     fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
         ty.is_freeze(self.tcx(), self.typing_env())
     }
-
-    fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
-        if ty.is_sized(self.tcx(), self.typing_env()) {
-            return false;
-        }
-
-        let tail = self.tcx().struct_tail_for_codegen(ty, self.typing_env());
-        match tail.kind() {
-            ty::Foreign(..) => false,
-            ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
-            _ => bug!("unexpected unsized tail: {:?}", tail),
-        }
-    }
 }
 
 impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index 97fe614aa10..c77efdd1728 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -40,7 +40,7 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
     unsafe fn optimize(
         cgcx: &CodegenContext<Self>,
         dcx: DiagCtxtHandle<'_>,
-        module: &ModuleCodegen<Self::Module>,
+        module: &mut ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
     ) -> Result<(), FatalError>;
     fn optimize_fat(