Repository: bytecodealliance/wasmtime
Pull request #8205 (2024-03-21 14:54:41)

Bump MSRV to 1.75.0
Coupled with today's release of 1.77.0. Today's release actually has some nice functions and such I think we'll want to use in Wasmtime but we'll need to wait 3 months to be able to use them.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/Cargo.toml b/Cargo.toml
index e5c0f8f76..8ba4a3832 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -140,7 +140,7 @@ authors = ["The Wasmtime Project Developers"]
 edition = "2021"
 # Wasmtime's current policy is that this number can be no larger than the
 # current stable release of Rust minus 2.
-rust-version = "1.74.0"
+rust-version = "1.75.0"
 
 [workspace.lints.rust]
 # Turn on some lints which are otherwise allow-by-default in rustc.
diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle
index 15112a585..51107ab36 100644
--- a/cranelift/codegen/src/isa/aarch64/inst.isle
+++ b/cranelift/codegen/src/isa/aarch64/inst.isle
@@ -3454,6 +3454,27 @@
             (_ Unit (emit (MInst.AtomicCASLoop ty flags addr expect replace dst scratch))))
         dst))
 
+;; Copy a register of the given type to a new register.
+;;
+;; Generally, regalloc should take care of this kind of thing for us. This is
+;; only useful for implementing things like `bitcast` from an `r64` to an `i64`
+;; to avoid conflicting constraints on a single aliased value by splitting the
+;; value into two parts.
+(decl copy_reg (Type Reg) Reg)
+(rule (copy_reg $I32 src)
+      (let ((dst WritableReg (temp_writable_reg $I32))
+            (_ Unit (emit (MInst.Mov (OperandSize.Size32)
+                                     dst
+                                     src))))
+        dst))
+(rule (copy_reg $I64 src)
+      (let ((dst WritableReg (temp_writable_reg $I64))
+            (_ Unit (emit (MInst.Mov (OperandSize.Size64)
+                                     dst
+                                     src))))
+        dst))
+
+
 ;; Helper for emitting `MInst.MovPReg` instructions.
 (decl mov_from_preg (PReg) Reg)
 (rule (mov_from_preg src)
diff --git a/cranelift/codegen/src/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle
index 7af210286..6b5c22bec 100644
--- a/cranelift/codegen/src/isa/aarch64/lower.isle
+++ b/cranelift/codegen/src/isa/aarch64/lower.isle
@@ -2468,12 +2468,28 @@
       (if (ty_int_ref_scalar_64 out_ty))
       (mov_from_vec x 0 (scalar_size out_ty)))
 
+;; Bitcasts between `r{32,64}` and `i{32,64}` need to be a copy to avoid
+;; conflicting regalloc constraints on reference type values that both need to
+;; be in some register but also some safepoint stack slot at the same time.
+(rule 2 (lower (has_type dst_ty (bitcast _ x @ (value_type src_ty))))
+      (if (ty_int_ref_scalar_64 src_ty))
+      (if (ty_int_ref_scalar_64 dst_ty))
+      (if-let $true (is_ref_type src_ty))
+      (if-let $false (is_ref_type dst_ty))
+      (copy_reg dst_ty x))
+(rule 2 (lower (has_type dst_ty (bitcast _ x @ (value_type src_ty))))
+      (if (ty_int_ref_scalar_64 src_ty))
+      (if (ty_int_ref_scalar_64 dst_ty))
+      (if-let $false (is_ref_type src_ty))
+      (if-let $true (is_ref_type dst_ty))
+      (copy_reg src_ty x))
+
 ; GPR <=> GPR
-(rule 2 (lower (has_type out_ty (bitcast _ x @ (value_type in_ty))))
+(rule 1 (lower (has_type out_ty (bitcast _ x @ (value_type in_ty))))
       (if (ty_int_ref_scalar_64 out_ty))
       (if (ty_int_ref_scalar_64 in_ty))
       x)
-(rule 1 (lower (has_type $I128 (bitcast _ x @ (value_type $I128)))) x)
+(rule 0 (lower (has_type $I128 (bitcast _ x @ (value_type $I128)))) x)
 
 ;;; Rules for `extractlane` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
diff --git a/cranelift/codegen/src/isa/riscv64/inst.isle b/cranelift/codegen/src/isa/riscv64/inst.isle
index 8806ac3c5..3cc710196 100644
--- a/cranelift/codegen/src/isa/riscv64/inst.isle
+++ b/cranelift/codegen/src/isa/riscv64/inst.isle
@@ -2733,6 +2733,8 @@
 (rule 1 (gen_bitcast r $F64 $I64) (rv_fmvxd r))
 (rule 1 (gen_bitcast r $I32 $F32) (rv_fmvwx r))
 (rule 1 (gen_bitcast r $I64 $F64) (rv_fmvdx r))
+(rule 1 (gen_bitcast r $I64 $R64) (copy_reg r $I64))
+(rule 1 (gen_bitcast r $R64 $I64) (copy_reg r $I64))
 (rule (gen_bitcast r _ _) r)
 
 (decl move_f_to_x (FReg Type) XReg)
@@ -2844,6 +2846,20 @@
         (_ Unit (emit (MInst.MovFromPReg rd rm))))
     rd))
 
+;; Copy a register of the given type to a new register.
+;;
+;; Generally, regalloc should take care of this kind of thing for us. This is
+;; only useful for implementing things like `bitcast` from an `r64` to an `i64`
+;; to avoid conflicting constraints on a single aliased value by splitting the
+;; value into two parts.
+(decl copy_reg (XReg Type) XReg)
+(rule (copy_reg src ty)
+      (let ((dst WritableXReg (temp_writable_xreg))
+            (_ Unit (emit (MInst.Mov dst
+                                     src
+                                     ty))))
+        dst))
+
 (decl fp_reg () PReg)
 (extern constructor fp_reg fp_reg)
 
diff --git a/cranelift/codegen/src/isa/s390x/lower.isle b/cranelift/codegen/src/isa/s390x/lower.isle
index 6d6aa1e72..7f4c1542a 100644
--- a/cranelift/codegen/src/isa/s390x/lower.isle
+++ b/cranelift/codegen/src/isa/s390x/lower.isle
@@ -1726,19 +1726,35 @@
 (rule (lower (has_type $I32 (bitcast _ x @ (value_type $F32))))
       (vec_extract_lane $F32X4 x 0 (zero_reg)))
 
+;; Bitcasts between `r{32,64}` and `i{32,64}` need to be a copy to avoid
+;; conflicting regalloc constraints on reference type values that both need to
+;; be in some register but also some safepoint stack slot at the same time.
+(rule 6 (lower (has_type $R32 (bitcast _ x @ (value_type $I32))))
+      (copy_reg $I32 x))
+(rule 6 (lower (has_type $R64 (bitcast _ x @ (value_type $I64))))
+      (copy_reg $I64 x))
+(rule 6 (lower (has_type $I32 (bitcast _ x @ (value_type $R32))))
+      (copy_reg $I32 x))
+(rule 6 (lower (has_type $I64 (bitcast _ x @ (value_type $R64))))
+      (copy_reg $I64 x))
+
 ;; Bitcast between types residing in GPRs is a no-op.
 (rule 1 (lower (has_type (gpr32_ty _)
-                         (bitcast _ x @ (value_type (gpr32_ty _))))) x)
+                         (bitcast _ x @ (value_type (gpr32_ty _)))))
+      x)
 (rule 2 (lower (has_type (gpr64_ty _)
-                         (bitcast _ x @ (value_type (gpr64_ty _))))) x)
+                         (bitcast _ x @ (value_type (gpr64_ty _)))))
+      x)
 
 ;; Bitcast between types residing in FPRs is a no-op.
 (rule 3 (lower (has_type (ty_scalar_float _)
-                         (bitcast _ x @ (value_type (ty_scalar_float _))))) x)
+                         (bitcast _ x @ (value_type (ty_scalar_float _)))))
+      x)
 
 ;; Bitcast between types residing in VRs is a no-op if lane count is unchanged.
 (rule 5 (lower (has_type (multi_lane bits count)
-                         (bitcast _ x @ (value_type (multi_lane bits count))))) x)
+                         (bitcast _ x @ (value_type (multi_lane bits count)))))
+      x)
 
 ;; Bitcast between types residing in VRs with different lane counts is a
 ;; no-op if the operation's MemFlags indicate a byte order compatible with
diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle
index 0da546b6b..919678795 100644
--- a/cranelift/codegen/src/isa/x64/inst.isle
+++ b/cranelift/codegen/src/isa/x64/inst.isle
@@ -5226,6 +5226,20 @@
 (decl put_in_xmm_mem_aligned (Value) XmmMemAligned)
 (rule (put_in_xmm_mem_aligned val) (put_in_xmm_mem val))
 
+;; Copy a GPR of the given type to a new GPR.
+;;
+;; Generally, regalloc should take care of this kind of thing for us. This is
+;; only useful for implementing things like `bitcast` from an `r64` to an `i64`
+;; to avoid conflicting constraints on a single aliased value by splitting the
+;; value into two parts.
+(decl copy_gpr (Type Gpr) Gpr)
+(rule (copy_gpr ty src)
+      (let ((dst WritableGpr (temp_writable_gpr))
+            (_ Unit (emit (MInst.MovRR (operand_size_of_type_32_64 ty)
+                                       src
+                                       dst))))
+        dst))
+
 (decl mov_to_preg (PReg Gpr) SideEffectNoResult)
 (rule (mov_to_preg dst src)
       (SideEffectNoResult.Inst (MInst.MovToPReg src dst)))
diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle
index 31cc17518..50798aa2b 100644
--- a/cranelift/codegen/src/isa/x64/lower.isle
+++ b/cranelift/codegen/src/isa/x64/lower.isle
@@ -3983,11 +3983,27 @@
 
 ;; Bitcast between types residing in GPR registers is a no-op.
 (rule 1 (lower (has_type (is_gpr_type _)
-                         (bitcast _ x @ (value_type (is_gpr_type _))))) x)
+                         (bitcast _ x @ (value_type (is_gpr_type _)))))
+      x)
+
+;; Bitcasts between `r{32,64}` and `i{32,64}` need to be a copy to avoid
+;; conflicting regalloc constraints on reference type values that both need to
+;; be in some register but also some safepoint stack slot at the same time.
+(rule 2 (lower (has_type (is_gpr_type dst_ty)
+                         (bitcast _ x @ (value_type (is_gpr_type src_ty)))))
+      (if-let $true (is_ref_type src_ty))
+      (if-let $false (is_ref_type dst_ty))
+      (copy_gpr dst_ty x))
+(rule 2 (lower (has_type (is_gpr_type dst_ty)
+                         (bitcast _ x @ (value_type (is_gpr_type src_ty)))))
+      (if-let $false (is_ref_type src_ty))
+      (if-let $true (is_ref_type dst_ty))
+      (copy_gpr dst_ty x))
 
 ;; Bitcast between types residing in XMM registers is a no-op.
-(rule 2 (lower (has_type (is_xmm_type _)
-                         (bitcast _ x @ (value_type (is_xmm_type _))))) x)
+(rule 3 (lower (has_type (is_xmm_type _)
+                         (bitcast _ x @ (value_type (is_xmm_type _)))))
+      x)
 
 ;; Rules for `fcopysign` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle
index ed625559f..e7517fc41 100644
--- a/cranelift/codegen/src/prelude.isle
+++ b/cranelift/codegen/src/prelude.isle
@@ -326,6 +326,11 @@
 (decl pure ty_equal (Type Type) bool)
 (extern constructor ty_equal ty_equal)
 
+(decl pure is_ref_type (Type) bool)
+(rule 1 (is_ref_type $R32) $true)
+(rule 1 (is_ref_type $R64) $true)
+(rule 0 (is_ref_type _) $false)
+
 ;;;; `cranelift_codegen::ir::MemFlags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 ;; `MemFlags::trusted`
diff --git a/crates/wasi-nn/src/backend/onnxruntime.rs b/crates/wasi-nn/src/backend/onnxruntime.rs
index 5ceb4fd11..bddb03dc9 100644
--- a/crates/wasi-nn/src/backend/onnxruntime.rs
+++ b/crates/wasi-nn/src/backend/onnxruntime.rs
@@ -48,7 +48,7 @@ impl BackendFromDir for OnnxBackend {
     }
 }
 
-struct ONNXGraph(Arc<Mutex<Session>>, ExecutionTarget);
+struct ONNXGraph(Arc<Mutex<Session>>, #[allow(dead_code)] ExecutionTarget);
 
 unsafe impl Send for ONNXGraph {}
 unsafe impl Sync for ONNXGraph {}


Test patch:
diff --git a/cranelift/filetests/filetests/isa/issue-8180.clif b/cranelift/filetests/filetests/isa/issue-8180.clif
new file mode 100644
index 000000000..7ff22173d
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/issue-8180.clif
@@ -0,0 +1,30 @@
+;; https://github.com/bytecodealliance/wasmtime/issues/8180
+;;
+;; Make sure that bitcasting between integer and reference types doesn't result
+;; in conflicting regalloc constraints where a register has to be both in a
+;; register for a call and a stack slot for a safepoint.
+;;
+;; We aren't testing for any particular resuyting code sequence, just that
+;; compilation succeeds.
+
+test compile
+target x86_64
+target aarch64
+target riscv64
+target s390x
+
+function %a(i64, r64) fast {
+    sig0 = (i64) system_v
+block1(v0: i64, v1: r64):
+    v2 = bitcast.i64 v1
+    call_indirect sig0, v0(v2)
+    return
+}
+
+function %b(i64, i64) fast {
+    sig0 = (r64) system_v
+block1(v0: i64, v1: i64):
+    v2 = bitcast.r64 v1
+    call_indirect sig0, v0(v2)
+    return
+}
diff --git a/cranelift/filetests/filetests/isa/s390x/bitcast.clif b/cranelift/filetests/filetests/isa/s390x/bitcast.clif
index f783f9058..879c74d54 100644
--- a/cranelift/filetests/filetests/isa/s390x/bitcast.clif
+++ b/cranelift/filetests/filetests/isa/s390x/bitcast.clif
@@ -85,10 +85,12 @@ block0(v0: r64):
 
 ; VCode:
 ; block0:
+;   lgr %r2, %r2
 ;   br %r14
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
+;   lgr %r2, %r2
 ;   br %r14
 
 function %bitcast_i64_r64(i64) -> r64 {
@@ -99,10 +101,12 @@ block0(v0: i64):
 
 ; VCode:
 ; block0:
+;   lgr %r2, %r2
 ;   br %r14
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
+;   lgr %r2, %r2
 ;   br %r14
 
 function %bitcast_r64_r64(r64) -> r64 {