Repository: bytecodealliance/wasmtime
Pull request #7771 (2024-01-11 21:29:06)

[17.0.0] Backport fix x64 option i128 abi
LLVM passes the tag in rax and the u128 val in rdx/rcx. Before this change Cranelift would pass the first half of the value in rdx and the second half using an implicit return value pointer.

Backport of https://github.com/bytecodealliance/wasmtime/pull/7770 to 17.0.0


bjorn3: This only affects programs that use enable_llvm_abi_extensions, which is not Wasmtime. As such I think this ok to backport.

Patch:
diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs
index 49c54d529..d7df15c61 100644
--- a/cranelift/codegen/src/isa/x64/abi.rs
+++ b/cranelift/codegen/src/isa/x64/abi.rs
@@ -222,7 +222,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
                         ArgsOrRets::Args => {
                             get_intreg_for_arg(&call_conv, next_gpr, next_param_idx)
                         }
-                        ArgsOrRets::Rets => get_intreg_for_retval(&call_conv, next_gpr),
+                        ArgsOrRets::Rets => get_intreg_for_retval(&call_conv, flags, next_gpr),
                     }
                 } else {
                     match args_or_rets {
@@ -1035,7 +1035,11 @@ fn get_fltreg_for_arg(call_conv: &CallConv, idx: usize, arg_idx: usize) -> Optio
     }
 }
 
-fn get_intreg_for_retval(call_conv: &CallConv, intreg_idx: usize) -> Option<Reg> {
+fn get_intreg_for_retval(
+    call_conv: &CallConv,
+    flags: &settings::Flags,
+    intreg_idx: usize,
+) -> Option<Reg> {
     match call_conv {
         CallConv::Tail => match intreg_idx {
             0 => Some(regs::rax()),
@@ -1057,6 +1061,7 @@ fn get_intreg_for_retval(call_conv: &CallConv, intreg_idx: usize) -> Option<Reg>
         CallConv::Fast | CallConv::Cold | CallConv::SystemV => match intreg_idx {
             0 => Some(regs::rax()),
             1 => Some(regs::rdx()),
+            2 if flags.enable_llvm_abi_extensions() => Some(regs::rcx()),
             _ => None,
         },
         CallConv::WindowsFastcall => match intreg_idx {


Test patch:
diff --git a/cranelift/filetests/filetests/isa/x64/i128.clif b/cranelift/filetests/filetests/isa/x64/i128.clif
index 0654089de..eb69119cc 100644
--- a/cranelift/filetests/filetests/isa/x64/i128.clif
+++ b/cranelift/filetests/filetests/isa/x64/i128.clif
@@ -1366,17 +1366,17 @@ block0(v0: i128):
 ;   pushq   %rbp
 ;   movq    %rsp, %rbp
 ; block0:
-;   movq    %rdi, 0(%rdx)
-;   movq    %rsi, 8(%rdx)
-;   movq    %rdi, 16(%rdx)
-;   movq    %rsi, 24(%rdx)
+;   movq    %rsi, 0(%rdx)
+;   movq    %rdi, 8(%rdx)
+;   movq    %rsi, 16(%rdx)
+;   movq    %rdi, 24(%rdx)
 ;   movq    %rdi, 32(%rdx)
-;   movq    %rdi, 40(%rdx)
-;   movq    %rsi, 48(%rdx)
-;   movq    %rdi, 56(%rdx)
-;   movq    %rdi, %rax
-;   movq    %rsi, 64(%rdx)
+;   movq    %rsi, 40(%rdx)
+;   movq    %rdi, 48(%rdx)
+;   movq    %rdi, %rcx
+;   movq    %rsi, 56(%rdx)
 ;   movq    %rsi, %rdx
+;   movq    %rcx, %rax
 ;   movq    %rbp, %rsp
 ;   popq    %rbp
 ;   ret
@@ -1386,17 +1386,17 @@ block0(v0: i128):
 ;   pushq %rbp
 ;   movq %rsp, %rbp
 ; block1: ; offset 0x4
-;   movq %rdi, (%rdx)
-;   movq %rsi, 8(%rdx)
-;   movq %rdi, 0x10(%rdx)
-;   movq %rsi, 0x18(%rdx)
+;   movq %rsi, (%rdx)
+;   movq %rdi, 8(%rdx)
+;   movq %rsi, 0x10(%rdx)
+;   movq %rdi, 0x18(%rdx)
 ;   movq %rdi, 0x20(%rdx)
-;   movq %rdi, 0x28(%rdx)
-;   movq %rsi, 0x30(%rdx)
-;   movq %rdi, 0x38(%rdx)
-;   movq %rdi, %rax
-;   movq %rsi, 0x40(%rdx)
+;   movq %rsi, 0x28(%rdx)
+;   movq %rdi, 0x30(%rdx)
+;   movq %rdi, %rcx
+;   movq %rsi, 0x38(%rdx)
 ;   movq %rsi, %rdx
+;   movq %rcx, %rax
 ;   movq %rbp, %rsp
 ;   popq %rbp
 ;   retq
@@ -1421,12 +1421,10 @@ block0(v0: i128, v1: i128):
 ;   load_ext_name %g+0, %r9
 ;   call    *%r9
 ;   movq    0(%rsp), %r8
-;   movq    8(%rsp), %r9
 ;   addq    %rsp, $16, %rsp
 ;   virtual_sp_offset_adjust -16
-;   movq    %r13, %rcx
-;   movq    %r8, 0(%rcx)
-;   movq    %r9, 8(%rcx)
+;   movq    %r13, %r9
+;   movq    %r8, 0(%r9)
 ;   movq    0(%rsp), %r13
 ;   addq    %rsp, $16, %rsp
 ;   movq    %rbp, %rsp
@@ -1446,11 +1444,9 @@ block0(v0: i128, v1: i128):
 ;   movabsq $0, %r9 ; reloc_external Abs8 %g 0
 ;   callq *%r9
 ;   movq (%rsp), %r8
-;   movq 8(%rsp), %r9
 ;   addq $0x10, %rsp
-;   movq %r13, %rcx
-;   movq %r8, (%rcx)
-;   movq %r9, 8(%rcx)
+;   movq %r13, %r9
+;   movq %r8, (%r9)
 ;   movq (%rsp), %r13
 ;   addq $0x10, %rsp
 ;   movq %rbp, %rsp
diff --git a/cranelift/filetests/filetests/isa/x64/llvm-abi-option-u128.clif b/cranelift/filetests/filetests/isa/x64/llvm-abi-option-u128.clif
new file mode 100644
index 000000000..c777f9848
--- /dev/null
+++ b/cranelift/filetests/filetests/isa/x64/llvm-abi-option-u128.clif
@@ -0,0 +1,36 @@
+test compile precise-output
+set enable_llvm_abi_extensions=1
+target x86_64
+
+function u0:0(i64) -> i64, i128 system_v {
+block0(v0: i64):
+    v1 = iconst.i64 0x1000_0000_0000_0000
+    v2 = iconst.i64 0x2000_0000_0000_0000
+    v3 = iconcat v1, v2
+    v6 = iconst.i64 1
+    return v6, v3
+}
+
+; VCode:
+;   pushq   %rbp
+;   movq    %rsp, %rbp
+; block0:
+;   movabsq $1152921504606846976, %rdx
+;   movabsq $2305843009213693952, %rcx
+;   movl    $1, %eax
+;   movq    %rbp, %rsp
+;   popq    %rbp
+;   ret
+;
+; Disassembled:
+; block0: ; offset 0x0
+;   pushq %rbp
+;   movq %rsp, %rbp
+; block1: ; offset 0x4
+;   movabsq $0x1000000000000000, %rdx
+;   movabsq $0x2000000000000000, %rcx
+;   movl $1, %eax
+;   movq %rbp, %rsp
+;   popq %rbp
+;   retq
+