about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs17
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs59
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs55
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs17
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs21
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs19
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs60
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs50
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/naked_asm.rs45
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs17
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs49
-rw-r--r--compiler/rustc_hir/src/hir.rs21
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs52
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs8
-rw-r--r--compiler/rustc_interface/src/passes.rs11
-rw-r--r--compiler/rustc_interface/src/queries.rs8
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_lint/src/context.rs15
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs47
-rw-r--r--compiler/rustc_metadata/src/fs.rs46
-rw-r--r--compiler/rustc_middle/src/ty/context.rs25
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs16
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/drop.rs21
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drop.rs14
-rw-r--r--compiler/rustc_monomorphize/messages.ftl7
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs9
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs76
-rw-r--r--compiler/rustc_session/src/config.rs3
-rw-r--r--compiler/rustc_session/src/options.rs15
-rw-r--r--compiler/rustc_session/src/session.rs7
-rw-r--r--compiler/rustc_target/src/asm/loongarch.rs8
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs13
-rw-r--r--compiler/rustc_target/src/callconv/wasm.rs42
-rw-r--r--compiler/rustc_target/src/callconv/x86_64.rs5
-rw-r--r--compiler/rustc_target/src/spec/mod.rs16
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs26
49 files changed, 396 insertions, 657 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 6b51cbd7fbe..4489a424c0d 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1450,11 +1450,20 @@ impl Expr {
     }
 
     pub fn precedence(&self) -> ExprPrecedence {
+        fn prefix_attrs_precedence(attrs: &AttrVec) -> ExprPrecedence {
+            for attr in attrs {
+                if let AttrStyle::Outer = attr.style {
+                    return ExprPrecedence::Prefix;
+                }
+            }
+            ExprPrecedence::Unambiguous
+        }
+
         match &self.kind {
             ExprKind::Closure(closure) => {
                 match closure.fn_decl.output {
                     FnRetTy::Default(_) => ExprPrecedence::Jump,
-                    FnRetTy::Ty(_) => ExprPrecedence::Unambiguous,
+                    FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs),
                 }
             }
 
@@ -1463,7 +1472,7 @@ impl Expr {
             | ExprKind::Yield(YieldKind::Prefix(value))
             | ExprKind::Yeet(value) => match value {
                 Some(_) => ExprPrecedence::Jump,
-                None => ExprPrecedence::Unambiguous,
+                None => prefix_attrs_precedence(&self.attrs),
             },
 
             ExprKind::Become(_) => ExprPrecedence::Jump,
@@ -1490,7 +1499,7 @@ impl Expr {
             | ExprKind::Let(..)
             | ExprKind::Unary(..) => ExprPrecedence::Prefix,
 
-            // Never need parens
+            // Need parens if and only if there are prefix attributes.
             ExprKind::Array(_)
             | ExprKind::Await(..)
             | ExprKind::Use(..)
@@ -1525,7 +1534,7 @@ impl Expr {
             | ExprKind::While(..)
             | ExprKind::Yield(YieldKind::Postfix(..))
             | ExprKind::Err(_)
-            | ExprKind::Dummy => ExprPrecedence::Unambiguous,
+            | ExprKind::Dummy => prefix_attrs_precedence(&self.attrs),
         }
     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index a845431faca..c4b0f503664 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -342,6 +342,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
                                 }
                             }
                         } else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
+                            let sp = info
+                                .span
+                                .find_ancestor_in_same_ctxt(local_decl.source_info.span)
+                                .unwrap_or(info.span);
                             if info.tail_result_is_ignored {
                                 // #85581: If the first mutable borrow's scope contains
                                 // the second borrow, this suggestion isn't helpful.
@@ -349,7 +353,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
                                     old.to(info.span.shrink_to_hi()).contains(new)
                                 }) {
                                     err.span_suggestion_verbose(
-                                        info.span.shrink_to_hi(),
+                                        sp.shrink_to_hi(),
                                         "consider adding semicolon after the expression so its \
                                         temporaries are dropped sooner, before the local variables \
                                         declared by the block are dropped",
@@ -368,8 +372,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
                                      local variable `x` and then make `x` be the expression at the \
                                      end of the block",
                                     vec![
-                                        (info.span.shrink_to_lo(), "let x = ".to_string()),
-                                        (info.span.shrink_to_hi(), "; x".to_string()),
+                                        (sp.shrink_to_lo(), "let x = ".to_string()),
+                                        (sp.shrink_to_hi(), "; x".to_string()),
                                     ],
                                     Applicability::MaybeIncorrect,
                                 );
diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
index 6d8614aca69..9a0a5b51039 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
@@ -1,6 +1,6 @@
 //! Argument passing
 
-use cranelift_codegen::ir::{ArgumentExtension, ArgumentPurpose};
+use cranelift_codegen::ir::ArgumentPurpose;
 use rustc_abi::{Reg, RegKind};
 use rustc_target::callconv::{
     ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, PassMode,
@@ -32,13 +32,12 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
     AbiParam::new(clif_ty)
 }
 
-fn apply_arg_attrs_to_abi_param(mut param: AbiParam, arg_attrs: ArgAttributes) -> AbiParam {
+fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiParam {
     match arg_attrs.arg_ext {
-        RustcArgExtension::None => {}
-        RustcArgExtension::Zext => param.extension = ArgumentExtension::Uext,
-        RustcArgExtension::Sext => param.extension = ArgumentExtension::Sext,
+        RustcArgExtension::None => param,
+        RustcArgExtension::Zext => param.uext(),
+        RustcArgExtension::Sext => param.sext(),
     }
-    param
 }
 
 fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
@@ -82,7 +81,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
         match self.mode {
             PassMode::Ignore => smallvec![],
             PassMode::Direct(attrs) => match self.layout.backend_repr {
-                BackendRepr::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
+                BackendRepr::Scalar(scalar) => smallvec![apply_attrs_to_abi_param(
                     AbiParam::new(scalar_to_clif_type(tcx, scalar)),
                     attrs
                 )],
@@ -97,8 +96,8 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                     let a = scalar_to_clif_type(tcx, a);
                     let b = scalar_to_clif_type(tcx, b);
                     smallvec![
-                        apply_arg_attrs_to_abi_param(AbiParam::new(a), attrs_a),
-                        apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b),
+                        apply_attrs_to_abi_param(AbiParam::new(a), attrs_a),
+                        apply_attrs_to_abi_param(AbiParam::new(b), attrs_b),
                     ]
                 }
                 _ => unreachable!("{:?}", self.layout.backend_repr),
@@ -112,19 +111,19 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                     // Abi requires aligning struct size to pointer size
                     let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi);
                     let size = u32::try_from(size.bytes()).unwrap();
-                    smallvec![apply_arg_attrs_to_abi_param(
+                    smallvec![apply_attrs_to_abi_param(
                         AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),),
                         attrs
                     )]
                 } else {
-                    smallvec![apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)]
+                    smallvec![apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)]
                 }
             }
             PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
                 assert!(!on_stack);
                 smallvec![
-                    apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs),
-                    apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs),
+                    apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs),
+                    apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs),
                 ]
             }
         }
@@ -133,30 +132,46 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>) {
         match self.mode {
             PassMode::Ignore => (None, vec![]),
-            PassMode::Direct(_) => match self.layout.backend_repr {
-                BackendRepr::Scalar(scalar) => {
-                    (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))])
-                }
+            PassMode::Direct(attrs) => match self.layout.backend_repr {
+                BackendRepr::Scalar(scalar) => (
+                    None,
+                    vec![apply_attrs_to_abi_param(
+                        AbiParam::new(scalar_to_clif_type(tcx, scalar)),
+                        attrs,
+                    )],
+                ),
                 BackendRepr::SimdVector { .. } => {
                     let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout);
-                    (None, vec![AbiParam::new(vector_ty)])
+                    (None, vec![apply_attrs_to_abi_param(AbiParam::new(vector_ty), attrs)])
                 }
                 _ => unreachable!("{:?}", self.layout.backend_repr),
             },
-            PassMode::Pair(_, _) => match self.layout.backend_repr {
+            PassMode::Pair(attrs_a, attrs_b) => match self.layout.backend_repr {
                 BackendRepr::ScalarPair(a, b) => {
                     let a = scalar_to_clif_type(tcx, a);
                     let b = scalar_to_clif_type(tcx, b);
-                    (None, vec![AbiParam::new(a), AbiParam::new(b)])
+                    (
+                        None,
+                        vec![
+                            apply_attrs_to_abi_param(AbiParam::new(a), attrs_a),
+                            apply_attrs_to_abi_param(AbiParam::new(b), attrs_b),
+                        ],
+                    )
                 }
                 _ => unreachable!("{:?}", self.layout.backend_repr),
             },
             PassMode::Cast { ref cast, .. } => {
                 (None, cast_target_to_abi_params(cast).into_iter().collect())
             }
-            PassMode::Indirect { attrs: _, meta_attrs: None, on_stack } => {
+            PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
                 assert!(!on_stack);
-                (Some(AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn)), vec![])
+                (
+                    Some(apply_attrs_to_abi_param(
+                        AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn),
+                        attrs,
+                    )),
+                    vec![],
+                )
             }
             PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
                 unreachable!("unsized return value")
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 5d07c94859f..442151fe32d 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -11,7 +11,6 @@ use std::thread::JoinHandle;
 use cranelift_object::{ObjectBuilder, ObjectModule};
 use rustc_codegen_ssa::assert_module_sources::CguReuse;
 use rustc_codegen_ssa::back::link::ensure_removed;
-use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
 use rustc_codegen_ssa::base::determine_cgu_reuse;
 use rustc_codegen_ssa::{
     CodegenResults, CompiledModule, CrateInfo, ModuleKind, errors as ssa_errors,
@@ -19,7 +18,6 @@ use rustc_codegen_ssa::{
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
-use rustc_metadata::EncodedMetadata;
 use rustc_metadata::fs::copy_to_stdout;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@@ -61,8 +59,6 @@ impl<HCX> HashStable<HCX> for OngoingModuleCodegen {
 pub(crate) struct OngoingCodegen {
     modules: Vec<OngoingModuleCodegen>,
     allocator_module: Option<CompiledModule>,
-    metadata_module: Option<CompiledModule>,
-    metadata: EncodedMetadata,
     crate_info: CrateInfo,
     concurrency_limiter: ConcurrencyLimiter,
 }
@@ -134,8 +130,6 @@ impl OngoingCodegen {
         let codegen_results = CodegenResults {
             modules,
             allocator_module: self.allocator_module,
-            metadata_module: self.metadata_module,
-            metadata: self.metadata,
             crate_info: self.crate_info,
         };
 
@@ -646,42 +640,6 @@ fn module_codegen(
     }))
 }
 
-fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> CompiledModule {
-    use rustc_middle::mir::mono::CodegenUnitNameBuilder;
-
-    let _timer = tcx.sess.timer("write compressed metadata");
-
-    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
-    let metadata_cgu_name = cgu_name_builder
-        .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata"))
-        .as_str()
-        .to_string();
-
-    let tmp_file = tcx.output_filenames(()).temp_path_for_cgu(
-        OutputType::Metadata,
-        &metadata_cgu_name,
-        tcx.sess.invocation_temp.as_deref(),
-    );
-
-    let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx);
-    let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name);
-
-    if let Err(err) = std::fs::write(&tmp_file, obj) {
-        tcx.dcx().fatal(format!("error writing metadata object file: {}", err));
-    }
-
-    CompiledModule {
-        name: metadata_cgu_name,
-        kind: ModuleKind::Metadata,
-        object: Some(tmp_file),
-        dwarf_object: None,
-        bytecode: None,
-        assembly: None,
-        llvm_ir: None,
-        links_from_incr_cache: Vec::new(),
-    }
-}
-
 fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
     let mut allocator_module = make_module(tcx.sess, "allocator_shim".to_string());
     let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module);
@@ -706,11 +664,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
     }
 }
 
-pub(crate) fn run_aot(
-    tcx: TyCtxt<'_>,
-    metadata: EncodedMetadata,
-    need_metadata_module: bool,
-) -> Box<OngoingCodegen> {
+pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box<OngoingCodegen> {
     // FIXME handle `-Ctarget-cpu=native`
     let target_cpu = match tcx.sess.opts.cg.target_cpu {
         Some(ref name) => name,
@@ -726,8 +680,6 @@ pub(crate) fn run_aot(
         return Box::new(OngoingCodegen {
             modules: vec![],
             allocator_module: None,
-            metadata_module: None,
-            metadata,
             crate_info: CrateInfo::new(tcx, target_cpu),
             concurrency_limiter: ConcurrencyLimiter::new(0),
         });
@@ -787,14 +739,9 @@ pub(crate) fn run_aot(
 
     let allocator_module = emit_allocator_module(tcx);
 
-    let metadata_module =
-        if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None };
-
     Box::new(OngoingCodegen {
         modules,
         allocator_module,
-        metadata_module,
-        metadata,
         crate_info: CrateInfo::new(tcx, target_cpu),
         concurrency_limiter: concurrency_limiter.0,
     })
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 8ef623cde00..07ea29f3024 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -46,7 +46,6 @@ use cranelift_codegen::isa::TargetIsa;
 use cranelift_codegen::settings::{self, Configurable};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_codegen_ssa::{CodegenResults, TargetConfig};
-use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_session::Session;
 use rustc_session::config::OutputFilenames;
@@ -238,12 +237,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
         println!("Cranelift version: {}", cranelift_codegen::VERSION);
     }
 
-    fn codegen_crate(
-        &self,
-        tcx: TyCtxt<'_>,
-        metadata: EncodedMetadata,
-        need_metadata_module: bool,
-    ) -> Box<dyn Any> {
+    fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
         info!("codegen crate {}", tcx.crate_name(LOCAL_CRATE));
         let config = self.config.clone().unwrap_or_else(|| {
             BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
@@ -256,7 +250,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
             #[cfg(not(feature = "jit"))]
             tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
         } else {
-            driver::aot::run_aot(tcx, metadata, need_metadata_module)
+            driver::aot::run_aot(tcx)
         }
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 1bd89212100..68c6156fa4b 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_span::def_id::DefId;
 use rustc_target::callconv::FnAbi;
-use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi};
+use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};
 
 use crate::common::{SignType, TypeReflection, type_is_pointer};
 use crate::context::CodegenCx;
@@ -2394,12 +2394,6 @@ impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> HasWasmCAbiOpt for Builder<'_, '_, 'tcx> {
-    fn wasm_c_abi_opt(&self) -> WasmCAbi {
-        self.cx.wasm_c_abi_opt()
-    }
-}
-
 impl<'tcx> HasX86AbiOpt for Builder<'_, '_, 'tcx> {
     fn x86_abi_opt(&self) -> X86Abi {
         self.cx.x86_abi_opt()
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index c6c43201f21..4955e039e7b 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -19,9 +19,7 @@ use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_span::source_map::respan;
 use rustc_span::{DUMMY_SP, Span};
-use rustc_target::spec::{
-    HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi,
-};
+use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi};
 
 #[cfg(feature = "master")]
 use crate::abi::conv_to_fn_attribute;
@@ -512,12 +510,6 @@ impl<'gcc, 'tcx> HasTargetSpec for CodegenCx<'gcc, 'tcx> {
     }
 }
 
-impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
-    fn wasm_c_abi_opt(&self) -> WasmCAbi {
-        self.tcx.sess.opts.unstable_opts.wasm_c_abi
-    }
-}
-
 impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> {
     fn x86_abi_opt(&self) -> X86Abi {
         X86Abi {
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 0591ffa42e4..dbecbc42618 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -48,7 +48,6 @@ extern crate rustc_index;
 #[cfg(feature = "master")]
 extern crate rustc_interface;
 extern crate rustc_macros;
-extern crate rustc_metadata;
 extern crate rustc_middle;
 extern crate rustc_session;
 extern crate rustc_span;
@@ -106,7 +105,6 @@ use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetCon
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::IntoDynSyncSend;
 use rustc_errors::DiagCtxtHandle;
-use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::util::Providers;
@@ -230,20 +228,9 @@ impl CodegenBackend for GccCodegenBackend {
         providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
     }
 
-    fn codegen_crate(
-        &self,
-        tcx: TyCtxt<'_>,
-        metadata: EncodedMetadata,
-        need_metadata_module: bool,
-    ) -> Box<dyn Any> {
+    fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
         let target_cpu = target_cpu(tcx.sess);
-        let res = codegen_crate(
-            self.clone(),
-            tcx,
-            target_cpu.to_string(),
-            metadata,
-            need_metadata_module,
-        );
+        let res = codegen_crate(self.clone(), tcx, target_cpu.to_string());
 
         Box::new(res)
     }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 4185aef8b31..9ddadcf16aa 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -1021,6 +1021,15 @@ fn llvm_fixup_input<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
         }
+        (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F16) =>
+        {
+            // Smaller floats are always "NaN-boxed" inside larger floats on LoongArch.
+            let value = bx.bitcast(value, bx.type_i16());
+            let value = bx.zext(value, bx.type_i32());
+            let value = bx.or(value, bx.const_u32(0xFFFF_0000));
+            bx.bitcast(value, bx.type_f32())
+        }
         (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
@@ -1178,6 +1187,13 @@ fn llvm_fixup_output<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
         }
+        (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F16) =>
+        {
+            let value = bx.bitcast(value, bx.type_i32());
+            let value = bx.trunc(value, bx.type_i16());
+            bx.bitcast(value, bx.type_f16())
+        }
         (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
@@ -1318,6 +1334,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             cx.type_vector(cx.type_i16(), count)
         }
+        (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F16) =>
+        {
+            cx.type_f32()
+        }
         (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 6890923a594..cdfffbe47bf 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -340,18 +340,11 @@ impl CodegenBackend for LlvmCodegenBackend {
         target_config(sess)
     }
 
-    fn codegen_crate<'tcx>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        metadata: EncodedMetadata,
-        need_metadata_module: bool,
-    ) -> Box<dyn Any> {
+    fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any> {
         Box::new(rustc_codegen_ssa::base::codegen_crate(
             LlvmCodegenBackend(()),
             tcx,
             crate::llvm_util::target_cpu(tcx.sess).to_string(),
-            metadata,
-            need_metadata_module,
         ))
     }
 
@@ -376,14 +369,20 @@ impl CodegenBackend for LlvmCodegenBackend {
         (codegen_results, work_products)
     }
 
-    fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) {
+    fn link(
+        &self,
+        sess: &Session,
+        codegen_results: CodegenResults,
+        metadata: EncodedMetadata,
+        outputs: &OutputFilenames,
+    ) {
         use rustc_codegen_ssa::back::link::link_binary;
 
         use crate::back::archive::LlvmArchiveBuilderBuilder;
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
-        link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, outputs);
+        link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, metadata, outputs);
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 91f6af7fb93..5322fe58cf3 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -198,8 +198,6 @@ codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status
 codegen_ssa_malformed_cgu_name =
     found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
 
-codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
-
 codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
 
 codegen_ssa_missing_features = add the missing features in a `target_feature` attribute
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 1e1bdfb5977..84a56f6b0b5 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -14,11 +14,12 @@ use object::read::macho::FatArch;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::memmap::Mmap;
 use rustc_fs_util::TempDirBuilder;
+use rustc_metadata::EncodedMetadata;
 use rustc_session::Session;
 use rustc_span::Symbol;
 use tracing::trace;
 
-use super::metadata::search_for_section;
+use super::metadata::{create_compressed_metadata_file, search_for_section};
 use crate::common;
 // Re-exporting for rustc_codegen_llvm::back::archive
 pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
@@ -58,6 +59,15 @@ impl From<ImportLibraryItem> for COFFShortExport {
 pub trait ArchiveBuilderBuilder {
     fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
 
+    fn create_dylib_metadata_wrapper(
+        &self,
+        sess: &Session,
+        metadata: &EncodedMetadata,
+        symbol_name: &str,
+    ) -> Vec<u8> {
+        create_compressed_metadata_file(sess, metadata, symbol_name)
+    }
+
     /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
     /// and returns the path on disk to that import library.
     /// This functions doesn't take `self` so that it can be called from
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 18b76b33757..8c52ed6ed12 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -23,7 +23,8 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_macros::LintDiagnostic;
 use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
 use rustc_metadata::{
-    NativeLibSearchFallback, find_native_static_library, walk_native_lib_search_dirs,
+    EncodedMetadata, NativeLibSearchFallback, find_native_static_library,
+    walk_native_lib_search_dirs,
 };
 use rustc_middle::bug;
 use rustc_middle::lint::lint_level;
@@ -91,6 +92,7 @@ pub fn link_binary(
     sess: &Session,
     archive_builder_builder: &dyn ArchiveBuilderBuilder,
     codegen_results: CodegenResults,
+    metadata: EncodedMetadata,
     outputs: &OutputFilenames,
 ) {
     let _timer = sess.timer("link_binary");
@@ -142,6 +144,7 @@ pub fn link_binary(
                         sess,
                         archive_builder_builder,
                         &codegen_results,
+                        &metadata,
                         RlibFlavor::Normal,
                         &path,
                     )
@@ -152,6 +155,7 @@ pub fn link_binary(
                         sess,
                         archive_builder_builder,
                         &codegen_results,
+                        &metadata,
                         &out_filename,
                         &path,
                     );
@@ -163,6 +167,7 @@ pub fn link_binary(
                         crate_type,
                         &out_filename,
                         &codegen_results,
+                        &metadata,
                         path.as_ref(),
                     );
                 }
@@ -226,11 +231,7 @@ pub fn link_binary(
         let remove_temps_from_module =
             |module: &CompiledModule| maybe_remove_temps_from_module(false, false, module);
 
-        // Otherwise, always remove the metadata and allocator module temporaries.
-        if let Some(ref metadata_module) = codegen_results.metadata_module {
-            remove_temps_from_module(metadata_module);
-        }
-
+        // Otherwise, always remove the allocator module temporaries.
         if let Some(ref allocator_module) = codegen_results.allocator_module {
             remove_temps_from_module(allocator_module);
         }
@@ -312,6 +313,7 @@ fn link_rlib<'a>(
     sess: &'a Session,
     archive_builder_builder: &dyn ArchiveBuilderBuilder,
     codegen_results: &CodegenResults,
+    metadata: &EncodedMetadata,
     flavor: RlibFlavor,
     tmpdir: &MaybeTempDir,
 ) -> Box<dyn ArchiveBuilder + 'a> {
@@ -319,12 +321,9 @@ fn link_rlib<'a>(
 
     let trailing_metadata = match flavor {
         RlibFlavor::Normal => {
-            let (metadata, metadata_position) = create_wrapper_file(
-                sess,
-                ".rmeta".to_string(),
-                codegen_results.metadata.stub_or_full(),
-            );
-            let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME);
+            let (metadata, metadata_position) =
+                create_wrapper_file(sess, ".rmeta".to_string(), metadata.stub_or_full());
+            let metadata = emit_wrapper_file(sess, &metadata, tmpdir.as_ref(), METADATA_FILENAME);
             match metadata_position {
                 MetadataPosition::First => {
                     // Most of the time metadata in rlib files is wrapped in a "dummy" object
@@ -392,7 +391,7 @@ fn link_rlib<'a>(
             let src = read(path)
                 .unwrap_or_else(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }));
             let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src);
-            let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
+            let wrapper_file = emit_wrapper_file(sess, &data, tmpdir.as_ref(), filename.as_str());
             packed_bundled_libs.push(wrapper_file);
         } else {
             let path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);
@@ -473,6 +472,7 @@ fn link_staticlib(
     sess: &Session,
     archive_builder_builder: &dyn ArchiveBuilderBuilder,
     codegen_results: &CodegenResults,
+    metadata: &EncodedMetadata,
     out_filename: &Path,
     tempdir: &MaybeTempDir,
 ) {
@@ -481,6 +481,7 @@ fn link_staticlib(
         sess,
         archive_builder_builder,
         codegen_results,
+        metadata,
         RlibFlavor::StaticlibBase,
         tempdir,
     );
@@ -694,6 +695,7 @@ fn link_natively(
     crate_type: CrateType,
     out_filename: &Path,
     codegen_results: &CodegenResults,
+    metadata: &EncodedMetadata,
     tmpdir: &Path,
 ) {
     info!("preparing {:?} to {:?}", crate_type, out_filename);
@@ -718,6 +720,7 @@ fn link_natively(
         tmpdir,
         temp_filename,
         codegen_results,
+        metadata,
         self_contained_components,
     );
 
@@ -2095,17 +2098,25 @@ fn add_local_crate_allocator_objects(cmd: &mut dyn Linker, codegen_results: &Cod
 /// Add object files containing metadata for the current crate.
 fn add_local_crate_metadata_objects(
     cmd: &mut dyn Linker,
+    sess: &Session,
+    archive_builder_builder: &dyn ArchiveBuilderBuilder,
     crate_type: CrateType,
+    tmpdir: &Path,
     codegen_results: &CodegenResults,
+    metadata: &EncodedMetadata,
 ) {
     // When linking a dynamic library, we put the metadata into a section of the
     // executable. This metadata is in a separate object file from the main
-    // object file, so we link that in here.
-    if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro)
-        && let Some(m) = &codegen_results.metadata_module
-        && let Some(obj) = &m.object
-    {
-        cmd.add_object(obj);
+    // object file, so we create and link it in here.
+    if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro) {
+        let data = archive_builder_builder.create_dylib_metadata_wrapper(
+            sess,
+            &metadata,
+            &codegen_results.crate_info.metadata_symbol,
+        );
+        let obj = emit_wrapper_file(sess, &data, tmpdir, "rmeta.o");
+
+        cmd.add_object(&obj);
     }
 }
 
@@ -2195,6 +2206,7 @@ fn linker_with_args(
     tmpdir: &Path,
     out_filename: &Path,
     codegen_results: &CodegenResults,
+    metadata: &EncodedMetadata,
     self_contained_components: LinkSelfContainedComponents,
 ) -> Command {
     let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
@@ -2269,7 +2281,15 @@ fn linker_with_args(
     // in this DAG so far because they can only depend on other native libraries
     // and such dependencies are also required to be specified.
     add_local_crate_regular_objects(cmd, codegen_results);
-    add_local_crate_metadata_objects(cmd, crate_type, codegen_results);
+    add_local_crate_metadata_objects(
+        cmd,
+        sess,
+        archive_builder_builder,
+        crate_type,
+        tmpdir,
+        codegen_results,
+        metadata,
+    );
     add_local_crate_allocator_objects(cmd, codegen_results);
 
     // Avoid linking to dynamic libraries unless they satisfy some undefined symbols
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index a41ca8ce28b..bbf9cceef2a 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -24,7 +24,6 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental::{
     copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
 };
-use rustc_metadata::EncodedMetadata;
 use rustc_metadata::fs::copy_to_stdout;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -142,7 +141,6 @@ impl ModuleConfig {
             || match kind {
                 ModuleKind::Regular => sess.opts.output_types.contains_key(&OutputType::Object),
                 ModuleKind::Allocator => false,
-                ModuleKind::Metadata => sess.opts.output_types.contains_key(&OutputType::Metadata),
             };
 
         let emit_obj = if !should_emit_obj {
@@ -350,7 +348,6 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub output_filenames: Arc<OutputFilenames>,
     pub invocation_temp: Option<String>,
     pub regular_module_config: Arc<ModuleConfig>,
-    pub metadata_module_config: Arc<ModuleConfig>,
     pub allocator_module_config: Arc<ModuleConfig>,
     pub tm_factory: TargetMachineFactoryFn<B>,
     pub msvc_imps_needed: bool,
@@ -395,7 +392,6 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
     pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
         match kind {
             ModuleKind::Regular => &self.regular_module_config,
-            ModuleKind::Metadata => &self.metadata_module_config,
             ModuleKind::Allocator => &self.allocator_module_config,
         }
     }
@@ -474,8 +470,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
     backend: B,
     tcx: TyCtxt<'_>,
     target_cpu: String,
-    metadata: EncodedMetadata,
-    metadata_module: Option<CompiledModule>,
 ) -> OngoingCodegen<B> {
     let (coordinator_send, coordinator_receive) = channel();
 
@@ -485,7 +479,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
     let crate_info = CrateInfo::new(tcx, target_cpu);
 
     let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
-    let metadata_config = ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins);
     let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);
 
     let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
@@ -499,15 +492,12 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
         codegen_worker_send,
         coordinator_receive,
         Arc::new(regular_config),
-        Arc::new(metadata_config),
         Arc::new(allocator_config),
         coordinator_send.clone(),
     );
 
     OngoingCodegen {
         backend,
-        metadata,
-        metadata_module,
         crate_info,
 
         codegen_worker_receive,
@@ -843,12 +833,6 @@ pub(crate) fn compute_per_cgu_lto_type(
     sess_crate_types: &[CrateType],
     module_kind: ModuleKind,
 ) -> ComputedLtoType {
-    // Metadata modules never participate in LTO regardless of the lto
-    // settings.
-    if module_kind == ModuleKind::Metadata {
-        return ComputedLtoType::No;
-    }
-
     // If the linker does LTO, we don't have to do it. Note that we
     // keep doing full LTO, if it is requested, as not to break the
     // assumption that the output will be a single module.
@@ -1029,10 +1013,7 @@ fn finish_intra_module_work<B: ExtraBackendMethods>(
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
 
-    if !cgcx.opts.unstable_opts.combine_cgu
-        || module.kind == ModuleKind::Metadata
-        || module.kind == ModuleKind::Allocator
-    {
+    if !cgcx.opts.unstable_opts.combine_cgu || module.kind == ModuleKind::Allocator {
         let module = B::codegen(cgcx, dcx, module, module_config)?;
         Ok(WorkItemResult::Finished(module))
     } else {
@@ -1123,7 +1104,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
     codegen_worker_send: Sender<CguMessage>,
     coordinator_receive: Receiver<Box<dyn Any + Send>>,
     regular_config: Arc<ModuleConfig>,
-    metadata_config: Arc<ModuleConfig>,
     allocator_config: Arc<ModuleConfig>,
     tx_to_llvm_workers: Sender<Box<dyn Any + Send>>,
 ) -> thread::JoinHandle<Result<CompiledModules, ()>> {
@@ -1216,7 +1196,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
         diag_emitter: shared_emitter.clone(),
         output_filenames: Arc::clone(tcx.output_filenames(())),
         regular_module_config: regular_config,
-        metadata_module_config: metadata_config,
         allocator_module_config: allocator_config,
         tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features),
         msvc_imps_needed: msvc_imps_needed(tcx),
@@ -1673,7 +1652,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
                                     assert!(compiled_allocator_module.is_none());
                                     compiled_allocator_module = Some(compiled_module);
                                 }
-                                ModuleKind::Metadata => bug!("Should be handled separately"),
                             }
                         }
                         Ok(WorkItemResult::NeedsLink(module)) => {
@@ -2055,8 +2033,6 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
 
 pub struct OngoingCodegen<B: ExtraBackendMethods> {
     pub backend: B,
-    pub metadata: EncodedMetadata,
-    pub metadata_module: Option<CompiledModule>,
     pub crate_info: CrateInfo,
     pub codegen_worker_receive: Receiver<CguMessage>,
     pub shared_emitter_main: SharedEmitterMain,
@@ -2096,12 +2072,10 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
 
         (
             CodegenResults {
-                metadata: self.metadata,
                 crate_info: self.crate_info,
 
                 modules: compiled_modules.modules,
                 allocator_module: compiled_modules.allocator_module,
-                metadata_module: self.metadata_module,
             },
             work_products,
         )
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index c2d6a26de0f..a3d6c73ba85 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -15,11 +15,10 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_hir::ItemId;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
-use rustc_metadata::EncodedMetadata;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
-use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_middle::middle::{exported_symbols, lang_items};
+use rustc_middle::middle::exported_symbols::{self, SymbolExportKind};
+use rustc_middle::middle::lang_items;
 use rustc_middle::mir::BinOp;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
@@ -28,7 +27,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::Session;
-use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
+use rustc_session::config::{self, CrateType, EntryFnType};
 use rustc_span::{DUMMY_SP, Symbol, sym};
 use rustc_symbol_mangling::mangle_internal_symbol;
 use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
@@ -37,7 +36,6 @@ use tracing::{debug, info};
 
 use crate::assert_module_sources::CguReuse;
 use crate::back::link::are_upstream_rust_objects_already_included;
-use crate::back::metadata::create_compressed_metadata_file;
 use crate::back::write::{
     ComputedLtoType, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen,
     submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm,
@@ -48,8 +46,7 @@ use crate::mir::operand::OperandValue;
 use crate::mir::place::PlaceRef;
 use crate::traits::*;
 use crate::{
-    CachedModuleCodegen, CodegenLintLevels, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
-    errors, meth, mir,
+    CachedModuleCodegen, CodegenLintLevels, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir,
 };
 
 pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
@@ -669,12 +666,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     backend: B,
     tcx: TyCtxt<'_>,
     target_cpu: String,
-    metadata: EncodedMetadata,
-    need_metadata_module: bool,
 ) -> OngoingCodegen<B> {
     // Skip crate items and just output metadata in -Z no-codegen mode.
     if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
-        let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None);
+        let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu);
 
         ongoing_codegen.codegen_finished(tcx);
 
@@ -707,39 +702,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
         }
     }
 
-    let metadata_module = need_metadata_module.then(|| {
-        // Emit compressed metadata object.
-        let metadata_cgu_name =
-            cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
-        tcx.sess.time("write_compressed_metadata", || {
-            let file_name = tcx.output_filenames(()).temp_path_for_cgu(
-                OutputType::Metadata,
-                &metadata_cgu_name,
-                tcx.sess.invocation_temp.as_deref(),
-            );
-            let data = create_compressed_metadata_file(
-                tcx.sess,
-                &metadata,
-                &exported_symbols::metadata_symbol_name(tcx),
-            );
-            if let Err(error) = std::fs::write(&file_name, data) {
-                tcx.dcx().emit_fatal(errors::MetadataObjectFileWrite { error });
-            }
-            CompiledModule {
-                name: metadata_cgu_name,
-                kind: ModuleKind::Metadata,
-                object: Some(file_name),
-                dwarf_object: None,
-                bytecode: None,
-                assembly: None,
-                llvm_ir: None,
-                links_from_incr_cache: Vec::new(),
-            }
-        })
-    });
-
-    let ongoing_codegen =
-        start_async_codegen(backend.clone(), tcx, target_cpu, metadata, metadata_module);
+    let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu);
 
     // Codegen an allocator shim, if necessary.
     if let Some(kind) = allocator_kind_for_codegen(tcx) {
@@ -1010,6 +973,7 @@ impl CrateInfo {
             windows_subsystem,
             natvis_debugger_visualizers: Default::default(),
             lint_levels: CodegenLintLevels::from_tcx(tcx),
+            metadata_symbol: exported_symbols::metadata_symbol_name(tcx),
         };
 
         info.native_libraries.reserve(n_crates);
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index f843347db92..bac02bdf983 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -778,12 +778,6 @@ pub(crate) struct MultipleMainFunctions {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa_metadata_object_file_write)]
-pub(crate) struct MetadataObjectFileWrite {
-    pub error: Error,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_ssa_invalid_windows_subsystem)]
 pub(crate) struct InvalidWindowsSubsystem {
     pub subsystem: Symbol,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 84919645cf0..523c9f2ad1c 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -31,6 +31,7 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_hir::CRATE_HIR_ID;
 use rustc_hir::def_id::CrateNum;
 use rustc_macros::{Decodable, Encodable, HashStable};
+use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::lint::LevelAndSource;
 use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
@@ -169,7 +170,6 @@ pub(crate) struct CachedModuleCodegen {
 #[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable)]
 pub enum ModuleKind {
     Regular,
-    Metadata,
     Allocator,
 }
 
@@ -233,6 +233,7 @@ pub struct CrateInfo {
     pub windows_subsystem: Option<String>,
     pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
     pub lint_levels: CodegenLintLevels,
+    pub metadata_symbol: String,
 }
 
 /// Target-specific options that get set in `cfg(...)`.
@@ -257,8 +258,6 @@ pub struct TargetConfig {
 pub struct CodegenResults {
     pub modules: Vec<CompiledModule>,
     pub allocator_module: Option<CompiledModule>,
-    pub metadata_module: Option<CompiledModule>,
-    pub metadata: rustc_metadata::EncodedMetadata,
     pub crate_info: CrateInfo,
 }
 
@@ -303,6 +302,7 @@ impl CodegenResults {
         sess: &Session,
         rlink_file: &Path,
         codegen_results: &CodegenResults,
+        metadata: &EncodedMetadata,
         outputs: &OutputFilenames,
     ) -> Result<usize, io::Error> {
         let mut encoder = FileEncoder::new(rlink_file)?;
@@ -312,6 +312,7 @@ impl CodegenResults {
         encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
         encoder.emit_str(sess.cfg_version);
         Encodable::encode(codegen_results, &mut encoder);
+        Encodable::encode(metadata, &mut encoder);
         Encodable::encode(outputs, &mut encoder);
         encoder.finish().map_err(|(_path, err)| err)
     }
@@ -319,7 +320,7 @@ impl CodegenResults {
     pub fn deserialize_rlink(
         sess: &Session,
         data: Vec<u8>,
-    ) -> Result<(Self, OutputFilenames), CodegenErrors> {
+    ) -> Result<(Self, EncodedMetadata, OutputFilenames), CodegenErrors> {
         // The Decodable machinery is not used here because it panics if the input data is invalid
         // and because its internal representation may change.
         if !data.starts_with(RLINK_MAGIC) {
@@ -350,8 +351,9 @@ impl CodegenResults {
         }
 
         let codegen_results = CodegenResults::decode(&mut decoder);
+        let metadata = EncodedMetadata::decode(&mut decoder);
         let outputs = OutputFilenames::decode(&mut decoder);
-        Ok((codegen_results, outputs))
+        Ok((codegen_results, metadata, outputs))
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index 46fb9a89513..b805dc094e9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -1,14 +1,13 @@
 use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
 use rustc_attr_data_structures::InstructionSetAttr;
-use rustc_hir::def_id::DefId;
 use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility};
 use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::{bug, span_bug, ty};
+use rustc_middle::{bug, ty};
 use rustc_span::sym;
 use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
-use rustc_target::spec::{BinaryFormat, WasmCAbi};
+use rustc_target::spec::BinaryFormat;
 
 use crate::common;
 use crate::mir::AsmCodegenMethods;
@@ -287,12 +286,7 @@ fn prefix_and_suffix<'tcx>(
                 writeln!(begin, "{}", arch_prefix).unwrap();
             }
             writeln!(begin, "{asm_name}:").unwrap();
-            writeln!(
-                begin,
-                ".functype {asm_name} {}",
-                wasm_functype(tcx, fn_abi, instance.def_id())
-            )
-            .unwrap();
+            writeln!(begin, ".functype {asm_name} {}", wasm_functype(tcx, fn_abi)).unwrap();
 
             writeln!(end).unwrap();
             // .size is ignored for function symbols, so we can skip it
@@ -333,7 +327,7 @@ fn prefix_and_suffix<'tcx>(
 /// The webassembly type signature for the given function.
 ///
 /// Used by the `.functype` directive on wasm targets.
-fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId) -> String {
+fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
     let mut signature = String::with_capacity(64);
 
     let ptr_type = match tcx.data_layout.pointer_size.bits() {
@@ -342,17 +336,6 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
         other => bug!("wasm pointer size cannot be {other} bits"),
     };
 
-    // FIXME: remove this once the wasm32-unknown-unknown ABI is fixed
-    // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
-    // basically the commit introducing this comment should be reverted
-    if let PassMode::Pair { .. } = fn_abi.ret.mode {
-        let _ = WasmCAbi::Legacy { with_lint: true };
-        span_bug!(
-            tcx.def_span(def_id),
-            "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
-        );
-    }
-
     let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
 
     signature.push('(');
@@ -366,7 +349,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
 
     let mut it = fn_abi.args.iter().peekable();
     while let Some(arg_abi) = it.next() {
-        wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id);
+        wasm_type(&mut signature, arg_abi, ptr_type);
         if it.peek().is_some() {
             signature.push_str(", ");
         }
@@ -375,7 +358,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
     signature.push_str(") -> (");
 
     if !hidden_return {
-        wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id);
+        wasm_type(&mut signature, &fn_abi.ret, ptr_type);
     }
 
     signature.push(')');
@@ -383,27 +366,13 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
     signature
 }
 
-fn wasm_type<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    signature: &mut String,
-    arg_abi: &ArgAbi<'_, Ty<'tcx>>,
-    ptr_type: &'static str,
-    def_id: DefId,
-) {
+fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_type: &'static str) {
     match arg_abi.mode {
         PassMode::Ignore => { /* do nothing */ }
         PassMode::Direct(_) => {
             let direct_type = match arg_abi.layout.backend_repr {
                 BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type),
                 BackendRepr::SimdVector { .. } => "v128",
-                BackendRepr::Memory { .. } => {
-                    // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
-                    let _ = WasmCAbi::Legacy { with_lint: true };
-                    span_bug!(
-                        tcx.def_span(def_id),
-                        "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
-                    );
-                }
                 other => unreachable!("unexpected BackendRepr: {:?}", other),
             };
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 95bf3b16685..29ec7eb1da3 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -74,12 +74,7 @@ pub trait CodegenBackend {
 
     fn provide(&self, _providers: &mut Providers) {}
 
-    fn codegen_crate<'tcx>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        metadata: EncodedMetadata,
-        need_metadata_module: bool,
-    ) -> Box<dyn Any>;
+    fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any>;
 
     /// This is called on the returned `Box<dyn Any>` from [`codegen_crate`](Self::codegen_crate)
     ///
@@ -94,8 +89,14 @@ pub trait CodegenBackend {
     ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>);
 
     /// This is called on the returned [`CodegenResults`] from [`join_codegen`](Self::join_codegen).
-    fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) {
-        link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs);
+    fn link(
+        &self,
+        sess: &Session,
+        codegen_results: CodegenResults,
+        metadata: EncodedMetadata,
+        outputs: &OutputFilenames,
+    ) {
+        link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, metadata, outputs);
     }
 }
 
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 0cd9e36a927..d53126d0414 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -557,27 +557,34 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
         let rlink_data = fs::read(file).unwrap_or_else(|err| {
             dcx.emit_fatal(RlinkUnableToRead { err });
         });
-        let (codegen_results, outputs) = match CodegenResults::deserialize_rlink(sess, rlink_data) {
-            Ok((codegen, outputs)) => (codegen, outputs),
-            Err(err) => {
-                match err {
-                    CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
-                    CodegenErrors::EmptyVersionNumber => dcx.emit_fatal(RLinkEmptyVersionNumber),
-                    CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => dcx
-                        .emit_fatal(RLinkEncodingVersionMismatch { version_array, rlink_version }),
-                    CodegenErrors::RustcVersionMismatch { rustc_version } => {
-                        dcx.emit_fatal(RLinkRustcVersionMismatch {
-                            rustc_version,
-                            current_version: sess.cfg_version,
-                        })
-                    }
-                    CodegenErrors::CorruptFile => {
-                        dcx.emit_fatal(RlinkCorruptFile { file });
-                    }
-                };
-            }
-        };
-        compiler.codegen_backend.link(sess, codegen_results, &outputs);
+        let (codegen_results, metadata, outputs) =
+            match CodegenResults::deserialize_rlink(sess, rlink_data) {
+                Ok((codegen, metadata, outputs)) => (codegen, metadata, outputs),
+                Err(err) => {
+                    match err {
+                        CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
+                        CodegenErrors::EmptyVersionNumber => {
+                            dcx.emit_fatal(RLinkEmptyVersionNumber)
+                        }
+                        CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
+                            dcx.emit_fatal(RLinkEncodingVersionMismatch {
+                                version_array,
+                                rlink_version,
+                            })
+                        }
+                        CodegenErrors::RustcVersionMismatch { rustc_version } => {
+                            dcx.emit_fatal(RLinkRustcVersionMismatch {
+                                rustc_version,
+                                current_version: sess.cfg_version,
+                            })
+                        }
+                        CodegenErrors::CorruptFile => {
+                            dcx.emit_fatal(RlinkCorruptFile { file });
+                        }
+                    };
+                }
+            };
+        compiler.codegen_backend.link(sess, codegen_results, metadata, &outputs);
     } else {
         dcx.emit_fatal(RlinkNotAFile {});
     }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 3cc6bde8c32..556f50a85af 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2285,12 +2285,23 @@ pub struct Expr<'hir> {
 }
 
 impl Expr<'_> {
-    pub fn precedence(&self) -> ExprPrecedence {
+    pub fn precedence(
+        &self,
+        for_each_attr: &dyn Fn(HirId, &mut dyn FnMut(&Attribute)),
+    ) -> ExprPrecedence {
+        let prefix_attrs_precedence = || -> ExprPrecedence {
+            let mut has_outer_attr = false;
+            for_each_attr(self.hir_id, &mut |attr: &Attribute| {
+                has_outer_attr |= matches!(attr.style(), AttrStyle::Outer)
+            });
+            if has_outer_attr { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous }
+        };
+
         match &self.kind {
             ExprKind::Closure(closure) => {
                 match closure.fn_decl.output {
                     FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump,
-                    FnRetTy::Return(_) => ExprPrecedence::Unambiguous,
+                    FnRetTy::Return(_) => prefix_attrs_precedence(),
                 }
             }
 
@@ -2315,7 +2326,7 @@ impl Expr<'_> {
             | ExprKind::Let(..)
             | ExprKind::Unary(..) => ExprPrecedence::Prefix,
 
-            // Never need parens
+            // Need parens if and only if there are prefix attributes.
             ExprKind::Array(_)
             | ExprKind::Block(..)
             | ExprKind::Call(..)
@@ -2337,9 +2348,9 @@ impl Expr<'_> {
             | ExprKind::Type(..)
             | ExprKind::UnsafeBinderCast(..)
             | ExprKind::Use(..)
-            | ExprKind::Err(_) => ExprPrecedence::Unambiguous,
+            | ExprKind::Err(_) => prefix_attrs_precedence(),
 
-            ExprKind::DropTemps(expr, ..) => expr.precedence(),
+            ExprKind::DropTemps(expr, ..) => expr.precedence(for_each_attr),
         }
     }
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index b23b3125c59..fc507285860 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -80,6 +80,13 @@ impl<'a> State<'a> {
         (self.attrs)(id)
     }
 
+    fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
+        let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&hir::Attribute)| {
+            self.attrs(id).iter().for_each(callback);
+        };
+        expr.precedence(&for_each_attr)
+    }
+
     fn print_attrs_as_inner(&mut self, attrs: &[hir::Attribute]) {
         self.print_either_attributes(attrs, ast::AttrStyle::Inner)
     }
@@ -1164,7 +1171,7 @@ impl<'a> State<'a> {
         }
         self.space();
         self.word_space("=");
-        let npals = || parser::needs_par_as_let_scrutinee(init.precedence());
+        let npals = || parser::needs_par_as_let_scrutinee(self.precedence(init));
         self.print_expr_cond_paren(init, Self::cond_needs_par(init) || npals())
     }
 
@@ -1265,7 +1272,7 @@ impl<'a> State<'a> {
     fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
         let needs_paren = match func.kind {
             hir::ExprKind::Field(..) => true,
-            _ => func.precedence() < ExprPrecedence::Unambiguous,
+            _ => self.precedence(func) < ExprPrecedence::Unambiguous,
         };
 
         self.print_expr_cond_paren(func, needs_paren);
@@ -1279,7 +1286,10 @@ impl<'a> State<'a> {
         args: &[hir::Expr<'_>],
     ) {
         let base_args = args;
-        self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous);
+        self.print_expr_cond_paren(
+            receiver,
+            self.precedence(receiver) < ExprPrecedence::Unambiguous,
+        );
         self.word(".");
         self.print_ident(segment.ident);
 
@@ -1293,8 +1303,8 @@ impl<'a> State<'a> {
 
     fn print_expr_binary(&mut self, op: hir::BinOpKind, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
         let binop_prec = op.precedence();
-        let left_prec = lhs.precedence();
-        let right_prec = rhs.precedence();
+        let left_prec = self.precedence(lhs);
+        let right_prec = self.precedence(rhs);
 
         let (mut left_needs_paren, right_needs_paren) = match op.fixity() {
             Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
@@ -1323,7 +1333,7 @@ impl<'a> State<'a> {
 
     fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
         self.word(op.as_str());
-        self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
+        self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix);
     }
 
     fn print_expr_addr_of(
@@ -1340,7 +1350,7 @@ impl<'a> State<'a> {
                 self.print_mutability(mutability, true);
             }
         }
-        self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
+        self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix);
     }
 
     fn print_literal(&mut self, lit: &hir::Lit) {
@@ -1483,7 +1493,7 @@ impl<'a> State<'a> {
                 self.print_literal(lit);
             }
             hir::ExprKind::Cast(expr, ty) => {
-                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast);
+                self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Cast);
                 self.space();
                 self.word_space("as");
                 self.print_type(ty);
@@ -1580,24 +1590,30 @@ impl<'a> State<'a> {
                 self.print_block(blk, cb, ib);
             }
             hir::ExprKind::Assign(lhs, rhs, _) => {
-                self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
+                self.print_expr_cond_paren(lhs, self.precedence(lhs) <= ExprPrecedence::Assign);
                 self.space();
                 self.word_space("=");
-                self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
+                self.print_expr_cond_paren(rhs, self.precedence(rhs) < ExprPrecedence::Assign);
             }
             hir::ExprKind::AssignOp(op, lhs, rhs) => {
-                self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
+                self.print_expr_cond_paren(lhs, self.precedence(lhs) <= ExprPrecedence::Assign);
                 self.space();
                 self.word_space(op.node.as_str());
-                self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
+                self.print_expr_cond_paren(rhs, self.precedence(rhs) < ExprPrecedence::Assign);
             }
             hir::ExprKind::Field(expr, ident) => {
-                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
+                self.print_expr_cond_paren(
+                    expr,
+                    self.precedence(expr) < ExprPrecedence::Unambiguous,
+                );
                 self.word(".");
                 self.print_ident(ident);
             }
             hir::ExprKind::Index(expr, index, _) => {
-                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
+                self.print_expr_cond_paren(
+                    expr,
+                    self.precedence(expr) < ExprPrecedence::Unambiguous,
+                );
                 self.word("[");
                 self.print_expr(index);
                 self.word("]");
@@ -1611,7 +1627,7 @@ impl<'a> State<'a> {
                 }
                 if let Some(expr) = opt_expr {
                     self.space();
-                    self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
+                    self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump);
                 }
             }
             hir::ExprKind::Continue(destination) => {
@@ -1625,13 +1641,13 @@ impl<'a> State<'a> {
                 self.word("return");
                 if let Some(expr) = result {
                     self.word(" ");
-                    self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
+                    self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump);
                 }
             }
             hir::ExprKind::Become(result) => {
                 self.word("become");
                 self.word(" ");
-                self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump);
+                self.print_expr_cond_paren(result, self.precedence(result) < ExprPrecedence::Jump);
             }
             hir::ExprKind::InlineAsm(asm) => {
                 self.word("asm!");
@@ -1669,7 +1685,7 @@ impl<'a> State<'a> {
             }
             hir::ExprKind::Yield(expr, _) => {
                 self.word_space("yield");
-                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
+                self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump);
             }
             hir::ExprKind::Err(_) => {
                 self.popen();
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index e915b4fc626..80bff09d0a4 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -620,7 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
 
             if let Ok(rest_snippet) = rest_snippet {
-                let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous {
+                let sugg = if self.precedence(callee_expr) >= ExprPrecedence::Unambiguous {
                     vec![
                         (up_to_rcvr_span, "".to_string()),
                         (rest_span, format!(".{}({rest_snippet}", segment.ident)),
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index e17cfc15a43..6f8abc1e67d 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -1100,7 +1100,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
-        let expr_prec = self.expr.precedence();
+        let expr_prec = fcx.precedence(self.expr);
         let needs_parens = expr_prec < ExprPrecedence::Unambiguous;
 
         let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 30bf557dc93..55c39d960e7 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -6,6 +6,7 @@
 //! See [`rustc_hir_analysis::check`] for more context on type checking in general.
 
 use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx};
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::unord::UnordMap;
@@ -17,7 +18,7 @@ use rustc_errors::{
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{ExprKind, HirId, QPath};
+use rustc_hir::{Attribute, ExprKind, HirId, QPath};
 use rustc_hir_analysis::NoVariantNamed;
 use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _};
 use rustc_infer::infer;
@@ -54,6 +55,30 @@ use crate::{
 };
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+    pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
+        let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&Attribute)| {
+            for attr in self.tcx.hir_attrs(id) {
+                // For the purpose of rendering suggestions, disregard attributes
+                // that originate from desugaring of any kind. For example, `x?`
+                // desugars to `#[allow(unreachable_code)] match ...`. Failing to
+                // ignore the prefix attribute in the desugaring would cause this
+                // suggestion:
+                //
+                //     let y: u32 = x?.try_into().unwrap();
+                //                    ++++++++++++++++++++
+                //
+                // to be rendered as:
+                //
+                //     let y: u32 = (x?).try_into().unwrap();
+                //                  +  +++++++++++++++++++++
+                if attr.span().desugaring_kind().is_none() {
+                    callback(attr);
+                }
+            }
+        };
+        expr.precedence(&for_each_attr)
+    }
+
     /// Check an expr with an expectation type, and also demand that the expr's
     /// evaluated type is a subtype of the expectation at the end. This is a
     /// *hard* requirement.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 66af085cfd4..7e5f1d97a8b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -399,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // so we remove the user's `clone` call.
                     {
                         vec![(receiver_method.ident.span, conversion_method_name.to_string())]
-                    } else if expr.precedence() < ExprPrecedence::Unambiguous {
+                    } else if self.precedence(expr) < ExprPrecedence::Unambiguous {
                         vec![
                             (expr.span.shrink_to_lo(), "(".to_string()),
                             (expr.span.shrink_to_hi(), format!(").{}()", conversion_method_name)),
@@ -1395,7 +1395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             let span = expr.span.find_oldest_ancestor_in_same_ctxt();
 
-            let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous {
+            let mut sugg = if self.precedence(expr) >= ExprPrecedence::Unambiguous {
                 vec![(span.shrink_to_hi(), ".into()".to_owned())]
             } else {
                 vec![
@@ -3106,7 +3106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
         );
 
-        let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous {
+        let close_paren = if self.precedence(expr) < ExprPrecedence::Unambiguous {
             sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
             ")"
         } else {
@@ -3131,7 +3131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let len = src.trim_end_matches(&checked_ty.to_string()).len();
                 span.with_lo(span.lo() + BytePos(len as u32))
             },
-            if expr.precedence() < ExprPrecedence::Unambiguous {
+            if self.precedence(expr) < ExprPrecedence::Unambiguous {
                 // Readd `)`
                 format!("{expected_ty})")
             } else {
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 0238d6a3947..02d1ebdb31a 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -18,6 +18,7 @@ use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
 use rustc_hir::definitions::Definitions;
 use rustc_incremental::setup_dep_graph;
 use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store};
+use rustc_metadata::EncodedMetadata;
 use rustc_metadata::creader::CStore;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepsType;
@@ -1174,7 +1175,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
 pub(crate) fn start_codegen<'tcx>(
     codegen_backend: &dyn CodegenBackend,
     tcx: TyCtxt<'tcx>,
-) -> Box<dyn Any> {
+) -> (Box<dyn Any>, EncodedMetadata) {
     // Hook for tests.
     if let Some((def_id, _)) = tcx.entry_fn(())
         && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query)
@@ -1197,11 +1198,9 @@ pub(crate) fn start_codegen<'tcx>(
 
     info!("Pre-codegen\n{:?}", tcx.debug_stats());
 
-    let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
+    let metadata = rustc_metadata::fs::encode_and_write_metadata(tcx);
 
-    let codegen = tcx.sess.time("codegen_crate", move || {
-        codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
-    });
+    let codegen = tcx.sess.time("codegen_crate", move || codegen_backend.codegen_crate(tcx));
 
     info!("Post-codegen\n{:?}", tcx.debug_stats());
 
@@ -1211,7 +1210,7 @@ pub(crate) fn start_codegen<'tcx>(
         tcx.sess.code_stats.print_type_sizes();
     }
 
-    codegen
+    (codegen, metadata)
 }
 
 /// Compute and validate the crate name.
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index c8914c9be9c..9a474b910f6 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -5,6 +5,7 @@ use rustc_codegen_ssa::CodegenResults;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::DepGraph;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
@@ -18,6 +19,7 @@ pub struct Linker {
     output_filenames: Arc<OutputFilenames>,
     // Only present when incr. comp. is enabled.
     crate_hash: Option<Svh>,
+    metadata: EncodedMetadata,
     ongoing_codegen: Box<dyn Any>,
 }
 
@@ -26,7 +28,7 @@ impl Linker {
         tcx: TyCtxt<'_>,
         codegen_backend: &dyn CodegenBackend,
     ) -> Linker {
-        let ongoing_codegen = passes::start_codegen(codegen_backend, tcx);
+        let (ongoing_codegen, metadata) = passes::start_codegen(codegen_backend, tcx);
 
         Linker {
             dep_graph: tcx.dep_graph.clone(),
@@ -36,6 +38,7 @@ impl Linker {
             } else {
                 None
             },
+            metadata,
             ongoing_codegen,
         }
     }
@@ -75,6 +78,7 @@ impl Linker {
                 sess,
                 &rlink_file,
                 &codegen_results,
+                &self.metadata,
                 &*self.output_filenames,
             )
             .unwrap_or_else(|error| {
@@ -84,6 +88,6 @@ impl Linker {
         }
 
         let _timer = sess.prof.verbose_generic_activity("link_crate");
-        codegen_backend.link(sess, codegen_results, &self.output_filenames)
+        codegen_backend.link(sess, codegen_results, self.metadata, &self.output_filenames)
     }
 }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 5419d688caa..82823581c12 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -27,7 +27,7 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
 use rustc_span::{FileName, SourceFileHashAlgorithm, sym};
 use rustc_target::spec::{
     CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
-    RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, WasmCAbi,
+    RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel,
 };
 
 use crate::interface::{initialize_checked_jobserver, parse_cfg};
@@ -882,7 +882,6 @@ fn test_unstable_options_tracking_hash() {
     tracked!(verify_llvm_ir, true);
     tracked!(virtual_function_elimination, true);
     tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
-    tracked!(wasm_c_abi, WasmCAbi::Spec);
     // tidy-alphabetical-end
 
     macro_rules! tracked_no_crate_hash {
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 5679d4566dc..b6bf45dfbcf 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -7,6 +7,7 @@ use std::cell::Cell;
 use std::slice;
 
 use rustc_ast::BindingMode;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync;
 use rustc_data_structures::unord::UnordMap;
@@ -850,6 +851,20 @@ impl<'tcx> LateContext<'tcx> {
             })
     }
 
+    /// Returns the effective precedence of an expression for the purpose of
+    /// rendering diagnostic. This is not the same as the precedence that would
+    /// be used for pretty-printing HIR by rustc_hir_pretty.
+    pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
+        let for_each_attr = |id: hir::HirId, callback: &mut dyn FnMut(&hir::Attribute)| {
+            for attr in self.tcx.hir_attrs(id) {
+                if attr.span().desugaring_kind().is_none() {
+                    callback(attr);
+                }
+            }
+        };
+        expr.precedence(&for_each_attr)
+    }
+
     /// If the given expression is a local binding, find the initializer expression.
     /// If that initializer expression is another local binding, find its initializer again.
     ///
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index e84cdb581b5..9a1490d3eea 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -623,6 +623,7 @@ fn register_builtins(store: &mut LintStore) {
         "converted into hard error, \
          see <https://github.com/rust-lang/rust/issues/40107> for more information",
     );
+    store.register_removed("wasm_c_abi", "the wasm C ABI has been fixed");
 }
 
 fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 295dd82fead..b0ea9689e50 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -140,7 +140,6 @@ declare_lint_pass! {
         UNUSED_VARIABLES,
         USELESS_DEPRECATED,
         WARNINGS,
-        WASM_C_ABI,
         // tidy-alphabetical-end
     ]
 }
@@ -4100,6 +4099,7 @@ declare_lint! {
     @future_incompatible = FutureIncompatibleInfo {
         reason: FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(Edition::Edition2024),
         reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>",
+        report_in_deps: true,
     };
     @edition Edition2024 => Deny;
     report_in_external_macro
@@ -4154,6 +4154,7 @@ declare_lint! {
     @future_incompatible = FutureIncompatibleInfo {
         reason: FutureIncompatibilityReason::EditionAndFutureReleaseError(Edition::Edition2024),
         reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>",
+        report_in_deps: true,
     };
     report_in_external_macro
 }
@@ -4981,50 +4982,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
-    /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
-    /// of this target.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,ignore (needs wasm32-unknown-unknown)
-    /// #[repr(C)]
-    /// struct MyType(i32, i32);
-    ///
-    /// extern "C" my_fun(x: MyType) {}
-    /// ```
-    ///
-    /// This will produce:
-    ///
-    /// ```text
-    /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
-    ///   --> $DIR/wasm_c_abi_transition.rs:17:1
-    ///    |
-    ///    | pub extern "C" fn my_fun(_x: MyType) {}
-    ///    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    ///    |
-    ///    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    ///    = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
-    ///    = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
-    /// ```
-    ///
-    /// ### Explanation
-    ///
-    /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
-    /// has caused incompatibilities with other compilers and Wasm targets. In a future version
-    /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
-    /// stop functioning.
-    pub WASM_C_ABI,
-    Warn,
-    "detects code relying on rustc's non-spec-compliant wasm C ABI",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseError,
-        reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
-        report_in_deps: true,
-    };
-}
-
-declare_lint! {
     /// The `aarch64_softfloat_neon` lint detects usage of `#[target_feature(enable = "neon")]` on
     /// softfloat aarch64 targets. Enabling this target feature causes LLVM to alter the ABI of
     /// function calls, making this attribute unsound to use.
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index e57534b847e..1eaad26ff8e 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -4,9 +4,9 @@ use std::{fs, io};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_fs_util::TempDirBuilder;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::Session;
 use rustc_session::config::{CrateType, OutFileName, OutputType};
 use rustc_session::output::filename_for_metadata;
-use rustc_session::{MetadataKind, Session};
 
 use crate::errors::{
     BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile,
@@ -22,13 +22,8 @@ pub const METADATA_FILENAME: &str = "lib.rmeta";
 /// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
 /// directory being searched for `extern crate` (observing an incomplete file).
 /// The returned path is the temporary file containing the complete metadata.
-pub fn emit_wrapper_file(
-    sess: &Session,
-    data: &[u8],
-    tmpdir: &MaybeTempDir,
-    name: &str,
-) -> PathBuf {
-    let out_filename = tmpdir.as_ref().join(name);
+pub fn emit_wrapper_file(sess: &Session, data: &[u8], tmpdir: &Path, name: &str) -> PathBuf {
+    let out_filename = tmpdir.join(name);
     let result = fs::write(&out_filename, data);
 
     if let Err(err) = result {
@@ -38,7 +33,7 @@ pub fn emit_wrapper_file(
     out_filename
 }
 
-pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
+pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
     let out_filename = filename_for_metadata(tcx.sess, tcx.output_filenames(()));
     // To avoid races with another rustc process scanning the output directory,
     // we need to write the file somewhere else and atomically move it to its
@@ -59,25 +54,20 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
         None
     };
 
-    // Always create a file at `metadata_filename`, even if we have nothing to write to it.
-    // This simplifies the creation of the output `out_filename` when requested.
-    let metadata_kind = tcx.metadata_kind();
-    match metadata_kind {
-        MetadataKind::None => {
-            std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
-                tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
+    if tcx.needs_metadata() {
+        encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref());
+    } else {
+        // Always create a file at `metadata_filename`, even if we have nothing to write to it.
+        // This simplifies the creation of the output `out_filename` when requested.
+        std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
+            tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
+        });
+        if let Some(metadata_stub_filename) = &metadata_stub_filename {
+            std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| {
+                tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err });
             });
-            if let Some(metadata_stub_filename) = &metadata_stub_filename {
-                std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| {
-                    tcx.dcx()
-                        .emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err });
-                });
-            }
-        }
-        MetadataKind::Uncompressed | MetadataKind::Compressed => {
-            encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref())
         }
-    };
+    }
 
     let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata");
 
@@ -118,9 +108,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
                 tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err });
             });
 
-    let need_metadata_module = metadata_kind == MetadataKind::Compressed;
-
-    (metadata, need_metadata_module)
+    metadata
 }
 
 #[cfg(not(target_os = "linux"))]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b4d8b2e7176..fe4dd8d080b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -47,7 +47,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::CrateType;
 use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
-use rustc_session::{Limit, MetadataKind, Session};
+use rustc_session::{Limit, Session};
 use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
 use rustc_type_ir::TyKind::*;
@@ -1858,23 +1858,14 @@ impl<'tcx> TyCtxt<'tcx> {
         &self.crate_types
     }
 
-    pub fn metadata_kind(self) -> MetadataKind {
-        self.crate_types()
-            .iter()
-            .map(|ty| match *ty {
-                CrateType::Executable
-                | CrateType::Staticlib
-                | CrateType::Cdylib
-                | CrateType::Sdylib => MetadataKind::None,
-                CrateType::Rlib => MetadataKind::Uncompressed,
-                CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed,
-            })
-            .max()
-            .unwrap_or(MetadataKind::None)
-    }
-
     pub fn needs_metadata(self) -> bool {
-        self.metadata_kind() != MetadataKind::None
+        self.crate_types().iter().any(|ty| match *ty {
+            CrateType::Executable
+            | CrateType::Staticlib
+            | CrateType::Cdylib
+            | CrateType::Sdylib => false,
+            CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
+        })
     }
 
     pub fn needs_crate_hash(self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 9bce2845680..13c281a6182 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -16,9 +16,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
 use rustc_session::config::OptLevel;
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
 use rustc_target::callconv::FnAbi;
-use rustc_target::spec::{
-    HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, PanicStrategy, Target, WasmCAbi, X86Abi,
-};
+use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, PanicStrategy, Target, X86Abi};
 use tracing::debug;
 use {rustc_abi as abi, rustc_hir as hir};
 
@@ -565,12 +563,6 @@ impl<'tcx> HasTargetSpec for TyCtxt<'tcx> {
     }
 }
 
-impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> {
-    fn wasm_c_abi_opt(&self) -> WasmCAbi {
-        self.sess.opts.unstable_opts.wasm_c_abi
-    }
-}
-
 impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> {
     fn x86_abi_opt(&self) -> X86Abi {
         X86Abi {
@@ -625,12 +617,6 @@ impl<'tcx> HasTargetSpec for LayoutCx<'tcx> {
     }
 }
 
-impl<'tcx> HasWasmCAbiOpt for LayoutCx<'tcx> {
-    fn wasm_c_abi_opt(&self) -> WasmCAbi {
-        self.calc.cx.wasm_c_abi_opt()
-    }
-}
-
 impl<'tcx> HasX86AbiOpt for LayoutCx<'tcx> {
     fn x86_abi_opt(&self) -> X86Abi {
         self.calc.cx.x86_abi_opt()
diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs
index 6021e795d21..dc68629ec0d 100644
--- a/compiler/rustc_mir_transform/src/coroutine/drop.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs
@@ -132,6 +132,7 @@ fn build_poll_switch<'tcx>(
     body: &mut Body<'tcx>,
     poll_enum: Ty<'tcx>,
     poll_unit_place: &Place<'tcx>,
+    fut_pin_place: &Place<'tcx>,
     ready_block: BasicBlock,
     yield_block: BasicBlock,
 ) -> BasicBlock {
@@ -162,9 +163,11 @@ fn build_poll_switch<'tcx>(
             Rvalue::Discriminant(*poll_unit_place),
         ))),
     };
+    let storage_dead =
+        Statement { source_info, kind: StatementKind::StorageDead(fut_pin_place.local) };
     let unreachable_block = insert_term_block(body, TerminatorKind::Unreachable);
     body.basic_blocks_mut().push(BasicBlockData {
-        statements: [discr_assign].to_vec(),
+        statements: [storage_dead, discr_assign].to_vec(),
         terminator: Some(Terminator {
             source_info,
             kind: TerminatorKind::SwitchInt {
@@ -332,10 +335,17 @@ pub(super) fn expand_async_drops<'tcx>(
             kind: StatementKind::Assign(Box::new((context_ref_place, arg))),
         });
         let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
-        let switch_block =
-            build_poll_switch(tcx, body, poll_enum, &poll_unit_place, target, yield_block);
         let (pin_bb, fut_pin_place) =
             build_pin_fut(tcx, body, fut_place.clone(), UnwindAction::Continue);
+        let switch_block = build_poll_switch(
+            tcx,
+            body,
+            poll_enum,
+            &poll_unit_place,
+            &fut_pin_place,
+            target,
+            yield_block,
+        );
         let call_bb = build_poll_call(
             tcx,
             body,
@@ -357,16 +367,17 @@ pub(super) fn expand_async_drops<'tcx>(
                 body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)),
             );
             let drop_yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
+            let (pin_bb2, fut_pin_place2) =
+                build_pin_fut(tcx, body, fut_place, UnwindAction::Continue);
             let drop_switch_block = build_poll_switch(
                 tcx,
                 body,
                 poll_enum,
                 &poll_unit_place,
+                &fut_pin_place2,
                 drop.unwrap(),
                 drop_yield_block,
             );
-            let (pin_bb2, fut_pin_place2) =
-                build_pin_fut(tcx, body, fut_place, UnwindAction::Continue);
             let drop_call_bb = build_poll_call(
                 tcx,
                 body,
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index 3a5e2620b14..c9bc52c6c7e 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -390,6 +390,20 @@ where
             Location { block: self.succ, statement_index: 0 },
             StatementKind::StorageDead(fut.local),
         );
+        // StorageDead(fut) in unwind block (at the begin)
+        if let Unwind::To(block) = unwind {
+            self.elaborator.patch().add_statement(
+                Location { block, statement_index: 0 },
+                StatementKind::StorageDead(fut.local),
+            );
+        }
+        // StorageDead(fut) in dropline block (at the begin)
+        if let Some(block) = dropline {
+            self.elaborator.patch().add_statement(
+                Location { block, statement_index: 0 },
+                StatementKind::StorageDead(fut.local),
+            );
+        }
 
         // #1:pin_obj_bb >>> call Pin<ObjTy>::new_unchecked(&mut obj)
         self.elaborator.patch().patch_terminator(
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 35bedf4318f..2bd19e81b01 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -60,11 +60,4 @@ monomorphize_start_not_found = using `fn main` requires the standard library
 
 monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
 
-monomorphize_wasm_c_abi_transition =
-    this function {$is_call ->
-      [true] call
-      *[false] definition
-    } involves an argument of type `{$ty}` which is affected by the wasm ABI transition
-    .help = the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
-
 monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index acf77b5916e..938c427b56c 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -100,12 +100,3 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
     /// Whether this is a problem at a call site or at a declaration.
     pub is_call: bool,
 }
-
-#[derive(LintDiagnostic)]
-#[diag(monomorphize_wasm_c_abi_transition)]
-#[help]
-pub(crate) struct WasmCAbiTransition<'a> {
-    pub ty: Ty<'a>,
-    /// Whether this is a problem at a call site or at a declaration.
-    pub is_call: bool,
-}
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 8dbbb4d1713..b8c001d357e 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -3,13 +3,10 @@
 use rustc_abi::{BackendRepr, CanonAbi, RegKind, X86Call};
 use rustc_hir::{CRATE_HIR_ID, HirId};
 use rustc_middle::mir::{self, Location, traversal};
-use rustc_middle::ty::layout::LayoutCx;
-use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
-use rustc_session::lint::builtin::WASM_C_ABI;
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
-use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
-use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi};
+use rustc_target::callconv::{FnAbi, PassMode};
 
 use crate::errors;
 
@@ -81,73 +78,6 @@ fn do_check_simd_vector_abi<'tcx>(
     }
 }
 
-/// Determines whether the given argument is passed the same way on the old and new wasm ABIs.
-fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
-    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
-        return true;
-    }
-
-    // Both the old and the new ABIs treat vector types like `v128` the same
-    // way.
-    if uses_vector_registers(&arg.mode, &arg.layout.backend_repr) {
-        return true;
-    }
-
-    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
-    if arg.layout.is_aggregate() {
-        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
-        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
-            let size = arg.layout.size;
-            // Ensure there's just a single `unit` element in `arg`.
-            if unit.size == size {
-                return true;
-            }
-        }
-    }
-
-    // Zero-sized types are dropped in both ABIs, so they're safe
-    if arg.layout.is_zst() {
-        return true;
-    }
-
-    false
-}
-
-/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
-/// ABI transition.
-fn do_check_wasm_abi<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    abi: &FnAbi<'tcx, Ty<'tcx>>,
-    is_call: bool,
-    loc: impl Fn() -> (Span, HirId),
-) {
-    // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what
-    // `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`), and only proceed if
-    // `wasm_c_abi_opt` indicates we should emit the lint.
-    if !(tcx.sess.target.arch == "wasm32"
-        && tcx.sess.target.os == "unknown"
-        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true }
-        && abi.conv == CanonAbi::C)
-    {
-        return;
-    }
-    // Warn against all types whose ABI will change. Return values are not affected by this change.
-    for arg_abi in abi.args.iter() {
-        if wasm_abi_safe(tcx, arg_abi) {
-            continue;
-        }
-        let (span, hir_id) = loc();
-        tcx.emit_node_span_lint(
-            WASM_C_ABI,
-            hir_id,
-            span,
-            errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call },
-        );
-        // Let's only warn once per function.
-        break;
-    }
-}
-
 /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
 /// or return values for which the corresponding target feature is not enabled.
 fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
@@ -173,7 +103,6 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
         )
     };
     do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc);
-    do_check_wasm_abi(tcx, abi, /*is_call*/ false, loc);
 }
 
 /// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -212,7 +141,6 @@ fn check_call_site_abi<'tcx>(
         return;
     };
     do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc);
-    do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, loc);
 }
 
 fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 8984634e5ec..406a6bd335a 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -3066,7 +3066,7 @@ pub(crate) mod dep_tracking {
     use rustc_target::spec::{
         CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
         RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple,
-        TlsModel, WasmCAbi,
+        TlsModel,
     };
 
     use super::{
@@ -3177,7 +3177,6 @@ pub(crate) mod dep_tracking {
         Polonius,
         InliningThreshold,
         FunctionReturn,
-        WasmCAbi,
         Align,
     );
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 6218521d4f0..f76f258d00d 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -16,7 +16,7 @@ use rustc_span::{RealFileName, SourceFileHashAlgorithm};
 use rustc_target::spec::{
     CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
     RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
-    TargetTuple, TlsModel, WasmCAbi,
+    TargetTuple, TlsModel,
 };
 
 use crate::config::*;
@@ -802,7 +802,6 @@ mod desc {
         "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
     pub(crate) const parse_llvm_module_flag: &str = "<key>:<type>:<value>:<behavior>. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)";
     pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`";
-    pub(crate) const parse_wasm_c_abi: &str = "`legacy` or `spec`";
     pub(crate) const parse_mir_include_spans: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)";
     pub(crate) const parse_align: &str = "a number that is a power of 2 between 1 and 2^29";
@@ -1898,16 +1897,6 @@ pub mod parse {
         true
     }
 
-    pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
-        match v {
-            Some("spec") => *slot = WasmCAbi::Spec,
-            // Explicitly setting the `-Z` flag suppresses the lint.
-            Some("legacy") => *slot = WasmCAbi::Legacy { with_lint: false },
-            _ => return false,
-        }
-        true
-    }
-
     pub(crate) fn parse_mir_include_spans(slot: &mut MirIncludeSpans, v: Option<&str>) -> bool {
         *slot = match v {
             Some("on" | "yes" | "y" | "true") | None => MirIncludeSpans::On,
@@ -2642,8 +2631,6 @@ written to standard error output)"),
         Requires `-Clto[=[fat,yes]]`"),
     wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
         "whether to build a wasi command or reactor"),
-    wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy { with_lint: true }, parse_wasm_c_abi, [TRACKED],
-        "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"),
     write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED],
         "whether long type names should be written to files instead of being printed in errors"),
     // tidy-alphabetical-end
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 6b85e0abc86..b8b4518b14e 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -215,13 +215,6 @@ pub struct Session {
     pub invocation_temp: Option<String>,
 }
 
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-pub enum MetadataKind {
-    None,
-    Uncompressed,
-    Compressed,
-}
-
 #[derive(Clone, Copy)]
 pub enum CodegenUnits {
     /// Specified by the user. In this case we try fairly hard to produce the
diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs
index 8783d3953b1..51e7ee8daa4 100644
--- a/compiler/rustc_target/src/asm/loongarch.rs
+++ b/compiler/rustc_target/src/asm/loongarch.rs
@@ -37,9 +37,11 @@ impl LoongArchInlineAsmRegClass {
         arch: InlineAsmArch,
     ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match (self, arch) {
-            (Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; },
-            (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F32; },
-            (Self::freg, _) => types! { f: F32; d: F64; },
+            (Self::reg, InlineAsmArch::LoongArch64) => {
+                types! { _: I8, I16, I32, I64, F16, F32, F64; }
+            }
+            (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F16, F32; },
+            (Self::freg, _) => types! { f: F16, F32; d: F64; },
             _ => unreachable!("unsupported register class"),
         }
     }
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index f9ecf02f857..2ff7a71ca82 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -7,7 +7,7 @@ use rustc_abi::{
 use rustc_macros::HashStable_Generic;
 
 pub use crate::spec::AbiMap;
-use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
+use crate::spec::{HasTargetSpec, HasX86AbiOpt};
 
 mod aarch64;
 mod amdgpu;
@@ -593,7 +593,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
     pub fn adjust_for_foreign_abi<C>(&mut self, cx: &C, abi: ExternAbi)
     where
         Ty: TyAbiInterface<'a, C> + Copy,
-        C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasX86AbiOpt,
+        C: HasDataLayout + HasTargetSpec + HasX86AbiOpt,
     {
         if abi == ExternAbi::X86Interrupt {
             if let Some(arg) = self.args.first_mut() {
@@ -669,14 +669,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "hexagon" => hexagon::compute_abi_info(self),
             "xtensa" => xtensa::compute_abi_info(cx, self),
             "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
-            "wasm32" => {
-                if spec.os == "unknown" && matches!(cx.wasm_c_abi_opt(), WasmCAbi::Legacy { .. }) {
-                    wasm::compute_wasm_abi_info(self)
-                } else {
-                    wasm::compute_c_abi_info(cx, self)
-                }
-            }
-            "wasm64" => wasm::compute_c_abi_info(cx, self),
+            "wasm32" | "wasm64" => wasm::compute_abi_info(cx, self),
             "bpf" => bpf::compute_abi_info(self),
             arch => panic!("no lowering implemented for {arch}"),
         }
diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs
index 881168c98c3..a308f378ee8 100644
--- a/compiler/rustc_target/src/callconv/wasm.rs
+++ b/compiler/rustc_target/src/callconv/wasm.rs
@@ -59,7 +59,7 @@ where
 }
 
 /// The purpose of this ABI is to match the C ABI (aka clang) exactly.
-pub(crate) fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
+pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
@@ -75,43 +75,3 @@ where
         classify_arg(cx, arg);
     }
 }
-
-/// The purpose of this ABI is for matching the WebAssembly standard. This
-/// intentionally diverges from the C ABI and is specifically crafted to take
-/// advantage of LLVM's support of multiple returns in WebAssembly.
-///
-/// This ABI is *bad*! It uses `PassMode::Direct` for `abi::Aggregate` types, which leaks LLVM
-/// implementation details into the ABI. It's just hard to fix because ABIs are hard to change.
-/// Also see <https://github.com/rust-lang/rust/issues/115666>.
-pub(crate) fn compute_wasm_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
-    if !fn_abi.ret.is_ignore() {
-        classify_ret_wasm_abi(&mut fn_abi.ret);
-    }
-
-    for arg in fn_abi.args.iter_mut() {
-        if arg.is_ignore() {
-            continue;
-        }
-        classify_arg_wasm_abi(arg);
-    }
-
-    fn classify_ret_wasm_abi<Ty>(ret: &mut ArgAbi<'_, Ty>) {
-        if !ret.layout.is_sized() {
-            // Not touching this...
-            return;
-        }
-        // FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666
-        ret.make_direct_deprecated();
-        ret.extend_integer_width_to(32);
-    }
-
-    fn classify_arg_wasm_abi<Ty>(arg: &mut ArgAbi<'_, Ty>) {
-        if !arg.layout.is_sized() {
-            // Not touching this...
-            return;
-        }
-        // FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666
-        arg.make_direct_deprecated();
-        arg.extend_integer_width_to(32);
-    }
-}
diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs
index 300b19f62e7..700ee73c8fd 100644
--- a/compiler/rustc_target/src/callconv/x86_64.rs
+++ b/compiler/rustc_target/src/callconv/x86_64.rs
@@ -7,6 +7,7 @@ use rustc_abi::{
 };
 
 use crate::callconv::{ArgAbi, CastTarget, FnAbi};
+use crate::spec::HasTargetSpec;
 
 /// Classification of "eightbyte" components.
 // N.B., the order of the variants is from general to specific,
@@ -175,7 +176,7 @@ const MAX_SSE_REGS: usize = 8; // XMM0-7
 pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
-    C: HasDataLayout,
+    C: HasDataLayout + HasTargetSpec,
 {
     let mut int_regs = MAX_INT_REGS;
     let mut sse_regs = MAX_SSE_REGS;
@@ -236,7 +237,7 @@ where
                 if arg.layout.is_aggregate() {
                     let size = arg.layout.size;
                     arg.cast_to(cast_target(cls, size));
-                } else {
+                } else if is_arg || cx.target_spec().is_like_darwin {
                     arg.extend_integer_width_to(32);
                 }
             }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index c360fe63a00..010355abd78 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2233,22 +2233,6 @@ impl HasTargetSpec for Target {
     }
 }
 
-/// Which C ABI to use for `wasm32-unknown-unknown`.
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub enum WasmCAbi {
-    /// Spec-compliant C ABI.
-    Spec,
-    /// Legacy ABI. Which is non-spec-compliant.
-    Legacy {
-        /// Indicates whether the `wasm_c_abi` lint should be emitted.
-        with_lint: bool,
-    },
-}
-
-pub trait HasWasmCAbiOpt {
-    fn wasm_c_abi_opt(&self) -> WasmCAbi;
-}
-
 /// x86 (32-bit) abi options.
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct X86Abi {
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index bb5187e4f5c..f0ff50318ab 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -403,28 +403,18 @@ fn fn_abi_sanity_check<'tcx>(
                         // For an unsized type we'd only pass the sized prefix, so there is no universe
                         // in which we ever want to allow this.
                         assert!(sized, "`PassMode::Direct` for unsized type in ABI: {:#?}", fn_abi);
+
                         // This really shouldn't happen even for sized aggregates, since
                         // `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an
                         // LLVM type. This means all sorts of Rust type details leak into the ABI.
-                        // However wasm sadly *does* currently use this mode for it's "C" ABI so we
-                        // have to allow it -- but we absolutely shouldn't let any more targets do
-                        // that. (Also see <https://github.com/rust-lang/rust/issues/115666>.)
-                        //
-                        // The unadjusted ABI also uses Direct for all args and is ill-specified,
+                        // The unadjusted ABI however uses Direct for all args. It is ill-specified,
                         // but unfortunately we need it for calling certain LLVM intrinsics.
-
-                        match spec_abi {
-                            ExternAbi::Unadjusted => {}
-                            ExternAbi::C { unwind: _ }
-                                if matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") => {}
-                            _ => {
-                                panic!(
-                                    "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" functions and on wasm\n\
-                                      Problematic type: {:#?}",
-                                    arg.layout,
-                                );
-                            }
-                        }
+                        assert!(
+                            matches!(spec_abi, ExternAbi::Unadjusted),
+                            "`PassMode::Direct` for aggregates only allowed for \"unadjusted\"\n\
+                             Problematic type: {:#?}",
+                            arg.layout,
+                        );
                     }
                 }
             }