Browse Source

Handle Win64 builtins ABI change in LLVM 14

As of https://reviews.llvm.org/D110413, these no longer use the
unadjusted ABI (and use normal C ABI instead, passing i128
indirectly and returning it as <2 x i64>).

To support both LLVM 14 and older versions, rustc will expose a
"llvm14-builtins-abi" target feature, based on which
compiler-builtins can chose the appropriate ABI.

This is needed for rust-lang/rust#93577.
Nikita Popov 3 years ago
parent
commit
f47e0c7615
1 changed files with 81 additions and 35 deletions
  1. 81 35
      src/float/conv.rs

+ 81 - 35
src/float/conv.rs

@@ -109,16 +109,6 @@ intrinsics! {
         }
     }
 
-    #[unadjusted_on_win64]
-    pub extern "C" fn __floattisf(i: i128) -> f32 {
-        int_to_float(i)
-    }
-
-    #[unadjusted_on_win64]
-    pub extern "C" fn __floattidf(i: i128) -> f64 {
-        int_to_float(i)
-    }
-
     #[arm_aeabi_alias = __aeabi_ui2f]
     pub extern "C" fn __floatunsisf(i: u32) -> f32 {
         int_to_float(i)
@@ -140,16 +130,6 @@ intrinsics! {
     pub extern "C" fn __floatundidf(i: u64) -> f64 {
         int_to_float(i)
     }
-
-    #[unadjusted_on_win64]
-    pub extern "C" fn __floatuntisf(i: u128) -> f32 {
-        int_to_float(i)
-    }
-
-    #[unadjusted_on_win64]
-    pub extern "C" fn __floatuntidf(i: u128) -> f64 {
-        int_to_float(i)
-    }
 }
 
 fn float_to_int<F: Float, I: Int>(f: F) -> I
@@ -224,11 +204,6 @@ intrinsics! {
         float_to_int(f)
     }
 
-    #[unadjusted_on_win64]
-    pub extern "C" fn __fixsfti(f: f32) -> i128 {
-        float_to_int(f)
-    }
-
     #[arm_aeabi_alias = __aeabi_d2iz]
     pub extern "C" fn __fixdfsi(f: f64) -> i32 {
         float_to_int(f)
@@ -239,11 +214,6 @@ intrinsics! {
         float_to_int(f)
     }
 
-    #[unadjusted_on_win64]
-    pub extern "C" fn __fixdfti(f: f64) -> i128 {
-        float_to_int(f)
-    }
-
     #[arm_aeabi_alias = __aeabi_f2uiz]
     pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
         float_to_int(f)
@@ -254,11 +224,6 @@ intrinsics! {
         float_to_int(f)
     }
 
-    #[unadjusted_on_win64]
-    pub extern "C" fn __fixunssfti(f: f32) -> u128 {
-        float_to_int(f)
-    }
-
     #[arm_aeabi_alias = __aeabi_d2uiz]
     pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
         float_to_int(f)
@@ -268,6 +233,87 @@ intrinsics! {
     pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
         float_to_int(f)
     }
+}
+
+// The ABI for the following intrinsics changed in LLVM 14. On Win64, they now
+// use Win64 ABI rather than unadjusted ABI. Pick the correct ABI based on the
+// llvm14-builtins-abi target feature.
+
+#[cfg(target_feature = "llvm14-builtins-abi")]
+intrinsics! {
+    pub extern "C" fn __floattisf(i: i128) -> f32 {
+        int_to_float(i)
+    }
+
+    pub extern "C" fn __floattidf(i: i128) -> f64 {
+        int_to_float(i)
+    }
+
+    pub extern "C" fn __floatuntisf(i: u128) -> f32 {
+        int_to_float(i)
+    }
+
+    pub extern "C" fn __floatuntidf(i: u128) -> f64 {
+        int_to_float(i)
+    }
+
+    #[win64_128bit_abi_hack]
+    pub extern "C" fn __fixsfti(f: f32) -> i128 {
+        float_to_int(f)
+    }
+
+    #[win64_128bit_abi_hack]
+    pub extern "C" fn __fixdfti(f: f64) -> i128 {
+        float_to_int(f)
+    }
+
+    #[win64_128bit_abi_hack]
+    pub extern "C" fn __fixunssfti(f: f32) -> u128 {
+        float_to_int(f)
+    }
+
+    #[win64_128bit_abi_hack]
+    pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
+        float_to_int(f)
+    }
+}
+
+#[cfg(not(target_feature = "llvm14-builtins-abi"))]
+intrinsics! {
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floattisf(i: i128) -> f32 {
+        int_to_float(i)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floattidf(i: i128) -> f64 {
+        int_to_float(i)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floatuntisf(i: u128) -> f32 {
+        int_to_float(i)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floatuntidf(i: u128) -> f64 {
+        int_to_float(i)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __fixsfti(f: f32) -> i128 {
+        float_to_int(f)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __fixdfti(f: f64) -> i128 {
+        float_to_int(f)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __fixunssfti(f: f32) -> u128 {
+        float_to_int(f)
+    }
 
     #[unadjusted_on_win64]
     pub extern "C" fn __fixunsdfti(f: f64) -> u128 {