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

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