github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/backend/isa/amd64/abi_go_call_test.go (about)

     1  package amd64
     2  
     3  import (
     4  	"context"
     5  	"sort"
     6  	"testing"
     7  
     8  	"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
     9  	"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
    10  	"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
    11  	"github.com/tetratelabs/wazero/internal/testing/require"
    12  )
    13  
    14  func Test_calleeSavedVRegs(t *testing.T) {
    15  	var exp []regalloc.VReg
    16  	regInfo.CalleeSavedRegisters.Range(func(r regalloc.RealReg) {
    17  		exp = append(exp, regInfo.RealRegToVReg[r])
    18  	})
    19  	require.Equal(t, exp, calleeSavedVRegs)
    20  }
    21  
    22  func TestMachine_CompileGoFunctionTrampoline(t *testing.T) {
    23  	for _, tc := range []struct {
    24  		name                 string
    25  		exitCode             wazevoapi.ExitCode
    26  		sig                  *ssa.Signature
    27  		needModuleContextPtr bool
    28  		exp                  string
    29  	}{
    30  		{
    31  			name:     "go call",
    32  			exitCode: wazevoapi.ExitCodeCallGoFunctionWithIndex(100, false),
    33  			sig: &ssa.Signature{
    34  				Params:  []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64},
    35  				Results: []ssa.Type{ssa.TypeI32, ssa.TypeI64, ssa.TypeF32, ssa.TypeF64},
    36  			},
    37  			needModuleContextPtr: true,
    38  			exp: `
    39  	pushq %rbp
    40  	movq %rsp, %rbp
    41  	sub $40, %rsp
    42  	cmpq 40(%rax), %rsp
    43  	jnbe L1
    44  	add $40, %rsp
    45  	pushq %r15
    46  	movabsq $40, %r15
    47  	mov.q %r15, 64(%rax)
    48  	popq %r15
    49  	callq *80(%rax)
    50  	jmp L2
    51  L1:
    52  	add $40, %rsp
    53  L2:
    54  	mov.q %rdx, 96(%rax)
    55  	mov.q %r12, 112(%rax)
    56  	mov.q %r13, 128(%rax)
    57  	mov.q %r14, 144(%rax)
    58  	mov.q %r15, 160(%rax)
    59  	movdqu %xmm8, 176(%rax)
    60  	movdqu %xmm9, 192(%rax)
    61  	movdqu %xmm10, 208(%rax)
    62  	movdqu %xmm11, 224(%rax)
    63  	movdqu %xmm12, 240(%rax)
    64  	movdqu %xmm13, 256(%rax)
    65  	movdqu %xmm14, 272(%rax)
    66  	movdqu %xmm15, 288(%rax)
    67  	mov.q %rbx, 1120(%rax)
    68  	sub $32, %rsp
    69  	movsd %xmm0, (%rsp)
    70  	pushq $32
    71  	movl $25606, %r12d
    72  	mov.l %r12, (%rax)
    73  	mov.q %rsp, 56(%rax)
    74  	mov.q %rbp, 1152(%rax)
    75  	lea L3, %r12
    76  	mov.q %r12, 48(%rax)
    77  	exit_sequence %rax
    78  L3:
    79  	add $8, %rsp
    80  	movq 8(%rsp), %rbx
    81  	movss 16(%rsp), %xmm0
    82  	movsd 24(%rsp), %xmm1
    83  	movq 96(%rax), %rdx
    84  	movq 112(%rax), %r12
    85  	movq 128(%rax), %r13
    86  	movq 144(%rax), %r14
    87  	movq 160(%rax), %r15
    88  	movdqu 176(%rax), %xmm8
    89  	movdqu 192(%rax), %xmm9
    90  	movdqu 208(%rax), %xmm10
    91  	movdqu 224(%rax), %xmm11
    92  	movdqu 240(%rax), %xmm12
    93  	movdqu 256(%rax), %xmm13
    94  	movdqu 272(%rax), %xmm14
    95  	movdqu 288(%rax), %xmm15
    96  	movq (%rsp), %rax
    97  	movq %rbp, %rsp
    98  	popq %rbp
    99  	ret
   100  `,
   101  		},
   102  		{
   103  			name:     "go call",
   104  			exitCode: wazevoapi.ExitCodeCallGoFunctionWithIndex(100, false),
   105  			sig: &ssa.Signature{
   106  				Params:  []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeF64, ssa.TypeI32, ssa.TypeI32},
   107  				Results: []ssa.Type{},
   108  			},
   109  			needModuleContextPtr: true,
   110  			exp: `
   111  	pushq %rbp
   112  	movq %rsp, %rbp
   113  	sub $40, %rsp
   114  	cmpq 40(%rax), %rsp
   115  	jnbe L1
   116  	add $40, %rsp
   117  	pushq %r15
   118  	movabsq $40, %r15
   119  	mov.q %r15, 64(%rax)
   120  	popq %r15
   121  	callq *80(%rax)
   122  	jmp L2
   123  L1:
   124  	add $40, %rsp
   125  L2:
   126  	mov.q %rdx, 96(%rax)
   127  	mov.q %r12, 112(%rax)
   128  	mov.q %r13, 128(%rax)
   129  	mov.q %r14, 144(%rax)
   130  	mov.q %r15, 160(%rax)
   131  	movdqu %xmm8, 176(%rax)
   132  	movdqu %xmm9, 192(%rax)
   133  	movdqu %xmm10, 208(%rax)
   134  	movdqu %xmm11, 224(%rax)
   135  	movdqu %xmm12, 240(%rax)
   136  	movdqu %xmm13, 256(%rax)
   137  	movdqu %xmm14, 272(%rax)
   138  	movdqu %xmm15, 288(%rax)
   139  	mov.q %rbx, 1120(%rax)
   140  	sub $32, %rsp
   141  	movsd %xmm0, (%rsp)
   142  	movsd %xmm1, 8(%rsp)
   143  	mov.l %rcx, 16(%rsp)
   144  	mov.l %rdi, 24(%rsp)
   145  	pushq $32
   146  	movl $25606, %r12d
   147  	mov.l %r12, (%rax)
   148  	mov.q %rsp, 56(%rax)
   149  	mov.q %rbp, 1152(%rax)
   150  	lea L3, %r12
   151  	mov.q %r12, 48(%rax)
   152  	exit_sequence %rax
   153  L3:
   154  	add $8, %rsp
   155  	movq 96(%rax), %rdx
   156  	movq 112(%rax), %r12
   157  	movq 128(%rax), %r13
   158  	movq 144(%rax), %r14
   159  	movq 160(%rax), %r15
   160  	movdqu 176(%rax), %xmm8
   161  	movdqu 192(%rax), %xmm9
   162  	movdqu 208(%rax), %xmm10
   163  	movdqu 224(%rax), %xmm11
   164  	movdqu 240(%rax), %xmm12
   165  	movdqu 256(%rax), %xmm13
   166  	movdqu 272(%rax), %xmm14
   167  	movdqu 288(%rax), %xmm15
   168  	movq %rbp, %rsp
   169  	popq %rbp
   170  	ret
   171  `,
   172  		},
   173  		{
   174  			name:     "grow memory",
   175  			exitCode: wazevoapi.ExitCodeGrowMemory,
   176  			sig: &ssa.Signature{
   177  				Params:  []ssa.Type{ssa.TypeI32, ssa.TypeI32},
   178  				Results: []ssa.Type{ssa.TypeI32},
   179  			},
   180  			exp: `
   181  	pushq %rbp
   182  	movq %rsp, %rbp
   183  	sub $24, %rsp
   184  	cmpq 40(%rax), %rsp
   185  	jnbe L1
   186  	add $24, %rsp
   187  	pushq %r15
   188  	movabsq $24, %r15
   189  	mov.q %r15, 64(%rax)
   190  	popq %r15
   191  	callq *80(%rax)
   192  	jmp L2
   193  L1:
   194  	add $24, %rsp
   195  L2:
   196  	mov.q %rdx, 96(%rax)
   197  	mov.q %r12, 112(%rax)
   198  	mov.q %r13, 128(%rax)
   199  	mov.q %r14, 144(%rax)
   200  	mov.q %r15, 160(%rax)
   201  	movdqu %xmm8, 176(%rax)
   202  	movdqu %xmm9, 192(%rax)
   203  	movdqu %xmm10, 208(%rax)
   204  	movdqu %xmm11, 224(%rax)
   205  	movdqu %xmm12, 240(%rax)
   206  	movdqu %xmm13, 256(%rax)
   207  	movdqu %xmm14, 272(%rax)
   208  	movdqu %xmm15, 288(%rax)
   209  	sub $16, %rsp
   210  	mov.l %rbx, (%rsp)
   211  	pushq $8
   212  	movl $2, %r12d
   213  	mov.l %r12, (%rax)
   214  	mov.q %rsp, 56(%rax)
   215  	mov.q %rbp, 1152(%rax)
   216  	lea L3, %r12
   217  	mov.q %r12, 48(%rax)
   218  	exit_sequence %rax
   219  L3:
   220  	add $8, %rsp
   221  	movq 96(%rax), %rdx
   222  	movq 112(%rax), %r12
   223  	movq 128(%rax), %r13
   224  	movq 144(%rax), %r14
   225  	movq 160(%rax), %r15
   226  	movdqu 176(%rax), %xmm8
   227  	movdqu 192(%rax), %xmm9
   228  	movdqu 208(%rax), %xmm10
   229  	movdqu 224(%rax), %xmm11
   230  	movdqu 240(%rax), %xmm12
   231  	movdqu 256(%rax), %xmm13
   232  	movdqu 272(%rax), %xmm14
   233  	movdqu 288(%rax), %xmm15
   234  	movq (%rsp), %rax
   235  	movq %rbp, %rsp
   236  	popq %rbp
   237  	ret
   238  `,
   239  		},
   240  		{
   241  			name:     "many",
   242  			exitCode: wazevoapi.ExitCodeCallGoFunctionWithIndex(100, false),
   243  			sig: &ssa.Signature{
   244  				Params: []ssa.Type{
   245  					ssa.TypeI64, ssa.TypeI64, ssa.TypeF64,
   246  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   247  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   248  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   249  				},
   250  				Results: []ssa.Type{
   251  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   252  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   253  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   254  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   255  					ssa.TypeF64, ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeF32,
   256  				},
   257  			},
   258  			exp: `
   259  	pushq %rbp
   260  	movq %rsp, %rbp
   261  	sub $248, %rsp
   262  	cmpq 40(%rax), %rsp
   263  	jnbe L1
   264  	add $248, %rsp
   265  	pushq %r15
   266  	movabsq $248, %r15
   267  	mov.q %r15, 64(%rax)
   268  	popq %r15
   269  	callq *80(%rax)
   270  	jmp L2
   271  L1:
   272  	add $248, %rsp
   273  L2:
   274  	mov.q %rdx, 96(%rax)
   275  	mov.q %r12, 112(%rax)
   276  	mov.q %r13, 128(%rax)
   277  	mov.q %r14, 144(%rax)
   278  	mov.q %r15, 160(%rax)
   279  	movdqu %xmm8, 176(%rax)
   280  	movdqu %xmm9, 192(%rax)
   281  	movdqu %xmm10, 208(%rax)
   282  	movdqu %xmm11, 224(%rax)
   283  	movdqu %xmm12, 240(%rax)
   284  	movdqu %xmm13, 256(%rax)
   285  	movdqu %xmm14, 272(%rax)
   286  	movdqu %xmm15, 288(%rax)
   287  	mov.q %rbx, 1120(%rax)
   288  	sub $240, %rsp
   289  	movsd %xmm0, (%rsp)
   290  	movsd %xmm1, 8(%rsp)
   291  	movdqu %xmm2, 16(%rsp)
   292  	mov.l %rcx, 32(%rsp)
   293  	mov.q %rdi, 40(%rsp)
   294  	movss %xmm3, 48(%rsp)
   295  	movsd %xmm4, 56(%rsp)
   296  	movdqu %xmm5, 64(%rsp)
   297  	mov.l %rsi, 80(%rsp)
   298  	mov.q %r8, 88(%rsp)
   299  	movss %xmm6, 96(%rsp)
   300  	movsd %xmm7, 104(%rsp)
   301  	movdqu 16(%rbp), %xmm15
   302  	movdqu %xmm15, 112(%rsp)
   303  	mov.l %r9, 128(%rsp)
   304  	mov.q %r10, 136(%rsp)
   305  	movss 32(%rbp), %xmm15
   306  	movss %xmm15, 144(%rsp)
   307  	pushq $240
   308  	movl $25606, %r12d
   309  	mov.l %r12, (%rax)
   310  	mov.q %rsp, 56(%rax)
   311  	mov.q %rbp, 1152(%rax)
   312  	lea L3, %r12
   313  	mov.q %r12, 48(%rax)
   314  	exit_sequence %rax
   315  L3:
   316  	add $8, %rsp
   317  	movsd (%rsp), %xmm0
   318  	movdqu 8(%rsp), %xmm1
   319  	movq 32(%rsp), %rbx
   320  	movss 40(%rsp), %xmm2
   321  	movsd 48(%rsp), %xmm3
   322  	movdqu 56(%rsp), %xmm4
   323  	movzx.lq 72(%rsp), %rcx
   324  	movq 80(%rsp), %rdi
   325  	movss 88(%rsp), %xmm5
   326  	movsd 96(%rsp), %xmm6
   327  	movdqu 104(%rsp), %xmm7
   328  	movzx.lq 120(%rsp), %rsi
   329  	movq 128(%rsp), %r8
   330  	movss 136(%rsp), %xmm15
   331  	movss %xmm15, 40(%rbp)
   332  	movsd 144(%rsp), %xmm15
   333  	movsd %xmm15, 48(%rbp)
   334  	movdqu 152(%rsp), %xmm15
   335  	movdqu %xmm15, 56(%rbp)
   336  	movzx.lq 168(%rsp), %r9
   337  	movq 176(%rsp), %r10
   338  	movss 184(%rsp), %xmm15
   339  	movss %xmm15, 72(%rbp)
   340  	movsd 192(%rsp), %xmm15
   341  	movsd %xmm15, 80(%rbp)
   342  	movdqu 200(%rsp), %xmm15
   343  	movdqu %xmm15, 88(%rbp)
   344  	movzx.lq 216(%rsp), %r11
   345  	movq 224(%rsp), %r15
   346  	mov.q %r15, 104(%rbp)
   347  	movss 232(%rsp), %xmm15
   348  	movss %xmm15, 112(%rbp)
   349  	movq 96(%rax), %rdx
   350  	movq 112(%rax), %r12
   351  	movq 128(%rax), %r13
   352  	movq 144(%rax), %r14
   353  	movq 160(%rax), %r15
   354  	movdqu 176(%rax), %xmm8
   355  	movdqu 192(%rax), %xmm9
   356  	movdqu 208(%rax), %xmm10
   357  	movdqu 224(%rax), %xmm11
   358  	movdqu 240(%rax), %xmm12
   359  	movdqu 256(%rax), %xmm13
   360  	movdqu 272(%rax), %xmm14
   361  	movdqu 288(%rax), %xmm15
   362  	movq 24(%rsp), %rax
   363  	movq %rbp, %rsp
   364  	popq %rbp
   365  	ret
   366  `,
   367  			needModuleContextPtr: true,
   368  		},
   369  	} {
   370  		t.Run(tc.name, func(t *testing.T) {
   371  			_, _, m := newSetupWithMockContext()
   372  			m.CompileGoFunctionTrampoline(tc.exitCode, tc.sig, tc.needModuleContextPtr)
   373  			require.Equal(t, tc.exp, m.Format())
   374  			err := m.Encode(context.Background())
   375  			require.NoError(t, err)
   376  		})
   377  	}
   378  }
   379  
   380  func Test_stackGrowSaveVRegs(t *testing.T) {
   381  	var exp []regalloc.VReg
   382  	for _, rs := range regInfo.AllocatableRegisters {
   383  		for _, r := range rs {
   384  			if r != rsp && r != rbp && r != rax {
   385  				exp = append(exp, regInfo.RealRegToVReg[r])
   386  			}
   387  		}
   388  	}
   389  	// Copy stackGrowSaveVRegs to avoid modifying the original.
   390  	var actual []regalloc.VReg
   391  	actual = append(actual, stackGrowSaveVRegs...)
   392  	sort.Slice(exp, func(i, j int) bool { return exp[i].ID() < exp[j].ID() })
   393  	sort.Slice(actual, func(i, j int) bool { return actual[i].ID() < actual[j].ID() })
   394  	require.Equal(t, exp, actual)
   395  }
   396  
   397  func TestMachine_CompileStackGrowCallSequence(t *testing.T) {
   398  	_, _, m := newSetupWithMockContext()
   399  	_ = m.CompileStackGrowCallSequence()
   400  
   401  	require.Equal(t, `
   402  	pushq %rbp
   403  	movq %rsp, %rbp
   404  	mov.q %rdx, 96(%rax)
   405  	mov.q %r12, 112(%rax)
   406  	mov.q %r13, 128(%rax)
   407  	mov.q %r14, 144(%rax)
   408  	mov.q %r15, 160(%rax)
   409  	mov.q %rcx, 176(%rax)
   410  	mov.q %rbx, 192(%rax)
   411  	mov.q %rsi, 208(%rax)
   412  	mov.q %rdi, 224(%rax)
   413  	mov.q %r8, 240(%rax)
   414  	mov.q %r9, 256(%rax)
   415  	mov.q %r10, 272(%rax)
   416  	mov.q %r11, 288(%rax)
   417  	movdqu %xmm8, 304(%rax)
   418  	movdqu %xmm9, 320(%rax)
   419  	movdqu %xmm10, 336(%rax)
   420  	movdqu %xmm11, 352(%rax)
   421  	movdqu %xmm12, 368(%rax)
   422  	movdqu %xmm13, 384(%rax)
   423  	movdqu %xmm14, 400(%rax)
   424  	movdqu %xmm15, 416(%rax)
   425  	movdqu %xmm0, 432(%rax)
   426  	movdqu %xmm1, 448(%rax)
   427  	movdqu %xmm2, 464(%rax)
   428  	movdqu %xmm3, 480(%rax)
   429  	movdqu %xmm4, 496(%rax)
   430  	movdqu %xmm5, 512(%rax)
   431  	movdqu %xmm6, 528(%rax)
   432  	movdqu %xmm7, 544(%rax)
   433  	movl $1, %r12d
   434  	mov.l %r12, (%rax)
   435  	mov.q %rsp, 56(%rax)
   436  	mov.q %rbp, 1152(%rax)
   437  	lea L1, %r12
   438  	mov.q %r12, 48(%rax)
   439  	exit_sequence %rax
   440  L1:
   441  	movq 96(%rax), %rdx
   442  	movq 112(%rax), %r12
   443  	movq 128(%rax), %r13
   444  	movq 144(%rax), %r14
   445  	movq 160(%rax), %r15
   446  	movq 176(%rax), %rcx
   447  	movq 192(%rax), %rbx
   448  	movq 208(%rax), %rsi
   449  	movq 224(%rax), %rdi
   450  	movq 240(%rax), %r8
   451  	movq 256(%rax), %r9
   452  	movq 272(%rax), %r10
   453  	movq 288(%rax), %r11
   454  	movdqu 304(%rax), %xmm8
   455  	movdqu 320(%rax), %xmm9
   456  	movdqu 336(%rax), %xmm10
   457  	movdqu 352(%rax), %xmm11
   458  	movdqu 368(%rax), %xmm12
   459  	movdqu 384(%rax), %xmm13
   460  	movdqu 400(%rax), %xmm14
   461  	movdqu 416(%rax), %xmm15
   462  	movdqu 432(%rax), %xmm0
   463  	movdqu 448(%rax), %xmm1
   464  	movdqu 464(%rax), %xmm2
   465  	movdqu 480(%rax), %xmm3
   466  	movdqu 496(%rax), %xmm4
   467  	movdqu 512(%rax), %xmm5
   468  	movdqu 528(%rax), %xmm6
   469  	movdqu 544(%rax), %xmm7
   470  	movq %rbp, %rsp
   471  	popq %rbp
   472  	ret
   473  `, m.Format())
   474  }
   475  
   476  func TestMachine_insertStackBoundsCheck(t *testing.T) {
   477  	for _, tc := range []struct {
   478  		exp               string
   479  		requiredStackSize int64
   480  	}{
   481  		{
   482  			requiredStackSize: 0x1000,
   483  			exp: `
   484  	sub $4096, %rsp
   485  	cmpq 40(%rax), %rsp
   486  	jnbe L1
   487  	add $4096, %rsp
   488  	pushq %r15
   489  	movabsq $4096, %r15
   490  	mov.q %r15, 64(%rax)
   491  	popq %r15
   492  	callq *80(%rax)
   493  	jmp L2
   494  L1:
   495  	add $4096, %rsp
   496  L2:
   497  `,
   498  		},
   499  		{
   500  			requiredStackSize: 0x10,
   501  			exp: `
   502  	sub $16, %rsp
   503  	cmpq 40(%rax), %rsp
   504  	jnbe L1
   505  	add $16, %rsp
   506  	pushq %r15
   507  	movabsq $16, %r15
   508  	mov.q %r15, 64(%rax)
   509  	popq %r15
   510  	callq *80(%rax)
   511  	jmp L2
   512  L1:
   513  	add $16, %rsp
   514  L2:
   515  `,
   516  		},
   517  	} {
   518  		tc := tc
   519  		t.Run(tc.exp, func(t *testing.T) {
   520  			_, _, m := newSetupWithMockContext()
   521  			m.ectx.RootInstr = m.allocateNop()
   522  			m.insertStackBoundsCheck(tc.requiredStackSize, m.ectx.RootInstr)
   523  			err := m.Encode(context.Background())
   524  			require.NoError(t, err)
   525  			require.Equal(t, tc.exp, m.Format())
   526  		})
   527  	}
   528  }