Repository: bytecodealliance/wasmtime
Pull request #7325 (2023-10-22 15:20:44)

Preserve uext and sext flags for parameters on x86_64 and apple aarch64
This is required by the ABI and prevents a miscompilation when calling LLVM compiled functions.

Fixes https://github.com/bytecodealliance/wasmtime/issues/7210
Fixes https://github.com/bjorn3/rustc_codegen_cranelift/issues/1395


bjorn3: Moved it from a precise-output test to a regular compile test as precise-output doesn't allow any comments.
bjorn3: If possible a patch release with this would be nice. It is the last known miscompilation in cg_clif and IMO a blocker for https://github.com/rust-lang/rust/pull/81746.

Patch:
diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs
index bcf865d26..b5d6e56fc 100644
--- a/cranelift/codegen/src/isa/aarch64/abi.rs
+++ b/cranelift/codegen/src/isa/aarch64/abi.rs
@@ -1148,10 +1148,14 @@ impl ABIMachineSpec for AArch64MachineDeps {
     }
 
     fn get_ext_mode(
-        _call_conv: isa::CallConv,
-        _specified: ir::ArgumentExtension,
+        call_conv: isa::CallConv,
+        specified: ir::ArgumentExtension,
     ) -> ir::ArgumentExtension {
-        ir::ArgumentExtension::None
+        if call_conv == isa::CallConv::AppleAarch64 {
+            specified
+        } else {
+            ir::ArgumentExtension::None
+        }
     }
 
     fn compute_frame_layout(
diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs
index be005e102..d99933500 100644
--- a/cranelift/codegen/src/isa/x64/abi.rs
+++ b/cranelift/codegen/src/isa/x64/abi.rs
@@ -809,9 +809,9 @@ impl ABIMachineSpec for X64ABIMachineSpec {
 
     fn get_ext_mode(
         _call_conv: isa::CallConv,
-        _specified: ir::ArgumentExtension,
+        specified: ir::ArgumentExtension,
     ) -> ir::ArgumentExtension {
-        ir::ArgumentExtension::None
+        specified
     }
 
     fn compute_frame_layout(
diff --git a/examples/threads.rs b/examples/threads.rs
index 3c3564833..1c75bd167 100644
--- a/examples/threads.rs
+++ b/examples/threads.rs
@@ -15,7 +15,7 @@ const N_REPS: i32 = 3;
 fn main() -> Result<()> {
     println!("Initializing...");
 
-    // Initialize global per-process state. This state will be shared amonst all
+    // Initialize global per-process state. This state will be shared amongst all
     // threads. Notably this includes the compiled module as well as a `Linker`,
     // which contains all our host functions we want to define.
     let engine = Engine::default();


Test patch:
diff --git a/cranelift/filetests/filetests/isa/aarch64/uext-sext-handling.clif b/cranelift/filetests/filetests/isa/aarch64/uext-sext-handling.clif
new file mode 100644
index 000000000..473f3b7f1
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/aarch64/uext-sext-handling.clif
@@ -0,0 +1,36 @@
+test compile
+target aarch64
+
+; The aapcs64 call conv ignores the uext and sext flags
+function u0:0(i8) system_v {
+    sig0 = (i8 uext) system_v
+    fn0 = u0:0 sig0
+
+block0(v0: i8):
+    call fn0(v0)
+    return
+}
+
+; check: stp fp, lr, [sp, #-16]!
+; nextln: mov fp, sp
+; nextln: block0:
+; check-not: uxtb w0, w0
+; nextln: load_ext_name x2, User(userextname0)+0
+; nextln: blr x2
+
+; The aaple aarch64 call conv respects the uext and sext flags
+function u0:0(i8) apple_aarch64 {
+    sig0 = (i8 uext) apple_aarch64
+    fn0 = u0:0 sig0
+
+block0(v0: i8):
+    call fn0(v0)
+    return
+}
+
+; check: stp fp, lr, [sp, #-16]!
+; nextln: mov fp, sp
+; nextln: block0:
+; nextln: uxtb w0, w0
+; nextln: load_ext_name x4, User(userextname0)+0
+; nextln: blr x4
diff --git a/cranelift/filetests/filetests/isa/x64/uext-sext-handling.clif b/cranelift/filetests/filetests/isa/x64/uext-sext-handling.clif
new file mode 100644
index 000000000..0908bec08
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/x64/uext-sext-handling.clif
@@ -0,0 +1,38 @@
+test compile
+target x86_64
+
+; The x86_64 system_v call conv respects uext and sext
+function u0:0(i8) system_v {
+    sig0 = (i8 uext) system_v
+    fn0 = u0:0 sig0
+
+block0(v0: i8):
+    call fn0(v0)
+    return
+}
+
+; check: pushq   %rbp
+; nextln: movq    %rsp, %rbp
+; nextln: block0:
+; nextln: movzbq  %dil, %rdi
+; nextln: load_ext_name userextname0+0, %rdx
+; nextln: call    *%rdx
+
+; The x86_64 windows_fastcall call conv respects uext and sext
+function u0:0(i8) windows_fastcall {
+    sig0 = (i8 uext) windows_fastcall
+    fn0 = u0:0 sig0
+
+block0(v0: i8):
+    call fn0(v0)
+    return
+}
+
+; check: pushq   %rbp
+; nextln: movq    %rsp, %rbp
+; nextln: block0:
+; nextln: subq    %rsp, $$32, %rsp
+; nextln: virtual_sp_offset_adjust 32
+; nextln: movzbq  %cl, %rcx
+; nextln: load_ext_name userextname0+0, %r9
+; nextln: call    *%r9