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 }