From b77dbbd4fd2ed4083635f74612aa25b4be80fc43 Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross@umich.edu>
Date: Thu, 14 Nov 2024 15:48:21 -0600
Subject: [PATCH 1/2] Pass `f16` and `f128` by value in `const_assert!`

These types are currently passed by reference, which does not avoid the
backend crashes. Change these back to being passed by value, which makes
the types easier to detect for automatic inlining.
---
 library/core/src/num/f128.rs | 5 ++---
 library/core/src/num/f16.rs  | 5 ++---
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index c3862d994986a..3fac1ef099f35 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -1258,9 +1258,8 @@ impl f128 {
             min <= max,
             "min > max, or either was NaN",
             "min > max, or either was NaN. min = {min:?}, max = {max:?}",
-            // FIXME(f16_f128): Passed by-ref to avoid codegen crashes
-            min: &f128 = &min,
-            max: &f128 = &max,
+            min: f128,
+            max: f128,
         );
 
         if self < min {
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index ed35316cf8f9c..eaac19f22f751 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -1235,9 +1235,8 @@ impl f16 {
             min <= max,
             "min > max, or either was NaN",
             "min > max, or either was NaN. min = {min:?}, max = {max:?}",
-            // FIXME(f16_f128): Passed by-ref to avoid codegen crashes
-            min: &f16 = &min,
-            max: &f16 = &max,
+            min: f16,
+            max: f16,
         );
 
         if self < min {

From 5d818914af2760972943db448d2a08de27900c96 Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross@umich.edu>
Date: Thu, 14 Nov 2024 14:17:20 -0600
Subject: [PATCH 2/2] Always inline functions signatures containing `f16` or
 `f128`

There are a handful of tier 2 and tier 3 targets that cause a LLVM crash
or linker error when generating code that contains `f16` or `f128`. The
cranelift backend also does not support these types. To work around
this, every function in `std` or `core` that contains these types must
be marked `#[inline]` in order to avoid sending any code to the backend
unless specifically requested.

However, this is inconvenient and easy to forget. Introduce a check for
these types in the frontend that automatically inlines any function
signatures that take or return `f16` or `f128`.

Note that this is not a perfect fix because it does not account for the
types being passed by reference or as members of aggregate types, but
this is sufficient for what is currently needed in the standard library.

Fixes: https://github.com/rust-lang/rust/issues/133035
Closes: https://github.com/rust-lang/rust/pull/133037
---
 .../src/cross_crate_inline.rs                 | 10 +++++++
 tests/codegen/float/f16-f128-inline.rs        | 29 +++++++++++++++++++
 2 files changed, 39 insertions(+)
 create mode 100644 tests/codegen/float/f16-f128-inline.rs

diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 42cbece32d8c9..589be81558c2b 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -50,6 +50,16 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
         _ => {}
     }
 
+    let sig = tcx.fn_sig(def_id).instantiate_identity();
+    for ty in sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder()))
+    {
+        // FIXME(f16_f128): in order to avoid crashes building `core`, always inline to skip
+        // codegen if the function is not used.
+        if ty == &tcx.types.f16 || ty == &tcx.types.f128 {
+            return true;
+        }
+    }
+
     // Don't do any inference when incremental compilation is enabled; the additional inlining that
     // inference permits also creates more work for small edits.
     if tcx.sess.opts.incremental.is_some() {
diff --git a/tests/codegen/float/f16-f128-inline.rs b/tests/codegen/float/f16-f128-inline.rs
new file mode 100644
index 0000000000000..aa2c38c209e86
--- /dev/null
+++ b/tests/codegen/float/f16-f128-inline.rs
@@ -0,0 +1,29 @@
+//@ revisions: default nopt
+//@[nopt] compile-flags: -Copt-level=0 -Zcross-crate-inline-threshold=never -Zmir-opt-level=0 -Cno-prepopulate-passes
+
+// Ensure that functions using `f16` and `f128` are always inlined to avoid crashes
+// when the backend does not support these types.
+
+#![crate_type = "lib"]
+#![feature(f128)]
+#![feature(f16)]
+
+pub fn f16_arg(_a: f16) {
+    // CHECK-NOT: f16_arg
+    todo!()
+}
+
+pub fn f16_ret() -> f16 {
+    // CHECK-NOT: f16_ret
+    todo!()
+}
+
+pub fn f128_arg(_a: f128) {
+    // CHECK-NOT: f128_arg
+    todo!()
+}
+
+pub fn f128_ret() -> f128 {
+    // CHECK-NOT: f128_ret
+    todo!()
+}