github.com/tetratelabs/wazero@v1.7.1/internal/engine/wazevo/backend/isa/arm64/machine_pro_epi_logue_test.go (about)

     1  package arm64
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
     8  	"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
     9  	"github.com/tetratelabs/wazero/internal/testing/require"
    10  )
    11  
    12  func TestMachine_setupPrologue(t *testing.T) {
    13  	for _, tc := range []struct {
    14  		spillSlotSize int64
    15  		clobberedRegs []regalloc.VReg
    16  		exp           string
    17  		abi           backend.FunctionABI
    18  	}{
    19  		{
    20  			spillSlotSize: 0,
    21  			exp: `
    22  	stp x30, xzr, [sp, #-0x10]!
    23  	str xzr, [sp, #-0x10]!
    24  	udf
    25  `,
    26  		},
    27  		{
    28  			spillSlotSize: 0,
    29  			abi:           backend.FunctionABI{ArgStackSize: 16, RetStackSize: 16},
    30  			exp: `
    31  	orr x27, xzr, #0x20
    32  	sub sp, sp, x27
    33  	stp x30, x27, [sp, #-0x10]!
    34  	str xzr, [sp, #-0x10]!
    35  	udf
    36  `,
    37  		},
    38  		{
    39  			spillSlotSize: 16,
    40  			exp: `
    41  	stp x30, xzr, [sp, #-0x10]!
    42  	sub sp, sp, #0x10
    43  	orr x27, xzr, #0x10
    44  	str x27, [sp, #-0x10]!
    45  	udf
    46  `,
    47  		},
    48  		{
    49  			spillSlotSize: 0,
    50  			clobberedRegs: []regalloc.VReg{v18VReg, v19VReg, x18VReg, x25VReg},
    51  			exp: `
    52  	stp x30, xzr, [sp, #-0x10]!
    53  	str q18, [sp, #-0x10]!
    54  	str q19, [sp, #-0x10]!
    55  	str x18, [sp, #-0x10]!
    56  	str x25, [sp, #-0x10]!
    57  	orr x27, xzr, #0x40
    58  	str x27, [sp, #-0x10]!
    59  	udf
    60  `,
    61  		},
    62  		{
    63  			spillSlotSize: 320,
    64  			clobberedRegs: []regalloc.VReg{v18VReg, v19VReg, x18VReg, x25VReg},
    65  			exp: `
    66  	stp x30, xzr, [sp, #-0x10]!
    67  	str q18, [sp, #-0x10]!
    68  	str q19, [sp, #-0x10]!
    69  	str x18, [sp, #-0x10]!
    70  	str x25, [sp, #-0x10]!
    71  	sub sp, sp, #0x140
    72  	orr x27, xzr, #0x180
    73  	str x27, [sp, #-0x10]!
    74  	udf
    75  `,
    76  		},
    77  		{
    78  			spillSlotSize: 320,
    79  			abi:           backend.FunctionABI{ArgStackSize: 320, RetStackSize: 160},
    80  			clobberedRegs: []regalloc.VReg{v18VReg, v19VReg, x18VReg, x25VReg},
    81  			exp: `
    82  	orr x27, xzr, #0x1e0
    83  	sub sp, sp, x27
    84  	stp x30, x27, [sp, #-0x10]!
    85  	str q18, [sp, #-0x10]!
    86  	str q19, [sp, #-0x10]!
    87  	str x18, [sp, #-0x10]!
    88  	str x25, [sp, #-0x10]!
    89  	sub sp, sp, #0x140
    90  	orr x27, xzr, #0x180
    91  	str x27, [sp, #-0x10]!
    92  	udf
    93  `,
    94  		},
    95  	} {
    96  		tc := tc
    97  		t.Run(tc.exp, func(t *testing.T) {
    98  			_, _, m := newSetupWithMockContext()
    99  			m.DisableStackCheck()
   100  			m.spillSlotSize = tc.spillSlotSize
   101  			m.clobberedRegs = tc.clobberedRegs
   102  			m.currentABI = &tc.abi
   103  
   104  			root := m.allocateNop()
   105  			m.executableContext.RootInstr = root
   106  			udf := m.allocateInstr()
   107  			udf.asUDF()
   108  			root.next = udf
   109  			udf.prev = root
   110  
   111  			m.setupPrologue()
   112  			require.Equal(t, root, m.executableContext.RootInstr)
   113  			err := m.Encode(context.Background())
   114  			require.NoError(t, err)
   115  			require.Equal(t, tc.exp, m.Format())
   116  		})
   117  	}
   118  }
   119  
   120  func TestMachine_postRegAlloc(t *testing.T) {
   121  	for _, tc := range []struct {
   122  		exp           string
   123  		abi           backend.FunctionABI
   124  		clobberedRegs []regalloc.VReg
   125  		spillSlotSize int64
   126  	}{
   127  		{
   128  			exp: `
   129  	add sp, sp, #0x10
   130  	ldr x30, [sp], #0x10
   131  	ret
   132  `,
   133  			spillSlotSize: 0,
   134  			clobberedRegs: nil,
   135  		},
   136  		{
   137  			exp: `
   138  	add sp, sp, #0x10
   139  	add sp, sp, #0x50
   140  	ldr x30, [sp], #0x10
   141  	ret
   142  `,
   143  			spillSlotSize: 16 * 5,
   144  			clobberedRegs: nil,
   145  		},
   146  		{
   147  			exp: `
   148  	add sp, sp, #0x10
   149  	add sp, sp, #0x50
   150  	ldr x30, [sp], #0x10
   151  	add sp, sp, #0x20
   152  	ret
   153  `,
   154  			abi:           backend.FunctionABI{ArgStackSize: 16, RetStackSize: 16},
   155  			spillSlotSize: 16 * 5,
   156  			clobberedRegs: nil,
   157  		},
   158  		{
   159  			exp: `
   160  	add sp, sp, #0x10
   161  	ldr q27, [sp], #0x10
   162  	ldr q18, [sp], #0x10
   163  	ldr x30, [sp], #0x10
   164  	ret
   165  `,
   166  			clobberedRegs: []regalloc.VReg{v18VReg, v27VReg},
   167  		},
   168  		{
   169  			exp: `
   170  	add sp, sp, #0x10
   171  	ldr x25, [sp], #0x10
   172  	ldr x18, [sp], #0x10
   173  	ldr q27, [sp], #0x10
   174  	ldr q18, [sp], #0x10
   175  	ldr x30, [sp], #0x10
   176  	ret
   177  `,
   178  			clobberedRegs: []regalloc.VReg{v18VReg, v27VReg, x18VReg, x25VReg},
   179  		},
   180  		{
   181  			exp: `
   182  	add sp, sp, #0x10
   183  	add sp, sp, #0xa0
   184  	ldr x25, [sp], #0x10
   185  	ldr x18, [sp], #0x10
   186  	ldr q27, [sp], #0x10
   187  	ldr q18, [sp], #0x10
   188  	ldr x30, [sp], #0x10
   189  	ret
   190  `,
   191  			spillSlotSize: 16 * 10,
   192  			clobberedRegs: []regalloc.VReg{v18VReg, v27VReg, x18VReg, x25VReg},
   193  		},
   194  		{
   195  			exp: `
   196  	add sp, sp, #0x10
   197  	add sp, sp, #0xa0
   198  	ldr x25, [sp], #0x10
   199  	ldr x18, [sp], #0x10
   200  	ldr q27, [sp], #0x10
   201  	ldr q18, [sp], #0x10
   202  	ldr x30, [sp], #0x10
   203  	add sp, sp, #0x150
   204  	ret
   205  `,
   206  			spillSlotSize: 16 * 10,
   207  			abi:           backend.FunctionABI{ArgStackSize: 16, RetStackSize: 320},
   208  			clobberedRegs: []regalloc.VReg{v18VReg, v27VReg, x18VReg, x25VReg},
   209  		},
   210  	} {
   211  		tc := tc
   212  		t.Run(tc.exp, func(t *testing.T) {
   213  			_, _, m := newSetupWithMockContext()
   214  			m.spillSlotSize = tc.spillSlotSize
   215  			m.clobberedRegs = tc.clobberedRegs
   216  			m.currentABI = &tc.abi
   217  
   218  			root := m.allocateNop()
   219  			m.executableContext.RootInstr = root
   220  			ret := m.allocateInstr()
   221  			ret.asRet()
   222  			root.next = ret
   223  			ret.prev = root
   224  			m.postRegAlloc()
   225  
   226  			require.Equal(t, root, m.executableContext.RootInstr)
   227  			err := m.Encode(context.Background())
   228  			require.NoError(t, err)
   229  			require.Equal(t, tc.exp, m.Format())
   230  		})
   231  	}
   232  }
   233  
   234  func TestMachine_insertStackBoundsCheck(t *testing.T) {
   235  	for _, tc := range []struct {
   236  		exp               string
   237  		requiredStackSize int64
   238  	}{
   239  		{
   240  			requiredStackSize: 0xfff_0,
   241  			exp: `
   242  	movz x27, #0xfff0, lsl 0
   243  	sub x27, sp, x27
   244  	ldr x11, [x0, #0x28]
   245  	subs xzr, x27, x11
   246  	b.ge #0x14
   247  	movz x27, #0xfff0, lsl 0
   248  	str x27, [x0, #0x40]
   249  	ldr x27, [x0, #0x50]
   250  	bl x27
   251  `,
   252  		},
   253  		{
   254  			requiredStackSize: 0x10,
   255  			exp: `
   256  	sub x27, sp, #0x10
   257  	ldr x11, [x0, #0x28]
   258  	subs xzr, x27, x11
   259  	b.ge #0x14
   260  	orr x27, xzr, #0x10
   261  	str x27, [x0, #0x40]
   262  	ldr x27, [x0, #0x50]
   263  	bl x27
   264  `,
   265  		},
   266  	} {
   267  		tc := tc
   268  		t.Run(tc.exp, func(t *testing.T) {
   269  			_, _, m := newSetupWithMockContext()
   270  			m.executableContext.RootInstr = m.allocateInstr()
   271  			m.executableContext.RootInstr.asNop0()
   272  			m.insertStackBoundsCheck(tc.requiredStackSize, m.executableContext.RootInstr)
   273  			err := m.Encode(context.Background())
   274  			require.NoError(t, err)
   275  			require.Equal(t, tc.exp, m.Format())
   276  		})
   277  	}
   278  }
   279  
   280  func TestMachine_CompileStackGrowCallSequence(t *testing.T) {
   281  	_, _, m := newSetupWithMockContext()
   282  	_ = m.CompileStackGrowCallSequence()
   283  
   284  	require.Equal(t, `
   285  	str x1, [x0, #0x60]
   286  	str x2, [x0, #0x70]
   287  	str x3, [x0, #0x80]
   288  	str x4, [x0, #0x90]
   289  	str x5, [x0, #0xa0]
   290  	str x6, [x0, #0xb0]
   291  	str x7, [x0, #0xc0]
   292  	str x19, [x0, #0xd0]
   293  	str x20, [x0, #0xe0]
   294  	str x21, [x0, #0xf0]
   295  	str x22, [x0, #0x100]
   296  	str x23, [x0, #0x110]
   297  	str x24, [x0, #0x120]
   298  	str x25, [x0, #0x130]
   299  	str x26, [x0, #0x140]
   300  	str x28, [x0, #0x150]
   301  	str x30, [x0, #0x160]
   302  	str q0, [x0, #0x170]
   303  	str q1, [x0, #0x180]
   304  	str q2, [x0, #0x190]
   305  	str q3, [x0, #0x1a0]
   306  	str q4, [x0, #0x1b0]
   307  	str q5, [x0, #0x1c0]
   308  	str q6, [x0, #0x1d0]
   309  	str q7, [x0, #0x1e0]
   310  	str q18, [x0, #0x1f0]
   311  	str q19, [x0, #0x200]
   312  	str q20, [x0, #0x210]
   313  	str q21, [x0, #0x220]
   314  	str q22, [x0, #0x230]
   315  	str q23, [x0, #0x240]
   316  	str q24, [x0, #0x250]
   317  	str q25, [x0, #0x260]
   318  	str q26, [x0, #0x270]
   319  	str q27, [x0, #0x280]
   320  	str q28, [x0, #0x290]
   321  	str q29, [x0, #0x2a0]
   322  	str q30, [x0, #0x2b0]
   323  	str q31, [x0, #0x2c0]
   324  	mov x27, sp
   325  	str x27, [x0, #0x38]
   326  	orr w17, wzr, #0x1
   327  	str w17, [x0]
   328  	adr x27, #0x20
   329  	str x27, [x0, #0x30]
   330  	exit_sequence x0
   331  	ldr x1, [x0, #0x60]
   332  	ldr x2, [x0, #0x70]
   333  	ldr x3, [x0, #0x80]
   334  	ldr x4, [x0, #0x90]
   335  	ldr x5, [x0, #0xa0]
   336  	ldr x6, [x0, #0xb0]
   337  	ldr x7, [x0, #0xc0]
   338  	ldr x19, [x0, #0xd0]
   339  	ldr x20, [x0, #0xe0]
   340  	ldr x21, [x0, #0xf0]
   341  	ldr x22, [x0, #0x100]
   342  	ldr x23, [x0, #0x110]
   343  	ldr x24, [x0, #0x120]
   344  	ldr x25, [x0, #0x130]
   345  	ldr x26, [x0, #0x140]
   346  	ldr x28, [x0, #0x150]
   347  	ldr x30, [x0, #0x160]
   348  	ldr q0, [x0, #0x170]
   349  	ldr q1, [x0, #0x180]
   350  	ldr q2, [x0, #0x190]
   351  	ldr q3, [x0, #0x1a0]
   352  	ldr q4, [x0, #0x1b0]
   353  	ldr q5, [x0, #0x1c0]
   354  	ldr q6, [x0, #0x1d0]
   355  	ldr q7, [x0, #0x1e0]
   356  	ldr q18, [x0, #0x1f0]
   357  	ldr q19, [x0, #0x200]
   358  	ldr q20, [x0, #0x210]
   359  	ldr q21, [x0, #0x220]
   360  	ldr q22, [x0, #0x230]
   361  	ldr q23, [x0, #0x240]
   362  	ldr q24, [x0, #0x250]
   363  	ldr q25, [x0, #0x260]
   364  	ldr q26, [x0, #0x270]
   365  	ldr q27, [x0, #0x280]
   366  	ldr q28, [x0, #0x290]
   367  	ldr q29, [x0, #0x2a0]
   368  	ldr q30, [x0, #0x2b0]
   369  	ldr q31, [x0, #0x2c0]
   370  	ret
   371  `, m.Format())
   372  }