Repository: tetratelabs/wazero
Pull request #1984 (2024-01-30 20:31:33)

wazevo(amd64): fixes calling conv to match Go runtime
there's mismatch in arg/res register order


Patch:
diff --git a/internal/engine/wazevo/backend/isa/amd64/abi.go b/internal/engine/wazevo/backend/isa/amd64/abi.go
index 00b762ef..e9e3c838 100644
--- a/internal/engine/wazevo/backend/isa/amd64/abi.go
+++ b/internal/engine/wazevo/backend/isa/amd64/abi.go
@@ -10,7 +10,7 @@ import (
 // https://github.com/golang/go/blob/49d42128fd8594c172162961ead19ac95e247d24/src/cmd/compile/abi-internal.md#amd64-architecture
 
 var (
-	intArgResultRegs   = []regalloc.RealReg{rax, rcx, rbx, rsi, rdi, r8, r9, r10, r11}
+	intArgResultRegs   = []regalloc.RealReg{rax, rbx, rcx, rdi, rsi, r8, r9, r10, r11}
 	floatArgResultRegs = []regalloc.RealReg{xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7}
 )
 
diff --git a/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s b/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s
index 81c29dda..e9cb131d 100644
--- a/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s
+++ b/internal/engine/wazevo/backend/isa/amd64/abi_entry_amd64.s
@@ -6,7 +6,7 @@ TEXT ·entrypoint(SB), NOSPLIT|NOFRAME, $0-48
 	MOVQ preambleExecutable+0(FP), R11
 	MOVQ functionExectuable+8(FP), R14
 	MOVQ executionContextPtr+16(FP), AX       // First argument is passed in AX.
-	MOVQ moduleContextPtr+24(FP), CX          // Second argument is passed in CX.
+	MOVQ moduleContextPtr+24(FP), BX          // Second argument is passed in BX.
 	MOVQ paramResultSlicePtr+32(FP), R12
 	MOVQ goAllocatedStackSlicePtr+40(FP), R13
 	JMP  R11
diff --git a/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go b/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go
index fcc898e6..6866fabe 100644
--- a/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go
+++ b/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble.go
@@ -62,7 +62,7 @@ func (m *machine) compileEntryPreamble(sig *ssa.Signature) *instruction {
 	var offset uint32
 	for i := range abi.Args {
 		if i < 2 {
-			// module context ptr and execution context ptr are passed in x0 and x1 by the Go assembly function.
+			// module context ptr and execution context ptr are passed in rax and rbx by the Go assembly function.
 			continue
 		}
 		arg := &abi.Args[i]
diff --git a/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go b/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go
index a364044b..1dc1bdb0 100644
--- a/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go
+++ b/internal/engine/wazevo/backend/isa/amd64/abi_go_call.go
@@ -55,7 +55,7 @@ func (m *machine) CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *
 	cur = m.saveRegistersInExecutionContext(cur, execCtrPtr, calleeSavedVRegs)
 
 	if needModuleContextPtr {
-		moduleCtrPtr := rcxVReg // Module context is always the second argument.
+		moduleCtrPtr := rbxVReg // Module context is always the second argument.
 		mem := newAmodeImmReg(
 			wazevoapi.ExecutionContextOffsetGoFunctionCallCalleeModuleContextOpaque.U32(),
 			execCtrPtr)
diff --git a/internal/engine/wazevo/backend/isa/amd64/machine.go b/internal/engine/wazevo/backend/isa/amd64/machine.go
index bb8dce5b..de75a519 100644
--- a/internal/engine/wazevo/backend/isa/amd64/machine.go
+++ b/internal/engine/wazevo/backend/isa/amd64/machine.go
@@ -1471,8 +1471,7 @@ func (m *machine) lowerIDivRem(si *ssa.Instruction, isDiv bool, signed bool) {
 			ifNotMinInt.asJmpIf(condNZ, newOperandLabel(end))
 		} else {
 			// If it is remainder, zeros DX register and compare the divisor to -1.
-			xor := m.allocateInstr()
-			xor.asAluRmiR(aluRmiROpcodeXor, newOperandReg(rdxVReg), rdxVReg, _64)
+			xor := m.allocateInstr().asZeros(rdxVReg)
 			m.insert(xor)
 
 			// We check if the divisor is -1.
diff --git a/internal/engine/wazevo/frontend/frontend.go b/internal/engine/wazevo/frontend/frontend.go
index 60fd3fef..6e7a287f 100644
--- a/internal/engine/wazevo/frontend/frontend.go
+++ b/internal/engine/wazevo/frontend/frontend.go
@@ -138,9 +138,7 @@ func (c *Compiler) declareSignatures(listenerOn bool) {
 
 	c.memmoveSig = ssa.Signature{
 		ID: c.refFuncSig.ID + 1,
-		// dst, src, and the byte count where the order is depending on the architecture.
-		// https://github.com/golang/go/blob/65f056d07ad1db7dd4fb23c4d35cf7b8bd0d6008/src/runtime/memmove_amd64.s#L36-L41
-		// https://github.com/golang/go/blob/65f056d07ad1db7dd4fb23c4d35cf7b8bd0d6008/src/runtime/memmove_arm64.s#L11-L13
+		// dst, src, and the byte count.
 		Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64},
 	}
 
diff --git a/internal/engine/wazevo/frontend/lower.go b/internal/engine/wazevo/frontend/lower.go
index 4774991d..64792c9b 100644
--- a/internal/engine/wazevo/frontend/lower.go
+++ b/internal/engine/wazevo/frontend/lower.go
@@ -4,7 +4,6 @@ import (
 	"encoding/binary"
 	"fmt"
 	"math"
-	"runtime"
 	"strings"
 
 	"github.com/tetratelabs/wazero/api"
@@ -3425,15 +3424,7 @@ func (c *Compiler) memOpSetup(baseAddr ssa.Value, constOffset, operationSizeInBy
 }
 
 func (c *Compiler) callMemmove(dst, src, size ssa.Value) {
-	var args []ssa.Value
-	if runtime.GOARCH == "amd64" {
-		// https://github.com/golang/go/blob/65f056d07ad1db7dd4fb23c4d35cf7b8bd0d6008/src/runtime/memmove_amd64.s#L36-L41
-		args = []ssa.Value{dst, size, src} // TODO: reuse the slice.
-	} else {
-		// https://github.com/golang/go/blob/65f056d07ad1db7dd4fb23c4d35cf7b8bd0d6008/src/runtime/memmove_arm64.s#L11-L13
-		args = []ssa.Value{dst, src, size} // TODO: reuse the slice.
-	}
-
+	args := []ssa.Value{dst, src, size} // TODO: reuse the slice.
 	if size.Type() != ssa.TypeI64 {
 		panic("TODO: memmove size must be i64")
 	}


Test patch:
diff --git a/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble_test.go b/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble_test.go
index 63b81db8..8a8f5c35 100644
--- a/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble_test.go
+++ b/internal/engine/wazevo/backend/isa/amd64/abi_entry_preamble_test.go
@@ -41,12 +41,12 @@ func TestMachineCompileEntryPreamble(t *testing.T) {
 	mov.q %rbp, 16(%rax)
 	mov.q %rsp, 24(%rax)
 	movq %r13, %rsp
-	movzx.lq (%r12), %rbx
-	movq 8(%r12), %rsi
+	movzx.lq (%r12), %rcx
+	movq 8(%r12), %rdi
 	movss 16(%r12), %xmm0
 	movsd 24(%r12), %xmm1
 	movdqu 32(%r12), %xmm2
-	movq 48(%r12), %rdi
+	movq 48(%r12), %rsi
 	callq *%r14
 	movq 16(%rdx), %rbp
 	movq 24(%rdx), %rsp
@@ -68,7 +68,7 @@ func TestMachineCompileEntryPreamble(t *testing.T) {
 	callq *%r14
 	mov.l %rax, (%r12)
 	movdqu %xmm0, 8(%r12)
-	mov.q %rcx, 24(%r12)
+	mov.q %rbx, 24(%r12)
 	movss %xmm1, 32(%r12)
 	movsd %xmm2, 40(%r12)
 	movq 16(%rdx), %rbp
@@ -88,16 +88,16 @@ func TestMachineCompileEntryPreamble(t *testing.T) {
 	mov.q %rbp, 16(%rax)
 	mov.q %rsp, 24(%rax)
 	movq %r13, %rsp
-	movzx.lq (%r12), %rbx
-	movq 8(%r12), %rsi
+	movzx.lq (%r12), %rcx
+	movq 8(%r12), %rdi
 	movss 16(%r12), %xmm0
 	movsd 24(%r12), %xmm1
 	movdqu 32(%r12), %xmm2
-	movq 48(%r12), %rdi
+	movq 48(%r12), %rsi
 	callq *%r14
 	mov.l %rax, (%r12)
 	movdqu %xmm0, 8(%r12)
-	mov.q %rcx, 24(%r12)
+	mov.q %rbx, 24(%r12)
 	movss %xmm1, 32(%r12)
 	movsd %xmm2, 40(%r12)
 	movq 16(%rdx), %rbp
@@ -121,12 +121,12 @@ func TestMachineCompileEntryPreamble(t *testing.T) {
 	mov.q %rsp, 24(%rax)
 	movq %r13, %rsp
 	sub $64, %rsp
-	movzx.lq (%r12), %rbx
-	movq 8(%r12), %rsi
+	movzx.lq (%r12), %rcx
+	movq 8(%r12), %rdi
 	movss 16(%r12), %xmm0
 	movsd 24(%r12), %xmm1
 	movdqu 32(%r12), %xmm2
-	movq 48(%r12), %rdi
+	movq 48(%r12), %rsi
 	movq 56(%r12), %r8
 	movq 64(%r12), %r9
 	movzx.lq 72(%r12), %r10
@@ -175,13 +175,13 @@ func TestMachineCompileEntryPreamble(t *testing.T) {
 	sub $64, %rsp
 	callq *%r14
 	mov.q %rax, (%r12)
-	mov.q %rcx, 8(%r12)
-	mov.l %rbx, 16(%r12)
-	mov.q %rsi, 24(%r12)
+	mov.q %rbx, 8(%r12)
+	mov.l %rcx, 16(%r12)
+	mov.q %rdi, 24(%r12)
 	movss %xmm0, 32(%r12)
 	movsd %xmm1, 40(%r12)
 	movdqu %xmm2, 48(%r12)
-	mov.q %rdi, 64(%r12)
+	mov.q %rsi, 64(%r12)
 	mov.q %r8, 72(%r12)
 	mov.q %r9, 80(%r12)
 	mov.l %r10, 88(%r12)
@@ -231,12 +231,12 @@ func TestMachineCompileEntryPreamble(t *testing.T) {
 	mov.q %rsp, 24(%rax)
 	movq %r13, %rsp
 	sub $128, %rsp
-	movzx.lq (%r12), %rbx
-	movq 8(%r12), %rsi
+	movzx.lq (%r12), %rcx
+	movq 8(%r12), %rdi
 	movss 16(%r12), %xmm0
 	movsd 24(%r12), %xmm1
 	movdqu 32(%r12), %xmm2
-	movq 48(%r12), %rdi
+	movq 48(%r12), %rsi
 	movq 56(%r12), %r8
 	movq 64(%r12), %r9
 	movzx.lq 72(%r12), %r10
@@ -262,13 +262,13 @@ func TestMachineCompileEntryPreamble(t *testing.T) {
 	mov.q %r15, 56(%rsp)
 	callq *%r14
 	mov.q %rax, (%r12)
-	mov.q %rcx, 8(%r12)
-	mov.l %rbx, 16(%r12)
-	mov.q %rsi, 24(%r12)
+	mov.q %rbx, 8(%r12)
+	mov.l %rcx, 16(%r12)
+	mov.q %rdi, 24(%r12)
 	movss %xmm0, 32(%r12)
 	movsd %xmm1, 40(%r12)
 	movdqu %xmm2, 48(%r12)
-	mov.q %rdi, 64(%r12)
+	mov.q %rsi, 64(%r12)
 	mov.q %r8, 72(%r12)
 	mov.q %r9, 80(%r12)
 	mov.l %r10, 88(%r12)
diff --git a/internal/engine/wazevo/backend/isa/amd64/abi_go_call_test.go b/internal/engine/wazevo/backend/isa/amd64/abi_go_call_test.go
index 3aca2b6b..45da2427 100644
--- a/internal/engine/wazevo/backend/isa/amd64/abi_go_call_test.go
+++ b/internal/engine/wazevo/backend/isa/amd64/abi_go_call_test.go
@@ -64,7 +64,7 @@ L2:
 	movdqu %xmm13, 256(%rax)
 	movdqu %xmm14, 272(%rax)
 	movdqu %xmm15, 288(%rax)
-	mov.q %rcx, 1120(%rax)
+	mov.q %rbx, 1120(%rax)
 	sub $32, %rsp
 	movsd %xmm0, (%rsp)
 	pushq $32
@@ -77,7 +77,7 @@ L2:
 	exit_sequence %rax
 L3:
 	add $8, %rsp
-	movq 8(%rsp), %rcx
+	movq 8(%rsp), %rbx
 	movss 16(%rsp), %xmm0
 	movsd 24(%rsp), %xmm1
 	movq 96(%rax), %rdx
@@ -136,12 +136,12 @@ L2:
 	movdqu %xmm13, 256(%rax)
 	movdqu %xmm14, 272(%rax)
 	movdqu %xmm15, 288(%rax)
-	mov.q %rcx, 1120(%rax)
+	mov.q %rbx, 1120(%rax)
 	sub $32, %rsp
 	movsd %xmm0, (%rsp)
 	movsd %xmm1, 8(%rsp)
-	mov.l %rbx, 16(%rsp)
-	mov.l %rsi, 24(%rsp)
+	mov.l %rcx, 16(%rsp)
+	mov.l %rdi, 24(%rsp)
 	pushq $32
 	movl $25606, %r12d
 	mov.l %r12, (%rax)
@@ -207,7 +207,7 @@ L2:
 	movdqu %xmm14, 272(%rax)
 	movdqu %xmm15, 288(%rax)
 	sub $16, %rsp
-	mov.l %rcx, (%rsp)
+	mov.l %rbx, (%rsp)
 	pushq $8
 	movl $2, %r12d
 	mov.l %r12, (%rax)
@@ -284,17 +284,17 @@ L2:
 	movdqu %xmm13, 256(%rax)
 	movdqu %xmm14, 272(%rax)
 	movdqu %xmm15, 288(%rax)
-	mov.q %rcx, 1120(%rax)
+	mov.q %rbx, 1120(%rax)
 	sub $240, %rsp
 	movsd %xmm0, (%rsp)
 	movsd %xmm1, 8(%rsp)
 	movdqu %xmm2, 16(%rsp)
-	mov.l %rbx, 32(%rsp)
-	mov.q %rsi, 40(%rsp)
+	mov.l %rcx, 32(%rsp)
+	mov.q %rdi, 40(%rsp)
 	movss %xmm3, 48(%rsp)
 	movsd %xmm4, 56(%rsp)
 	movdqu %xmm5, 64(%rsp)
-	mov.l %rdi, 80(%rsp)
+	mov.l %rsi, 80(%rsp)
 	mov.q %r8, 88(%rsp)
 	movss %xmm6, 96(%rsp)
 	movsd %xmm7, 104(%rsp)
@@ -316,16 +316,16 @@ L3:
 	add $8, %rsp
 	movsd (%rsp), %xmm0
 	movdqu 8(%rsp), %xmm1
-	movq 32(%rsp), %rcx
+	movq 32(%rsp), %rbx
 	movss 40(%rsp), %xmm2
 	movsd 48(%rsp), %xmm3
 	movdqu 56(%rsp), %xmm4
-	movzx.lq 72(%rsp), %rbx
-	movq 80(%rsp), %rsi
+	movzx.lq 72(%rsp), %rcx
+	movq 80(%rsp), %rdi
 	movss 88(%rsp), %xmm5
 	movsd 96(%rsp), %xmm6
 	movdqu 104(%rsp), %xmm7
-	movzx.lq 120(%rsp), %rdi
+	movzx.lq 120(%rsp), %rsi
 	movq 128(%rsp), %r8
 	movss 136(%rsp), %xmm15
 	movss %xmm15, 40(%rbp)
diff --git a/internal/engine/wazevo/e2e_test.go b/internal/engine/wazevo/e2e_test.go
index 63d938ab..aade7ac9 100644
--- a/internal/engine/wazevo/e2e_test.go
+++ b/internal/engine/wazevo/e2e_test.go
@@ -207,7 +207,7 @@ func TestE2E(t *testing.T) {
 		},
 
 		{
-			name: "divrem_signed_return32 inverted rem div order (different crash)", m: testcases.DivSReturn32_weird.Module,
+			name: "divrem_signed_return32 inverted rem div order", m: testcases.DivSReturn32_weird.Module,
 			calls: []callCase{
 				{
 					params: []uint64{21, 0, 1, 1},