From 16d37444d87ac32b7fdf36da8fdeb6e2b883ca03 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Wed, 20 Jul 2022 13:30:34 -0700
Subject: [PATCH] Fix a miscompile for s390x with constants

This carries over a narrow fix from #4427 to prior release branches. The
patch here was created by `@uweigand` during the investigation for #4487.
---
 cranelift/codegen/src/isa/s390x/lower/isle.rs | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/cranelift/codegen/src/isa/s390x/lower/isle.rs b/cranelift/codegen/src/isa/s390x/lower/isle.rs
index ded692c83496..6025dda33717 100644
--- a/cranelift/codegen/src/isa/s390x/lower/isle.rs
+++ b/cranelift/codegen/src/isa/s390x/lower/isle.rs
@@ -226,7 +226,8 @@ where
     fn u64_from_value(&mut self, val: Value) -> Option<u64> {
         let inst = self.lower_ctx.dfg().value_def(val).inst()?;
         let constant = self.lower_ctx.get_constant(inst)?;
-        Some(constant)
+        let ty = self.lower_ctx.output_ty(inst, 0);
+        Some(zero_extend_to_u64(constant, self.ty_bits(ty).unwrap()))
     }
 
     #[inline]
@@ -516,3 +517,14 @@ where
         self.lower_ctx.emit(inst.clone());
     }
 }
+
+/// Zero-extend the low `from_bits` bits of `value` to a full u64.
+#[inline]
+fn zero_extend_to_u64(value: u64, from_bits: u8) -> u64 {
+    assert!(from_bits <= 64);
+    if from_bits >= 64 {
+        value
+    } else {
+        value & ((1u64 << from_bits) - 1)
+    }
+}