about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock12
-rw-r--r--compiler/rustc/src/main.rs2
-rw-r--r--compiler/rustc_ast_lowering/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs83
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs2
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs86
-rw-r--r--compiler/rustc_codegen_gcc/src/archive.rs3
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs5
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/abort1.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/abort2.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/array.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/assign.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/closure.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/condition.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/mut_ref.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/operations.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/slice.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/static.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs100
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs57
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs99
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs27
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs34
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs63
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs35
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs9
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0094.md22
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0211.md10
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs17
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml1
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs11
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_infer/Cargo.toml2
-rw-r--r--compiler/rustc_lint/Cargo.toml1
-rw-r--r--compiler/rustc_lint/src/static_mut_refs.rs27
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp54
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp28
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs10
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs6
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs177
-rw-r--r--compiler/rustc_next_trait_solver/Cargo.toml1
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs22
-rw-r--r--compiler/rustc_passes/src/errors.rs9
-rw-r--r--compiler/rustc_session/src/cstore.rs5
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs16
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs34
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/Cargo.toml2
-rw-r--r--compiler/rustc_target/src/asm/mod.rs47
-rw-r--r--compiler/rustc_target/src/asm/sparc.rs138
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs135
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs81
-rw-r--r--compiler/stable_mir/src/compiler_interface.rs6
-rw-r--r--compiler/stable_mir/src/lib.rs13
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs101
-rw-r--r--compiler/stable_mir/src/ty.rs8
-rw-r--r--library/core/src/intrinsics/mod.rs (renamed from library/core/src/intrinsics.rs)180
-rw-r--r--library/std/src/f128/tests.rs22
-rw-r--r--library/std/src/sync/mpmc/list.rs8
-rw-r--r--src/bootstrap/src/bin/main.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs10
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs4
-rw-r--r--src/bootstrap/src/core/config/config.rs33
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md22
-rw-r--r--src/doc/unstable-book/src/language-features/intrinsics.md4
-rw-r--r--src/librustdoc/scrape_examples.rs33
-rw-r--r--src/tools/compiletest/src/common.rs7
-rw-r--r--src/tools/compiletest/src/directive-list.rs5
-rw-r--r--src/tools/compiletest/src/header/cfg.rs11
-rw-r--r--src/tools/compiletest/src/header/needs.rs10
-rw-r--r--src/tools/compiletest/src/header/tests.rs44
-rw-r--r--src/tools/compiletest/src/lib.rs9
-rw-r--r--src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs2
-rw-r--r--tests/assembly/asm/sparc-types.rs168
-rw-r--r--tests/assembly/rust-abi-arg-attr.rs7
-rw-r--r--tests/codegen/asm/sparc-clobbers.rs40
-rw-r--r--tests/codegen/binary-heap-peek-mut-pop-no-panic.rs2
-rw-r--r--tests/codegen/mem-replace-big-type.rs3
-rw-r--r--tests/codegen/mem-replace-simple-type.rs3
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs6
-rw-r--r--tests/codegen/slice-reverse.rs2
-rw-r--r--tests/codegen/vec-in-place.rs2
-rw-r--r--tests/codegen/vec-shrink-panik.rs2
-rw-r--r--tests/codegen/vec-with-capacity.rs2
-rw-r--r--tests/codegen/vecdeque-drain.rs2
-rw-r--r--tests/codegen/vecdeque_no_panic.rs2
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.rs3
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.rs2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.rs2
-rw-r--r--tests/run-make/crate-loading/multiple-dep-versions-3.rs5
-rw-r--r--tests/run-make/crate-loading/multiple-dep-versions.rs3
-rw-r--r--tests/run-make/crate-loading/rmake.rs89
-rw-r--r--tests/rustdoc/safe-intrinsic.rs25
-rw-r--r--tests/ui-fulldeps/stable-mir/check_crate_defs.rs149
-rw-r--r--tests/ui/asm/bad-arch.rs26
-rw-r--r--tests/ui/asm/bad-arch.stderr15
-rw-r--r--tests/ui/asm/sparc/bad-reg.rs66
-rw-r--r--tests/ui/asm/sparc/bad-reg.sparc.stderr98
-rw-r--r--tests/ui/asm/sparc/bad-reg.sparc64.stderr92
-rw-r--r--tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr98
-rw-r--r--tests/ui/consts/const-eval/raw-pointer-ub.stderr4
-rw-r--r--tests/ui/error-codes/E0094.rs13
-rw-r--r--tests/ui/error-codes/E0094.stderr6
-rw-r--r--tests/ui/error-codes/E0308.rs11
-rw-r--r--tests/ui/error-codes/E0308.stderr10
-rw-r--r--tests/ui/extern/extern-with-type-bounds.rs11
-rw-r--r--tests/ui/extern/extern-with-type-bounds.stderr2
-rw-r--r--tests/ui/intrinsics/always-gets-overridden.rs2
-rw-r--r--tests/ui/intrinsics/const-eval-select-bad.stderr8
-rw-r--r--tests/ui/intrinsics/feature-gate-safe-intrinsic.rs6
-rw-r--r--tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr21
-rw-r--r--tests/ui/intrinsics/intrinsic-alignment.rs10
-rw-r--r--tests/ui/intrinsics/intrinsics-integer.rs22
-rw-r--r--tests/ui/intrinsics/not-overridden.rs2
-rw-r--r--tests/ui/print_type_sizes/niche-filling.rs2
-rw-r--r--tests/ui/stable-mir-print/operands.rs48
-rw-r--r--tests/ui/stable-mir-print/operands.stdout263
-rw-r--r--tests/ui/statics/static-mut-shared-parens.rs13
-rw-r--r--tests/ui/statics/static-mut-shared-parens.stderr29
-rw-r--r--tests/ui/std/channel-stack-overflow-issue-102246.rs29
-rw-r--r--tests/ui/structs-enums/rec-align-u32.rs15
-rw-r--r--tests/ui/structs-enums/rec-align-u64.rs15
-rw-r--r--tests/ui/typeck/foreign_struct_trait_unimplemented.stderr7
142 files changed, 2623 insertions, 1033 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 93d3d118778..9cca91c25df 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3273,7 +3273,6 @@ name = "rustc_ast_lowering"
 version = "0.0.0"
 dependencies = [
  "rustc_ast",
- "rustc_ast_pretty",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -3468,7 +3467,6 @@ dependencies = [
  "rustc_macros",
  "rustc_metadata",
  "rustc_middle",
- "rustc_monomorphize",
  "rustc_query_system",
  "rustc_serialize",
  "rustc_session",
@@ -3744,7 +3742,6 @@ dependencies = [
  "rustc_feature",
  "rustc_fluent_macro",
  "rustc_hir",
- "rustc_hir_pretty",
  "rustc_index",
  "rustc_infer",
  "rustc_lint_defs",
@@ -3792,7 +3789,6 @@ dependencies = [
  "rustc_middle",
  "rustc_session",
  "rustc_span",
- "rustc_target",
  "rustc_trait_selection",
  "rustc_type_ir",
  "smallvec",
@@ -3852,9 +3848,7 @@ dependencies = [
  "rustc_index",
  "rustc_macros",
  "rustc_middle",
- "rustc_next_trait_solver",
  "rustc_span",
- "rustc_target",
  "rustc_type_ir",
  "smallvec",
  "thin-vec",
@@ -3933,7 +3927,6 @@ dependencies = [
  "rustc_feature",
  "rustc_fluent_macro",
  "rustc_hir",
- "rustc_hir_pretty",
  "rustc_index",
  "rustc_infer",
  "rustc_macros",
@@ -4161,7 +4154,6 @@ dependencies = [
 name = "rustc_next_trait_solver"
 version = "0.0.0"
 dependencies = [
- "bitflags 2.6.0",
  "derive-where",
  "rustc_ast_ir",
  "rustc_data_structures",
@@ -4457,9 +4449,7 @@ dependencies = [
  "object 0.36.4",
  "rustc_abi",
  "rustc_data_structures",
- "rustc_feature",
  "rustc_fs_util",
- "rustc_index",
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
@@ -4491,8 +4481,6 @@ dependencies = [
  "rustc_middle",
  "rustc_next_trait_solver",
  "rustc_parse_format",
- "rustc_query_system",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_transmute",
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index e9a7397557e..ccf88d8ff4b 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -1,5 +1,7 @@
 // We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
 #![feature(rustc_private)]
+// Several crates are depended upon but unused so that they are present in the sysroot
+#![expect(unused_crate_dependencies)]
 
 // A note about jemalloc: rustc uses jemalloc when built for CI and
 // distribution. The obvious way to do this is with the `#[global_allocator]`
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index 8cc4521e0a7..c47c12b4fd1 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -9,7 +9,6 @@ doctest = false
 [dependencies]
 # tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 42c7f5f0dc6..3da215fe6c0 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -616,25 +616,70 @@ pub union MaybeUninit<T> {
 }
 
 pub mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
-        #[rustc_safe_intrinsic]
-        pub fn size_of<T>() -> usize;
-        pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
-        #[rustc_safe_intrinsic]
-        pub fn min_align_of<T>() -> usize;
-        pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
-        pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
-        pub fn transmute<T, U>(e: T) -> U;
-        pub fn ctlz_nonzero<T>(x: T) -> u32;
-        #[rustc_safe_intrinsic]
-        pub fn needs_drop<T: ?::Sized>() -> bool;
-        #[rustc_safe_intrinsic]
-        pub fn bitreverse<T>(x: T) -> T;
-        #[rustc_safe_intrinsic]
-        pub fn bswap<T>(x: T) -> T;
-        pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn size_of<T>() -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn min_align_of<T>() -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn transmute<T, U>(_e: T) -> U {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32 {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn needs_drop<T: ?::Sized>() -> bool {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn bitreverse<T>(_x: T) -> T {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn bswap<T>(_x: T) -> T {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn unreachable() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index e5a12162687..1e2e41b3122 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -1,4 +1,4 @@
-//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, `extern "platform-intrinsic"`
+//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`,
 //! and LLVM intrinsics that have symbol names starting with `llvm.`.
 
 macro_rules! intrinsic_args {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 16fb68a7bdf..36a35d42c3e 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -1,4 +1,4 @@
-//! Codegen `extern "platform-intrinsic"` intrinsics.
+//! Codegen SIMD intrinsics.
 
 use cranelift_codegen::ir::immediates::Offset32;
 use rustc_target::abi::Endian;
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 0576b64ef6f..c887598f6e9 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -579,28 +579,70 @@ pub union MaybeUninit<T> {
 }
 
 pub mod intrinsics {
-    use crate::Sized;
-
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
-        #[rustc_safe_intrinsic]
-        pub fn size_of<T>() -> usize;
-        pub fn size_of_val<T: ?Sized>(val: *const T) -> usize;
-        #[rustc_safe_intrinsic]
-        pub fn min_align_of<T>() -> usize;
-        pub fn min_align_of_val<T: ?Sized>(val: *const T) -> usize;
-        pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
-        pub fn transmute<T, U>(e: T) -> U;
-        pub fn ctlz_nonzero<T>(x: T) -> u32;
-        #[rustc_safe_intrinsic]
-        pub fn needs_drop<T: ?Sized>() -> bool;
-        #[rustc_safe_intrinsic]
-        pub fn bitreverse<T>(x: T) -> T;
-        #[rustc_safe_intrinsic]
-        pub fn bswap<T>(x: T) -> T;
-        pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
-        pub fn unreachable() -> !;
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn size_of<T>() -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn min_align_of<T>() -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn transmute<T, U>(_e: T) -> U {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32 {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn needs_drop<T: ?::Sized>() -> bool {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn bitreverse<T>(_x: T) -> T {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn bswap<T>(_x: T) -> T {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) {
+        loop {}
+    }
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub unsafe fn unreachable() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs
index 0cee05f1cea..82e98370b37 100644
--- a/compiler/rustc_codegen_gcc/src/archive.rs
+++ b/compiler/rustc_codegen_gcc/src/archive.rs
@@ -2,6 +2,7 @@ use std::path::Path;
 
 use rustc_codegen_ssa::back::archive::{
     ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
+    ImportLibraryItem,
 };
 use rustc_session::Session;
 
@@ -16,7 +17,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
         &self,
         _sess: &Session,
         _lib_name: &str,
-        _import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+        _items: Vec<ImportLibraryItem>,
         _output_path: &Path,
     ) {
         unimplemented!("creating dll imports is not yet supported");
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index b44d4aa8cc8..6b067b35e71 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -688,6 +688,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
             ) => {
                 unreachable!("clobber-only")
             }
+            InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
             InlineAsmRegClass::Err => unreachable!(),
         },
     };
@@ -767,6 +769,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
             unreachable!("clobber-only")
         }
+        InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
+        InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
         InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
         InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
@@ -946,6 +950,7 @@ fn modifier_to_gcc(
         },
         InlineAsmRegClass::Avr(_) => None,
         InlineAsmRegClass::S390x(_) => None,
+        InlineAsmRegClass::Sparc(_) => None,
         InlineAsmRegClass::Msp430(_) => None,
         InlineAsmRegClass::M68k(_) => None,
         InlineAsmRegClass::CSKY(_) => None,
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
index 44297e12779..696197d7377 100644
--- a/compiler/rustc_codegen_gcc/tests/run/abort1.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs
@@ -33,9 +33,11 @@ pub(crate) unsafe auto trait Freeze {}
 mod intrinsics {
     use super::Sized;
 
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
index ce816927123..714cd6c0f38 100644
--- a/compiler/rustc_codegen_gcc/tests/run/abort2.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs
@@ -33,9 +33,11 @@ pub(crate) unsafe auto trait Freeze {}
 mod intrinsics {
     use super::Sized;
 
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/array.rs b/compiler/rustc_codegen_gcc/tests/run/array.rs
index 432f11ad8d4..d8de9f28d4c 100644
--- a/compiler/rustc_codegen_gcc/tests/run/array.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/array.rs
@@ -106,9 +106,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs
index e105d64a8ad..2a47f0c2966 100644
--- a/compiler/rustc_codegen_gcc/tests/run/assign.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs
@@ -56,9 +56,11 @@ mod libc {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/closure.rs b/compiler/rustc_codegen_gcc/tests/run/closure.rs
index 00e61cc001f..b0d0ca4ee8d 100644
--- a/compiler/rustc_codegen_gcc/tests/run/closure.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/closure.rs
@@ -98,9 +98,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/condition.rs b/compiler/rustc_codegen_gcc/tests/run/condition.rs
index 7b05b7decd3..770b18a89e3 100644
--- a/compiler/rustc_codegen_gcc/tests/run/condition.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/condition.rs
@@ -109,9 +109,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
index 4e96f376555..523544ee6bb 100644
--- a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs
@@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
index 5a3f72b6904..3ae79338216 100644
--- a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
@@ -58,9 +58,11 @@ mod libc {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs
index d697bd921cd..2e3c021d5f7 100644
--- a/compiler/rustc_codegen_gcc/tests/run/operations.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs
@@ -64,9 +64,11 @@ mod libc {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
index a94279182d6..c7510d16449 100644
--- a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs
@@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 }
 
 mod intrinsics {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/slice.rs b/compiler/rustc_codegen_gcc/tests/run/slice.rs
index e86fc823a1a..35ad594ecde 100644
--- a/compiler/rustc_codegen_gcc/tests/run/slice.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/slice.rs
@@ -103,9 +103,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 mod intrinsics {
     use super::Sized;
 
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs
index 6247e08f5e3..a17ea2a4893 100644
--- a/compiler/rustc_codegen_gcc/tests/run/static.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/static.rs
@@ -46,9 +46,11 @@ pub(crate) unsafe auto trait Freeze {}
 mod intrinsics {
     use super::Sized;
 
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn abort() -> !;
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    pub fn abort() -> ! {
+        loop {}
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index a1ccf0d1719..bb74dfe1487 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -268,6 +268,15 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 InlineAsmArch::S390x => {
                     constraints.push("~{cc}".to_string());
                 }
+                InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
+                    // In LLVM, ~{icc} represents icc and xcc in 64-bit code.
+                    // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.td#L64
+                    constraints.push("~{icc}".to_string());
+                    constraints.push("~{fcc0}".to_string());
+                    constraints.push("~{fcc1}".to_string());
+                    constraints.push("~{fcc2}".to_string());
+                    constraints.push("~{fcc3}".to_string());
+                }
                 InlineAsmArch::SpirV => {}
                 InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {}
                 InlineAsmArch::Bpf => {}
@@ -672,6 +681,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
             S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
                 unreachable!("clobber-only")
             }
+            Sparc(SparcInlineAsmRegClass::reg) => "r",
+            Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
             Msp430(Msp430InlineAsmRegClass::reg) => "r",
             M68k(M68kInlineAsmRegClass::reg) => "r",
             M68k(M68kInlineAsmRegClass::reg_addr) => "a",
@@ -765,6 +776,7 @@ fn modifier_to_llvm(
         },
         Avr(_) => None,
         S390x(_) => None,
+        Sparc(_) => None,
         Msp430(_) => None,
         SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"),
         M68k(_) => None,
@@ -835,6 +847,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
         S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
             unreachable!("clobber-only")
         }
+        Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
+        Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
         Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
         M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
         M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index 25037b97375..dcea9d3b391 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -44,6 +44,22 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
         let llfn = if tcx.sess.target.arch == "x86"
             && let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
         {
+            // When calling functions in generated import libraries, MSVC needs
+            // the fully decorated name (as would have been in the declaring
+            // object file), but MinGW wants the name as exported (as would be
+            // in the def file) which may be missing decorations.
+            let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&tcx.sess.target);
+            let llfn = cx.declare_fn(
+                &common::i686_decorated_name(
+                    dllimport,
+                    mingw_gnu_toolchain,
+                    true,
+                    !mingw_gnu_toolchain,
+                ),
+                fn_abi,
+                Some(instance),
+            );
+
             // Fix for https://github.com/rust-lang/rust/issues/104453
             // On x86 Windows, LLVM uses 'L' as the prefix for any private
             // global symbols, so when we create an undecorated function symbol
@@ -55,15 +71,6 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
             // LLVM will prefix the name with `__imp_`. Ideally, we'd like the
             // existing logic below to set the Storage Class, but it has an
             // exemption for MinGW for backwards compatibility.
-            let llfn = cx.declare_fn(
-                &common::i686_decorated_name(
-                    dllimport,
-                    common::is_mingw_gnu_toolchain(&tcx.sess.target),
-                    true,
-                ),
-                fn_abi,
-                Some(instance),
-            );
             unsafe {
                 llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
             }
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index bed64686a23..7ab4f45cd73 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -194,16 +194,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
         unsafe { llvm::LLVMSetInitializer(g2, g1) };
         g2
     } else if cx.tcx.sess.target.arch == "x86"
+        && common::is_mingw_gnu_toolchain(&cx.tcx.sess.target)
         && let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
     {
-        cx.declare_global(
-            &common::i686_decorated_name(
-                dllimport,
-                common::is_mingw_gnu_toolchain(&cx.tcx.sess.target),
-                true,
-            ),
-            llty,
-        )
+        cx.declare_global(&common::i686_decorated_name(dllimport, true, true, false), llty)
     } else {
         // Generate an external declaration.
         // FIXME(nagisa): investigate whether it can be changed into define_global
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index b7ab5d6d5f0..ba863d9d74b 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -154,6 +154,11 @@ pub(crate) unsafe fn create_module<'ll>(
             // See https://github.com/llvm/llvm-project/pull/106951
             target_data_layout = target_data_layout.replace("-i128:128", "");
         }
+        if sess.target.arch.starts_with("mips64") {
+            // LLVM 20 updates the mips64 layout to correctly align 128 bit integers to 128 bit.
+            // See https://github.com/llvm/llvm-project/pull/112084
+            target_data_layout = target_data_layout.replace("-i128:128", "");
+        }
     }
 
     // Ensure the data-layout values hardcoded remain the defaults.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
new file mode 100644
index 00000000000..99c2d12b261
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
@@ -0,0 +1,100 @@
+//! Safe wrappers for coverage-specific FFI functions.
+
+use std::ffi::CString;
+
+use crate::common::AsCCharPtr;
+use crate::coverageinfo::ffi;
+use crate::llvm;
+
+pub(crate) fn covmap_var_name() -> CString {
+    CString::new(llvm::build_byte_buffer(|s| unsafe {
+        llvm::LLVMRustCoverageWriteCovmapVarNameToString(s);
+    }))
+    .expect("covmap variable name should not contain NUL")
+}
+
+pub(crate) fn covmap_section_name(llmod: &llvm::Module) -> CString {
+    CString::new(llvm::build_byte_buffer(|s| unsafe {
+        llvm::LLVMRustCoverageWriteCovmapSectionNameToString(llmod, s);
+    }))
+    .expect("covmap section name should not contain NUL")
+}
+
+pub(crate) fn covfun_section_name(llmod: &llvm::Module) -> CString {
+    CString::new(llvm::build_byte_buffer(|s| unsafe {
+        llvm::LLVMRustCoverageWriteCovfunSectionNameToString(llmod, s);
+    }))
+    .expect("covfun section name should not contain NUL")
+}
+
+pub(crate) fn create_pgo_func_name_var<'ll>(
+    llfn: &'ll llvm::Value,
+    mangled_fn_name: &str,
+) -> &'ll llvm::Value {
+    unsafe {
+        llvm::LLVMRustCoverageCreatePGOFuncNameVar(
+            llfn,
+            mangled_fn_name.as_c_char_ptr(),
+            mangled_fn_name.len(),
+        )
+    }
+}
+
+pub(crate) fn write_filenames_to_buffer<'a>(
+    filenames: impl IntoIterator<Item = &'a str>,
+) -> Vec<u8> {
+    let (pointers, lengths) = filenames
+        .into_iter()
+        .map(|s: &str| (s.as_c_char_ptr(), s.len()))
+        .unzip::<_, _, Vec<_>, Vec<_>>();
+
+    llvm::build_byte_buffer(|buffer| unsafe {
+        llvm::LLVMRustCoverageWriteFilenamesToBuffer(
+            pointers.as_ptr(),
+            pointers.len(),
+            lengths.as_ptr(),
+            lengths.len(),
+            buffer,
+        );
+    })
+}
+
+pub(crate) fn write_function_mappings_to_buffer(
+    virtual_file_mapping: &[u32],
+    expressions: &[ffi::CounterExpression],
+    code_regions: &[ffi::CodeRegion],
+    branch_regions: &[ffi::BranchRegion],
+    mcdc_branch_regions: &[ffi::MCDCBranchRegion],
+    mcdc_decision_regions: &[ffi::MCDCDecisionRegion],
+) -> Vec<u8> {
+    llvm::build_byte_buffer(|buffer| unsafe {
+        llvm::LLVMRustCoverageWriteFunctionMappingsToBuffer(
+            virtual_file_mapping.as_ptr(),
+            virtual_file_mapping.len(),
+            expressions.as_ptr(),
+            expressions.len(),
+            code_regions.as_ptr(),
+            code_regions.len(),
+            branch_regions.as_ptr(),
+            branch_regions.len(),
+            mcdc_branch_regions.as_ptr(),
+            mcdc_branch_regions.len(),
+            mcdc_decision_regions.as_ptr(),
+            mcdc_decision_regions.len(),
+            buffer,
+        )
+    })
+}
+
+/// Hashes some bytes into a 64-bit hash, via LLVM's `IndexedInstrProf::ComputeHash`,
+/// as required for parts of the LLVM coverage mapping format.
+pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 {
+    unsafe { llvm::LLVMRustCoverageHashBytes(bytes.as_c_char_ptr(), bytes.len()) }
+}
+
+/// Returns LLVM's `coverage::CovMapVersion::CurrentVersion` (CoverageMapping.h)
+/// as a raw numeric value. For historical reasons, the numeric value is 1 less
+/// than the number in the version's name, so `Version7` is actually `6u32`.
+pub(crate) fn mapping_version() -> u32 {
+    unsafe { llvm::LLVMRustCoverageMappingVersion() }
+}
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index f6378199fe2..bb2f634cb25 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,4 +1,5 @@
 use std::ffi::CString;
+use std::iter;
 
 use itertools::Itertools as _;
 use rustc_abi::Align;
@@ -17,9 +18,9 @@ use rustc_target::spec::HasTargetSpec;
 use tracing::debug;
 
 use crate::common::CodegenCx;
-use crate::coverageinfo::ffi;
 use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
-use crate::{coverageinfo, llvm};
+use crate::coverageinfo::{ffi, llvm_cov};
+use crate::llvm;
 
 /// Generates and exports the coverage map, which is embedded in special
 /// linker sections in the final binary.
@@ -33,7 +34,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
     // agrees with our Rust-side code. Expected versions (encoded as n-1) are:
     // - `CovMapVersion::Version7` (6) used by LLVM 18-19
     let covmap_version = {
-        let llvm_covmap_version = coverageinfo::mapping_version();
+        let llvm_covmap_version = llvm_cov::mapping_version();
         let expected_versions = 6..=6;
         assert!(
             expected_versions.contains(&llvm_covmap_version),
@@ -78,7 +79,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
 
     let filenames_size = filenames_buffer.len();
     let filenames_val = cx.const_bytes(&filenames_buffer);
-    let filenames_ref = coverageinfo::hash_bytes(&filenames_buffer);
+    let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer);
 
     // Generate the coverage map header, which contains the filenames used by
     // this CGU's coverage mappings, and store it in a well-known global.
@@ -187,13 +188,10 @@ impl GlobalFileTable {
             .for_scope(tcx.sess, RemapPathScopeComponents::MACRO)
             .to_string_lossy();
 
-        llvm::build_byte_buffer(|buffer| {
-            coverageinfo::write_filenames_section_to_buffer(
-                // Insert the working dir at index 0, before the other filenames.
-                std::iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str)),
-                buffer,
-            );
-        })
+        // Insert the working dir at index 0, before the other filenames.
+        let filenames =
+            iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str));
+        llvm_cov::write_filenames_to_buffer(filenames)
     }
 }
 
@@ -296,17 +294,14 @@ fn encode_mappings_for_function(
     }
 
     // Encode the function's coverage mappings into a buffer.
-    llvm::build_byte_buffer(|buffer| {
-        coverageinfo::write_mapping_to_buffer(
-            virtual_file_mapping.into_vec(),
-            expressions,
-            &code_regions,
-            &branch_regions,
-            &mcdc_branch_regions,
-            &mcdc_decision_regions,
-            buffer,
-        );
-    })
+    llvm_cov::write_function_mappings_to_buffer(
+        &virtual_file_mapping.into_vec(),
+        &expressions,
+        &code_regions,
+        &branch_regions,
+        &mcdc_branch_regions,
+        &mcdc_decision_regions,
+    )
 }
 
 /// Generates the contents of the covmap record for this CGU, which mostly
@@ -335,23 +330,11 @@ fn generate_covmap_record<'ll>(
     let covmap_data =
         cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false);
 
-    let covmap_var_name = CString::new(llvm::build_byte_buffer(|s| unsafe {
-        llvm::LLVMRustCoverageWriteMappingVarNameToString(s);
-    }))
-    .unwrap();
-    debug!("covmap var name: {:?}", covmap_var_name);
-
-    let covmap_section_name = CString::new(llvm::build_byte_buffer(|s| unsafe {
-        llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s);
-    }))
-    .expect("covmap section name should not contain NUL");
-    debug!("covmap section name: {:?}", covmap_section_name);
-
-    let llglobal = llvm::add_global(cx.llmod, cx.val_ty(covmap_data), &covmap_var_name);
+    let llglobal = llvm::add_global(cx.llmod, cx.val_ty(covmap_data), &llvm_cov::covmap_var_name());
     llvm::set_initializer(llglobal, covmap_data);
     llvm::set_global_constant(llglobal, true);
     llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
-    llvm::set_section(llglobal, &covmap_section_name);
+    llvm::set_section(llglobal, &llvm_cov::covmap_section_name(cx.llmod));
     // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
     // <https://llvm.org/docs/CoverageMappingFormat.html>
     llvm::set_alignment(llglobal, Align::EIGHT);
@@ -373,7 +356,7 @@ fn generate_covfun_record(
     let coverage_mapping_size = coverage_mapping_buffer.len();
     let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer);
 
-    let func_name_hash = coverageinfo::hash_bytes(mangled_function_name.as_bytes());
+    let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes());
     let func_name_hash_val = cx.const_u64(func_name_hash);
     let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32);
     let source_hash_val = cx.const_u64(source_hash);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index aaba0684c12..bf773cd2667 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -1,24 +1,23 @@
 use std::cell::{OnceCell, RefCell};
 use std::ffi::{CStr, CString};
 
-use libc::c_uint;
 use rustc_abi::Size;
 use rustc_codegen_ssa::traits::{
     BuilderMethods, ConstCodegenMethods, CoverageInfoBuilderMethods, MiscCodegenMethods,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_llvm::RustString;
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::layout::HasTyCtxt;
 use tracing::{debug, instrument};
 
 use crate::builder::Builder;
-use crate::common::{AsCCharPtr, CodegenCx};
+use crate::common::CodegenCx;
 use crate::coverageinfo::map_data::FunctionCoverageCollector;
 use crate::llvm;
 
 pub(crate) mod ffi;
+mod llvm_cov;
 pub(crate) mod map_data;
 mod mapgen;
 
@@ -80,12 +79,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     /// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix)
     /// - `.lcovfun$M` on Windows (includes `$M` sorting suffix)
     fn covfun_section_name(&self) -> &CStr {
-        self.coverage_cx().covfun_section_name.get_or_init(|| {
-            CString::new(llvm::build_byte_buffer(|s| unsafe {
-                llvm::LLVMRustCoverageWriteFuncSectionNameToString(self.llmod, s);
-            }))
-            .expect("covfun section name should not contain NUL")
-        })
+        self.coverage_cx()
+            .covfun_section_name
+            .get_or_init(|| llvm_cov::covfun_section_name(self.llmod))
     }
 
     /// For LLVM codegen, returns a function-specific `Value` for a global
@@ -95,9 +91,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value {
         debug!("getting pgo_func_name_var for instance={:?}", instance);
         let mut pgo_func_name_var_map = self.coverage_cx().pgo_func_name_var_map.borrow_mut();
-        pgo_func_name_var_map
-            .entry(instance)
-            .or_insert_with(|| create_pgo_func_name_var(self, instance))
+        pgo_func_name_var_map.entry(instance).or_insert_with(|| {
+            let llfn = self.get_fn(instance);
+            let mangled_fn_name: &str = self.tcx.symbol_name(instance).name;
+            llvm_cov::create_pgo_func_name_var(llfn, mangled_fn_name)
+        })
     }
 }
 
@@ -225,80 +223,3 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
         }
     }
 }
-
-/// Calls llvm::createPGOFuncNameVar() with the given function instance's
-/// mangled function name. The LLVM API returns an llvm::GlobalVariable
-/// containing the function name, with the specific variable name and linkage
-/// required by LLVM InstrProf source-based coverage instrumentation. Use
-/// `bx.get_pgo_func_name_var()` to ensure the variable is only created once per
-/// `Instance`.
-fn create_pgo_func_name_var<'ll, 'tcx>(
-    cx: &CodegenCx<'ll, 'tcx>,
-    instance: Instance<'tcx>,
-) -> &'ll llvm::Value {
-    let mangled_fn_name: &str = cx.tcx.symbol_name(instance).name;
-    let llfn = cx.get_fn(instance);
-    unsafe {
-        llvm::LLVMRustCoverageCreatePGOFuncNameVar(
-            llfn,
-            mangled_fn_name.as_c_char_ptr(),
-            mangled_fn_name.len(),
-        )
-    }
-}
-
-pub(crate) fn write_filenames_section_to_buffer<'a>(
-    filenames: impl IntoIterator<Item = &'a str>,
-    buffer: &RustString,
-) {
-    let (pointers, lengths) = filenames
-        .into_iter()
-        .map(|s: &str| (s.as_c_char_ptr(), s.len()))
-        .unzip::<_, _, Vec<_>, Vec<_>>();
-
-    unsafe {
-        llvm::LLVMRustCoverageWriteFilenamesSectionToBuffer(
-            pointers.as_ptr(),
-            pointers.len(),
-            lengths.as_ptr(),
-            lengths.len(),
-            buffer,
-        );
-    }
-}
-
-pub(crate) fn write_mapping_to_buffer(
-    virtual_file_mapping: Vec<u32>,
-    expressions: Vec<ffi::CounterExpression>,
-    code_regions: &[ffi::CodeRegion],
-    branch_regions: &[ffi::BranchRegion],
-    mcdc_branch_regions: &[ffi::MCDCBranchRegion],
-    mcdc_decision_regions: &[ffi::MCDCDecisionRegion],
-    buffer: &RustString,
-) {
-    unsafe {
-        llvm::LLVMRustCoverageWriteMappingToBuffer(
-            virtual_file_mapping.as_ptr(),
-            virtual_file_mapping.len() as c_uint,
-            expressions.as_ptr(),
-            expressions.len() as c_uint,
-            code_regions.as_ptr(),
-            code_regions.len() as c_uint,
-            branch_regions.as_ptr(),
-            branch_regions.len() as c_uint,
-            mcdc_branch_regions.as_ptr(),
-            mcdc_branch_regions.len() as c_uint,
-            mcdc_decision_regions.as_ptr(),
-            mcdc_decision_regions.len() as c_uint,
-            buffer,
-        );
-    }
-}
-
-pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 {
-    unsafe { llvm::LLVMRustCoverageHashByteArray(bytes.as_c_char_ptr(), bytes.len()) }
-}
-
-pub(crate) fn mapping_version() -> u32 {
-    unsafe { llvm::LLVMRustCoverageMappingVersion() }
-}
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index b85d28a2f1f..49e616b5371 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -22,7 +22,6 @@
 
 use std::any::Any;
 use std::ffi::CStr;
-use std::io::Write;
 use std::mem::ManuallyDrop;
 
 use back::owned_target_machine::OwnedTargetMachine;
@@ -165,30 +164,12 @@ impl WriteBackendMethods for LlvmCodegenBackend {
     type ThinData = back::lto::ThinData;
     type ThinBuffer = back::lto::ThinBuffer;
     fn print_pass_timings(&self) {
-        unsafe {
-            let mut size = 0;
-            let cstr = llvm::LLVMRustPrintPassTimings(&raw mut size);
-            if cstr.is_null() {
-                println!("failed to get pass timings");
-            } else {
-                let timings = std::slice::from_raw_parts(cstr as *const u8, size);
-                std::io::stdout().write_all(timings).unwrap();
-                libc::free(cstr as *mut _);
-            }
-        }
+        let timings = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintPassTimings(s) }).unwrap();
+        print!("{timings}");
     }
     fn print_statistics(&self) {
-        unsafe {
-            let mut size = 0;
-            let cstr = llvm::LLVMRustPrintStatistics(&raw mut size);
-            if cstr.is_null() {
-                println!("failed to get pass stats");
-            } else {
-                let stats = std::slice::from_raw_parts(cstr as *const u8, size);
-                std::io::stdout().write_all(stats).unwrap();
-                libc::free(cstr as *mut _);
-            }
-        }
+        let stats = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap();
+        print!("{stats}");
     }
     fn run_link(
         cgcx: &CodegenContext<Self>,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index d84ae8d8836..8508f87c8d3 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1765,11 +1765,13 @@ unsafe extern "C" {
     /// Returns a string describing the last error caused by an LLVMRust* call.
     pub fn LLVMRustGetLastError() -> *const c_char;
 
-    /// Print the pass timings since static dtors aren't picking them up.
-    pub fn LLVMRustPrintPassTimings(size: *const size_t) -> *const c_char;
+    /// Prints the timing information collected by `-Ztime-llvm-passes`.
+    #[expect(improper_ctypes)]
+    pub(crate) fn LLVMRustPrintPassTimings(OutStr: &RustString);
 
-    /// Print the statistics since static dtors aren't picking them up.
-    pub fn LLVMRustPrintStatistics(size: *const size_t) -> *const c_char;
+    /// Prints the statistics collected by `-Zprint-codegen-stats`.
+    #[expect(improper_ctypes)]
+    pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString);
 
     /// Prepares inline assembly.
     pub fn LLVMRustInlineAsm(
@@ -1790,7 +1792,7 @@ unsafe extern "C" {
     ) -> bool;
 
     #[allow(improper_ctypes)]
-    pub(crate) fn LLVMRustCoverageWriteFilenamesSectionToBuffer(
+    pub(crate) fn LLVMRustCoverageWriteFilenamesToBuffer(
         Filenames: *const *const c_char,
         FilenamesLen: size_t,
         Lengths: *const size_t,
@@ -1799,19 +1801,19 @@ unsafe extern "C" {
     );
 
     #[allow(improper_ctypes)]
-    pub(crate) fn LLVMRustCoverageWriteMappingToBuffer(
+    pub(crate) fn LLVMRustCoverageWriteFunctionMappingsToBuffer(
         VirtualFileMappingIDs: *const c_uint,
-        NumVirtualFileMappingIDs: c_uint,
+        NumVirtualFileMappingIDs: size_t,
         Expressions: *const crate::coverageinfo::ffi::CounterExpression,
-        NumExpressions: c_uint,
+        NumExpressions: size_t,
         CodeRegions: *const crate::coverageinfo::ffi::CodeRegion,
-        NumCodeRegions: c_uint,
+        NumCodeRegions: size_t,
         BranchRegions: *const crate::coverageinfo::ffi::BranchRegion,
-        NumBranchRegions: c_uint,
+        NumBranchRegions: size_t,
         MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion,
-        NumMCDCBranchRegions: c_uint,
+        NumMCDCBranchRegions: size_t,
         MCDCDecisionRegions: *const crate::coverageinfo::ffi::MCDCDecisionRegion,
-        NumMCDCDecisionRegions: c_uint,
+        NumMCDCDecisionRegions: size_t,
         BufferOut: &RustString,
     );
 
@@ -1820,16 +1822,16 @@ unsafe extern "C" {
         FuncName: *const c_char,
         FuncNameLen: size_t,
     ) -> &Value;
-    pub(crate) fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
+    pub(crate) fn LLVMRustCoverageHashBytes(Bytes: *const c_char, NumBytes: size_t) -> u64;
 
     #[allow(improper_ctypes)]
-    pub(crate) fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString);
+    pub(crate) fn LLVMRustCoverageWriteCovmapSectionNameToString(M: &Module, OutStr: &RustString);
 
     #[allow(improper_ctypes)]
-    pub(crate) fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString);
+    pub(crate) fn LLVMRustCoverageWriteCovfunSectionNameToString(M: &Module, OutStr: &RustString);
 
     #[allow(improper_ctypes)]
-    pub(crate) fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
+    pub(crate) fn LLVMRustCoverageWriteCovmapVarNameToString(OutStr: &RustString);
 
     pub(crate) fn LLVMRustCoverageMappingVersion() -> u32;
     pub fn LLVMRustDebugMetadataVersion() -> u32;
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index dffb7a7271e..b898cfec796 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -28,7 +28,6 @@ rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_metadata = { path = "../rustc_metadata" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_monomorphize = { path = "../rustc_monomorphize" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 2f48c1fbf0d..e83bfa7b70d 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -26,6 +26,35 @@ use crate::errors::{
     DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
 };
 
+/// An item to be included in an import library.
+/// This is a slimmed down version of `COFFShortExport` from `ar-archive-writer`.
+pub struct ImportLibraryItem {
+    /// The name to be exported.
+    pub name: String,
+    /// The ordinal to be exported, if any.
+    pub ordinal: Option<u16>,
+    /// The original, decorated name if `name` is not decorated.
+    pub symbol_name: Option<String>,
+    /// True if this is a data export, false if it is a function export.
+    pub is_data: bool,
+}
+
+impl From<ImportLibraryItem> for COFFShortExport {
+    fn from(item: ImportLibraryItem) -> Self {
+        COFFShortExport {
+            name: item.name,
+            ext_name: None,
+            symbol_name: item.symbol_name,
+            alias_target: None,
+            ordinal: item.ordinal.unwrap_or(0),
+            noname: item.ordinal.is_some(),
+            data: item.is_data,
+            private: false,
+            constant: false,
+        }
+    }
+}
+
 pub trait ArchiveBuilderBuilder {
     fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
 
@@ -38,7 +67,7 @@ pub trait ArchiveBuilderBuilder {
         &self,
         sess: &Session,
         lib_name: &str,
-        import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+        items: Vec<ImportLibraryItem>,
         output_path: &Path,
     ) {
         if common::is_mingw_gnu_toolchain(&sess.target) {
@@ -47,21 +76,16 @@ pub trait ArchiveBuilderBuilder {
             // that loaded but crashed with an AV upon calling one of the imported
             // functions. Therefore, use binutils to create the import library instead,
             // by writing a .DEF file to the temp dir and calling binutils's dlltool.
-            create_mingw_dll_import_lib(
-                sess,
-                lib_name,
-                import_name_and_ordinal_vector,
-                output_path,
-            );
+            create_mingw_dll_import_lib(sess, lib_name, items, output_path);
         } else {
             trace!("creating import library");
             trace!("  dll_name {:#?}", lib_name);
             trace!("  output_path {}", output_path.display());
             trace!(
                 "  import names: {}",
-                import_name_and_ordinal_vector
+                items
                     .iter()
-                    .map(|(name, _ordinal)| name.clone())
+                    .map(|ImportLibraryItem { name, .. }| name.clone())
                     .collect::<Vec<_>>()
                     .join(", "),
             );
@@ -79,20 +103,7 @@ pub trait ArchiveBuilderBuilder {
                     .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
             };
 
-            let exports = import_name_and_ordinal_vector
-                .iter()
-                .map(|(name, ordinal)| COFFShortExport {
-                    name: name.to_string(),
-                    ext_name: None,
-                    symbol_name: None,
-                    alias_target: None,
-                    ordinal: ordinal.unwrap_or(0),
-                    noname: ordinal.is_some(),
-                    data: false,
-                    private: false,
-                    constant: false,
-                })
-                .collect::<Vec<_>>();
+            let exports = items.into_iter().map(Into::into).collect::<Vec<_>>();
             let machine = match &*sess.target.arch {
                 "x86_64" => MachineTypes::AMD64,
                 "x86" => MachineTypes::I386,
@@ -160,16 +171,16 @@ pub trait ArchiveBuilderBuilder {
 fn create_mingw_dll_import_lib(
     sess: &Session,
     lib_name: &str,
-    import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+    items: Vec<ImportLibraryItem>,
     output_path: &Path,
 ) {
     let def_file_path = output_path.with_extension("def");
 
     let def_file_content = format!(
         "EXPORTS\n{}",
-        import_name_and_ordinal_vector
+        items
             .into_iter()
-            .map(|(name, ordinal)| {
+            .map(|ImportLibraryItem { name, ordinal, .. }| {
                 match ordinal {
                     Some(n) => format!("{name} @{n} NONAME"),
                     None => name,
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 44581cfa64b..8f754debaf0 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -45,7 +45,7 @@ use rustc_target::spec::{
 use tempfile::Builder as TempFileBuilder;
 use tracing::{debug, info, warn};
 
-use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
+use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
 use super::command::Command;
 use super::linker::{self, Linker};
 use super::metadata::{MetadataPosition, create_wrapper_file};
@@ -495,16 +495,35 @@ fn create_dll_import_libs<'a>(
 
             let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
 
-            let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
+            let items: Vec<ImportLibraryItem> = raw_dylib_imports
                 .iter()
                 .map(|import: &DllImport| {
                     if sess.target.arch == "x86" {
-                        (
-                            common::i686_decorated_name(import, mingw_gnu_toolchain, false),
-                            import.ordinal(),
-                        )
+                        ImportLibraryItem {
+                            name: common::i686_decorated_name(
+                                import,
+                                mingw_gnu_toolchain,
+                                false,
+                                false,
+                            ),
+                            ordinal: import.ordinal(),
+                            symbol_name: import.is_missing_decorations().then(|| {
+                                common::i686_decorated_name(
+                                    import,
+                                    mingw_gnu_toolchain,
+                                    false,
+                                    true,
+                                )
+                            }),
+                            is_data: !import.is_fn,
+                        }
                     } else {
-                        (import.name.to_string(), import.ordinal())
+                        ImportLibraryItem {
+                            name: import.name.to_string(),
+                            ordinal: import.ordinal(),
+                            symbol_name: None,
+                            is_data: !import.is_fn,
+                        }
                     }
                 })
                 .collect();
@@ -512,7 +531,7 @@ fn create_dll_import_libs<'a>(
             archive_builder_builder.create_dll_import_lib(
                 sess,
                 &raw_dylib_name,
-                import_name_and_ordinal_vector,
+                items,
                 &output_path,
             );
 
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 582a2a87e48..965bd34ac14 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -187,12 +187,15 @@ pub fn i686_decorated_name(
     dll_import: &DllImport,
     mingw: bool,
     disable_name_mangling: bool,
+    force_fully_decorated: bool,
 ) -> String {
     let name = dll_import.name.as_str();
 
-    let (add_prefix, add_suffix) = match dll_import.import_name_type {
-        Some(PeImportNameType::NoPrefix) => (false, true),
-        Some(PeImportNameType::Undecorated) => (false, false),
+    let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
+        // No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
+        // ignore `force_fully_decorated` and always partially decorate it.
+        (_, Some(PeImportNameType::NoPrefix)) => (false, true),
+        (false, Some(PeImportNameType::Undecorated)) => (false, false),
         _ => (true, true),
     };
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md
index d8c1a3cb55c..efbfa0851a8 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0094.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0094.md
@@ -3,13 +3,15 @@ An invalid number of generic parameters was passed to an intrinsic function.
 Erroneous code example:
 
 ```compile_fail,E0094
-#![feature(intrinsics, rustc_attrs)]
+#![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    #[rustc_safe_intrinsic]
-    fn size_of<T, U>() -> usize; // error: intrinsic has wrong number
-                                 //        of type parameters
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+fn size_of<T, U>() -> usize // error: intrinsic has wrong number
+                            //        of type parameters
+{
+    loop {}
 }
 ```
 
@@ -18,11 +20,13 @@ and verify with the function declaration in the Rust source code.
 Example:
 
 ```
-#![feature(intrinsics, rustc_attrs)]
+#![feature(intrinsics)]
 #![allow(internal_features)]
 
-extern "rust-intrinsic" {
-    #[rustc_safe_intrinsic]
-    fn size_of<T>() -> usize; // ok!
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+fn size_of<T>() -> usize // ok!
+{
+    loop {}
 }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md
index 19a482f6c93..7aa42628549 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0211.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0211.md
@@ -4,12 +4,11 @@ You used a function or type which doesn't fit the requirements for where it was
 used. Erroneous code examples:
 
 ```compile_fail
-#![feature(intrinsics, rustc_attrs)]
+#![feature(intrinsics)]
 #![allow(internal_features)]
 
 extern "rust-intrinsic" {
-    #[rustc_safe_intrinsic]
-    fn size_of<T>(); // error: intrinsic has wrong type
+    fn unreachable(); // error: intrinsic has wrong type
 }
 
 // or:
@@ -41,12 +40,11 @@ impl Foo {
 For the first code example, please check the function definition. Example:
 
 ```
-#![feature(intrinsics, rustc_attrs)]
+#![feature(intrinsics)]
 #![allow(internal_features)]
 
 extern "rust-intrinsic" {
-    #[rustc_safe_intrinsic]
-    fn size_of<T>() -> usize; // ok!
+    fn unreachable() -> !; // ok!
 }
 ```
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index cc0bdec7019..a4820ba8b72 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -997,23 +997,18 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
         EncodeCrossCrate::Yes, r#"`rustc_doc_primitive` is a rustc internal attribute"#,
     ),
-    rustc_attr!(
-        rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No,
-        "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe"
-    ),
-    rustc_attr!(
-        rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
+    gated!(
+        rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
         "the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
     ),
+    gated!(
+        rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
+        "the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
+    ),
     rustc_attr!(
         rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
         "#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen"
     ),
-    rustc_attr!(
-        rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
-        "the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
-    ),
 
     // ==========================================================================
     // Internal attributes, Testing:
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index 3c8887f08bc..581ef2272d1 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -19,7 +19,6 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 1513ea7c9e8..cb954b0adcb 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -1,10 +1,9 @@
-//! Type-checking for the rust-intrinsic and platform-intrinsic
-//! intrinsics that the compiler exposes.
+//! Type-checking for the rust-intrinsic intrinsics that the compiler exposes.
 
 use rustc_abi::ExternAbi;
 use rustc_errors::codes::*;
 use rustc_errors::{DiagMessage, struct_span_code_err};
-use rustc_hir as hir;
+use rustc_hir::{self as hir, Safety};
 use rustc_middle::bug;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -76,10 +75,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
     let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
         tcx.fn_sig(intrinsic_id).skip_binder().safety()
     } else {
-        match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
-            true => hir::Safety::Safe,
-            false => hir::Safety::Unsafe,
-        }
+        // Old-style intrinsics are never safe
+        Safety::Unsafe
     };
     let is_in_list = match tcx.item_name(intrinsic_id.into()) {
         // When adding a new intrinsic to this list,
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 894402a8c2e..8ddbb4b3397 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -23,7 +23,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index ef5a1468c87..6d1a2d3de9e 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -16,9 +16,7 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
 rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
 rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index dd7b40d0a32..ec5f0f06c59 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -14,7 +14,6 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_lint/src/static_mut_refs.rs b/compiler/rustc_lint/src/static_mut_refs.rs
index 5d78b41944f..fed5c29284b 100644
--- a/compiler/rustc_lint/src/static_mut_refs.rs
+++ b/compiler/rustc_lint/src/static_mut_refs.rs
@@ -3,8 +3,8 @@ use rustc_hir::{Expr, Stmt};
 use rustc_middle::ty::{Mutability, TyKind};
 use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::{declare_lint, declare_lint_pass};
-use rustc_span::Span;
 use rustc_span::edition::Edition;
+use rustc_span::{BytePos, Span};
 
 use crate::lints::{MutRefSugg, RefOfMutStatic};
 use crate::{LateContext, LateLintPass, LintContext};
@@ -71,13 +71,24 @@ impl<'tcx> LateLintPass<'tcx> for StaticMutRefs {
                 if matches!(borrow_kind, hir::BorrowKind::Ref)
                     && let Some(err_span) = path_is_static_mut(ex, err_span) =>
             {
-                emit_static_mut_refs(
-                    cx,
-                    err_span,
-                    err_span.with_hi(ex.span.lo()),
-                    m,
-                    !expr.span.from_expansion(),
-                );
+                let source_map = cx.sess().source_map();
+                let snippet = source_map.span_to_snippet(err_span);
+
+                let sugg_span = if let Ok(snippet) = snippet {
+                    // ( ( &IDENT ) )
+                    // ~~~~ exclude these from the suggestion span to avoid unmatching parens
+                    let exclude_n_bytes: u32 = snippet
+                        .chars()
+                        .take_while(|ch| ch.is_whitespace() || *ch == '(')
+                        .map(|ch| ch.len_utf8() as u32)
+                        .sum();
+
+                    err_span.with_lo(err_span.lo() + BytePos(exclude_n_bytes)).with_hi(ex.span.lo())
+                } else {
+                    err_span.with_hi(ex.span.lo())
+                };
+
+                emit_static_mut_refs(cx, err_span, sugg_span, m, !expr.span.from_expansion());
             }
             hir::ExprKind::MethodCall(_, e, _, _)
                 if let Some(err_span) = path_is_static_mut(e, expr.span)
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index b32af5e5e75..2ee7454b652 100644
--- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -123,13 +123,13 @@ fromRust(LLVMRustCounterExprKind Kind) {
   report_fatal_error("Bad LLVMRustCounterExprKind!");
 }
 
-extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
+extern "C" void LLVMRustCoverageWriteFilenamesToBuffer(
     const char *const Filenames[], size_t FilenamesLen, // String start pointers
     const size_t *const Lengths, size_t LengthsLen,     // Corresponding lengths
     RustStringRef BufferOut) {
   if (FilenamesLen != LengthsLen) {
     report_fatal_error(
-        "Mismatched lengths in LLVMRustCoverageWriteFilenamesSectionToBuffer");
+        "Mismatched lengths in LLVMRustCoverageWriteFilenamesToBuffer");
   }
 
   SmallVector<std::string, 32> FilenameRefs;
@@ -143,16 +143,15 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
   FilenamesWriter.write(OS);
 }
 
-extern "C" void LLVMRustCoverageWriteMappingToBuffer(
-    const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs,
-    const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions,
-    const LLVMRustCoverageCodeRegion *CodeRegions, unsigned NumCodeRegions,
-    const LLVMRustCoverageBranchRegion *BranchRegions,
-    unsigned NumBranchRegions,
+extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer(
+    const unsigned *VirtualFileMappingIDs, size_t NumVirtualFileMappingIDs,
+    const LLVMRustCounterExpression *RustExpressions, size_t NumExpressions,
+    const LLVMRustCoverageCodeRegion *CodeRegions, size_t NumCodeRegions,
+    const LLVMRustCoverageBranchRegion *BranchRegions, size_t NumBranchRegions,
     const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions,
-    unsigned NumMCDCBranchRegions,
+    size_t NumMCDCBranchRegions,
     const LLVMRustCoverageMCDCDecisionRegion *MCDCDecisionRegions,
-    unsigned NumMCDCDecisionRegions, RustStringRef BufferOut) {
+    size_t NumMCDCDecisionRegions, RustStringRef BufferOut) {
   // Convert from FFI representation to LLVM representation.
 
   // Expressions:
@@ -219,34 +218,37 @@ LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName,
   return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
 }
 
-extern "C" uint64_t LLVMRustCoverageHashByteArray(const char *Bytes,
-                                                  size_t NumBytes) {
-  auto StrRef = StringRef(Bytes, NumBytes);
-  return IndexedInstrProf::ComputeHash(StrRef);
+extern "C" uint64_t LLVMRustCoverageHashBytes(const char *Bytes,
+                                              size_t NumBytes) {
+  return IndexedInstrProf::ComputeHash(StringRef(Bytes, NumBytes));
 }
 
-static void WriteSectionNameToString(LLVMModuleRef M, InstrProfSectKind SK,
-                                     RustStringRef Str) {
+// Private helper function for getting the covmap and covfun section names.
+static void writeInstrProfSectionNameToString(LLVMModuleRef M,
+                                              InstrProfSectKind SectKind,
+                                              RustStringRef OutStr) {
   auto TargetTriple = Triple(unwrap(M)->getTargetTriple());
-  auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat());
-  auto OS = RawRustStringOstream(Str);
+  auto name = getInstrProfSectionName(SectKind, TargetTriple.getObjectFormat());
+  auto OS = RawRustStringOstream(OutStr);
   OS << name;
 }
 
-extern "C" void LLVMRustCoverageWriteMapSectionNameToString(LLVMModuleRef M,
-                                                            RustStringRef Str) {
-  WriteSectionNameToString(M, IPSK_covmap, Str);
+extern "C" void
+LLVMRustCoverageWriteCovmapSectionNameToString(LLVMModuleRef M,
+                                               RustStringRef OutStr) {
+  writeInstrProfSectionNameToString(M, IPSK_covmap, OutStr);
 }
 
 extern "C" void
-LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M,
-                                             RustStringRef Str) {
-  WriteSectionNameToString(M, IPSK_covfun, Str);
+LLVMRustCoverageWriteCovfunSectionNameToString(LLVMModuleRef M,
+                                               RustStringRef OutStr) {
+  writeInstrProfSectionNameToString(M, IPSK_covfun, OutStr);
 }
 
-extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
+extern "C" void
+LLVMRustCoverageWriteCovmapVarNameToString(RustStringRef OutStr) {
   auto name = getCoverageMappingVarName();
-  auto OS = RawRustStringOstream(Str);
+  auto OS = RawRustStringOstream(OutStr);
   OS << name;
 }
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 645b4082be5..a68eed03e61 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -140,26 +140,14 @@ extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
   unwrap(M)->setTargetTriple(Triple::normalize(Triple));
 }
 
-extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) {
-  std::string buf;
-  auto SS = raw_string_ostream(buf);
-  TimerGroup::printAll(SS);
-  SS.flush();
-  *Len = buf.length();
-  char *CStr = (char *)malloc(*Len);
-  memcpy(CStr, buf.c_str(), *Len);
-  return CStr;
-}
-
-extern "C" const char *LLVMRustPrintStatistics(size_t *Len) {
-  std::string buf;
-  auto SS = raw_string_ostream(buf);
-  llvm::PrintStatistics(SS);
-  SS.flush();
-  *Len = buf.length();
-  char *CStr = (char *)malloc(*Len);
-  memcpy(CStr, buf.c_str(), *Len);
-  return CStr;
+extern "C" void LLVMRustPrintPassTimings(RustStringRef OutBuf) {
+  auto OS = RawRustStringOstream(OutBuf);
+  TimerGroup::printAll(OS);
+}
+
+extern "C" void LLVMRustPrintStatistics(RustStringRef OutBuf) {
+  auto OS = RawRustStringOstream(OutBuf);
+  llvm::PrintStatistics(OS);
 }
 
 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index f06f2fdc5e5..045fd0565ba 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -384,6 +384,7 @@ provide! { tcx, def_id, other, cdata,
     crate_hash => { cdata.root.header.hash }
     crate_host_hash => { cdata.host_hash }
     crate_name => { cdata.root.header.name }
+    num_extern_def_ids => { cdata.num_def_ids() }
 
     extra_filename => { cdata.root.extra_filename.clone() }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f58426601cd..8ae89ea6e2c 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1844,6 +1844,16 @@ rustc_queries! {
         desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
     }
 
+    /// Gets the number of definitions in a foreign crate.
+    ///
+    /// This allows external tools to iterate over all definitions in a foreign crate.
+    ///
+    /// This should never be used for the local crate, instead use `iter_local_def_id`.
+    query num_extern_def_ids(_: CrateNum) -> usize {
+        desc { "fetching the number of definitions in a crate" }
+        separate_provide_extern
+    }
+
     query lib_features(_: CrateNum) -> &'tcx LibFeatures {
         desc { "calculating the lib features defined in a crate" }
         separate_provide_extern
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 7ee13bc1725..0d1c56f0d38 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -71,7 +71,7 @@ pub enum InstanceKind<'tcx> {
     /// - coroutines
     Item(DefId),
 
-    /// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
+    /// An intrinsic `fn` item (with `"rust-intrinsic"` ABI).
     ///
     /// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR.
     /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 56e723ab517..fc5a3b762e5 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1785,9 +1785,9 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 /// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may
 /// cause an ICE that we otherwise may want to prevent.
 pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
-    if (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
-        && tcx.features().intrinsics())
-        || (tcx.has_attr(def_id, sym::rustc_intrinsic) && tcx.features().rustc_attrs())
+    if tcx.features().intrinsics()
+        && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic)
+            || tcx.has_attr(def_id, sym::rustc_intrinsic))
     {
         Some(ty::IntrinsicDef {
             name: tcx.item_name(def_id.into()),
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 168262bf01c..092bce1de2c 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -1,7 +1,7 @@
 use std::cmp::Ordering;
 use std::collections::VecDeque;
-use std::iter;
 use std::ops::{Index, IndexMut};
+use std::{iter, mem, slice};
 
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
@@ -127,10 +127,10 @@ impl CoverageGraph {
         let mut bcbs = IndexVec::<BasicCoverageBlock, _>::with_capacity(num_basic_blocks);
         let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks);
 
-        let mut add_basic_coverage_block = |basic_blocks: &mut Vec<BasicBlock>| {
+        let mut flush_chain_into_new_bcb = |current_chain: &mut Vec<BasicBlock>| {
             // Take the accumulated list of blocks, leaving the vector empty
             // to be used by subsequent BCBs.
-            let basic_blocks = std::mem::take(basic_blocks);
+            let basic_blocks = mem::take(current_chain);
 
             let bcb = bcbs.next_index();
             for &bb in basic_blocks.iter() {
@@ -141,48 +141,41 @@ impl CoverageGraph {
                 bcb_filtered_successors(mir_body[bb].terminator()).is_out_summable()
             });
             let bcb_data = BasicCoverageBlockData { basic_blocks, is_out_summable };
-            debug!("adding bcb{}: {:?}", bcb.index(), bcb_data);
+            debug!("adding {bcb:?}: {bcb_data:?}");
             bcbs.push(bcb_data);
         };
 
-        // Walk the MIR CFG using a Preorder traversal, which starts from `START_BLOCK` and follows
-        // each block terminator's `successors()`. Coverage spans must map to actual source code,
-        // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal
-        // intentionally omits unwind paths.
-        // FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
-        // `catch_unwind()` handlers.
+        // Traverse the MIR control-flow graph, accumulating chains of blocks
+        // that can be combined into a single node in the coverage graph.
+        // A depth-first search ensures that if two nodes can be chained
+        // together, they will be adjacent in the traversal order.
 
         // Accumulates a chain of blocks that will be combined into one BCB.
-        let mut basic_blocks = Vec::new();
+        let mut current_chain = vec![];
 
-        let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator());
-        for bb in short_circuit_preorder(mir_body, filtered_successors)
+        let subgraph = CoverageRelevantSubgraph::new(&mir_body.basic_blocks);
+        for bb in graph::depth_first_search(subgraph, mir::START_BLOCK)
             .filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable)
         {
-            // If the previous block can't be chained into `bb`, flush the accumulated
-            // blocks into a new BCB, then start building the next chain.
-            if let Some(&prev) = basic_blocks.last()
-                && (!filtered_successors(prev).is_chainable() || {
-                    // If `bb` has multiple predecessor blocks, or `prev` isn't
-                    // one of its predecessors, we can't chain and must flush.
-                    let predecessors = &mir_body.basic_blocks.predecessors()[bb];
-                    predecessors.len() > 1 || !predecessors.contains(&prev)
-                })
-            {
-                debug!(
-                    terminator_kind = ?mir_body[prev].terminator().kind,
-                    predecessors = ?&mir_body.basic_blocks.predecessors()[bb],
-                    "can't chain from {prev:?} to {bb:?}"
-                );
-                add_basic_coverage_block(&mut basic_blocks);
+            if let Some(&prev) = current_chain.last() {
+                // Adding a block to a non-empty chain is allowed if the
+                // previous block permits chaining, and the current block has
+                // `prev` as its sole predecessor.
+                let can_chain = subgraph.coverage_successors(prev).is_out_chainable()
+                    && mir_body.basic_blocks.predecessors()[bb].as_slice() == &[prev];
+                if !can_chain {
+                    // The current block can't be added to the existing chain, so
+                    // flush that chain into a new BCB, and start a new chain.
+                    flush_chain_into_new_bcb(&mut current_chain);
+                }
             }
 
-            basic_blocks.push(bb);
+            current_chain.push(bb);
         }
 
-        if !basic_blocks.is_empty() {
+        if !current_chain.is_empty() {
             debug!("flushing accumulated blocks into one last BCB");
-            add_basic_coverage_block(&mut basic_blocks);
+            flush_chain_into_new_bcb(&mut current_chain);
         }
 
         (bcbs, bb_to_bcb)
@@ -389,34 +382,28 @@ impl BasicCoverageBlockData {
 /// indicates whether that block can potentially be combined into the same BCB
 /// as its sole successor.
 #[derive(Clone, Copy, Debug)]
-enum CoverageSuccessors<'a> {
-    /// The terminator has exactly one straight-line successor, so its block can
-    /// potentially be combined into the same BCB as that successor.
-    Chainable(BasicBlock),
-    /// The block cannot be combined into the same BCB as its successor(s).
-    NotChainable(&'a [BasicBlock]),
-    /// Yield terminators are not chainable, and their execution count can also
-    /// differ from the execution count of their out-edge.
-    Yield(BasicBlock),
+struct CoverageSuccessors<'a> {
+    /// Coverage-relevant successors of the corresponding terminator.
+    /// There might be 0, 1, or multiple targets.
+    targets: &'a [BasicBlock],
+    /// `Yield` terminators are not chainable, because their sole out-edge is
+    /// only followed if/when the generator is resumed after the yield.
+    is_yield: bool,
 }
 
 impl CoverageSuccessors<'_> {
-    fn is_chainable(&self) -> bool {
-        match self {
-            Self::Chainable(_) => true,
-            Self::NotChainable(_) => false,
-            Self::Yield(_) => false,
-        }
+    /// If `false`, this terminator cannot be chained into another block when
+    /// building the coverage graph.
+    fn is_out_chainable(&self) -> bool {
+        // If a terminator is out-summable and has exactly one out-edge, then
+        // it is eligible to be chained into its successor block.
+        self.is_out_summable() && self.targets.len() == 1
     }
 
     /// Returns true if the terminator itself is assumed to have the same
     /// execution count as the sum of its out-edges (assuming no panics).
     fn is_out_summable(&self) -> bool {
-        match self {
-            Self::Chainable(_) => true,
-            Self::NotChainable(_) => true,
-            Self::Yield(_) => false,
-        }
+        !self.is_yield && !self.targets.is_empty()
     }
 }
 
@@ -425,12 +412,7 @@ impl IntoIterator for CoverageSuccessors<'_> {
     type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;
 
     fn into_iter(self) -> Self::IntoIter {
-        match self {
-            Self::Chainable(bb) | Self::Yield(bb) => {
-                Some(bb).into_iter().chain((&[]).iter().copied())
-            }
-            Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()),
-        }
+        self.targets.iter().copied()
     }
 }
 
@@ -440,14 +422,17 @@ impl IntoIterator for CoverageSuccessors<'_> {
 // `catch_unwind()` handlers.
 fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> {
     use TerminatorKind::*;
-    match terminator.kind {
+    let mut is_yield = false;
+    let targets = match &terminator.kind {
         // A switch terminator can have many coverage-relevant successors.
-        // (If there is exactly one successor, we still treat it as not chainable.)
-        SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()),
+        SwitchInt { targets, .. } => targets.all_targets(),
 
         // A yield terminator has exactly 1 successor, but should not be chained,
         // because its resume edge has a different execution count.
-        Yield { resume, .. } => CoverageSuccessors::Yield(resume),
+        Yield { resume, .. } => {
+            is_yield = true;
+            slice::from_ref(resume)
+        }
 
         // These terminators have exactly one coverage-relevant successor,
         // and can be chained into it.
@@ -455,24 +440,15 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
         | Drop { target, .. }
         | FalseEdge { real_target: target, .. }
         | FalseUnwind { real_target: target, .. }
-        | Goto { target } => CoverageSuccessors::Chainable(target),
+        | Goto { target } => slice::from_ref(target),
 
         // A call terminator can normally be chained, except when it has no
         // successor because it is known to diverge.
-        Call { target: maybe_target, .. } => match maybe_target {
-            Some(target) => CoverageSuccessors::Chainable(target),
-            None => CoverageSuccessors::NotChainable(&[]),
-        },
+        Call { target: maybe_target, .. } => maybe_target.as_slice(),
 
         // An inline asm terminator can normally be chained, except when it
         // diverges or uses asm goto.
-        InlineAsm { ref targets, .. } => {
-            if let [target] = targets[..] {
-                CoverageSuccessors::Chainable(target)
-            } else {
-                CoverageSuccessors::NotChainable(targets)
-            }
-        }
+        InlineAsm { targets, .. } => &targets,
 
         // These terminators have no coverage-relevant successors.
         CoroutineDrop
@@ -480,8 +456,10 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
         | TailCall { .. }
         | Unreachable
         | UnwindResume
-        | UnwindTerminate(_) => CoverageSuccessors::NotChainable(&[]),
-    }
+        | UnwindTerminate(_) => &[],
+    };
+
+    CoverageSuccessors { targets, is_yield }
 }
 
 /// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the
@@ -616,28 +594,31 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
     }
 }
 
-fn short_circuit_preorder<'a, 'tcx, F, Iter>(
-    body: &'a mir::Body<'tcx>,
-    filtered_successors: F,
-) -> impl Iterator<Item = BasicBlock> + Captures<'a> + Captures<'tcx>
-where
-    F: Fn(BasicBlock) -> Iter,
-    Iter: IntoIterator<Item = BasicBlock>,
-{
-    let mut visited = BitSet::new_empty(body.basic_blocks.len());
-    let mut worklist = vec![mir::START_BLOCK];
-
-    std::iter::from_fn(move || {
-        while let Some(bb) = worklist.pop() {
-            if !visited.insert(bb) {
-                continue;
-            }
-
-            worklist.extend(filtered_successors(bb));
+/// Wrapper around a [`mir::BasicBlocks`] graph that restricts each node's
+/// successors to only the ones considered "relevant" when building a coverage
+/// graph.
+#[derive(Clone, Copy)]
+struct CoverageRelevantSubgraph<'a, 'tcx> {
+    basic_blocks: &'a mir::BasicBlocks<'tcx>,
+}
+impl<'a, 'tcx> CoverageRelevantSubgraph<'a, 'tcx> {
+    fn new(basic_blocks: &'a mir::BasicBlocks<'tcx>) -> Self {
+        Self { basic_blocks }
+    }
 
-            return Some(bb);
-        }
+    fn coverage_successors(&self, bb: BasicBlock) -> CoverageSuccessors<'_> {
+        bcb_filtered_successors(self.basic_blocks[bb].terminator())
+    }
+}
+impl<'a, 'tcx> graph::DirectedGraph for CoverageRelevantSubgraph<'a, 'tcx> {
+    type Node = BasicBlock;
 
-        None
-    })
+    fn num_nodes(&self) -> usize {
+        self.basic_blocks.num_nodes()
+    }
+}
+impl<'a, 'tcx> graph::Successors for CoverageRelevantSubgraph<'a, 'tcx> {
+    fn successors(&self, bb: Self::Node) -> impl Iterator<Item = Self::Node> {
+        self.coverage_successors(bb).into_iter()
+    }
 }
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index fdf44e12378..451c215566b 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -5,7 +5,6 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
 derive-where = "1.2.7"
 rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index e5e70ba2033..6f0bcf5c3f0 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -679,10 +679,6 @@ passes_rustc_pub_transparent =
     attribute should be applied to `#[repr(transparent)]` types
     .label = not a `#[repr(transparent)]` type
 
-passes_rustc_safe_intrinsic =
-    attribute should be applied to intrinsic functions
-    .label = not an intrinsic function
-
 passes_rustc_std_internal_symbol =
     attribute should be applied to functions or statics
     .label = not a function or static
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 0a2926c0404..64a527ef106 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -210,9 +210,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 | [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target),
                 [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
                 [sym::rustc_confusables, ..] => self.check_confusables(attr, target),
-                [sym::rustc_safe_intrinsic, ..] => {
-                    self.check_rustc_safe_intrinsic(hir_id, attr, span, target)
-                }
                 [sym::cold, ..] => self.check_cold(hir_id, attr, span, target),
                 [sym::link, ..] => self.check_link(hir_id, attr, span, target),
                 [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
@@ -2055,25 +2052,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_rustc_safe_intrinsic(
-        &self,
-        hir_id: HirId,
-        attr: &Attribute,
-        span: Span,
-        target: Target,
-    ) {
-        if let Target::ForeignFn = target
-            && let hir::Node::Item(Item {
-                kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic, .. },
-                ..
-            }) = self.tcx.parent_hir_node(hir_id)
-        {
-            return;
-        }
-
-        self.dcx().emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span });
-    }
-
     fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
         match target {
             Target::Fn | Target::Static => {}
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 8bd767c1243..70c92f0144c 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -642,15 +642,6 @@ pub(crate) struct RustcAllowConstFnUnstable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_rustc_safe_intrinsic)]
-pub(crate) struct RustcSafeIntrinsic {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_rustc_std_internal_symbol)]
 pub(crate) struct RustcStdInternalSymbol {
     #[primary_span]
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 29d3d608388..3e2cbc18933 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -130,6 +130,11 @@ impl DllImport {
             None
         }
     }
+
+    pub fn is_missing_decorations(&self) -> bool {
+        self.import_name_type == Some(PeImportNameType::Undecorated)
+            || self.import_name_type == Some(PeImportNameType::NoPrefix)
+    }
 }
 
 /// Calling convention for a function defined in an external library.
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 2d6ca3571fa..3db65692af7 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -34,7 +34,7 @@ use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, I
 
 use crate::rustc_internal::RustcInternal;
 use crate::rustc_smir::builder::BodyBuilder;
-use crate::rustc_smir::{Stable, Tables, alloc, new_item_kind, smir_crate};
+use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate};
 
 impl<'tcx> Context for TablesWrapper<'tcx> {
     fn target_info(&self) -> MachineInfo {
@@ -80,6 +80,20 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
             .collect()
     }
 
+    fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let krate = crate_num.internal(&mut *tables, tcx);
+        filter_def_ids(tcx, krate, |def_id| tables.to_fn_def(def_id))
+    }
+
+    fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let krate = crate_num.internal(&mut *tables, tcx);
+        filter_def_ids(tcx, krate, |def_id| tables.to_static(def_id))
+    }
+
     fn foreign_module(
         &self,
         mod_def: stable_mir::ty::ForeignModuleDef,
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 9032156b257..c5d33f090a0 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -15,8 +15,8 @@ use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use stable_mir::abi::Layout;
-use stable_mir::mir::mono::InstanceDef;
-use stable_mir::ty::{MirConstId, Span, TyConstId};
+use stable_mir::mir::mono::{InstanceDef, StaticDef};
+use stable_mir::ty::{FnDef, MirConstId, Span, TyConstId};
 use stable_mir::{CtorKind, ItemKind};
 use tracing::debug;
 
@@ -79,6 +79,36 @@ impl<'tcx> Tables<'tcx> {
         };
         !must_override && self.tcx.is_mir_available(def_id)
     }
+
+    fn to_fn_def(&mut self, def_id: DefId) -> Option<FnDef> {
+        if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
+            Some(self.fn_def(def_id))
+        } else {
+            None
+        }
+    }
+
+    fn to_static(&mut self, def_id: DefId) -> Option<StaticDef> {
+        matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| self.static_def(def_id))
+    }
+}
+
+/// Iterate over the definitions of the given crate.
+pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T>
+where
+    F: FnMut(DefId) -> Option<T>,
+{
+    if krate == LOCAL_CRATE {
+        tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect()
+    } else {
+        let num_definitions = tcx.num_extern_def_ids(krate);
+        (0..num_definitions)
+            .filter_map(move |i| {
+                let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) };
+                func(def_id)
+            })
+            .collect()
+    }
 }
 
 /// Build a stable mir crate from a given crate number.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 21a74bd4020..82cfbd28fff 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1733,7 +1733,6 @@ symbols! {
         rustc_reallocator,
         rustc_regions,
         rustc_reservation_impl,
-        rustc_safe_intrinsic,
         rustc_serialize,
         rustc_skip_during_method_dispatch,
         rustc_specialization_trait,
@@ -2175,6 +2174,7 @@ symbols! {
         yes,
         yield_expr,
         ymm_reg,
+        yreg,
         zfh,
         zfhmin,
         zmm_reg,
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index c7d24154e8b..e33431ba122 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -8,9 +8,7 @@ edition = "2021"
 bitflags = "2.4.1"
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_feature = { path = "../rustc_feature" }
 rustc_fs_util = { path = "../rustc_fs_util" }
-rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 460b6e4b647..10778e9acf1 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -191,6 +191,7 @@ mod nvptx;
 mod powerpc;
 mod riscv;
 mod s390x;
+mod sparc;
 mod spirv;
 mod wasm;
 mod x86;
@@ -209,6 +210,7 @@ pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
 pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
 pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
 pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass};
+pub use sparc::{SparcInlineAsmReg, SparcInlineAsmRegClass};
 pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
 pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
 pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
@@ -230,6 +232,8 @@ pub enum InlineAsmArch {
     PowerPC,
     PowerPC64,
     S390x,
+    Sparc,
+    Sparc64,
     SpirV,
     Wasm32,
     Wasm64,
@@ -260,6 +264,8 @@ impl FromStr for InlineAsmArch {
             "mips" | "mips32r6" => Ok(Self::Mips),
             "mips64" | "mips64r6" => Ok(Self::Mips64),
             "s390x" => Ok(Self::S390x),
+            "sparc" => Ok(Self::Sparc),
+            "sparc64" => Ok(Self::Sparc64),
             "spirv" => Ok(Self::SpirV),
             "wasm32" => Ok(Self::Wasm32),
             "wasm64" => Ok(Self::Wasm64),
@@ -286,6 +292,7 @@ pub enum InlineAsmReg {
     LoongArch(LoongArchInlineAsmReg),
     Mips(MipsInlineAsmReg),
     S390x(S390xInlineAsmReg),
+    Sparc(SparcInlineAsmReg),
     SpirV(SpirVInlineAsmReg),
     Wasm(WasmInlineAsmReg),
     Bpf(BpfInlineAsmReg),
@@ -309,6 +316,7 @@ impl InlineAsmReg {
             Self::LoongArch(r) => r.name(),
             Self::Mips(r) => r.name(),
             Self::S390x(r) => r.name(),
+            Self::Sparc(r) => r.name(),
             Self::Bpf(r) => r.name(),
             Self::Avr(r) => r.name(),
             Self::Msp430(r) => r.name(),
@@ -329,6 +337,7 @@ impl InlineAsmReg {
             Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()),
             Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
             Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
+            Self::Sparc(r) => InlineAsmRegClass::Sparc(r.reg_class()),
             Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
             Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()),
             Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()),
@@ -361,6 +370,9 @@ impl InlineAsmReg {
                 Self::Mips(MipsInlineAsmReg::parse(name)?)
             }
             InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?),
+            InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
+                Self::Sparc(SparcInlineAsmReg::parse(name)?)
+            }
             InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?),
             InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
                 Self::Wasm(WasmInlineAsmReg::parse(name)?)
@@ -393,6 +405,7 @@ impl InlineAsmReg {
             }
             Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
             Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Sparc(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
             Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
             Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
             Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
@@ -420,6 +433,7 @@ impl InlineAsmReg {
             Self::LoongArch(r) => r.emit(out, arch, modifier),
             Self::Mips(r) => r.emit(out, arch, modifier),
             Self::S390x(r) => r.emit(out, arch, modifier),
+            Self::Sparc(r) => r.emit(out, arch, modifier),
             Self::Bpf(r) => r.emit(out, arch, modifier),
             Self::Avr(r) => r.emit(out, arch, modifier),
             Self::Msp430(r) => r.emit(out, arch, modifier),
@@ -440,6 +454,7 @@ impl InlineAsmReg {
             Self::LoongArch(_) => cb(self),
             Self::Mips(_) => cb(self),
             Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))),
+            Self::Sparc(_) => cb(self),
             Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
             Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))),
             Self::Msp430(_) => cb(self),
@@ -463,6 +478,7 @@ pub enum InlineAsmRegClass {
     LoongArch(LoongArchInlineAsmRegClass),
     Mips(MipsInlineAsmRegClass),
     S390x(S390xInlineAsmRegClass),
+    Sparc(SparcInlineAsmRegClass),
     SpirV(SpirVInlineAsmRegClass),
     Wasm(WasmInlineAsmRegClass),
     Bpf(BpfInlineAsmRegClass),
@@ -487,6 +503,7 @@ impl InlineAsmRegClass {
             Self::LoongArch(r) => r.name(),
             Self::Mips(r) => r.name(),
             Self::S390x(r) => r.name(),
+            Self::Sparc(r) => r.name(),
             Self::SpirV(r) => r.name(),
             Self::Wasm(r) => r.name(),
             Self::Bpf(r) => r.name(),
@@ -513,6 +530,7 @@ impl InlineAsmRegClass {
             Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch),
             Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
             Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x),
+            Self::Sparc(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Sparc),
             Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
             Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
             Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
@@ -542,6 +560,7 @@ impl InlineAsmRegClass {
             Self::LoongArch(r) => r.suggest_modifier(arch, ty),
             Self::Mips(r) => r.suggest_modifier(arch, ty),
             Self::S390x(r) => r.suggest_modifier(arch, ty),
+            Self::Sparc(r) => r.suggest_modifier(arch, ty),
             Self::SpirV(r) => r.suggest_modifier(arch, ty),
             Self::Wasm(r) => r.suggest_modifier(arch, ty),
             Self::Bpf(r) => r.suggest_modifier(arch, ty),
@@ -571,6 +590,7 @@ impl InlineAsmRegClass {
             Self::LoongArch(r) => r.default_modifier(arch),
             Self::Mips(r) => r.default_modifier(arch),
             Self::S390x(r) => r.default_modifier(arch),
+            Self::Sparc(r) => r.default_modifier(arch),
             Self::SpirV(r) => r.default_modifier(arch),
             Self::Wasm(r) => r.default_modifier(arch),
             Self::Bpf(r) => r.default_modifier(arch),
@@ -599,6 +619,7 @@ impl InlineAsmRegClass {
             Self::LoongArch(r) => r.supported_types(arch),
             Self::Mips(r) => r.supported_types(arch),
             Self::S390x(r) => r.supported_types(arch),
+            Self::Sparc(r) => r.supported_types(arch),
             Self::SpirV(r) => r.supported_types(arch),
             Self::Wasm(r) => r.supported_types(arch),
             Self::Bpf(r) => r.supported_types(arch),
@@ -632,6 +653,9 @@ impl InlineAsmRegClass {
                 Self::Mips(MipsInlineAsmRegClass::parse(name)?)
             }
             InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
+                Self::Sparc(SparcInlineAsmRegClass::parse(name)?)
+            }
             InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?),
             InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
                 Self::Wasm(WasmInlineAsmRegClass::parse(name)?)
@@ -658,6 +682,7 @@ impl InlineAsmRegClass {
             Self::LoongArch(r) => r.valid_modifiers(arch),
             Self::Mips(r) => r.valid_modifiers(arch),
             Self::S390x(r) => r.valid_modifiers(arch),
+            Self::Sparc(r) => r.valid_modifiers(arch),
             Self::SpirV(r) => r.valid_modifiers(arch),
             Self::Wasm(r) => r.valid_modifiers(arch),
             Self::Bpf(r) => r.valid_modifiers(arch),
@@ -843,6 +868,11 @@ pub fn allocatable_registers(
             s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
+        InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
+            let mut map = sparc::regclass_map();
+            sparc::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
+            map
+        }
         InlineAsmArch::SpirV => {
             let mut map = spirv::regclass_map();
             spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
@@ -1128,6 +1158,21 @@ impl InlineAsmClobberAbi {
             },
             InlineAsmClobberAbi::PowerPC => clobbered_regs! {
                 PowerPC PowerPCInlineAsmReg {
+                    // Refs:
+                    // - PPC32 SysV: "3.2. Function Calling Sequence" in Power Architecture® 32-bit Application Binary Interface Supplement 1.0 - Linux® & Embedded
+                    //   https://web.archive.org/web/20120608163804/https://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf
+                    // - PPC64 ELFv1: "3.2. Function Calling Sequence" in 64-bit PowerPC ELF Application Binary Interface Supplement 1.9
+                    //   https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-CALL
+                    // - PPC64 ELFv2: "2.2 Function Calling Sequence" in 64-Bit ELF V2 ABI Specification: Power Architecture, Revision 1.5
+                    //   https://openpowerfoundation.org/specifications/64bitelfabi/
+                    // - AIX:
+                    //   - Register usage and conventions
+                    //     https://www.ibm.com/docs/en/aix/7.3?topic=overview-register-usage-conventions
+                    //   - Special registers in the PowerPC®
+                    //     https://www.ibm.com/docs/en/aix/7.3?topic=overview-special-registers-in-powerpc
+                    //   - AIX vector programming
+                    //     https://www.ibm.com/docs/en/aix/7.3?topic=concepts-aix-vector-programming
+
                     // r0, r3-r12
                     r0,
                     r3, r4, r5, r6, r7,
@@ -1138,8 +1183,6 @@ impl InlineAsmClobberAbi {
                     f8, f9, f10, f11, f12, f13,
 
                     // v0-v19
-                    // FIXME: PPC32 SysV ABI does not mention vector registers processing.
-                    // https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
                     v0, v1, v2, v3, v4, v5, v6, v7,
                     v8, v9, v10, v11, v12, v13, v14,
                     v15, v16, v17, v18, v19,
diff --git a/compiler/rustc_target/src/asm/sparc.rs b/compiler/rustc_target/src/asm/sparc.rs
new file mode 100644
index 00000000000..6261708642b
--- /dev/null
+++ b/compiler/rustc_target/src/asm/sparc.rs
@@ -0,0 +1,138 @@
+use std::fmt;
+
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+use crate::spec::{RelocModel, Target};
+
+def_reg_class! {
+    Sparc SparcInlineAsmRegClass {
+        reg,
+        yreg,
+    }
+}
+
+impl SparcInlineAsmRegClass {
+    pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
+        &[]
+    }
+
+    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+        None
+    }
+
+    pub fn suggest_modifier(
+        self,
+        _arch: InlineAsmArch,
+        _ty: InlineAsmType,
+    ) -> Option<ModifierInfo> {
+        None
+    }
+
+    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
+        None
+    }
+
+    pub fn supported_types(
+        self,
+        arch: InlineAsmArch,
+    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
+        match self {
+            Self::reg => {
+                if arch == InlineAsmArch::Sparc {
+                    types! {
+                        _: I8, I16, I32;
+                        // FIXME: i64 is ok for g*/o* registers on SPARC-V8+ ("h" constraint in GCC),
+                        //        but not yet supported in LLVM.
+                        // v8plus: I64;
+                    }
+                } else {
+                    types! { _: I8, I16, I32, I64; }
+                }
+            }
+            Self::yreg => &[],
+        }
+    }
+}
+
+fn reserved_g5(
+    arch: InlineAsmArch,
+    _reloc_model: RelocModel,
+    _target_features: &FxIndexSet<Symbol>,
+    _target: &Target,
+    _is_clobber: bool,
+) -> Result<(), &'static str> {
+    if arch == InlineAsmArch::Sparc {
+        // FIXME: Section 2.1.5 "Function Registers with Unassigned Roles" of the V8+ Technical
+        // Specification says "%g5; no longer reserved for system software" [1], but LLVM always
+        // reserves it on SPARC32 [2].
+        // [1]: https://temlib.org/pub/SparcStation/Standards/V8plus.pdf
+        // [2]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L64-L66
+        Err("g5 is reserved for system on SPARC32")
+    } else {
+        Ok(())
+    }
+}
+
+def_regs! {
+    Sparc SparcInlineAsmReg SparcInlineAsmRegClass {
+        // FIXME:
+        // - LLVM has reserve-{g,o,l,i}N feature to reserve each general-purpose registers.
+        // - g2-g4 are reserved for application (optional in both LLVM and GCC, and GCC has -mno-app-regs option to reserve them).
+        // There are currently no builtin targets that use them, but in the future they may need to
+        // be supported via options similar to AArch64's -Z fixed-x18.
+        r2: reg = ["r2", "g2"], // % reserved_g2
+        r3: reg = ["r3", "g3"], // % reserved_g3
+        r4: reg = ["r4", "g4"], // % reserved_g4
+        r5: reg = ["r5", "g5"] % reserved_g5,
+        r8: reg = ["r8", "o0"], // % reserved_o0
+        r9: reg = ["r9", "o1"], // % reserved_o1
+        r10: reg = ["r10", "o2"], // % reserved_o2
+        r11: reg = ["r11", "o3"], // % reserved_o3
+        r12: reg = ["r12", "o4"], // % reserved_o4
+        r13: reg = ["r13", "o5"], // % reserved_o5
+        r15: reg = ["r15", "o7"], // % reserved_o7
+        r16: reg = ["r16", "l0"], // % reserved_l0
+        r17: reg = ["r17", "l1"], // % reserved_l1
+        r18: reg = ["r18", "l2"], // % reserved_l2
+        r19: reg = ["r19", "l3"], // % reserved_l3
+        r20: reg = ["r20", "l4"], // % reserved_l4
+        r21: reg = ["r21", "l5"], // % reserved_l5
+        r22: reg = ["r22", "l6"], // % reserved_l6
+        r23: reg = ["r23", "l7"], // % reserved_l7
+        r24: reg = ["r24", "i0"], // % reserved_i0
+        r25: reg = ["r25", "i1"], // % reserved_i1
+        r26: reg = ["r26", "i2"], // % reserved_i2
+        r27: reg = ["r27", "i3"], // % reserved_i3
+        r28: reg = ["r28", "i4"], // % reserved_i4
+        r29: reg = ["r29", "i5"], // % reserved_i5
+        y: yreg = ["y"],
+        #error = ["r0", "g0"] =>
+            "g0 is always zero and cannot be used as an operand for inline asm",
+        // FIXME: %g1 is volatile in ABI, but used internally by LLVM.
+        // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L55-L56
+        // > FIXME: G1 reserved for now for large imm generation by frame code.
+        #error = ["r1", "g1"] =>
+            "reserved by LLVM and cannot be used as an operand for inline asm",
+        #error = ["r6", "g6", "r7", "g7"] =>
+            "reserved for system and cannot be used as an operand for inline asm",
+        #error = ["sp", "r14", "o6"] =>
+            "the stack pointer cannot be used as an operand for inline asm",
+        #error = ["fp", "r30", "i6"] =>
+            "the frame pointer cannot be used as an operand for inline asm",
+        #error = ["r31", "i7"] =>
+            "the return address register cannot be used as an operand for inline asm",
+    }
+}
+
+impl SparcInlineAsmReg {
+    pub fn emit(
+        self,
+        out: &mut dyn fmt::Write,
+        _arch: InlineAsmArch,
+        _modifier: Option<char>,
+    ) -> fmt::Result {
+        write!(out, "%{}", self.name())
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
index e83a43c1df2..b7415bf683d 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
             std: None, // ?
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64".into(),
         options: TargetOptions {
             abi: "abi64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
index 252d614e9ac..75da4abc6b6 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64".into(),
         options: TargetOptions {
             abi: "abi64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
index a1a596c9f1b..69af2da1100 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64".into(),
         options: TargetOptions {
             abi: "abi64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
index 35d2911fa9d..c7d24871225 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64".into(),
         options: TargetOptions {
             abi: "abi64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
index 9dab932aed4..4f50e8b7033 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64".into(),
         options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base },
     }
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
index 89ba7b889ec..c5948b745ff 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
             std: None, // ?
         },
         pointer_width: 64,
-        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64r6".into(),
         options: TargetOptions {
             abi: "abi64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
index 195894d9aac..60bda7a5996 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
             std: Some(true),
         },
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "mips64r6".into(),
         options: TargetOptions {
             abi: "abi64".into(),
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 86072a6dd60..e29ed9a4b56 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -19,8 +19,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
 rustc_parse_format = { path = "../rustc_parse_format" }
-rustc_query_system = { path = "../rustc_query_system" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index a1c97a38567..1109b11d2a7 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1707,15 +1707,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // one crate version and the type comes from another crate version, even though they both
         // are from the same crate.
         let trait_def_id = trait_ref.def_id();
-        if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind()
-            && let found_type = def.did()
-            && trait_def_id.krate != found_type.krate
-            && self.tcx.crate_name(trait_def_id.krate) == self.tcx.crate_name(found_type.krate)
-        {
-            let name = self.tcx.crate_name(trait_def_id.krate);
-            let spans: Vec<_> = [trait_def_id, found_type]
-                .into_iter()
-                .filter(|def_id| def_id.krate != LOCAL_CRATE)
+        let trait_name = self.tcx.item_name(trait_def_id);
+        let crate_name = self.tcx.crate_name(trait_def_id.krate);
+        if let Some(other_trait_def_id) = self.tcx.all_traits().find(|def_id| {
+            trait_name == self.tcx.item_name(trait_def_id)
+                && trait_def_id.krate != def_id.krate
+                && crate_name == self.tcx.crate_name(def_id.krate)
+        }) {
+            // We've found two different traits with the same name, same crate name, but
+            // different crate `DefId`. We highlight the traits.
+
+            let found_type =
+                if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind() {
+                    Some(def.did())
+                } else {
+                    None
+                };
+            let candidates = if impl_candidates.is_empty() {
+                alternative_candidates(trait_def_id)
+            } else {
+                impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
+            };
+            let mut span: MultiSpan = self.tcx.def_span(trait_def_id).into();
+            span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
+            for (sp, label) in [trait_def_id, other_trait_def_id]
+                .iter()
                 .filter_map(|def_id| self.tcx.extern_crate(def_id.krate))
                 .map(|data| {
                     let dependency = if data.dependency_of == LOCAL_CRATE {
@@ -1726,57 +1742,86 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     };
                     (
                         data.span,
-                        format!("one version of crate `{name}` is used here, as a {dependency}"),
+                        format!(
+                            "one version of crate `{crate_name}` is used here, as a {dependency}"
+                        ),
                     )
                 })
-                .collect();
-            let mut span: MultiSpan = spans.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
-            for (sp, label) in spans.into_iter() {
+            {
                 span.push_span_label(sp, label);
             }
-            err.highlighted_span_help(span, vec![
+            let mut points_at_type = false;
+            if let Some(found_type) = found_type {
+                span.push_span_label(
+                    self.tcx.def_span(found_type),
+                    "this type doesn't implement the required trait",
+                );
+                for trait_ref in candidates {
+                    if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
+                        && let candidate_def_id = def.did()
+                        && let Some(name) = self.tcx.opt_item_name(candidate_def_id)
+                        && let Some(found) = self.tcx.opt_item_name(found_type)
+                        && name == found
+                        && candidate_def_id.krate != found_type.krate
+                        && self.tcx.crate_name(candidate_def_id.krate)
+                            == self.tcx.crate_name(found_type.krate)
+                    {
+                        // A candidate was found of an item with the same name, from two separate
+                        // versions of the same crate, let's clarify.
+                        let candidate_span = self.tcx.def_span(candidate_def_id);
+                        span.push_span_label(
+                            candidate_span,
+                            "this type implements the required trait",
+                        );
+                        points_at_type = true;
+                    }
+                }
+            }
+            span.push_span_label(self.tcx.def_span(other_trait_def_id), "this is the found trait");
+            err.highlighted_span_note(span, vec![
                 StringPart::normal("there are ".to_string()),
                 StringPart::highlighted("multiple different versions".to_string()),
                 StringPart::normal(" of crate `".to_string()),
-                StringPart::highlighted(format!("{name}")),
-                StringPart::normal("` in the dependency graph".to_string()),
+                StringPart::highlighted(format!("{crate_name}")),
+                StringPart::normal("` in the dependency graph\n".to_string()),
             ]);
-            let candidates = if impl_candidates.is_empty() {
-                alternative_candidates(trait_def_id)
-            } else {
-                impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
-            };
-            if let Some((sp_candidate, sp_found)) = candidates.iter().find_map(|trait_ref| {
-                if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
-                    && let candidate_def_id = def.did()
-                    && let Some(name) = self.tcx.opt_item_name(candidate_def_id)
-                    && let Some(found) = self.tcx.opt_item_name(found_type)
-                    && name == found
-                    && candidate_def_id.krate != found_type.krate
-                    && self.tcx.crate_name(candidate_def_id.krate)
-                        == self.tcx.crate_name(found_type.krate)
-                {
-                    // A candidate was found of an item with the same name, from two separate
-                    // versions of the same crate, let's clarify.
-                    Some((self.tcx.def_span(candidate_def_id), self.tcx.def_span(found_type)))
-                } else {
-                    None
-                }
-            }) {
-                let mut span: MultiSpan = vec![sp_candidate, sp_found].into();
-                span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
-                span.push_span_label(sp_candidate, "this type implements the required trait");
-                span.push_span_label(sp_found, "this type doesn't implement the required trait");
-                err.highlighted_span_note(span, vec![
+            if points_at_type {
+                // We only clarify that the same type from different crate versions are not the
+                // same when we *find* the same type coming from different crate versions, otherwise
+                // it could be that it was a type provided by a different crate than the one that
+                // provides the trait, and mentioning this adds verbosity without clarification.
+                err.highlighted_note(vec![
                     StringPart::normal(
                         "two types coming from two different versions of the same crate are \
-                             different types "
+                         different types "
                             .to_string(),
                     ),
                     StringPart::highlighted("even if they look the same".to_string()),
                 ]);
             }
-            err.help("you can use `cargo tree` to explore your dependency tree");
+            err.highlighted_help(vec![
+                StringPart::normal("you can use `".to_string()),
+                StringPart::highlighted("cargo tree".to_string()),
+                StringPart::normal("` to explore your dependency tree".to_string()),
+            ]);
+
+            // FIXME: this is a giant hack for the benefit of this specific diagnostic. Because
+            // we're so nested in method calls before the error gets emitted, bubbling a single bit
+            // flag informing the top level caller to stop adding extra detail to the diagnostic,
+            // would actually be harder to follow. So we do something naughty here: we consume the
+            // diagnostic, emit it and leave in its place a "delayed bug" that will continue being
+            // modified but won't actually be printed to end users. This *is not ideal*, but allows
+            // us to reduce the verbosity of an error that is already quite verbose and increase its
+            // specificity. Below we modify the main message as well, in a way that *could* break if
+            // the implementation of Diagnostics change significantly, but that would be caught with
+            // a make test failure when this diagnostic is tested.
+            err.primary_message(format!(
+                "{} because the trait comes from a different crate version",
+                err.messages[0].0.as_str().unwrap(),
+            ));
+            let diag = err.clone();
+            err.downgrade_to_delayed_bug();
+            self.tcx.dcx().emit_diagnostic(diag);
             return true;
         }
 
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 0838978a891..0184e93acf1 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -463,43 +463,64 @@ fn fn_abi_sanity_check<'tcx>(
         arg: &ArgAbi<'tcx, Ty<'tcx>>,
     ) {
         let tcx = cx.tcx();
+
+        if spec_abi == ExternAbi::Rust
+            || spec_abi == ExternAbi::RustCall
+            || spec_abi == ExternAbi::RustCold
+        {
+            if arg.layout.is_zst() {
+                // Casting closures to function pointers depends on ZST closure types being
+                // omitted entirely in the calling convention.
+                assert!(arg.is_ignore());
+            }
+            if let PassMode::Indirect { on_stack, .. } = arg.mode {
+                assert!(!on_stack, "rust abi shouldn't use on_stack");
+            }
+        }
+
         match &arg.mode {
-            PassMode::Ignore => {}
+            PassMode::Ignore => {
+                assert!(arg.layout.is_zst() || arg.layout.is_uninhabited());
+            }
             PassMode::Direct(_) => {
                 // Here the Rust type is used to determine the actual ABI, so we have to be very
-                // careful. Scalar/ScalarPair is fine, since backends will generally use
-                // `layout.abi` and ignore everything else. We should just reject `Aggregate`
-                // entirely here, but some targets need to be fixed first.
-                if matches!(arg.layout.backend_repr, BackendRepr::Memory { .. }) {
-                    // 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!(
-                        arg.layout.is_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 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 unstable abi `PtxKernel` also uses Direct for now.
-                    // It needs to switch to something else before stabilization can happen.
-                    // (See issue: https://github.com/rust-lang/rust/issues/117271)
-                    assert!(
-                        matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64")
-                            || matches!(spec_abi, ExternAbi::PtxKernel | ExternAbi::Unadjusted),
-                        "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\
+                // careful. Scalar/Vector is fine, since backends will generally use
+                // `layout.backend_repr` and ignore everything else. We should just reject
+                //`Aggregate` entirely here, but some targets need to be fixed first.
+                match arg.layout.backend_repr {
+                    BackendRepr::Uninhabited
+                    | BackendRepr::Scalar(_)
+                    | BackendRepr::Vector { .. } => {}
+                    BackendRepr::ScalarPair(..) => {
+                        panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty)
+                    }
+                    BackendRepr::Memory { sized } => {
+                        // 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 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 unstable abi `PtxKernel` also uses Direct for now.
+                        // It needs to switch to something else before stabilization can happen.
+                        // (See issue: https://github.com/rust-lang/rust/issues/117271)
+                        assert!(
+                            matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64")
+                                || matches!(spec_abi, ExternAbi::PtxKernel | ExternAbi::Unadjusted),
+                            "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\
                           Problematic type: {:#?}",
-                        arg.layout,
-                    );
+                            arg.layout,
+                        );
+                    }
                 }
             }
             PassMode::Pair(_, _) => {
-                // Similar to `Direct`, we need to make sure that backends use `layout.abi` and
-                // ignore the rest of the layout.
+                // Similar to `Direct`, we need to make sure that backends use `layout.backend_repr`
+                // and ignore the rest of the layout.
                 assert!(
                     matches!(arg.layout.backend_repr, BackendRepr::ScalarPair(..)),
                     "PassMode::Pair for type {}",
diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs
index 4b7707ebccf..a6f7c254583 100644
--- a/compiler/stable_mir/src/compiler_interface.rs
+++ b/compiler/stable_mir/src/compiler_interface.rs
@@ -34,6 +34,12 @@ pub trait Context {
     /// Check whether the body of a function is available.
     fn has_body(&self, item: DefId) -> bool;
     fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>;
+
+    /// Retrieve all functions defined in this crate.
+    fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef>;
+
+    /// Retrieve all static items defined in this crate.
+    fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef>;
     fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule;
     fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>;
     fn all_trait_decls(&self) -> TraitDecls;
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index b523e949cde..0b4cebadad1 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -25,8 +25,9 @@ use serde::Serialize;
 use crate::compiler_interface::with;
 pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
 pub use crate::error::*;
+use crate::mir::mono::StaticDef;
 use crate::mir::{Body, Mutability};
-use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
+use crate::ty::{FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
 
 pub mod abi;
 #[macro_use]
@@ -96,6 +97,16 @@ impl Crate {
     pub fn trait_impls(&self) -> ImplTraitDecls {
         with(|cx| cx.trait_impls(self.id))
     }
+
+    /// Return a list of function definitions from this crate independent on their visibility.
+    pub fn fn_defs(&self) -> Vec<FnDef> {
+        with(|cx| cx.crate_functions(self.id))
+    }
+
+    /// Return a list of static items defined in this crate independent on their visibility.
+    pub fn statics(&self) -> Vec<StaticDef> {
+        with(|cx| cx.crate_statics(self.id))
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)]
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 13e3d229d06..01a50d46b2d 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -1,13 +1,14 @@
+//! Implement methods to pretty print stable MIR body.
 use std::fmt::Debug;
 use std::io::Write;
 use std::{fmt, io, iter};
 
 use fmt::{Display, Formatter};
 
-use super::{AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind};
+use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind};
 use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents};
-use crate::ty::{IndexedVal, MirConst, Ty, TyConst};
-use crate::{Body, Mutability, with};
+use crate::ty::{AdtKind, IndexedVal, MirConst, Ty, TyConst};
+use crate::{Body, CrateDef, Mutability, with};
 
 impl Display for Ty {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
@@ -23,10 +24,11 @@ impl Debug for Place {
 
 pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -> io::Result<()> {
     write!(writer, "fn {name}(")?;
-    body.arg_locals()
-        .iter()
-        .enumerate()
-        .try_for_each(|(index, local)| write!(writer, "_{}: {}", index + 1, local.ty))?;
+    let mut sep = "";
+    for (index, local) in body.arg_locals().iter().enumerate() {
+        write!(writer, "{}_{}: {}", sep, index + 1, local.ty)?;
+        sep = ", ";
+    }
     write!(writer, ")")?;
 
     let return_local = body.ret_local();
@@ -73,39 +75,40 @@ pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -
 }
 
 fn pretty_statement<W: Write>(writer: &mut W, statement: &StatementKind) -> io::Result<()> {
+    const INDENT: &str = "        ";
     match statement {
         StatementKind::Assign(place, rval) => {
-            write!(writer, "        {place:?} = ")?;
+            write!(writer, "{INDENT}{place:?} = ")?;
             pretty_rvalue(writer, rval)?;
             writeln!(writer, ";")
         }
         // FIXME: Add rest of the statements
         StatementKind::FakeRead(cause, place) => {
-            writeln!(writer, "FakeRead({cause:?}, {place:?});")
+            writeln!(writer, "{INDENT}FakeRead({cause:?}, {place:?});")
         }
         StatementKind::SetDiscriminant { place, variant_index } => {
-            writeln!(writer, "discriminant({place:?} = {};", variant_index.to_index())
+            writeln!(writer, "{INDENT}discriminant({place:?} = {};", variant_index.to_index())
         }
         StatementKind::Deinit(place) => writeln!(writer, "Deinit({place:?};"),
         StatementKind::StorageLive(local) => {
-            writeln!(writer, "StorageLive(_{local});")
+            writeln!(writer, "{INDENT}StorageLive(_{local});")
         }
         StatementKind::StorageDead(local) => {
-            writeln!(writer, "StorageDead(_{local});")
+            writeln!(writer, "{INDENT}StorageDead(_{local});")
         }
         StatementKind::Retag(kind, place) => writeln!(writer, "Retag({kind:?}, {place:?});"),
         StatementKind::PlaceMention(place) => {
-            writeln!(writer, "PlaceMention({place:?};")
+            writeln!(writer, "{INDENT}PlaceMention({place:?};")
         }
         StatementKind::ConstEvalCounter => {
-            writeln!(writer, "ConstEvalCounter;")
+            writeln!(writer, "{INDENT}ConstEvalCounter;")
         }
-        StatementKind::Nop => writeln!(writer, "nop;"),
+        StatementKind::Nop => writeln!(writer, "{INDENT}nop;"),
         StatementKind::AscribeUserType { .. }
         | StatementKind::Coverage(_)
         | StatementKind::Intrinsic(_) => {
             // FIX-ME: Make them pretty.
-            writeln!(writer, "{statement:?};")
+            writeln!(writer, "{INDENT}{statement:?};")
         }
     }
 }
@@ -322,15 +325,11 @@ fn pretty_ty_const(ct: &TyConst) -> String {
 fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
     match rval {
         Rvalue::AddressOf(mutability, place) => {
-            write!(writer, "&raw {}(*{:?})", pretty_mut(*mutability), place)
+            write!(writer, "&raw {} {:?}", pretty_mut(*mutability), place)
         }
         Rvalue::Aggregate(aggregate_kind, operands) => {
             // FIXME: Add pretty_aggregate function that returns a pretty string
-            write!(writer, "{aggregate_kind:?} (")?;
-            let mut op_iter = operands.iter();
-            op_iter.next().map_or(Ok(()), |op| write!(writer, "{}", pretty_operand(op)))?;
-            op_iter.try_for_each(|op| write!(writer, ", {}", pretty_operand(op)))?;
-            write!(writer, ")")
+            pretty_aggregate(writer, aggregate_kind, operands)
         }
         Rvalue::BinaryOp(bin, op1, op2) => {
             write!(writer, "{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2))
@@ -360,22 +359,74 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
             write!(writer, "{kind}{place:?}")
         }
         Rvalue::Repeat(op, cnst) => {
-            write!(writer, "{} \" \" {}", pretty_operand(op), pretty_ty_const(cnst))
+            write!(writer, "[{}; {}]", pretty_operand(op), pretty_ty_const(cnst))
         }
         Rvalue::ShallowInitBox(_, _) => Ok(()),
         Rvalue::ThreadLocalRef(item) => {
             write!(writer, "thread_local_ref{item:?}")
         }
         Rvalue::NullaryOp(nul, ty) => {
-            write!(writer, "{nul:?} {ty} \" \"")
+            write!(writer, "{nul:?}::<{ty}>() \" \"")
         }
         Rvalue::UnaryOp(un, op) => {
-            write!(writer, "{} \" \" {:?}", pretty_operand(op), un)
+            write!(writer, "{:?}({})", un, pretty_operand(op))
         }
         Rvalue::Use(op) => write!(writer, "{}", pretty_operand(op)),
     }
 }
 
+fn pretty_aggregate<W: Write>(
+    writer: &mut W,
+    aggregate_kind: &AggregateKind,
+    operands: &Vec<Operand>,
+) -> io::Result<()> {
+    let suffix = match aggregate_kind {
+        AggregateKind::Array(_) => {
+            write!(writer, "[")?;
+            "]"
+        }
+        AggregateKind::Tuple => {
+            write!(writer, "(")?;
+            ")"
+        }
+        AggregateKind::Adt(def, var, _, _, _) => {
+            if def.kind() == AdtKind::Enum {
+                write!(writer, "{}::{}", def.name(), def.variant(*var).unwrap().name())?;
+            } else {
+                write!(writer, "{}", def.variant(*var).unwrap().name())?;
+            }
+            if operands.is_empty() {
+                return Ok(());
+            }
+            // FIXME: Change this once we have CtorKind in StableMIR.
+            write!(writer, "(")?;
+            ")"
+        }
+        AggregateKind::Closure(def, _) => {
+            write!(writer, "{{closure@{}}}(", def.span().diagnostic())?;
+            ")"
+        }
+        AggregateKind::Coroutine(def, _, _) => {
+            write!(writer, "{{coroutine@{}}}(", def.span().diagnostic())?;
+            ")"
+        }
+        AggregateKind::RawPtr(ty, mutability) => {
+            write!(
+                writer,
+                "*{} {ty} from (",
+                if *mutability == Mutability::Mut { "mut" } else { "const" }
+            )?;
+            ")"
+        }
+    };
+    let mut separator = "";
+    for op in operands {
+        write!(writer, "{}{}", separator, pretty_operand(op))?;
+        separator = ", ";
+    }
+    write!(writer, "{suffix}")
+}
+
 fn pretty_mut(mutability: Mutability) -> &'static str {
     match mutability {
         Mutability::Not => " ",
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 8db1258b65f..9ce72f155f9 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -271,6 +271,14 @@ impl Span {
     pub fn get_lines(&self) -> LineInfo {
         with(|c| c.get_lines(self))
     }
+
+    /// Return the span location to be printed in diagnostic messages.
+    ///
+    /// This may leak local file paths and should not be used to build artifacts that may be
+    /// distributed.
+    pub fn diagnostic(&self) -> String {
+        with(|c| c.span_to_string(*self))
+    }
 }
 
 #[derive(Clone, Copy, Debug, Serialize)]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics/mod.rs
index d33a403cfda..b6e22c42eee 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -904,38 +904,6 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
 
-    /// Magic intrinsic that derives its meaning from attributes
-    /// attached to the function.
-    ///
-    /// For example, dataflow uses this to inject static assertions so
-    /// that `rustc_peek(potentially_uninitialized)` would actually
-    /// double-check that dataflow did indeed compute that it is
-    /// uninitialized at that point in the control flow.
-    ///
-    /// This intrinsic should not be used outside of the compiler.
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn rustc_peek<T>(_: T) -> T;
-
-    /// Aborts the execution of the process.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible,
-    /// as its behavior is more user-friendly and more stable.
-    ///
-    /// The current implementation of `intrinsics::abort` is to invoke an invalid instruction,
-    /// on most platforms.
-    /// On Unix, the
-    /// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
-    /// `SIGBUS`.  The precise behavior is not guaranteed and not stable.
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn abort() -> !;
-
     /// Executes a breakpoint trap, for inspection by a debugger.
     ///
     /// This intrinsic does not have a stable counterpart.
@@ -943,6 +911,44 @@ extern "rust-intrinsic" {
     pub fn breakpoint();
 }
 
+/// Magic intrinsic that derives its meaning from attributes
+/// attached to the function.
+///
+/// For example, dataflow uses this to inject static assertions so
+/// that `rustc_peek(potentially_uninitialized)` would actually
+/// double-check that dataflow did indeed compute that it is
+/// uninitialized at that point in the control flow.
+///
+/// This intrinsic should not be used outside of the compiler.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn rustc_peek<T>(_: T) -> T {
+    unreachable!()
+}
+
+/// Aborts the execution of the process.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible,
+/// as its behavior is more user-friendly and more stable.
+///
+/// The current implementation of `intrinsics::abort` is to invoke an invalid instruction,
+/// on most platforms.
+/// On Unix, the
+/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
+/// `SIGBUS`.  The precise behavior is not guaranteed and not stable.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn abort() -> ! {
+    unreachable!()
+}
+
 /// Informs the optimizer that this point in the code is not reachable,
 /// enabling further optimizations.
 ///
@@ -1512,19 +1518,22 @@ pub const unsafe fn arith_offset<T>(_dst: *const T, _offset: isize) -> *const T
     unreachable!()
 }
 
-extern "rust-intrinsic" {
-    /// Masks out bits of the pointer according to a mask.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// Consider using [`pointer::mask`] instead.
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T;
+/// Masks out bits of the pointer according to a mask.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// Consider using [`pointer::mask`] instead.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn ptr_mask<T>(_ptr: *const T, _mask: usize) -> *const T {
+    unreachable!()
+}
 
+extern "rust-intrinsic" {
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
     /// a size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
@@ -2140,47 +2149,62 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn frem_fast<T: Copy>(a: T, b: T) -> T;
 
-    /// Float addition that allows optimizations based on algebraic rules.
+    /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range
+    /// (<https://github.com/rust-lang/rust/issues/10184>)
     ///
-    /// This intrinsic does not have a stable counterpart.
+    /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
     #[rustc_nounwind]
-    #[rustc_safe_intrinsic]
-    pub fn fadd_algebraic<T: Copy>(a: T, b: T) -> T;
+    pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+}
 
-    /// Float subtraction that allows optimizations based on algebraic rules.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    #[rustc_safe_intrinsic]
-    pub fn fsub_algebraic<T: Copy>(a: T, b: T) -> T;
+/// Float addition that allows optimizations based on algebraic rules.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn fadd_algebraic<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
 
-    /// Float multiplication that allows optimizations based on algebraic rules.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    #[rustc_safe_intrinsic]
-    pub fn fmul_algebraic<T: Copy>(a: T, b: T) -> T;
+/// Float subtraction that allows optimizations based on algebraic rules.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn fsub_algebraic<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
 
-    /// Float division that allows optimizations based on algebraic rules.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    #[rustc_safe_intrinsic]
-    pub fn fdiv_algebraic<T: Copy>(a: T, b: T) -> T;
+/// Float multiplication that allows optimizations based on algebraic rules.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn fmul_algebraic<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
 
-    /// Float remainder that allows optimizations based on algebraic rules.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    #[rustc_safe_intrinsic]
-    pub fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
+/// Float division that allows optimizations based on algebraic rules.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn fdiv_algebraic<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
 
-    /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range
-    /// (<https://github.com/rust-lang/rust/issues/10184>)
-    ///
-    /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
-    #[rustc_nounwind]
-    pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+/// Float remainder that allows optimizations based on algebraic rules.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn frem_algebraic<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
 }
 
 /// Returns the number of bits set in an integer type `T`
diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs
index 7051c051bf7..cbcf9f96239 100644
--- a/library/std/src/f128/tests.rs
+++ b/library/std/src/f128/tests.rs
@@ -2,7 +2,10 @@
 #![cfg(reliable_f128)]
 
 use crate::f128::consts;
-use crate::num::{FpCategory as Fp, *};
+use crate::num::FpCategory as Fp;
+#[cfg(reliable_f128_math)]
+use crate::ops::Rem;
+use crate::ops::{Add, Div, Mul, Sub};
 
 // Note these tolerances make sense around zero, but not for more extreme exponents.
 
@@ -53,7 +56,22 @@ macro_rules! assert_f128_biteq {
 
 #[test]
 fn test_num_f128() {
-    test_num(10f128, 2f128);
+    // FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128`
+    // function is available on all platforms.
+    let ten = 10f128;
+    let two = 2f128;
+    assert_eq!(ten.add(two), ten + two);
+    assert_eq!(ten.sub(two), ten - two);
+    assert_eq!(ten.mul(two), ten * two);
+    assert_eq!(ten.div(two), ten / two);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_num_f128_rem() {
+    let ten = 10f128;
+    let two = 2f128;
+    assert_eq!(ten.rem(two), ten % two);
 }
 
 #[test]
diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs
index 88a8c75f7c8..523e6d2f3bb 100644
--- a/library/std/src/sync/mpmc/list.rs
+++ b/library/std/src/sync/mpmc/list.rs
@@ -63,14 +63,14 @@ struct Block<T> {
 
 impl<T> Block<T> {
     /// Creates an empty block.
-    fn new() -> Block<T> {
+    fn new() -> Box<Block<T>> {
         // SAFETY: This is safe because:
         //  [1] `Block::next` (AtomicPtr) may be safely zero initialized.
         //  [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4].
         //  [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it
         //       holds a MaybeUninit.
         //  [4] `Slot::state` (AtomicUsize) may be safely zero initialized.
-        unsafe { MaybeUninit::zeroed().assume_init() }
+        unsafe { Box::new_zeroed().assume_init() }
     }
 
     /// Waits until the next pointer is set.
@@ -199,13 +199,13 @@ impl<T> Channel<T> {
             // If we're going to have to install the next block, allocate it in advance in order to
             // make the wait for other threads as short as possible.
             if offset + 1 == BLOCK_CAP && next_block.is_none() {
-                next_block = Some(Box::new(Block::<T>::new()));
+                next_block = Some(Block::<T>::new());
             }
 
             // If this is the first message to be sent into the channel, we need to allocate the
             // first block and install it.
             if block.is_null() {
-                let new = Box::into_raw(Box::new(Block::<T>::new()));
+                let new = Box::into_raw(Block::<T>::new());
 
                 if self
                     .tail
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index e9ec79e417b..409a644b9be 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -33,7 +33,7 @@ fn main() {
         // Display PID of process holding the lock
         // PID will be stored in a lock file
         let lock_path = config.out.join("lock");
-        let pid = fs::read_to_string(&lock_path).unwrap_or_default();
+        let pid = fs::read_to_string(&lock_path);
 
         build_lock = fd_lock::RwLock::new(t!(fs::OpenOptions::new()
             .write(true)
@@ -47,7 +47,11 @@ fn main() {
             }
             err => {
                 drop(err);
-                println!("WARNING: build directory locked by process {pid}, waiting for lock");
+                if let Ok(pid) = pid {
+                    println!("WARNING: build directory locked by process {pid}, waiting for lock");
+                } else {
+                    println!("WARNING: build directory locked, waiting for lock");
+                }
                 let mut lock = t!(build_lock.write());
                 t!(lock.write(process::id().to_string().as_ref()));
                 lock
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index bcce2748c2e..2c36d8bab82 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1938,9 +1938,13 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
 
         cmd.arg("--json");
 
-        if builder.config.rust_debug_assertions_std {
-            cmd.arg("--with-debug-assertions");
-        };
+        if builder.config.rustc_debug_assertions {
+            cmd.arg("--with-rustc-debug-assertions");
+        }
+
+        if builder.config.std_debug_assertions {
+            cmd.arg("--with-std-debug-assertions");
+        }
 
         let mut llvm_components_passed = false;
         let mut copts_passed = false;
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index c3d0994f164..134da5db96d 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -833,9 +833,9 @@ impl Builder<'_> {
         cargo.env(
             profile_var("DEBUG_ASSERTIONS"),
             if mode == Mode::Std {
-                self.config.rust_debug_assertions_std.to_string()
+                self.config.std_debug_assertions.to_string()
             } else {
-                self.config.rust_debug_assertions.to_string()
+                self.config.rustc_debug_assertions.to_string()
             },
         );
         cargo.env(
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 8115aea033d..f977c285a74 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -263,8 +263,10 @@ pub struct Config {
     pub rust_optimize: RustOptimize,
     pub rust_codegen_units: Option<u32>,
     pub rust_codegen_units_std: Option<u32>,
-    pub rust_debug_assertions: bool,
-    pub rust_debug_assertions_std: bool,
+
+    pub rustc_debug_assertions: bool,
+    pub std_debug_assertions: bool,
+
     pub rust_overflow_checks: bool,
     pub rust_overflow_checks_std: bool,
     pub rust_debug_logging: bool,
@@ -1115,9 +1117,9 @@ define_config! {
         debug: Option<bool> = "debug",
         codegen_units: Option<u32> = "codegen-units",
         codegen_units_std: Option<u32> = "codegen-units-std",
-        debug_assertions: Option<bool> = "debug-assertions",
+        rustc_debug_assertions: Option<bool> = "debug-assertions",
         randomize_layout: Option<bool> = "randomize-layout",
-        debug_assertions_std: Option<bool> = "debug-assertions-std",
+        std_debug_assertions: Option<bool> = "debug-assertions-std",
         overflow_checks: Option<bool> = "overflow-checks",
         overflow_checks_std: Option<bool> = "overflow-checks-std",
         debug_logging: Option<bool> = "debug-logging",
@@ -1652,8 +1654,8 @@ impl Config {
         let mut llvm_offload = None;
         let mut llvm_plugins = None;
         let mut debug = None;
-        let mut debug_assertions = None;
-        let mut debug_assertions_std = None;
+        let mut rustc_debug_assertions = None;
+        let mut std_debug_assertions = None;
         let mut overflow_checks = None;
         let mut overflow_checks_std = None;
         let mut debug_logging = None;
@@ -1675,8 +1677,8 @@ impl Config {
                 debug: debug_toml,
                 codegen_units,
                 codegen_units_std,
-                debug_assertions: debug_assertions_toml,
-                debug_assertions_std: debug_assertions_std_toml,
+                rustc_debug_assertions: rustc_debug_assertions_toml,
+                std_debug_assertions: std_debug_assertions_toml,
                 overflow_checks: overflow_checks_toml,
                 overflow_checks_std: overflow_checks_std_toml,
                 debug_logging: debug_logging_toml,
@@ -1734,8 +1736,8 @@ impl Config {
                 config.download_ci_rustc_commit(download_rustc, config.llvm_assertions);
 
             debug = debug_toml;
-            debug_assertions = debug_assertions_toml;
-            debug_assertions_std = debug_assertions_std_toml;
+            rustc_debug_assertions = rustc_debug_assertions_toml;
+            std_debug_assertions = std_debug_assertions_toml;
             overflow_checks = overflow_checks_toml;
             overflow_checks_std = overflow_checks_std_toml;
             debug_logging = debug_logging_toml;
@@ -2148,14 +2150,13 @@ impl Config {
         config.rust_std_features = std_features.unwrap_or(default_std_features);
 
         let default = debug == Some(true);
-        config.rust_debug_assertions = debug_assertions.unwrap_or(default);
-        config.rust_debug_assertions_std =
-            debug_assertions_std.unwrap_or(config.rust_debug_assertions);
+        config.rustc_debug_assertions = rustc_debug_assertions.unwrap_or(default);
+        config.std_debug_assertions = std_debug_assertions.unwrap_or(config.rustc_debug_assertions);
         config.rust_overflow_checks = overflow_checks.unwrap_or(default);
         config.rust_overflow_checks_std =
             overflow_checks_std.unwrap_or(config.rust_overflow_checks);
 
-        config.rust_debug_logging = debug_logging.unwrap_or(config.rust_debug_assertions);
+        config.rust_debug_logging = debug_logging.unwrap_or(config.rustc_debug_assertions);
 
         let with_defaults = |debuginfo_level_specific: Option<_>| {
             debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
@@ -3075,8 +3076,8 @@ fn check_incompatible_options_for_ci_rustc(
         debug: _,
         codegen_units: _,
         codegen_units_std: _,
-        debug_assertions: _,
-        debug_assertions_std: _,
+        rustc_debug_assertions: _,
+        std_debug_assertions: _,
         overflow_checks: _,
         overflow_checks_std: _,
         debuginfo_level: _,
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 5264f778a93..3029c3989c9 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -20,6 +20,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 - CSKY
 - s390x
 - Arm64EC
+- SPARC
 
 ## Register classes
 
@@ -56,6 +57,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | s390x        | `freg`         | `f[0-15]`                          | `f`                  |
 | s390x        | `vreg`         | `v[0-31]`                          | Only clobbers        |
 | s390x        | `areg`         | `a[2-15]`                          | Only clobbers        |
+| SPARC        | `reg`          | `r[2-29]`                          | `r`                  |
+| SPARC        | `yreg`         | `y`                                | Only clobbers        |
 | Arm64EC      | `reg`          | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r`            |
 | Arm64EC      | `vreg`         | `v[0-15]`                          | `w`                  |
 | Arm64EC      | `vreg_low16`   | `v[0-15]`                          | `x`                  |
@@ -97,6 +100,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | s390x        | `freg`                          | None           | `f32`, `f64`                            |
 | s390x        | `vreg`                          | N/A            | Only clobbers                           |
 | s390x        | `areg`                          | N/A            | Only clobbers                           |
+| SPARC        | `reg`                           | None           | `i8`, `i16`, `i32`, `i64` (SPARC64 only) |
+| SPARC        | `yreg`                          | N/A            | Only clobbers                           |
 | Arm64EC      | `reg`                           | None           | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
 | Arm64EC      | `vreg`                          | None           | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
 
@@ -135,6 +140,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | CSKY         | `r29`         | `rtb`     |
 | CSKY         | `r30`         | `svbr`    |
 | CSKY         | `r31`         | `tls`     |
+| SPARC        | `r[0-7]`      | `g[0-7]`  |
+| SPARC        | `r[8-15]`     | `o[0-7]`  |
+| SPARC        | `r[16-23]`    | `l[0-7]`  |
+| SPARC        | `r[24-31]`    | `i[0-7]`  |
 | Arm64EC      | `x[0-30]`     | `w[0-30]` |
 | Arm64EC      | `x29`         | `fp`      |
 | Arm64EC      | `x30`         | `lr`      |
@@ -150,8 +159,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 
 | Architecture | Unsupported register                    | Reason                                                                                                                                                                              |
 | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| All          | `sp`, `r15` (s390x)                     | The stack pointer must be restored to its original value at the end of an asm code block.                                                                                           |
-| All          | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output.                                                 |
+| All          | `sp`, `r15` (s390x), `r14`/`o6` (SPARC) | The stack pointer must be restored to its original value at the end of an asm code block.                                                                                           |
+| All          | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `r30`/`i6` (SPARC), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output.                             |
 | All          | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames.                                                             |
 | MIPS         | `$0` or `$zero`                         | This is a constant zero register which can't be modified.                                                                                                                           |
 | MIPS         | `$1` or `$at`                           | Reserved for assembler.                                                                                                                                                             |
@@ -174,6 +183,11 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | CSKY         | `r31`                                   | This is the TLS register.  |
 | s390x        | `c[0-15]`                               | Reserved by the kernel. |
 | s390x        | `a[0-1]`                                | Reserved for system use. |
+| SPARC        | `r0`/`g0`                               | This is always zero and cannot be used as inputs or outputs. |
+| SPARC        | `r1`/`g1`                               | Used internally by LLVM. |
+| SPARC        | `r5`/`g5`                               | Reserved for system. (SPARC32 only) |
+| SPARC        | `r6`/`g6`, `r7`/`g7`                    | Reserved for system. |
+| SPARC        | `r31`/`i7`                              | Return address cannot be used as inputs or outputs. |
 | Arm64EC      | `xzr`                                   | This is a constant zero register which can't be modified. |
 | Arm64EC      | `x18`                                   | This is an OS-reserved register. |
 | Arm64EC      | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]` | These are AArch64 registers that are not supported for Arm64EC. |
@@ -195,6 +209,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | s390x        | `reg`          | None     | `%r0`          | None          |
 | s390x        | `reg_addr`     | None     | `%r1`          | None          |
 | s390x        | `freg`         | None     | `%f0`          | None          |
+| SPARC        | `reg`          | None     | `%o0`          | None          |
 | CSKY         | `reg`          | None     | `r0`           | None          |
 | CSKY         | `freg`         | None     | `f0`           | None          |
 | Arm64EC      | `reg`          | None     | `x0`           | `x`           |
@@ -219,6 +234,9 @@ These flags registers must be restored upon exiting the asm block if the `preser
   - The condition code register `ccr`.
 - s390x
   - The condition code register `cc`.
+- SPARC
+  - Integer condition codes (`icc` and `xcc`)
+  - Floating-point condition codes (`fcc[0-3]`)
 - Arm64EC
   - Condition flags (`NZCV` register).
   - Floating-point status (`FPSR` register).
diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md
index c262d3f6da1..13a6814d31b 100644
--- a/src/doc/unstable-book/src/language-features/intrinsics.md
+++ b/src/doc/unstable-book/src/language-features/intrinsics.md
@@ -18,7 +18,7 @@ All intrinsic fallback bodies are automatically made cross-crate inlineable (lik
 by the codegen backend, but not the MIR inliner.
 
 ```rust
-#![feature(rustc_attrs)]
+#![feature(intrinsics)]
 #![allow(internal_features)]
 
 #[rustc_intrinsic]
@@ -28,7 +28,7 @@ const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
 Since these are just regular functions, it is perfectly ok to create the intrinsic twice:
 
 ```rust
-#![feature(rustc_attrs)]
+#![feature(intrinsics)]
 #![allow(internal_features)]
 
 #[rustc_intrinsic]
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 3134d25e544..980a9f7a47c 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -42,10 +42,16 @@ impl ScrapeExamplesOptions {
                 scrape_tests,
             }),
             (Some(_), false, _) | (None, true, _) => {
-                dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
+                dcx.fatal(
+                    "must use --scrape-examples-output-path and --scrape-examples-target-crate \
+                     together",
+                );
             }
             (None, false, true) => {
-                dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests");
+                dcx.fatal(
+                    "must use --scrape-examples-output-path and \
+                     --scrape-examples-target-crate with --scrape-tests",
+                );
             }
             (None, false, false) => None,
         }
@@ -163,14 +169,15 @@ where
         };
 
         // If this span comes from a macro expansion, then the source code may not actually show
-        // a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
+        // a use of the given item, so it would be a poor example. Hence, we skip all uses in
+        // macros.
         if call_span.from_expansion() {
             trace!("Rejecting expr from macro: {call_span:?}");
             return;
         }
 
-        // If the enclosing item has a span coming from a proc macro, then we also don't want to include
-        // the example.
+        // If the enclosing item has a span coming from a proc macro, then we also don't want to
+        // include the example.
         let enclosing_item_span =
             tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id).into());
         if enclosing_item_span.from_expansion() {
@@ -178,11 +185,12 @@ where
             return;
         }
 
-        // If the enclosing item doesn't actually enclose the call, this means we probably have a weird
-        // macro issue even though the spans aren't tagged as being from an expansion.
+        // If the enclosing item doesn't actually enclose the call, this means we probably have a
+        // weird macro issue even though the spans aren't tagged as being from an expansion.
         if !enclosing_item_span.contains(call_span) {
             warn!(
-                "Attempted to scrape call at [{call_span:?}] whose enclosing item [{enclosing_item_span:?}] doesn't contain the span of the call."
+                "Attempted to scrape call at [{call_span:?}] whose enclosing item \
+                 [{enclosing_item_span:?}] doesn't contain the span of the call."
             );
             return;
         }
@@ -190,7 +198,8 @@ where
         // Similarly for the call w/ the function ident.
         if !call_span.contains(ident_span) {
             warn!(
-                "Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was not contained in the span of the call."
+                "Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was \
+                 not contained in the span of the call."
             );
             return;
         }
@@ -224,7 +233,8 @@ where
                     Some(url) => url,
                     None => {
                         trace!(
-                            "Rejecting expr ({call_span:?}) whose clean span ({clean_span:?}) cannot be turned into a link"
+                            "Rejecting expr ({call_span:?}) whose clean span ({clean_span:?}) \
+                             cannot be turned into a link"
                         );
                         return;
                     }
@@ -272,7 +282,8 @@ pub(crate) fn run(
         let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?;
 
         // Collect CrateIds corresponding to provided target crates
-        // If two different versions of the crate in the dependency tree, then examples will be collected from both.
+        // If two different versions of the crate in the dependency tree, then examples will be
+        // collected from both.
         let all_crates = tcx
             .crates(())
             .iter()
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index ecb8343fba3..e6fbba943a4 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -236,8 +236,11 @@ pub struct Config {
     /// Run ignored tests
     pub run_ignored: bool,
 
-    /// Whether to run tests with `ignore-debug` header
-    pub with_debug_assertions: bool,
+    /// Whether rustc was built with debug assertions.
+    pub with_rustc_debug_assertions: bool,
+
+    /// Whether std was built with debug assertions.
+    pub with_std_debug_assertions: bool,
 
     /// Only run tests that match these filters
     pub filters: Vec<String>,
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 980b3f6829a..8570a8ce115 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -46,7 +46,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-coverage-map",
     "ignore-coverage-run",
     "ignore-cross-compile",
-    "ignore-debug",
     "ignore-eabi",
     "ignore-emscripten",
     "ignore-endian-big",
@@ -82,6 +81,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-powerpc",
     "ignore-remote",
     "ignore-riscv64",
+    "ignore-rustc-debug-assertions",
     "ignore-s390x",
     "ignore-sgx",
     "ignore-sparc64",
@@ -89,6 +89,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-stable",
     "ignore-stage1",
     "ignore-stage2",
+    "ignore-std-debug-assertions",
     "ignore-test",
     "ignore-thumb",
     "ignore-thumbv8m.base-none-eabi",
@@ -135,6 +136,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-relocation-model-pic",
     "needs-run-enabled",
     "needs-rust-lld",
+    "needs-rustc-debug-assertions",
     "needs-sanitizer-address",
     "needs-sanitizer-cfi",
     "needs-sanitizer-dataflow",
@@ -147,6 +149,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-shadow-call-stack",
     "needs-sanitizer-support",
     "needs-sanitizer-thread",
+    "needs-std-debug-assertions",
     "needs-symlink",
     "needs-threads",
     "needs-unwind",
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index b9314f0abbb..3ab552903dc 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -202,9 +202,14 @@ pub(super) fn parse_cfg_name_directive<'a>(
         message: "when running tests remotely",
     }
     condition! {
-        name: "debug",
-        condition: config.with_debug_assertions,
-        message: "when running tests with `ignore-debug` header",
+        name: "rustc-debug-assertions",
+        condition: config.with_rustc_debug_assertions,
+        message: "when rustc is built with debug assertions",
+    }
+    condition! {
+        name: "std-debug-assertions",
+        condition: config.with_std_debug_assertions,
+        message: "when std is built with debug assertions",
     }
     condition! {
         name: config.debugger.as_ref().map(|d| d.to_str()),
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index a744fb61b9c..77570c58db5 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -159,6 +159,16 @@ pub(super) fn handle_needs(
             condition: cache.llvm_zstd,
             ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
         },
+        Need {
+            name: "needs-rustc-debug-assertions",
+            condition: config.with_rustc_debug_assertions,
+            ignore_reason: "ignored if rustc wasn't built with debug assertions",
+        },
+        Need {
+            name: "needs-std-debug-assertions",
+            condition: config.with_std_debug_assertions,
+            ignore_reason: "ignored if std wasn't built with debug assertions",
+        },
     ];
 
     let (name, comment) = match ln.split_once([':', ' ']) {
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c79825e9e2a..c3fb8d4ab80 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -74,6 +74,8 @@ struct ConfigBuilder {
     git_hash: bool,
     system_llvm: bool,
     profiler_runtime: bool,
+    rustc_debug_assertions: bool,
+    std_debug_assertions: bool,
 }
 
 impl ConfigBuilder {
@@ -122,6 +124,16 @@ impl ConfigBuilder {
         self
     }
 
+    fn rustc_debug_assertions(&mut self, is_enabled: bool) -> &mut Self {
+        self.rustc_debug_assertions = is_enabled;
+        self
+    }
+
+    fn std_debug_assertions(&mut self, is_enabled: bool) -> &mut Self {
+        self.std_debug_assertions = is_enabled;
+        self
+    }
+
     fn build(&mut self) -> Config {
         let args = &[
             "compiletest",
@@ -170,6 +182,12 @@ impl ConfigBuilder {
         if self.profiler_runtime {
             args.push("--profiler-runtime".to_owned());
         }
+        if self.rustc_debug_assertions {
+            args.push("--with-rustc-debug-assertions".to_owned());
+        }
+        if self.std_debug_assertions {
+            args.push("--with-std-debug-assertions".to_owned());
+        }
 
         args.push("--rustc-path".to_string());
         // This is a subtle/fragile thing. On rust-lang CI, there is no global
@@ -315,6 +333,32 @@ fn only_target() {
 }
 
 #[test]
+fn rustc_debug_assertions() {
+    let config: Config = cfg().rustc_debug_assertions(false).build();
+
+    assert!(check_ignore(&config, "//@ needs-rustc-debug-assertions"));
+    assert!(!check_ignore(&config, "//@ ignore-rustc-debug-assertions"));
+
+    let config: Config = cfg().rustc_debug_assertions(true).build();
+
+    assert!(!check_ignore(&config, "//@ needs-rustc-debug-assertions"));
+    assert!(check_ignore(&config, "//@ ignore-rustc-debug-assertions"));
+}
+
+#[test]
+fn std_debug_assertions() {
+    let config: Config = cfg().std_debug_assertions(false).build();
+
+    assert!(check_ignore(&config, "//@ needs-std-debug-assertions"));
+    assert!(!check_ignore(&config, "//@ ignore-std-debug-assertions"));
+
+    let config: Config = cfg().std_debug_assertions(true).build();
+
+    assert!(!check_ignore(&config, "//@ needs-std-debug-assertions"));
+    assert!(check_ignore(&config, "//@ ignore-std-debug-assertions"));
+}
+
+#[test]
 fn stage() {
     let config: Config = cfg().stage_id("stage1-x86_64-unknown-linux-gnu").build();
 
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 5c06a39c477..bf4a3124075 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -88,7 +88,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .optopt("", "run", "whether to execute run-* tests", "auto | always | never")
         .optflag("", "ignored", "run tests marked as ignored")
         .optflag("", "has-enzyme", "run tests that require enzyme")
-        .optflag("", "with-debug-assertions", "whether to run tests with `ignore-debug` header")
+        .optflag("", "with-rustc-debug-assertions", "whether rustc was built with debug assertions")
+        .optflag("", "with-std-debug-assertions", "whether std was built with debug assertions")
         .optmulti(
             "",
             "skip",
@@ -235,7 +236,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
     let src_base = opt_path(matches, "src-base");
     let run_ignored = matches.opt_present("ignored");
-    let with_debug_assertions = matches.opt_present("with-debug-assertions");
+    let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
+    let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
     let mode = matches.opt_str("mode").unwrap().parse().expect("invalid mode");
     let has_html_tidy = if mode == Mode::Rustdoc {
         Command::new("tidy")
@@ -293,7 +295,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
         suite: matches.opt_str("suite").unwrap(),
         debugger: None,
         run_ignored,
-        with_debug_assertions,
+        with_rustc_debug_assertions,
+        with_std_debug_assertions,
         filters,
         skip: matches.opt_strs("skip"),
         filter_exact: matches.opt_present("exact"),
diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs
index fa7c0bf5c0c..e95ef4d9062 100644
--- a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs
+++ b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs
@@ -1,4 +1,4 @@
-#![feature(rustc_attrs)]
+#![feature(intrinsics, rustc_attrs)]
 
 #[rustc_intrinsic]
 #[rustc_nounwind]
diff --git a/tests/assembly/asm/sparc-types.rs b/tests/assembly/asm/sparc-types.rs
new file mode 100644
index 00000000000..2270679e837
--- /dev/null
+++ b/tests/assembly/asm/sparc-types.rs
@@ -0,0 +1,168 @@
+//@ revisions: sparc sparcv8plus sparc64
+//@ assembly-output: emit-asm
+//@[sparc] compile-flags: --target sparc-unknown-none-elf
+//@[sparc] needs-llvm-components: sparc
+//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
+//@[sparcv8plus] needs-llvm-components: sparc
+//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
+//@[sparc64] needs-llvm-components: sparc
+//@ compile-flags: -Zmerge-functions=disabled
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i32;
+
+impl Copy for i8 {}
+impl Copy for u8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov," {}, {}"), in($class) x, out($class) y);
+        y
+    }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        let y;
+        asm!(concat!($mov, " %", $reg, ", %", $reg), in($reg) x, lateout($reg) y);
+        y
+    }
+};}
+
+// CHECK-LABEL: sym_fn_32:
+// CHECK: !APP
+// CHECK-NEXT: call extern_func
+// CHECK-NEXT: !NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn_32() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: !APP
+// CHECK-NEXT: call extern_static
+// CHECK-NEXT: !NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("call {}", sym extern_static);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_i8, i8, reg, "mov");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_i16, i16, reg, "mov");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_i32, i32, reg, "mov");
+
+// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
+// sparc64-LABEL: reg_i64:
+// sparc64: !APP
+// sparc64-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// sparc64-NEXT: !NO_APP
+#[cfg(sparc64)]
+check!(reg_i64, i64, reg, "mov");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: !APP
+// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
+// CHECK-NEXT: !NO_APP
+check!(reg_ptr, ptr, reg, "mov");
+
+// CHECK-LABEL: o0_i8:
+// CHECK: !APP
+// CHECK-NEXT: mov %o0, %o0
+// CHECK-NEXT: !NO_APP
+check_reg!(o0_i8, i8, "o0", "mov");
+
+// CHECK-LABEL: o0_i16:
+// CHECK: !APP
+// CHECK-NEXT: mov %o0, %o0
+// CHECK-NEXT: !NO_APP
+check_reg!(o0_i16, i16, "o0", "mov");
+
+// CHECK-LABEL: o0_i32:
+// CHECK: !APP
+// CHECK-NEXT: mov %o0, %o0
+// CHECK-NEXT: !NO_APP
+check_reg!(o0_i32, i32, "o0", "mov");
+
+// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
+// sparc64-LABEL: o0_i64:
+// sparc64: !APP
+// sparc64-NEXT: mov %o0, %o0
+// sparc64-NEXT: !NO_APP
+#[cfg(sparc64)]
+check_reg!(o0_i64, i64, "o0", "mov");
+
+// CHECK-LABEL: r9_i8:
+// CHECK: !APP
+// CHECK-NEXT: mov %o1, %o1
+// CHECK-NEXT: !NO_APP
+check_reg!(r9_i8, i8, "r9", "mov");
+
+// CHECK-LABEL: r9_i16:
+// CHECK: !APP
+// CHECK-NEXT: mov %o1, %o1
+// CHECK-NEXT: !NO_APP
+check_reg!(r9_i16, i16, "r9", "mov");
+
+// CHECK-LABEL: r9_i32:
+// CHECK: !APP
+// CHECK-NEXT: mov %o1, %o1
+// CHECK-NEXT: !NO_APP
+check_reg!(r9_i32, i32, "r9", "mov");
+
+// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
+// sparc64-LABEL: r9_i64:
+// sparc64: !APP
+// sparc64-NEXT: mov %o1, %o1
+// sparc64-NEXT: !NO_APP
+#[cfg(sparc64)]
+check_reg!(r9_i64, i64, "r9", "mov");
diff --git a/tests/assembly/rust-abi-arg-attr.rs b/tests/assembly/rust-abi-arg-attr.rs
index 2a113eed4ba..e55a53fbdeb 100644
--- a/tests/assembly/rust-abi-arg-attr.rs
+++ b/tests/assembly/rust-abi-arg-attr.rs
@@ -50,9 +50,10 @@ enum Ordering {
     Greater = 1,
 }
 
-extern "rust-intrinsic" {
-    #[rustc_safe_intrinsic]
-    fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering;
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering {
+    loop {}
 }
 
 // ^^^^^ core
diff --git a/tests/codegen/asm/sparc-clobbers.rs b/tests/codegen/asm/sparc-clobbers.rs
new file mode 100644
index 00000000000..843abd55352
--- /dev/null
+++ b/tests/codegen/asm/sparc-clobbers.rs
@@ -0,0 +1,40 @@
+//@ revisions: sparc sparcv8plus sparc64
+//@[sparc] compile-flags: --target sparc-unknown-none-elf
+//@[sparc] needs-llvm-components: sparc
+//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
+//@[sparcv8plus] needs-llvm-components: sparc
+//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
+//@[sparc64] needs-llvm-components: sparc
+
+#![crate_type = "rlib"]
+#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+// CHECK-LABEL: @cc_clobber
+// CHECK: call void asm sideeffect "", "~{icc},~{fcc0},~{fcc1},~{fcc2},~{fcc3}"()
+#[no_mangle]
+pub unsafe fn cc_clobber() {
+    asm!("", options(nostack, nomem));
+}
+
+// CHECK-LABEL: @no_clobber
+// CHECK: call void asm sideeffect "", ""()
+#[no_mangle]
+pub unsafe fn no_clobber() {
+    asm!("", options(nostack, nomem, preserves_flags));
+}
+
+// CHECK-LABEL: @y_clobber
+// CHECK: call void asm sideeffect "", "~{y}"()
+#[no_mangle]
+pub unsafe fn y_clobber() {
+    asm!("", out("y") _, options(nostack, nomem, preserves_flags));
+}
diff --git a/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs b/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs
index 9cf4f210e52..e3bc9a4761c 100644
--- a/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs
+++ b/tests/codegen/binary-heap-peek-mut-pop-no-panic.rs
@@ -1,5 +1,5 @@
 //@ compile-flags: -O
-//@ ignore-debug
+//@ ignore-std-debug-assertions
 #![crate_type = "lib"]
 
 use std::collections::binary_heap::PeekMut;
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index e62f1a953df..e62adfa0ba6 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -4,7 +4,8 @@
 // known to be `1` after inlining).
 
 //@ compile-flags: -C no-prepopulate-passes -Zinline-mir=no
-//@ ignore-debug: precondition checks in ptr::read make them a bad candidate for MIR inlining
+//@ ignore-std-debug-assertions
+// Reason: precondition checks in ptr::read make them a bad candidate for MIR inlining
 //@ needs-deterministic-layouts
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/mem-replace-simple-type.rs b/tests/codegen/mem-replace-simple-type.rs
index 7209fa21925..41c3660dc15 100644
--- a/tests/codegen/mem-replace-simple-type.rs
+++ b/tests/codegen/mem-replace-simple-type.rs
@@ -1,6 +1,7 @@
 //@ compile-flags: -O -C no-prepopulate-passes
 //@ only-x86_64 (to not worry about usize differing)
-//@ ignore-debug: precondition checks make mem::replace not a candidate for MIR inlining
+//@ ignore-std-debug-assertions
+// Reason: precondition checks make mem::replace not a candidate for MIR inlining
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
index 81ac90269b7..e9112f1f321 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
@@ -31,7 +31,7 @@ extern "rust-intrinsic" {
 // CHECK-LABEL: @bitmask_int
 #[no_mangle]
 pub unsafe fn bitmask_int(x: i32x2) -> u8 {
-    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
     // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
     // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
     // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
@@ -41,7 +41,7 @@ pub unsafe fn bitmask_int(x: i32x2) -> u8 {
 // CHECK-LABEL: @bitmask_uint
 #[no_mangle]
 pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
-    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
+    // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
     // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
     // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
     // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
@@ -51,7 +51,7 @@ pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
 // CHECK-LABEL: @bitmask_int16
 #[no_mangle]
 pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
-    // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>
+    // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, {{<i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>|splat \(i8 7\)}}
     // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1>
     // CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16
     // CHECK-NOT: zext
diff --git a/tests/codegen/slice-reverse.rs b/tests/codegen/slice-reverse.rs
index 21add929f05..87cdad47962 100644
--- a/tests/codegen/slice-reverse.rs
+++ b/tests/codegen/slice-reverse.rs
@@ -1,6 +1,6 @@
 //@ compile-flags: -O
 //@ only-x86_64
-//@ ignore-debug: debug assertions prevent generating shufflevector
+//@ ignore-std-debug-assertions (debug assertions prevent generating shufflevector)
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs
index c6b77363a4e..5d05f242617 100644
--- a/tests/codegen/vec-in-place.rs
+++ b/tests/codegen/vec-in-place.rs
@@ -1,4 +1,4 @@
-//@ ignore-debug: FIXME: checks for call detect scoped noalias metadata
+//@ ignore-std-debug-assertions (FIXME: checks for call detect scoped noalias metadata)
 //@ compile-flags: -O -Z merge-functions=disabled
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs
index 4b798fe6c9c..873904c2569 100644
--- a/tests/codegen/vec-shrink-panik.rs
+++ b/tests/codegen/vec-shrink-panik.rs
@@ -1,7 +1,7 @@
 // LLVM 17 realizes double panic is not possible and doesn't generate calls
 // to panic_cannot_unwind.
 //@ compile-flags: -O
-//@ ignore-debug: plain old debug assertions
+//@ ignore-std-debug-assertions (plain old debug assertions)
 //@ needs-unwind
 #![crate_type = "lib"]
 #![feature(shrink_to)]
diff --git a/tests/codegen/vec-with-capacity.rs b/tests/codegen/vec-with-capacity.rs
index 47051f2eef8..e8c5bc88bd0 100644
--- a/tests/codegen/vec-with-capacity.rs
+++ b/tests/codegen/vec-with-capacity.rs
@@ -1,5 +1,5 @@
 //@ compile-flags: -O
-//@ ignore-debug
+//@ ignore-std-debug-assertions
 // (with debug assertions turned on, `assert_unchecked` generates a real assertion)
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/vecdeque-drain.rs b/tests/codegen/vecdeque-drain.rs
index fca1ed367e6..8a34ba0674b 100644
--- a/tests/codegen/vecdeque-drain.rs
+++ b/tests/codegen/vecdeque-drain.rs
@@ -2,7 +2,7 @@
 
 //@ compile-flags: -O
 //@ needs-deterministic-layouts
-//@ ignore-debug: FIXME: checks for call detect scoped noalias metadata
+//@ ignore-std-debug-assertions (FIXME: checks for call detect scoped noalias metadata)
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/vecdeque_no_panic.rs b/tests/codegen/vecdeque_no_panic.rs
index be2c4810ebc..da948d12254 100644
--- a/tests/codegen/vecdeque_no_panic.rs
+++ b/tests/codegen/vecdeque_no_panic.rs
@@ -1,7 +1,7 @@
 // This test checks that `VecDeque::front[_mut]()` and `VecDeque::back[_mut]()` can't panic.
 
 //@ compile-flags: -O
-//@ ignore-debug: plain old debug assertions
+//@ ignore-std-debug-assertions (plain old debug assertions)
 
 #![crate_type = "lib"]
 
diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs
index a68fe31f609..be23dcdb22a 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.rs
+++ b/tests/mir-opt/pre-codegen/mem_replace.rs
@@ -1,6 +1,7 @@
 // skip-filecheck
 //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
-//@ ignore-debug: precondition checks on ptr::read/write are under cfg(debug_assertions)
+//@ ignore-std-debug-assertions
+// Reason: precondition checks on ptr::read/write are under cfg(debug_assertions)
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
 #![crate_type = "lib"]
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.rs b/tests/mir-opt/pre-codegen/ptr_offset.rs
index 88ee00296a0..120be99fc94 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.rs
+++ b/tests/mir-opt/pre-codegen/ptr_offset.rs
@@ -1,6 +1,6 @@
 // skip-filecheck
 //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
-//@ ignore-debug: precondition checks are under cfg(debug_assertions)
+//@ ignore-std-debug-assertions (precondition checks are under cfg(debug_assertions))
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
 #![crate_type = "lib"]
diff --git a/tests/mir-opt/pre-codegen/slice_iter.rs b/tests/mir-opt/pre-codegen/slice_iter.rs
index fee4214982d..46ded729852 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.rs
+++ b/tests/mir-opt/pre-codegen/slice_iter.rs
@@ -1,7 +1,7 @@
 // skip-filecheck
 //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
 //@ only-64bit (constants for `None::<&T>` show in the output)
-//@ ignore-debug: precondition checks on ptr::add are under cfg(debug_assertions)
+//@ ignore-std-debug-assertions (precondition checks on ptr::add are under cfg(debug_assertions))
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
 #![crate_type = "lib"]
diff --git a/tests/run-make/crate-loading/multiple-dep-versions-3.rs b/tests/run-make/crate-loading/multiple-dep-versions-3.rs
index 07d888e9f10..f5c4d1baa81 100644
--- a/tests/run-make/crate-loading/multiple-dep-versions-3.rs
+++ b/tests/run-make/crate-loading/multiple-dep-versions-3.rs
@@ -3,3 +3,8 @@
 
 extern crate dependency;
 pub use dependency::Type;
+pub struct OtherType;
+impl dependency::Trait for OtherType {
+    fn foo(&self) {}
+    fn bar() {}
+}
diff --git a/tests/run-make/crate-loading/multiple-dep-versions.rs b/tests/run-make/crate-loading/multiple-dep-versions.rs
index 113af9c3025..c68a9e6489f 100644
--- a/tests/run-make/crate-loading/multiple-dep-versions.rs
+++ b/tests/run-make/crate-loading/multiple-dep-versions.rs
@@ -1,10 +1,11 @@
 extern crate dep_2_reexport;
 extern crate dependency;
-use dep_2_reexport::Type;
+use dep_2_reexport::{OtherType, Type};
 use dependency::{Trait, do_something};
 
 fn main() {
     do_something(Type);
     Type.foo();
     Type::bar();
+    do_something(OtherType);
 }
diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs
index 5d3302c7b02..2d5913c4bcb 100644
--- a/tests/run-make/crate-loading/rmake.rs
+++ b/tests/run-make/crate-loading/rmake.rs
@@ -18,47 +18,39 @@ fn main() {
         .extern_("dependency", rust_lib_name("dependency"))
         .extern_("dep_2_reexport", rust_lib_name("foo"))
         .run_fail()
-        .assert_stderr_contains(
-            r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied
-  --> multiple-dep-versions.rs:7:18
-   |
-7  |     do_something(Type);
-   |     ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type`
-   |     |
-   |     required by a bound introduced by this call
-   |
-help: there are multiple different versions of crate `dependency` in the dependency graph
-  --> multiple-dep-versions.rs:1:1
-   |
-1  | extern crate dep_2_reexport;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a dependency of crate `foo`
-2  | extern crate dependency;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate"#,
-        )
-        .assert_stderr_contains(
-            r#"
-3  | pub struct Type(pub i32);
-   | ^^^^^^^^^^^^^^^ this type implements the required trait
-4  | pub trait Trait {
-   | --------------- this is the required trait"#,
-        )
-        .assert_stderr_contains(
-            r#"
-3  | pub struct Type;
-   | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait"#,
-        )
-        .assert_stderr_contains(
-            r#"
-error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope
+        .assert_stderr_contains(r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied because the trait comes from a different crate version
+ --> multiple-dep-versions.rs:7:18
+  |
+7 |     do_something(Type);
+  |                  ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type`
+  |
+note: there are multiple different versions of crate `dependency` in the dependency graph"#)
+        .assert_stderr_contains(r#"
+3 | pub struct Type(pub i32);
+  | --------------- this type implements the required trait
+4 | pub trait Trait {
+  | ^^^^^^^^^^^^^^^ this is the required trait
+"#)
+        .assert_stderr_contains(r#"
+1 | extern crate dep_2_reexport;
+  | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
+2 | extern crate dependency;
+  | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate"#)
+        .assert_stderr_contains(r#"
+3 | pub struct Type;
+  | --------------- this type doesn't implement the required trait
+4 | pub trait Trait {
+  | --------------- this is the found trait
+  = note: two types coming from two different versions of the same crate are different types even if they look the same
+  = help: you can use `cargo tree` to explore your dependency tree"#)
+        .assert_stderr_contains(r#"error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope
  --> multiple-dep-versions.rs:8:10
   |
 8 |     Type.foo();
   |          ^^^ method not found in `Type`
   |
-note: there are multiple different versions of crate `dependency` in the dependency graph"#,
-        )
-        .assert_stderr_contains(
-            r#"
+note: there are multiple different versions of crate `dependency` in the dependency graph"#)
+        .assert_stderr_contains(r#"
 4 | pub trait Trait {
   | ^^^^^^^^^^^^^^^ this is the trait that is needed
 5 |     fn foo(&self);
@@ -67,25 +59,19 @@ note: there are multiple different versions of crate `dependency` in the depende
  ::: multiple-dep-versions.rs:4:18
   |
 4 | use dependency::{Trait, do_something};
-  |                  ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#,
-        )
-        .assert_stderr_contains(
-            r#"
+  |                  ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#)
+        .assert_stderr_contains(r#"
 4 | pub trait Trait {
-  | --------------- this is the trait that was imported"#,
-        )
-        .assert_stderr_contains(
-            r#"
+  | --------------- this is the trait that was imported"#)
+        .assert_stderr_contains(r#"
 error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope
  --> multiple-dep-versions.rs:9:11
   |
 9 |     Type::bar();
   |           ^^^ function or associated item not found in `Type`
   |
-note: there are multiple different versions of crate `dependency` in the dependency graph"#,
-        )
-        .assert_stderr_contains(
-            r#"
+note: there are multiple different versions of crate `dependency` in the dependency graph"#)
+        .assert_stderr_contains(r#"
 4 | pub trait Trait {
   | ^^^^^^^^^^^^^^^ this is the trait that is needed
 5 |     fn foo(&self);
@@ -95,6 +81,9 @@ note: there are multiple different versions of crate `dependency` in the depende
  ::: multiple-dep-versions.rs:4:18
   |
 4 | use dependency::{Trait, do_something};
-  |                  ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#,
-        );
+  |                  ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#)
+        .assert_stderr_contains(
+          r#"
+6  | pub struct OtherType;
+   | -------------------- this type doesn't implement the required trait"#);
 }
diff --git a/tests/rustdoc/safe-intrinsic.rs b/tests/rustdoc/safe-intrinsic.rs
index b46ffed99c3..07af04ace60 100644
--- a/tests/rustdoc/safe-intrinsic.rs
+++ b/tests/rustdoc/safe-intrinsic.rs
@@ -5,18 +5,17 @@
 #![no_core]
 #![crate_name = "foo"]
 
-extern "rust-intrinsic" {
-    //@ has 'foo/fn.abort.html'
-    //@ has - '//pre[@class="rust item-decl"]' 'pub extern "rust-intrinsic" fn abort() -> !'
-    #[rustc_safe_intrinsic]
-    pub fn abort() -> !;
-    //@ has 'foo/fn.unreachable.html'
-    //@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
-    pub fn unreachable() -> !;
+//@ has 'foo/fn.abort.html'
+//@ has - '//pre[@class="rust item-decl"]' 'pub fn abort() -> !'
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub fn abort() -> ! {
+    loop {}
 }
-
-extern "C" {
-    //@ has 'foo/fn.needs_drop.html'
-    //@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
-    pub fn needs_drop() -> !;
+//@ has 'foo/fn.unreachable.html'
+//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !'
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub unsafe fn unreachable() -> ! {
+    loop {}
 }
diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
new file mode 100644
index 00000000000..e039ca07dd4
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs
@@ -0,0 +1,149 @@
+//@ run-pass
+//! Test information about crate definitions (local and external).
+
+//@ ignore-stage1
+//@ ignore-cross-compile
+//@ ignore-remote
+//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
+
+#![feature(rustc_private)]
+#![feature(assert_matches)]
+
+extern crate rustc_hir;
+#[macro_use]
+extern crate rustc_smir;
+extern crate rustc_driver;
+extern crate rustc_interface;
+extern crate stable_mir;
+
+use rustc_smir::rustc_internal;
+use stable_mir::CrateDef;
+use std::collections::HashSet;
+use std::io::Write;
+use std::ops::ControlFlow;
+
+const CRATE_NAME: &str = "crate_defs";
+
+/// This function uses the Stable MIR APIs to get information about the test crate.
+fn test_stable_mir() -> ControlFlow<()> {
+    // Find items in the local crate.
+    let local = stable_mir::local_crate();
+    check_items(&local.statics(), &["PRIVATE_STATIC", "dummy::PUBLIC_STATIC"]);
+    check_items(
+        &local.fn_defs(),
+        &[
+            "top_level",
+            "dummy::public_fn",
+            "dummy::private_fn",
+            "dummy::PrivateStruct::new",
+            "<dummy::PrivateStruct as std::ops::Drop>::drop",
+            "DummyTrait::method",
+            "<T as DummyTrait>::method",
+        ],
+    );
+
+    // Find items inside core crate.
+    // FIXME: We are currently missing primitive type methods and trait implementations for external
+    // crates.
+    let core = stable_mir::find_crates("core").pop().expect("Cannot find `core` crate");
+    contains(
+        &core.fn_defs(),
+        &[
+            "std::fmt::Debug::fmt",
+            "std::option::Option::<T>::is_some",
+            "std::ptr::swap",
+            "<std::slice::Iter<'a, T> as std::iter::Iterator>::next",
+            "core::num::<impl u8>::abs_diff",
+        ],
+    );
+    // Ensure nothing crashes. There is no public static in core that we can test here.
+    let _ = core.statics();
+
+    ControlFlow::Continue(())
+}
+
+/// Check if the list of definitions matches the expected list.
+/// Note that order doesn't matter.
+fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) {
+    let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect();
+    let item_names: HashSet<_> = items.iter().map(|item| item.name()).collect();
+    assert_eq!(item_names, expected);
+}
+
+/// Check that the list contains the expected items.
+fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) {
+    let expected: HashSet<_> = expected.iter().map(|s| s.to_string()).collect();
+    let item_names = items.iter().map(|item| item.name()).collect();
+    let not_found: Vec<_> = expected.difference(&item_names).collect();
+    assert!(not_found.is_empty(), "Missing items: {:?}", not_found);
+}
+
+/// This test will generate and analyze a dummy crate using the stable mir.
+/// For that, it will first write the dummy crate into a file.
+/// Then it will create a `StableMir` using custom arguments and then
+/// it will run the compiler.
+fn main() {
+    let path = "crate_definitions.rs";
+    generate_input(&path).unwrap();
+    let args = vec![
+        "rustc".to_string(),
+        "--crate-type=lib".to_string(),
+        "--crate-name".to_string(),
+        CRATE_NAME.to_string(),
+        path.to_string(),
+    ];
+    run!(args, test_stable_mir).unwrap();
+}
+
+fn generate_input(path: &str) -> std::io::Result<()> {
+    let mut file = std::fs::File::create(path)?;
+    write!(
+        file,
+        r#"
+        #![allow(dead_code, unused_variables)]
+        static PRIVATE_STATIC: u8 = 0;
+        fn top_level() -> &'static str {{
+            "hello"
+        }}
+
+        pub trait DummyTrait {{
+            fn method(&self) -> Self;
+        }}
+
+        impl<T: Copy> DummyTrait for T {{
+            fn method(&self) -> T {{
+                *self
+            }}
+        }}
+
+        pub mod dummy {{
+            pub static mut PUBLIC_STATIC: Option<char> = None;
+
+            pub fn public_fn(input: bool) -> bool {{
+                private_fn(!input)
+            }}
+
+            fn private_fn(input: bool) -> bool {{
+                todo!()
+            }}
+
+            struct PrivateStruct {{
+                field: u32,
+            }}
+
+            impl PrivateStruct {{
+                fn new() -> Self {{
+                    Self {{ field: 42 }}
+                }}
+            }}
+
+            impl Drop for PrivateStruct {{
+                fn drop(&mut self) {{
+                    println!("Dropping PrivateStruct");
+                }}
+            }}
+        }}
+        "#
+    )?;
+    Ok(())
+}
diff --git a/tests/ui/asm/bad-arch.rs b/tests/ui/asm/bad-arch.rs
deleted file mode 100644
index f84b9944b36..00000000000
--- a/tests/ui/asm/bad-arch.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-//@ compile-flags: --target sparc-unknown-linux-gnu
-//@ needs-llvm-components: sparc
-
-#![feature(no_core, lang_items, rustc_attrs)]
-#![no_core]
-
-#[rustc_builtin_macro]
-macro_rules! asm {
-    () => {};
-}
-#[rustc_builtin_macro]
-macro_rules! global_asm {
-    () => {};
-}
-#[lang = "sized"]
-trait Sized {}
-
-fn main() {
-    unsafe {
-        asm!("");
-        //~^ ERROR inline assembly is unsupported on this target
-    }
-}
-
-global_asm!("");
-//~^ ERROR inline assembly is unsupported on this target
diff --git a/tests/ui/asm/bad-arch.stderr b/tests/ui/asm/bad-arch.stderr
deleted file mode 100644
index c6f726600eb..00000000000
--- a/tests/ui/asm/bad-arch.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0472]: inline assembly is unsupported on this target
-  --> $DIR/bad-arch.rs:20:9
-   |
-LL |         asm!("");
-   |         ^^^^^^^^
-
-error[E0472]: inline assembly is unsupported on this target
-  --> $DIR/bad-arch.rs:25:1
-   |
-LL | global_asm!("");
-   | ^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0472`.
diff --git a/tests/ui/asm/sparc/bad-reg.rs b/tests/ui/asm/sparc/bad-reg.rs
new file mode 100644
index 00000000000..b824f5adf3a
--- /dev/null
+++ b/tests/ui/asm/sparc/bad-reg.rs
@@ -0,0 +1,66 @@
+//@ revisions: sparc sparcv8plus sparc64
+//@[sparc] compile-flags: --target sparc-unknown-none-elf
+//@[sparc] needs-llvm-components: sparc
+//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
+//@[sparcv8plus] needs-llvm-components: sparc
+//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
+//@[sparc64] needs-llvm-components: sparc
+//@ needs-asm-support
+
+#![crate_type = "rlib"]
+#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for i32 {}
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+fn f() {
+    let mut x = 0;
+    unsafe {
+        // Unsupported registers
+        asm!("", out("g0") _);
+        //~^ ERROR invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
+        // FIXME: see FIXME in compiler/rustc_target/src/asm/sparc.rs.
+        asm!("", out("g1") _);
+        //~^ ERROR invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
+        asm!("", out("g2") _);
+        asm!("", out("g3") _);
+        asm!("", out("g4") _);
+        asm!("", out("g5") _);
+        //[sparc,sparcv8plus]~^ ERROR cannot use register `r5`: g5 is reserved for system on SPARC32
+        asm!("", out("g6") _);
+        //~^ ERROR invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
+        asm!("", out("g7") _);
+        //~^ ERROR invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
+        asm!("", out("sp") _);
+        //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+        asm!("", out("fp") _);
+        //~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+        asm!("", out("i7") _);
+        //~^ ERROR invalid register `i7`: the return address register cannot be used as an operand for inline asm
+
+        // Clobber-only registers
+        // yreg
+        asm!("", out("y") _); // ok
+        asm!("", in("y") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("", out("y") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", in(yreg) x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", out(yreg) _);
+        //~^ ERROR can only be used as a clobber
+    }
+}
diff --git a/tests/ui/asm/sparc/bad-reg.sparc.stderr b/tests/ui/asm/sparc/bad-reg.sparc.stderr
new file mode 100644
index 00000000000..cb7558c0f43
--- /dev/null
+++ b/tests/ui/asm/sparc/bad-reg.sparc.stderr
@@ -0,0 +1,98 @@
+error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:30:18
+   |
+LL |         asm!("", out("g0") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:33:18
+   |
+LL |         asm!("", out("g1") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", out("g6") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:42:18
+   |
+LL |         asm!("", out("g7") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:44:18
+   |
+LL |         asm!("", out("sp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:46:18
+   |
+LL |         asm!("", out("fp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", out("i7") _);
+   |                  ^^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:54:18
+   |
+LL |         asm!("", in("y") x);
+   |                  ^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:57:18
+   |
+LL |         asm!("", out("y") x);
+   |                  ^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:60:26
+   |
+LL |         asm!("/* {} */", in(yreg) x);
+   |                          ^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:63:26
+   |
+LL |         asm!("/* {} */", out(yreg) _);
+   |                          ^^^^^^^^^^^
+
+error: cannot use register `r5`: g5 is reserved for system on SPARC32
+  --> $DIR/bad-reg.rs:38:18
+   |
+LL |         asm!("", out("g5") _);
+   |                  ^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:54:26
+   |
+LL |         asm!("", in("y") x);
+   |                          ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:57:27
+   |
+LL |         asm!("", out("y") x);
+   |                           ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:60:35
+   |
+LL |         asm!("/* {} */", in(yreg) x);
+   |                                   ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: aborting due to 15 previous errors
+
diff --git a/tests/ui/asm/sparc/bad-reg.sparc64.stderr b/tests/ui/asm/sparc/bad-reg.sparc64.stderr
new file mode 100644
index 00000000000..e5606ab3124
--- /dev/null
+++ b/tests/ui/asm/sparc/bad-reg.sparc64.stderr
@@ -0,0 +1,92 @@
+error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:30:18
+   |
+LL |         asm!("", out("g0") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:33:18
+   |
+LL |         asm!("", out("g1") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", out("g6") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:42:18
+   |
+LL |         asm!("", out("g7") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:44:18
+   |
+LL |         asm!("", out("sp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:46:18
+   |
+LL |         asm!("", out("fp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", out("i7") _);
+   |                  ^^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:54:18
+   |
+LL |         asm!("", in("y") x);
+   |                  ^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:57:18
+   |
+LL |         asm!("", out("y") x);
+   |                  ^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:60:26
+   |
+LL |         asm!("/* {} */", in(yreg) x);
+   |                          ^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:63:26
+   |
+LL |         asm!("/* {} */", out(yreg) _);
+   |                          ^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:54:26
+   |
+LL |         asm!("", in("y") x);
+   |                          ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:57:27
+   |
+LL |         asm!("", out("y") x);
+   |                           ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:60:35
+   |
+LL |         asm!("/* {} */", in(yreg) x);
+   |                                   ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: aborting due to 14 previous errors
+
diff --git a/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr b/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr
new file mode 100644
index 00000000000..cb7558c0f43
--- /dev/null
+++ b/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr
@@ -0,0 +1,98 @@
+error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:30:18
+   |
+LL |         asm!("", out("g0") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:33:18
+   |
+LL |         asm!("", out("g1") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", out("g6") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:42:18
+   |
+LL |         asm!("", out("g7") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:44:18
+   |
+LL |         asm!("", out("sp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:46:18
+   |
+LL |         asm!("", out("fp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", out("i7") _);
+   |                  ^^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:54:18
+   |
+LL |         asm!("", in("y") x);
+   |                  ^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:57:18
+   |
+LL |         asm!("", out("y") x);
+   |                  ^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:60:26
+   |
+LL |         asm!("/* {} */", in(yreg) x);
+   |                          ^^^^^^^^^^
+
+error: register class `yreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:63:26
+   |
+LL |         asm!("/* {} */", out(yreg) _);
+   |                          ^^^^^^^^^^^
+
+error: cannot use register `r5`: g5 is reserved for system on SPARC32
+  --> $DIR/bad-reg.rs:38:18
+   |
+LL |         asm!("", out("g5") _);
+   |                  ^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:54:26
+   |
+LL |         asm!("", in("y") x);
+   |                          ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:57:27
+   |
+LL |         asm!("", out("y") x);
+   |                           ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:60:35
+   |
+LL |         asm!("/* {} */", in(yreg) x);
+   |                                   ^
+   |
+   = note: register class `yreg` supports these types: 
+
+error: aborting due to 15 previous errors
+
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
index 3426a768cb6..c3360c8b3e2 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
@@ -11,12 +11,12 @@ LL |     *ptr = 0;
    |     ^^^^^^^^ accessing memory based on pointer with alignment 1, but alignment 4 is required
 
 error[E0080]: evaluation of constant value failed
-  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
    |
    = note: accessing memory with alignment 1, but alignment 4 is required
    |
 note: inside `copy_nonoverlapping::<u32>`
-  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 note: inside `std::ptr::const_ptr::<impl *const u32>::copy_to_nonoverlapping`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `MISALIGNED_COPY`
diff --git a/tests/ui/error-codes/E0094.rs b/tests/ui/error-codes/E0094.rs
index 97ebcff99dc..da59d3decac 100644
--- a/tests/ui/error-codes/E0094.rs
+++ b/tests/ui/error-codes/E0094.rs
@@ -1,9 +1,10 @@
-#![feature(intrinsics, rustc_attrs)]
+#![feature(intrinsics)]
 
-extern "rust-intrinsic" {
-    #[rustc_safe_intrinsic]
-    fn size_of<T, U>() -> usize; //~ ERROR E0094
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+fn size_of<T, U>() -> usize {
+    //~^ ERROR E0094
+    loop {}
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/error-codes/E0094.stderr b/tests/ui/error-codes/E0094.stderr
index 1bad5bd950e..e45cc0ea063 100644
--- a/tests/ui/error-codes/E0094.stderr
+++ b/tests/ui/error-codes/E0094.stderr
@@ -1,8 +1,8 @@
 error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
-  --> $DIR/E0094.rs:5:15
+  --> $DIR/E0094.rs:5:11
    |
-LL |     fn size_of<T, U>() -> usize;
-   |               ^^^^^^ expected 1 type parameter
+LL | fn size_of<T, U>() -> usize {
+   |           ^^^^^^ expected 1 type parameter
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0308.rs b/tests/ui/error-codes/E0308.rs
index dd9e0b284ea..f8f93d49a8e 100644
--- a/tests/ui/error-codes/E0308.rs
+++ b/tests/ui/error-codes/E0308.rs
@@ -1,10 +1,11 @@
 #![feature(intrinsics)]
 #![feature(rustc_attrs)]
 
-extern "rust-intrinsic" {
-    #[rustc_safe_intrinsic]
-    fn size_of<T>(); //~ ERROR E0308
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+fn size_of<T>() {
+    //~^ ERROR E0308
+    loop {}
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/error-codes/E0308.stderr b/tests/ui/error-codes/E0308.stderr
index 709b3119276..77e5c06e06a 100644
--- a/tests/ui/error-codes/E0308.stderr
+++ b/tests/ui/error-codes/E0308.stderr
@@ -1,11 +1,11 @@
 error[E0308]: intrinsic has wrong type
-  --> $DIR/E0308.rs:6:20
+  --> $DIR/E0308.rs:6:16
    |
-LL |     fn size_of<T>();
-   |                    ^ expected `usize`, found `()`
+LL | fn size_of<T>() {
+   |                ^ expected `usize`, found `()`
    |
-   = note: expected signature `extern "rust-intrinsic" fn() -> usize`
-              found signature `extern "rust-intrinsic" fn() -> ()`
+   = note: expected signature `fn() -> usize`
+              found signature `fn() -> ()`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs
index 99e9801fd40..3fbddfc99a6 100644
--- a/tests/ui/extern/extern-with-type-bounds.rs
+++ b/tests/ui/extern/extern-with-type-bounds.rs
@@ -1,18 +1,17 @@
 #![feature(intrinsics, rustc_attrs)]
 
-extern "rust-intrinsic" {
-    // Real example from libcore
-    #[rustc_safe_intrinsic]
-    fn type_id<T: ?Sized + 'static>() -> u64;
+// Intrinsics are the only (?) extern blocks supporting generics.
+// Once intrinsics have to be declared via `#[rustc_intrinsic]`,
+// the entire support for generics in extern fn can probably be removed.
 
+extern "rust-intrinsic" {
     // Silent bounds made explicit to make sure they are actually
     // resolved.
     fn transmute<T: Sized, U: Sized>(val: T) -> U;
 
     // Bounds aren't checked right now, so this should work
     // even though it's incorrect.
-    #[rustc_safe_intrinsic]
-    fn size_of<T: Clone>() -> usize;
+    fn size_of_val<T: Clone>(x: *const T) -> usize;
 
     // Unresolved bounds should still error.
     fn align_of<T: NoSuchTrait>() -> usize;
diff --git a/tests/ui/extern/extern-with-type-bounds.stderr b/tests/ui/extern/extern-with-type-bounds.stderr
index 42448d9e924..893947e831f 100644
--- a/tests/ui/extern/extern-with-type-bounds.stderr
+++ b/tests/ui/extern/extern-with-type-bounds.stderr
@@ -1,5 +1,5 @@
 error[E0405]: cannot find trait `NoSuchTrait` in this scope
-  --> $DIR/extern-with-type-bounds.rs:18:20
+  --> $DIR/extern-with-type-bounds.rs:17:20
    |
 LL |     fn align_of<T: NoSuchTrait>() -> usize;
    |                    ^^^^^^^^^^^ not found in this scope
diff --git a/tests/ui/intrinsics/always-gets-overridden.rs b/tests/ui/intrinsics/always-gets-overridden.rs
index ad2c2be4daa..2fb64f96d83 100644
--- a/tests/ui/intrinsics/always-gets-overridden.rs
+++ b/tests/ui/intrinsics/always-gets-overridden.rs
@@ -1,6 +1,6 @@
 //! Check that `vtable_size` gets overridden by llvm backend even if there is no
 //! `rustc_intrinsic_must_be_overridden` attribute on this usage.
-#![feature(rustc_attrs)]
+#![feature(intrinsics)]
 //@run-pass
 
 #[rustc_intrinsic]
diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr
index 50092edda4f..e317ed23ab1 100644
--- a/tests/ui/intrinsics/const-eval-select-bad.stderr
+++ b/tests/ui/intrinsics/const-eval-select-bad.stderr
@@ -27,7 +27,7 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = help: the trait `FnOnce()` is not implemented for `{integer}`
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
-  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
 error[E0277]: expected a `FnOnce()` closure, found `{integer}`
   --> $DIR/const-eval-select-bad.rs:10:31
@@ -40,7 +40,7 @@ LL |     const_eval_select((), 42, 0xDEADBEEF);
    = help: the trait `FnOnce()` is not implemented for `{integer}`
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `const_eval_select`
-  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
 error: this argument must be a function item
   --> $DIR/const-eval-select-bad.rs:10:27
@@ -69,7 +69,7 @@ LL |     const_eval_select((1,), foo, bar);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `const_eval_select`
-  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/const-eval-select-bad.rs:37:32
@@ -85,7 +85,7 @@ LL |     const_eval_select((true,), foo, baz);
    = note: expected function signature `fn(bool) -> _`
               found function signature `fn(i32) -> _`
 note: required by a bound in `const_eval_select`
-  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
 help: consider wrapping the function in a closure
    |
 LL |     const_eval_select((true,), |arg0: bool| foo(/* i32 */), baz);
diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs
deleted file mode 100644
index ffaa4d771d9..00000000000
--- a/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#[rustc_safe_intrinsic]
-//~^ ERROR the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe
-//~| ERROR attribute should be applied to intrinsic functions
-fn safe() {}
-
-fn main() {}
diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr
deleted file mode 100644
index e49880e9bb8..00000000000
--- a/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe
-  --> $DIR/feature-gate-safe-intrinsic.rs:1:1
-   |
-LL | #[rustc_safe_intrinsic]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: attribute should be applied to intrinsic functions
-  --> $DIR/feature-gate-safe-intrinsic.rs:1:1
-   |
-LL | #[rustc_safe_intrinsic]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | fn safe() {}
-   | ------------ not an intrinsic function
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs
index 4cb05f6a8df..ab99aa5fd03 100644
--- a/tests/ui/intrinsics/intrinsic-alignment.rs
+++ b/tests/ui/intrinsics/intrinsic-alignment.rs
@@ -1,14 +1,8 @@
 //@ run-pass
 
-#![feature(intrinsics, rustc_attrs)]
+#![feature(core_intrinsics, rustc_attrs)]
 
-mod rusti {
-    extern "rust-intrinsic" {
-        pub fn pref_align_of<T>() -> usize;
-        #[rustc_safe_intrinsic]
-        pub fn min_align_of<T>() -> usize;
-    }
-}
+use std::intrinsics as rusti;
 
 #[cfg(any(
     target_os = "android",
diff --git a/tests/ui/intrinsics/intrinsics-integer.rs b/tests/ui/intrinsics/intrinsics-integer.rs
index 7dbc4b8b7ce..8eb03924feb 100644
--- a/tests/ui/intrinsics/intrinsics-integer.rs
+++ b/tests/ui/intrinsics/intrinsics-integer.rs
@@ -1,24 +1,8 @@
 //@ run-pass
 
-#![feature(intrinsics)]
-#![feature(rustc_attrs)]
-
-mod rusti {
-    extern "rust-intrinsic" {
-        #[rustc_safe_intrinsic]
-        pub fn ctpop<T>(x: T) -> u32;
-        #[rustc_safe_intrinsic]
-        pub fn ctlz<T>(x: T) -> u32;
-        pub fn ctlz_nonzero<T>(x: T) -> u32;
-        #[rustc_safe_intrinsic]
-        pub fn cttz<T>(x: T) -> u32;
-        pub fn cttz_nonzero<T>(x: T) -> u32;
-        #[rustc_safe_intrinsic]
-        pub fn bswap<T>(x: T) -> T;
-        #[rustc_safe_intrinsic]
-        pub fn bitreverse<T>(x: T) -> T;
-    }
-}
+#![feature(core_intrinsics)]
+
+use std::intrinsics as rusti;
 
 pub fn main() {
     use rusti::*;
diff --git a/tests/ui/intrinsics/not-overridden.rs b/tests/ui/intrinsics/not-overridden.rs
index e1f1bbe0951..16f8e9bcf6a 100644
--- a/tests/ui/intrinsics/not-overridden.rs
+++ b/tests/ui/intrinsics/not-overridden.rs
@@ -1,6 +1,6 @@
 //! Check that intrinsics that do not get overridden, but are marked as such,
 //! cause an error instead of silently invoking the body.
-#![feature(rustc_attrs)]
+#![feature(intrinsics)]
 //@ build-fail
 //@ failure-status:101
 //@ normalize-stderr-test: ".*note: .*\n\n" -> ""
diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs
index 5dda0da8458..36739e3fc04 100644
--- a/tests/ui/print_type_sizes/niche-filling.rs
+++ b/tests/ui/print_type_sizes/niche-filling.rs
@@ -9,7 +9,7 @@
 //! padding and overall computed sizes can be quite different.
 //!
 //@ compile-flags: -Z print-type-sizes --crate-type lib
-//@ ignore-debug: debug assertions will print more types
+//@ ignore-std-debug-assertions (debug assertions will print more types)
 //@ build-pass
 //@ ignore-pass
 //  ^-- needed because `--pass check` does not emit the output needed.
diff --git a/tests/ui/stable-mir-print/operands.rs b/tests/ui/stable-mir-print/operands.rs
new file mode 100644
index 00000000000..34a74e2287e
--- /dev/null
+++ b/tests/ui/stable-mir-print/operands.rs
@@ -0,0 +1,48 @@
+//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort
+//@ check-pass
+//@ only-x86_64
+//@ needs-unwind unwind edges are different with panic=abort
+//! Check how stable mir pretty printer prints different operands and abort strategy.
+
+pub fn operands(val: u8) {
+    let array = [val; 10];
+    let first = array[0];
+    let last = array[10 - 1];
+    assert_eq!(first, last);
+
+    let reference = &first;
+    let dereferenced = *reference;
+    assert_eq!(dereferenced, first);
+
+    let tuple = (first, last);
+    let (first_again, _) = tuple;
+    let first_again_again = tuple.0;
+    assert_eq!(first_again, first_again_again);
+
+    let length = array.len();
+    let size_of = std::mem::size_of_val(&length);
+    assert_eq!(length, size_of);
+}
+
+pub struct Dummy {
+    c: char,
+    i: i32,
+}
+
+pub enum Ctors {
+    Unit,
+    StructLike { d: Dummy },
+    TupLike(bool),
+}
+
+pub fn more_operands() -> [Ctors; 3] {
+    let dummy = Dummy { c: 'a', i: i32::MIN };
+    let unit = Ctors::Unit;
+    let struct_like = Ctors::StructLike { d: dummy };
+    let tup_like = Ctors::TupLike(false);
+    [unit, struct_like, tup_like]
+}
+
+pub fn closures(x: bool, z: bool) -> impl FnOnce(bool) -> bool {
+    move |y: bool| (x ^ y) || z
+}
diff --git a/tests/ui/stable-mir-print/operands.stdout b/tests/ui/stable-mir-print/operands.stdout
new file mode 100644
index 00000000000..3c27878b3cf
--- /dev/null
+++ b/tests/ui/stable-mir-print/operands.stdout
@@ -0,0 +1,263 @@
+// WARNING: This is highly experimental output it's intended for stable-mir developers only.
+// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir.
+fn operands(_1: u8) -> () {
+    let mut _0: ();
+    let  _2: [u8; 10];
+    let  _3: u8;
+    let  _4: usize;
+    let mut _5: usize;
+    let mut _6: bool;
+    let  _7: u8;
+    let  _8: usize;
+    let mut _9: (usize, bool);
+    let mut _10: usize;
+    let mut _11: bool;
+    let mut _12: (&u8, &u8);
+    let mut _13: &u8;
+    let mut _14: &u8;
+    let  _15: &u8;
+    let  _16: &u8;
+    let mut _17: bool;
+    let mut _18: u8;
+    let mut _19: u8;
+    let  _20: core::panicking::AssertKind;
+    let  _21: !;
+    let mut _22: Option<Arguments<'_>>;
+    let  _23: &u8;
+    let  _24: u8;
+    let mut _25: (&u8, &u8);
+    let mut _26: &u8;
+    let mut _27: &u8;
+    let  _28: &u8;
+    let  _29: &u8;
+    let mut _30: bool;
+    let mut _31: u8;
+    let mut _32: u8;
+    let  _33: core::panicking::AssertKind;
+    let  _34: !;
+    let mut _35: Option<Arguments<'_>>;
+    let  _36: (u8, u8);
+    let  _37: u8;
+    let  _38: u8;
+    let mut _39: (&u8, &u8);
+    let mut _40: &u8;
+    let mut _41: &u8;
+    let  _42: &u8;
+    let  _43: &u8;
+    let mut _44: bool;
+    let mut _45: u8;
+    let mut _46: u8;
+    let  _47: core::panicking::AssertKind;
+    let  _48: !;
+    let mut _49: Option<Arguments<'_>>;
+    let  _50: usize;
+    let mut _51: &[u8];
+    let mut _52: &[u8; 10];
+    let  _53: usize;
+    let  _54: &usize;
+    let mut _55: (&usize, &usize);
+    let mut _56: &usize;
+    let mut _57: &usize;
+    let  _58: &usize;
+    let  _59: &usize;
+    let mut _60: bool;
+    let mut _61: usize;
+    let mut _62: usize;
+    let  _63: core::panicking::AssertKind;
+    let  _64: !;
+    let mut _65: Option<Arguments<'_>>;
+    debug val => _1;
+    debug array => _2;
+    debug first => _3;
+    debug last => _7;
+    debug left_val => _15;
+    debug right_val => _16;
+    debug kind => _20;
+    debug reference => _23;
+    debug dereferenced => _24;
+    debug left_val => _28;
+    debug right_val => _29;
+    debug kind => _33;
+    debug tuple => _36;
+    debug first_again => _37;
+    debug first_again_again => _38;
+    debug left_val => _42;
+    debug right_val => _43;
+    debug kind => _47;
+    debug length => _50;
+    debug size_of => _53;
+    debug left_val => _58;
+    debug right_val => _59;
+    debug kind => _63;
+    bb0: {
+        _2 = [_1; 10];
+        _4 = 0_usize;
+        _5 = 10_usize;
+        _6 = Lt(_4, _5);
+        assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable];
+    }
+    bb1: {
+        _3 = _2[_4];
+        _9 = CheckedSub(10_usize, 1_usize);
+        assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable];
+    }
+    bb2: {
+        _8 = move (_9.0: usize);
+        _10 = 10_usize;
+        _11 = Lt(_8, _10);
+        assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _8) -> [success: bb3, unwind unreachable];
+    }
+    bb3: {
+        _7 = _2[_8];
+        _13 = &_3;
+        _14 = &_7;
+        _12 = (move _13, move _14);
+        _15 = (_12.0: &u8);
+        _16 = (_12.1: &u8);
+        _18 = (*_15);
+        _19 = (*_16);
+        _17 = Eq(move _18, move _19);
+        switchInt(move _17) -> [0: bb5, otherwise: bb4];
+    }
+    bb4: {
+        _23 = &_3;
+        _24 = (*_23);
+        _26 = &_24;
+        _27 = &_3;
+        _25 = (move _26, move _27);
+        _28 = (_25.0: &u8);
+        _29 = (_25.1: &u8);
+        _31 = (*_28);
+        _32 = (*_29);
+        _30 = Eq(move _31, move _32);
+        switchInt(move _30) -> [0: bb7, otherwise: bb6];
+    }
+    bb5: {
+        _20 = core::panicking::AssertKind::Eq;
+        _22 = std::option::Option::None;
+        _21 = core::panicking::assert_failed::<u8, u8>(move _20, _15, _16, move _22) -> unwind unreachable;
+    }
+    bb6: {
+        _36 = (_3, _7);
+        _37 = (_36.0: u8);
+        _38 = (_36.0: u8);
+        _40 = &_37;
+        _41 = &_38;
+        _39 = (move _40, move _41);
+        _42 = (_39.0: &u8);
+        _43 = (_39.1: &u8);
+        _45 = (*_42);
+        _46 = (*_43);
+        _44 = Eq(move _45, move _46);
+        switchInt(move _44) -> [0: bb9, otherwise: bb8];
+    }
+    bb7: {
+        _33 = core::panicking::AssertKind::Eq;
+        _35 = std::option::Option::None;
+        _34 = core::panicking::assert_failed::<u8, u8>(move _33, _28, _29, move _35) -> unwind unreachable;
+    }
+    bb8: {
+        _52 = &_2;
+        _51 = move _52 as &[u8];
+        _50 = PtrMetadata(move _51);
+        _54 = &_50;
+        _53 = std::mem::size_of_val::<usize>(_54) -> [return: bb10, unwind unreachable];
+    }
+    bb9: {
+        _47 = core::panicking::AssertKind::Eq;
+        _49 = std::option::Option::None;
+        _48 = core::panicking::assert_failed::<u8, u8>(move _47, _42, _43, move _49) -> unwind unreachable;
+    }
+    bb10: {
+        _56 = &_50;
+        _57 = &_53;
+        _55 = (move _56, move _57);
+        _58 = (_55.0: &usize);
+        _59 = (_55.1: &usize);
+        _61 = (*_58);
+        _62 = (*_59);
+        _60 = Eq(move _61, move _62);
+        switchInt(move _60) -> [0: bb12, otherwise: bb11];
+    }
+    bb11: {
+        return;
+    }
+    bb12: {
+        _63 = core::panicking::AssertKind::Eq;
+        _65 = std::option::Option::None;
+        _64 = core::panicking::assert_failed::<usize, usize>(move _63, _58, _59, move _65) -> unwind unreachable;
+    }
+}
+fn operands::{constant#0}() -> usize {
+    let mut _0: usize;
+    bb0: {
+        _0 = 10_usize;
+        return;
+    }
+}
+fn more_operands() -> [Ctors; 3] {
+    let mut _0: [Ctors; 3];
+    let  _1: Dummy;
+    let  _2: Ctors;
+    let  _3: Ctors;
+    let  _4: Ctors;
+    debug dummy => _1;
+    debug unit => _2;
+    debug struct_like => _3;
+    debug tup_like => _4;
+    bb0: {
+        _1 = Dummy('a', core::num::<impl i32>::MIN);
+        _2 = Ctors::Unit;
+        _3 = Ctors::StructLike(move _1);
+        _4 = Ctors::TupLike(false);
+        _0 = [move _2, move _3, move _4];
+        return;
+    }
+}
+fn more_operands::{constant#0}() -> usize {
+    let mut _0: usize;
+    bb0: {
+        _0 = 3_usize;
+        return;
+    }
+}
+fn closures(_1: bool, _2: bool) -> {closure@$DIR/operands.rs:47:5: 47:19} {
+    let mut _0: {closure@$DIR/operands.rs:47:5: 47:19};
+    debug x => _1;
+    debug z => _2;
+    bb0: {
+        _0 = {closure@$DIR/operands.rs:47:5: 47:19}(_1, _2);
+        return;
+    }
+}
+fn closures::{closure#0}(_1: {closure@$DIR/operands.rs:47:5: 47:19}, _2: bool) -> bool {
+    let mut _0: bool;
+    let mut _3: bool;
+    let mut _4: bool;
+    debug y => _2;
+    debug x => (_1.0: bool);
+    debug z => (_1.1: bool);
+    bb0: {
+        _4 = (_1.0: bool);
+        _3 = BitXor(move _4, _2);
+        switchInt(move _3) -> [0: bb2, otherwise: bb1];
+    }
+    bb1: {
+        _0 = true;
+        goto -> bb3;
+    }
+    bb2: {
+        _0 = (_1.1: bool);
+        goto -> bb3;
+    }
+    bb3: {
+        return;
+    }
+}
+fn Ctors::TupLike(_1: bool) -> Ctors {
+    let mut _0: Ctors;
+    bb0: {
+        _0 = Ctors::TupLike(move _1);
+        return;
+    }
+}
diff --git a/tests/ui/statics/static-mut-shared-parens.rs b/tests/ui/statics/static-mut-shared-parens.rs
new file mode 100644
index 00000000000..8e58152e27a
--- /dev/null
+++ b/tests/ui/statics/static-mut-shared-parens.rs
@@ -0,0 +1,13 @@
+//Missing paren in diagnostic msg: https://github.com/rust-lang/rust/issues/131977
+//@check-pass
+
+
+static mut TEST: usize = 0;
+
+fn main() {
+    let _ = unsafe { (&TEST) as *const usize };
+    //~^WARN creating a shared reference to mutable static is discouraged
+
+    let _ = unsafe { ((&mut TEST)) as *const usize };
+    //~^WARN creating a mutable reference to mutable static is discouraged
+}
diff --git a/tests/ui/statics/static-mut-shared-parens.stderr b/tests/ui/statics/static-mut-shared-parens.stderr
new file mode 100644
index 00000000000..aa7a760ded8
--- /dev/null
+++ b/tests/ui/statics/static-mut-shared-parens.stderr
@@ -0,0 +1,29 @@
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-shared-parens.rs:8:22
+   |
+LL |     let _ = unsafe { (&TEST) as *const usize };
+   |                      ^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+   = note: `#[warn(static_mut_refs)]` on by default
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |     let _ = unsafe { (&raw const TEST) as *const usize };
+   |                       ~~~~~~~~~~
+
+warning: creating a mutable reference to mutable static is discouraged
+  --> $DIR/static-mut-shared-parens.rs:11:22
+   |
+LL |     let _ = unsafe { ((&mut TEST)) as *const usize };
+   |                      ^^^^^^^^^^^^^ mutable reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
+help: use `&raw mut` instead to create a raw pointer
+   |
+LL |     let _ = unsafe { ((&raw mut TEST)) as *const usize };
+   |                        ~~~~~~~~
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/std/channel-stack-overflow-issue-102246.rs b/tests/ui/std/channel-stack-overflow-issue-102246.rs
new file mode 100644
index 00000000000..984ebdd553f
--- /dev/null
+++ b/tests/ui/std/channel-stack-overflow-issue-102246.rs
@@ -0,0 +1,29 @@
+//@ run-pass
+//@ needs-threads
+//@ compile-flags: -Copt-level=0
+
+// The channel's `Block::new` was causing a stack overflow because it held 32 item slots, which is
+// 1MiB for this test's `BigStruct` -- instantiated on the stack before moving to `Box::new`.
+//
+// That block is now initialized directly on the heap.
+//
+// Ref: https://github.com/rust-lang/rust/issues/102246
+
+use std::sync::mpsc::channel;
+use std::thread;
+
+const N: usize = 32_768;
+struct BigStruct {
+    _data: [u8; N],
+}
+
+fn main() {
+    let (sender, receiver) = channel::<BigStruct>();
+
+    let thread1 = thread::spawn(move || {
+        sender.send(BigStruct { _data: [0u8; N] }).unwrap();
+    });
+
+    thread1.join().unwrap();
+    for _data in receiver.try_iter() {}
+}
diff --git a/tests/ui/structs-enums/rec-align-u32.rs b/tests/ui/structs-enums/rec-align-u32.rs
index 9cd2a988871..44879189739 100644
--- a/tests/ui/structs-enums/rec-align-u32.rs
+++ b/tests/ui/structs-enums/rec-align-u32.rs
@@ -3,17 +3,10 @@
 #![allow(unused_unsafe)]
 // Issue #2303
 
-#![feature(intrinsics, rustc_attrs)]
+#![feature(core_intrinsics, rustc_attrs)]
 
 use std::mem;
-
-mod rusti {
-    extern "rust-intrinsic" {
-        pub fn pref_align_of<T>() -> usize;
-        #[rustc_safe_intrinsic]
-        pub fn min_align_of<T>() -> usize;
-    }
-}
+use std::intrinsics;
 
 // This is the type with the questionable alignment
 #[derive(Debug)]
@@ -41,12 +34,12 @@ pub fn main() {
         // Send it through the shape code
         let y = format!("{:?}", x);
 
-        println!("align inner = {:?}", rusti::min_align_of::<Inner>());
+        println!("align inner = {:?}", intrinsics::min_align_of::<Inner>());
         println!("size outer = {:?}", mem::size_of::<Outer>());
         println!("y = {:?}", y);
 
         // per clang/gcc the alignment of `inner` is 4 on x86.
-        assert_eq!(rusti::min_align_of::<Inner>(), m::align());
+        assert_eq!(intrinsics::min_align_of::<Inner>(), m::align());
 
         // per clang/gcc the size of `outer` should be 12
         // because `inner`s alignment was 4.
diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs
index 313ce6d578d..8b501ea5509 100644
--- a/tests/ui/structs-enums/rec-align-u64.rs
+++ b/tests/ui/structs-enums/rec-align-u64.rs
@@ -4,17 +4,10 @@
 
 // Issue #2303
 
-#![feature(intrinsics, rustc_attrs)]
+#![feature(core_intrinsics, rustc_attrs)]
 
 use std::mem;
-
-mod rusti {
-    extern "rust-intrinsic" {
-        pub fn pref_align_of<T>() -> usize;
-        #[rustc_safe_intrinsic]
-        pub fn min_align_of<T>() -> usize;
-    }
-}
+use std::intrinsics;
 
 // This is the type with the questionable alignment
 #[derive(Debug)]
@@ -90,12 +83,12 @@ pub fn main() {
 
         let y = format!("{:?}", x);
 
-        println!("align inner = {:?}", rusti::min_align_of::<Inner>());
+        println!("align inner = {:?}", intrinsics::min_align_of::<Inner>());
         println!("size outer = {:?}", mem::size_of::<Outer>());
         println!("y = {:?}", y);
 
         // per clang/gcc the alignment of `Inner` is 4 on x86.
-        assert_eq!(rusti::min_align_of::<Inner>(), m::m::align());
+        assert_eq!(intrinsics::min_align_of::<Inner>(), m::m::align());
 
         // per clang/gcc the size of `Outer` should be 12
         // because `Inner`s alignment was 4.
diff --git a/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr b/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr
index b9bb97548f6..70de107b1ae 100644
--- a/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr
+++ b/tests/ui/typeck/foreign_struct_trait_unimplemented.stderr
@@ -6,12 +6,7 @@ LL |     needs_test(foreign_struct_trait_unimplemented::B);
    |     |
    |     required by a bound introduced by this call
    |
-help: there are multiple different versions of crate `foreign_struct_trait_unimplemented` in the dependency graph
-  --> $DIR/foreign_struct_trait_unimplemented.rs:3:1
-   |
-LL | extern crate foreign_struct_trait_unimplemented;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `foreign_struct_trait_unimplemented` is used here, as a direct dependency of the current crate
-   = help: you can use `cargo tree` to explore your dependency tree
+   = help: the trait `Test` is implemented for `A`
 note: required by a bound in `needs_test`
   --> $DIR/foreign_struct_trait_unimplemented.rs:10:23
    |