github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/backend/isa/arm64/abi_go_call_test.go (about)

     1  package arm64
     2  
     3  import (
     4  	"sort"
     5  	"testing"
     6  
     7  	"github.com/wasilibs/wazerox/internal/engine/wazevo/backend"
     8  	"github.com/wasilibs/wazerox/internal/engine/wazevo/backend/regalloc"
     9  	"github.com/wasilibs/wazerox/internal/engine/wazevo/ssa"
    10  	"github.com/wasilibs/wazerox/internal/engine/wazevo/wazevoapi"
    11  	"github.com/wasilibs/wazerox/internal/testing/require"
    12  )
    13  
    14  func Test_calleeSavedRegistersSorted(t *testing.T) {
    15  	var exp []regalloc.VReg
    16  	for i, r := range regInfo.CalleeSavedRegisters {
    17  		if r {
    18  			exp = append(exp, regInfo.RealRegToVReg[i])
    19  		}
    20  	}
    21  	sort.Slice(exp, func(i, j int) bool {
    22  		return exp[i].RealReg() < exp[j].RealReg()
    23  	})
    24  
    25  	require.Equal(t, exp, calleeSavedRegistersSorted)
    26  }
    27  
    28  func TestMachine_CompileGoFunctionTrampoline(t *testing.T) {
    29  	for _, tc := range []struct {
    30  		name                 string
    31  		exitCode             wazevoapi.ExitCode
    32  		sig                  *ssa.Signature
    33  		needModuleContextPtr bool
    34  		exp                  string
    35  	}{
    36  		{
    37  			name:                 "listener",
    38  			exitCode:             wazevoapi.ExitCodeCallListenerBefore,
    39  			needModuleContextPtr: true,
    40  			sig: &ssa.Signature{
    41  				Params: []ssa.Type{
    42  					ssa.TypeI64, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32, ssa.TypeV128,
    43  					ssa.TypeI64, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32, ssa.TypeV128,
    44  					ssa.TypeI64, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32, ssa.TypeV128,
    45  					ssa.TypeI64, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32, ssa.TypeV128,
    46  				},
    47  				Results: []ssa.Type{
    48  					ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32,
    49  					ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32,
    50  					ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32,
    51  					ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32,
    52  					ssa.TypeV128, ssa.TypeI32, ssa.TypeI64, ssa.TypeV128, ssa.TypeF32,
    53  				},
    54  			},
    55  			exp: `
    56  	movz x27, #0xa0, lsl 0
    57  	sub sp, sp, x27
    58  	stp x30, x27, [sp, #-0x10]!
    59  	sub x27, sp, #0x130
    60  	ldr x11, [x0, #0x28]
    61  	subs xzr, x27, x11
    62  	b.ge #0x14
    63  	movz x27, #0x130, lsl 0
    64  	str x27, [x0, #0x40]
    65  	ldr x27, [x0, #0x50]
    66  	bl x27
    67  	add x17, sp, #0x10
    68  	str x19, [x0, #0x60]
    69  	str x20, [x0, #0x70]
    70  	str x21, [x0, #0x80]
    71  	str x22, [x0, #0x90]
    72  	str x23, [x0, #0xa0]
    73  	str x24, [x0, #0xb0]
    74  	str x25, [x0, #0xc0]
    75  	str x26, [x0, #0xd0]
    76  	str x28, [x0, #0xe0]
    77  	str q18, [x0, #0xf0]
    78  	str q19, [x0, #0x100]
    79  	str q20, [x0, #0x110]
    80  	str q21, [x0, #0x120]
    81  	str q22, [x0, #0x130]
    82  	str q23, [x0, #0x140]
    83  	str q24, [x0, #0x150]
    84  	str q25, [x0, #0x160]
    85  	str q26, [x0, #0x170]
    86  	str q27, [x0, #0x180]
    87  	str q28, [x0, #0x190]
    88  	str q29, [x0, #0x1a0]
    89  	str q30, [x0, #0x1b0]
    90  	str q31, [x0, #0x1c0]
    91  	str x1, [x0, #0x460]
    92  	sub sp, sp, #0x120
    93  	mov x15, sp
    94  	str q0, [x15], #0x10
    95  	str d1, [x15], #0x8
    96  	str q2, [x15], #0x10
    97  	str x2, [x15], #0x8
    98  	str x3, [x15], #0x8
    99  	str q3, [x15], #0x10
   100  	str d4, [x15], #0x8
   101  	str q5, [x15], #0x10
   102  	str x4, [x15], #0x8
   103  	str x5, [x15], #0x8
   104  	str q6, [x15], #0x10
   105  	str d7, [x15], #0x8
   106  	ldr q11, [x17], #0x10
   107  	str q11, [x15], #0x10
   108  	str x6, [x15], #0x8
   109  	str x7, [x15], #0x8
   110  	ldr q11, [x17], #0x10
   111  	str q11, [x15], #0x10
   112  	ldr s11, [x17], #0x8
   113  	str d11, [x15], #0x8
   114  	ldr q11, [x17], #0x10
   115  	str q11, [x15], #0x10
   116  	movz x27, #0x120, lsl 0
   117  	movz x16, #0x23, lsl 0
   118  	stp x27, x16, [sp, #-0x10]!
   119  	orr w17, wzr, #0xe
   120  	str w17, [x0]
   121  	mov x27, sp
   122  	str x27, [x0, #0x38]
   123  	adr x27, #0x20
   124  	str x27, [x0, #0x30]
   125  	exit_sequence x0
   126  	ldr x19, [x0, #0x60]
   127  	ldr x20, [x0, #0x70]
   128  	ldr x21, [x0, #0x80]
   129  	ldr x22, [x0, #0x90]
   130  	ldr x23, [x0, #0xa0]
   131  	ldr x24, [x0, #0xb0]
   132  	ldr x25, [x0, #0xc0]
   133  	ldr x26, [x0, #0xd0]
   134  	ldr x28, [x0, #0xe0]
   135  	ldr q18, [x0, #0xf0]
   136  	ldr q19, [x0, #0x100]
   137  	ldr q20, [x0, #0x110]
   138  	ldr q21, [x0, #0x120]
   139  	ldr q22, [x0, #0x130]
   140  	ldr q23, [x0, #0x140]
   141  	ldr q24, [x0, #0x150]
   142  	ldr q25, [x0, #0x160]
   143  	ldr q26, [x0, #0x170]
   144  	ldr q27, [x0, #0x180]
   145  	ldr q28, [x0, #0x190]
   146  	ldr q29, [x0, #0x1a0]
   147  	ldr q30, [x0, #0x1b0]
   148  	ldr q31, [x0, #0x1c0]
   149  	add x15, sp, #0x10
   150  	add sp, sp, #0x130
   151  	ldr x30, [sp], #0x10
   152  	add x17, sp, #0x38
   153  	add sp, sp, #0xa0
   154  	ldr q0, [x15], #0x10
   155  	ldr w0, [x15], #0x8
   156  	ldr x1, [x15], #0x8
   157  	ldr q1, [x15], #0x10
   158  	ldr s2, [x15], #0x8
   159  	ldr q3, [x15], #0x10
   160  	ldr w2, [x15], #0x8
   161  	ldr x3, [x15], #0x8
   162  	ldr q4, [x15], #0x10
   163  	ldr s5, [x15], #0x8
   164  	ldr q6, [x15], #0x10
   165  	ldr w4, [x15], #0x8
   166  	ldr x5, [x15], #0x8
   167  	ldr q7, [x15], #0x10
   168  	ldr s11, [x15], #0x8
   169  	str s11, [x17], #0x8
   170  	ldr q11, [x15], #0x10
   171  	str q11, [x17], #0x10
   172  	ldr w6, [x15], #0x8
   173  	ldr x7, [x15], #0x8
   174  	ldr q11, [x15], #0x10
   175  	str q11, [x17], #0x10
   176  	ldr s11, [x15], #0x8
   177  	str s11, [x17], #0x8
   178  	ldr q11, [x15], #0x10
   179  	str q11, [x17], #0x10
   180  	ldr w11, [x15], #0x8
   181  	str w11, [x17], #0x8
   182  	ldr x11, [x15], #0x8
   183  	str x11, [x17], #0x8
   184  	ldr q11, [x15], #0x10
   185  	str q11, [x17], #0x10
   186  	ldr s11, [x15], #0x8
   187  	str s11, [x17], #0x8
   188  	ret
   189  `,
   190  		},
   191  		{
   192  			name:     "go call",
   193  			exitCode: wazevoapi.ExitCodeCallGoFunctionWithIndex(100, false),
   194  			sig: &ssa.Signature{
   195  				Params:  []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64},
   196  				Results: []ssa.Type{ssa.TypeI32, ssa.TypeI64, ssa.TypeF32, ssa.TypeF64},
   197  			},
   198  			needModuleContextPtr: true,
   199  			exp: `
   200  	stp x30, xzr, [sp, #-0x10]!
   201  	sub x27, sp, #0x30
   202  	ldr x11, [x0, #0x28]
   203  	subs xzr, x27, x11
   204  	b.ge #0x14
   205  	orr x27, xzr, #0x30
   206  	str x27, [x0, #0x40]
   207  	ldr x27, [x0, #0x50]
   208  	bl x27
   209  	str x19, [x0, #0x60]
   210  	str x20, [x0, #0x70]
   211  	str x21, [x0, #0x80]
   212  	str x22, [x0, #0x90]
   213  	str x23, [x0, #0xa0]
   214  	str x24, [x0, #0xb0]
   215  	str x25, [x0, #0xc0]
   216  	str x26, [x0, #0xd0]
   217  	str x28, [x0, #0xe0]
   218  	str q18, [x0, #0xf0]
   219  	str q19, [x0, #0x100]
   220  	str q20, [x0, #0x110]
   221  	str q21, [x0, #0x120]
   222  	str q22, [x0, #0x130]
   223  	str q23, [x0, #0x140]
   224  	str q24, [x0, #0x150]
   225  	str q25, [x0, #0x160]
   226  	str q26, [x0, #0x170]
   227  	str q27, [x0, #0x180]
   228  	str q28, [x0, #0x190]
   229  	str q29, [x0, #0x1a0]
   230  	str q30, [x0, #0x1b0]
   231  	str q31, [x0, #0x1c0]
   232  	str x1, [x0, #0x460]
   233  	sub sp, sp, #0x20
   234  	mov x15, sp
   235  	str d0, [x15], #0x8
   236  	orr x27, xzr, #0x20
   237  	orr x16, xzr, #0x4
   238  	stp x27, x16, [sp, #-0x10]!
   239  	movz w17, #0x6406, lsl 0
   240  	str w17, [x0]
   241  	mov x27, sp
   242  	str x27, [x0, #0x38]
   243  	adr x27, #0x20
   244  	str x27, [x0, #0x30]
   245  	exit_sequence x0
   246  	ldr x19, [x0, #0x60]
   247  	ldr x20, [x0, #0x70]
   248  	ldr x21, [x0, #0x80]
   249  	ldr x22, [x0, #0x90]
   250  	ldr x23, [x0, #0xa0]
   251  	ldr x24, [x0, #0xb0]
   252  	ldr x25, [x0, #0xc0]
   253  	ldr x26, [x0, #0xd0]
   254  	ldr x28, [x0, #0xe0]
   255  	ldr q18, [x0, #0xf0]
   256  	ldr q19, [x0, #0x100]
   257  	ldr q20, [x0, #0x110]
   258  	ldr q21, [x0, #0x120]
   259  	ldr q22, [x0, #0x130]
   260  	ldr q23, [x0, #0x140]
   261  	ldr q24, [x0, #0x150]
   262  	ldr q25, [x0, #0x160]
   263  	ldr q26, [x0, #0x170]
   264  	ldr q27, [x0, #0x180]
   265  	ldr q28, [x0, #0x190]
   266  	ldr q29, [x0, #0x1a0]
   267  	ldr q30, [x0, #0x1b0]
   268  	ldr q31, [x0, #0x1c0]
   269  	add x15, sp, #0x10
   270  	add sp, sp, #0x30
   271  	ldr x30, [sp], #0x10
   272  	ldr w0, [x15], #0x8
   273  	ldr x1, [x15], #0x8
   274  	ldr s0, [x15], #0x8
   275  	ldr d1, [x15], #0x8
   276  	ret
   277  `,
   278  		},
   279  		{
   280  			name:     "go call",
   281  			exitCode: wazevoapi.ExitCodeCallGoFunctionWithIndex(100, false),
   282  			sig: &ssa.Signature{
   283  				Params:  []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeF64, ssa.TypeI32, ssa.TypeI32},
   284  				Results: []ssa.Type{},
   285  			},
   286  			needModuleContextPtr: true,
   287  			exp: `
   288  	stp x30, xzr, [sp, #-0x10]!
   289  	sub x27, sp, #0x30
   290  	ldr x11, [x0, #0x28]
   291  	subs xzr, x27, x11
   292  	b.ge #0x14
   293  	orr x27, xzr, #0x30
   294  	str x27, [x0, #0x40]
   295  	ldr x27, [x0, #0x50]
   296  	bl x27
   297  	str x19, [x0, #0x60]
   298  	str x20, [x0, #0x70]
   299  	str x21, [x0, #0x80]
   300  	str x22, [x0, #0x90]
   301  	str x23, [x0, #0xa0]
   302  	str x24, [x0, #0xb0]
   303  	str x25, [x0, #0xc0]
   304  	str x26, [x0, #0xd0]
   305  	str x28, [x0, #0xe0]
   306  	str q18, [x0, #0xf0]
   307  	str q19, [x0, #0x100]
   308  	str q20, [x0, #0x110]
   309  	str q21, [x0, #0x120]
   310  	str q22, [x0, #0x130]
   311  	str q23, [x0, #0x140]
   312  	str q24, [x0, #0x150]
   313  	str q25, [x0, #0x160]
   314  	str q26, [x0, #0x170]
   315  	str q27, [x0, #0x180]
   316  	str q28, [x0, #0x190]
   317  	str q29, [x0, #0x1a0]
   318  	str q30, [x0, #0x1b0]
   319  	str q31, [x0, #0x1c0]
   320  	str x1, [x0, #0x460]
   321  	sub sp, sp, #0x20
   322  	mov x15, sp
   323  	str d0, [x15], #0x8
   324  	str d1, [x15], #0x8
   325  	str x2, [x15], #0x8
   326  	str x3, [x15], #0x8
   327  	orr x27, xzr, #0x20
   328  	orr x16, xzr, #0x4
   329  	stp x27, x16, [sp, #-0x10]!
   330  	movz w17, #0x6406, lsl 0
   331  	str w17, [x0]
   332  	mov x27, sp
   333  	str x27, [x0, #0x38]
   334  	adr x27, #0x20
   335  	str x27, [x0, #0x30]
   336  	exit_sequence x0
   337  	ldr x19, [x0, #0x60]
   338  	ldr x20, [x0, #0x70]
   339  	ldr x21, [x0, #0x80]
   340  	ldr x22, [x0, #0x90]
   341  	ldr x23, [x0, #0xa0]
   342  	ldr x24, [x0, #0xb0]
   343  	ldr x25, [x0, #0xc0]
   344  	ldr x26, [x0, #0xd0]
   345  	ldr x28, [x0, #0xe0]
   346  	ldr q18, [x0, #0xf0]
   347  	ldr q19, [x0, #0x100]
   348  	ldr q20, [x0, #0x110]
   349  	ldr q21, [x0, #0x120]
   350  	ldr q22, [x0, #0x130]
   351  	ldr q23, [x0, #0x140]
   352  	ldr q24, [x0, #0x150]
   353  	ldr q25, [x0, #0x160]
   354  	ldr q26, [x0, #0x170]
   355  	ldr q27, [x0, #0x180]
   356  	ldr q28, [x0, #0x190]
   357  	ldr q29, [x0, #0x1a0]
   358  	ldr q30, [x0, #0x1b0]
   359  	ldr q31, [x0, #0x1c0]
   360  	add sp, sp, #0x30
   361  	ldr x30, [sp], #0x10
   362  	ret
   363  `,
   364  		},
   365  		{
   366  			name:     "grow memory",
   367  			exitCode: wazevoapi.ExitCodeGrowMemory,
   368  			sig: &ssa.Signature{
   369  				Params:  []ssa.Type{ssa.TypeI32, ssa.TypeI32},
   370  				Results: []ssa.Type{ssa.TypeI32},
   371  			},
   372  			exp: `
   373  	stp x30, xzr, [sp, #-0x10]!
   374  	sub x27, sp, #0x20
   375  	ldr x11, [x0, #0x28]
   376  	subs xzr, x27, x11
   377  	b.ge #0x14
   378  	orr x27, xzr, #0x20
   379  	str x27, [x0, #0x40]
   380  	ldr x27, [x0, #0x50]
   381  	bl x27
   382  	str x19, [x0, #0x60]
   383  	str x20, [x0, #0x70]
   384  	str x21, [x0, #0x80]
   385  	str x22, [x0, #0x90]
   386  	str x23, [x0, #0xa0]
   387  	str x24, [x0, #0xb0]
   388  	str x25, [x0, #0xc0]
   389  	str x26, [x0, #0xd0]
   390  	str x28, [x0, #0xe0]
   391  	str q18, [x0, #0xf0]
   392  	str q19, [x0, #0x100]
   393  	str q20, [x0, #0x110]
   394  	str q21, [x0, #0x120]
   395  	str q22, [x0, #0x130]
   396  	str q23, [x0, #0x140]
   397  	str q24, [x0, #0x150]
   398  	str q25, [x0, #0x160]
   399  	str q26, [x0, #0x170]
   400  	str q27, [x0, #0x180]
   401  	str q28, [x0, #0x190]
   402  	str q29, [x0, #0x1a0]
   403  	str q30, [x0, #0x1b0]
   404  	str q31, [x0, #0x1c0]
   405  	sub sp, sp, #0x10
   406  	mov x15, sp
   407  	str x1, [x15], #0x8
   408  	orr x27, xzr, #0x10
   409  	orr x16, xzr, #0x1
   410  	stp x27, x16, [sp, #-0x10]!
   411  	orr w17, wzr, #0x2
   412  	str w17, [x0]
   413  	mov x27, sp
   414  	str x27, [x0, #0x38]
   415  	adr x27, #0x20
   416  	str x27, [x0, #0x30]
   417  	exit_sequence x0
   418  	ldr x19, [x0, #0x60]
   419  	ldr x20, [x0, #0x70]
   420  	ldr x21, [x0, #0x80]
   421  	ldr x22, [x0, #0x90]
   422  	ldr x23, [x0, #0xa0]
   423  	ldr x24, [x0, #0xb0]
   424  	ldr x25, [x0, #0xc0]
   425  	ldr x26, [x0, #0xd0]
   426  	ldr x28, [x0, #0xe0]
   427  	ldr q18, [x0, #0xf0]
   428  	ldr q19, [x0, #0x100]
   429  	ldr q20, [x0, #0x110]
   430  	ldr q21, [x0, #0x120]
   431  	ldr q22, [x0, #0x130]
   432  	ldr q23, [x0, #0x140]
   433  	ldr q24, [x0, #0x150]
   434  	ldr q25, [x0, #0x160]
   435  	ldr q26, [x0, #0x170]
   436  	ldr q27, [x0, #0x180]
   437  	ldr q28, [x0, #0x190]
   438  	ldr q29, [x0, #0x1a0]
   439  	ldr q30, [x0, #0x1b0]
   440  	ldr q31, [x0, #0x1c0]
   441  	add x15, sp, #0x10
   442  	add sp, sp, #0x20
   443  	ldr x30, [sp], #0x10
   444  	ldr w0, [x15], #0x8
   445  	ret
   446  `,
   447  		},
   448  	} {
   449  		t.Run(tc.name, func(t *testing.T) {
   450  			_, _, m := newSetupWithMockContext()
   451  			m.CompileGoFunctionTrampoline(tc.exitCode, tc.sig, tc.needModuleContextPtr)
   452  
   453  			require.Equal(t, tc.exp, m.Format())
   454  
   455  			m.Encode()
   456  		})
   457  	}
   458  }
   459  
   460  func Test_goFunctionCallRequiredStackSize(t *testing.T) {
   461  	for _, tc := range []struct {
   462  		name     string
   463  		sig      *ssa.Signature
   464  		argBegin int
   465  		exp      int64
   466  	}{
   467  		{
   468  			name: "no param",
   469  			sig:  &ssa.Signature{},
   470  			exp:  0,
   471  		},
   472  		{
   473  			name: "only param",
   474  			sig:  &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeV128}},
   475  			exp:  32,
   476  		},
   477  		{
   478  			name: "only result",
   479  			sig:  &ssa.Signature{Results: []ssa.Type{ssa.TypeI64, ssa.TypeV128, ssa.TypeI32}},
   480  			exp:  32,
   481  		},
   482  		{
   483  			name: "param < result",
   484  			sig:  &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeV128}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeV128, ssa.TypeI32}},
   485  			exp:  32,
   486  		},
   487  		{
   488  			name: "param > result",
   489  			sig:  &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeV128, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeV128}},
   490  			exp:  32,
   491  		},
   492  		{
   493  			name:     "param < result / argBegin=2",
   494  			argBegin: 2,
   495  			sig:      &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeV128, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeF64}},
   496  			exp:      16,
   497  		},
   498  	} {
   499  		tc := tc
   500  		t.Run(tc.name, func(t *testing.T) {
   501  			requiredSize, _ := goFunctionCallRequiredStackSize(tc.sig, tc.argBegin)
   502  			require.Equal(t, tc.exp, requiredSize)
   503  		})
   504  	}
   505  }
   506  
   507  func Test_goFunctionCallLoadStackArg(t *testing.T) {
   508  	originalArg0Reg := x17VReg
   509  	intVReg := x11VReg
   510  	floatVReg := v11VReg
   511  	for _, tc := range []struct {
   512  		name         string
   513  		arg          *backend.ABIArg
   514  		expResultReg regalloc.VReg
   515  		exp          string
   516  	}{
   517  		{
   518  			name:         "i32",
   519  			arg:          &backend.ABIArg{Type: ssa.TypeI32},
   520  			expResultReg: x11VReg,
   521  			exp: `
   522  	ldr w11, [x17], #0x8
   523  `,
   524  		},
   525  		{
   526  			name:         "i64",
   527  			arg:          &backend.ABIArg{Type: ssa.TypeI64},
   528  			expResultReg: x11VReg,
   529  			exp: `
   530  	ldr x11, [x17], #0x8
   531  `,
   532  		},
   533  		{
   534  			name:         "f32",
   535  			arg:          &backend.ABIArg{Type: ssa.TypeF32},
   536  			expResultReg: v11VReg,
   537  			exp: `
   538  	ldr s11, [x17], #0x8
   539  `,
   540  		},
   541  		{
   542  			name:         "f64",
   543  			arg:          &backend.ABIArg{Type: ssa.TypeF64},
   544  			expResultReg: v11VReg,
   545  			exp: `
   546  	ldr d11, [x17], #0x8
   547  `,
   548  		},
   549  		{
   550  			name:         "v128",
   551  			arg:          &backend.ABIArg{Type: ssa.TypeV128},
   552  			expResultReg: v11VReg,
   553  			exp: `
   554  	ldr q11, [x17], #0x10
   555  `,
   556  		},
   557  	} {
   558  		tc := tc
   559  		t.Run(tc.name, func(t *testing.T) {
   560  			t.Run(tc.name, func(t *testing.T) {
   561  				_, _, m := newSetupWithMockContext()
   562  
   563  				nop := m.allocateNop()
   564  				_, result := m.goFunctionCallLoadStackArg(nop, originalArg0Reg, tc.arg, intVReg, floatVReg)
   565  				require.Equal(t, tc.expResultReg, result)
   566  
   567  				m.rootInstr = nop
   568  
   569  				require.Equal(t, tc.exp, m.Format())
   570  				m.Encode()
   571  			})
   572  		})
   573  	}
   574  }
   575  
   576  func Test_goFunctionCallStoreStackResult(t *testing.T) {
   577  	for _, tc := range []struct {
   578  		name      string
   579  		result    *backend.ABIArg
   580  		resultReg regalloc.VReg
   581  		exp       string
   582  	}{
   583  		{
   584  			name:      "i32",
   585  			result:    &backend.ABIArg{Offset: 16 * 3, Type: ssa.TypeI32},
   586  			resultReg: x11VReg,
   587  			exp: `
   588  	str w11, [sp], #0x8
   589  `,
   590  		},
   591  		{
   592  			name:      "i64",
   593  			result:    &backend.ABIArg{Offset: 16 * 3, Type: ssa.TypeI64},
   594  			resultReg: x11VReg,
   595  			exp: `
   596  	str x11, [sp], #0x8
   597  `,
   598  		},
   599  		{
   600  			name:      "f32",
   601  			result:    &backend.ABIArg{Offset: 16 * 3, Type: ssa.TypeF32},
   602  			resultReg: v11VReg,
   603  			exp: `
   604  	str s11, [sp], #0x8
   605  `,
   606  		},
   607  		{
   608  			name:      "f64",
   609  			result:    &backend.ABIArg{Offset: 16 * 3, Type: ssa.TypeF64},
   610  			resultReg: v11VReg,
   611  			exp: `
   612  	str d11, [sp], #0x8
   613  `,
   614  		},
   615  		{
   616  			name:      "v128",
   617  			result:    &backend.ABIArg{Offset: 16 * 3, Type: ssa.TypeV128},
   618  			resultReg: v11VReg,
   619  			exp: `
   620  	str q11, [sp], #0x10
   621  `,
   622  		},
   623  	} {
   624  		tc := tc
   625  		t.Run(tc.name, func(t *testing.T) {
   626  			t.Run(tc.name, func(t *testing.T) {
   627  				_, _, m := newSetupWithMockContext()
   628  				m.currentABI = &abiImpl{argStackSize: 8}
   629  
   630  				nop := m.allocateNop()
   631  				m.goFunctionCallStoreStackResult(nop, spVReg, tc.result, tc.resultReg)
   632  
   633  				m.rootInstr = nop
   634  
   635  				require.Equal(t, tc.exp, m.Format())
   636  				m.Encode()
   637  			})
   638  		})
   639  	}
   640  }