github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/engine/wazevo/backend/isa/arm64/lower_constant_test.go (about)

     1  package arm64
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/bananabytelabs/wazero/internal/engine/wazevo/backend/regalloc"
    10  	"github.com/bananabytelabs/wazero/internal/testing/require"
    11  )
    12  
    13  func TestMachine_lowerConstant(t *testing.T) {
    14  	t.Run("zero i32", func(t *testing.T) {
    15  		ssaB, m := newSetup()
    16  		ssaConstInstr := ssaB.AllocateInstruction()
    17  		ssaConstInstr.AsIconst32(0)
    18  		ssaB.InsertInstruction(ssaConstInstr)
    19  
    20  		vr := m.lowerConstant(ssaConstInstr)
    21  		machInstr := getPendingInstr(m)
    22  		require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID())
    23  		require.Equal(t, regalloc.RegTypeInt, vr.RegType())
    24  		require.Equal(t, mov64, machInstr.kind)
    25  		require.Equal(t, "mov x128?, xzr", formatEmittedInstructionsInCurrentBlock(m))
    26  	})
    27  
    28  	t.Run("zero i64", func(t *testing.T) {
    29  		ssaB, m := newSetup()
    30  		ssaConstInstr := ssaB.AllocateInstruction()
    31  		ssaConstInstr.AsIconst64(0)
    32  		ssaB.InsertInstruction(ssaConstInstr)
    33  
    34  		vr := m.lowerConstant(ssaConstInstr)
    35  		machInstr := getPendingInstr(m)
    36  		require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID())
    37  		require.Equal(t, regalloc.RegTypeInt, vr.RegType())
    38  		require.Equal(t, mov64, machInstr.kind)
    39  		require.Equal(t, "mov x128?, xzr", formatEmittedInstructionsInCurrentBlock(m))
    40  	})
    41  
    42  	t.Run("TypeF32", func(t *testing.T) {
    43  		ssaB, m := newSetup()
    44  		ssaConstInstr := ssaB.AllocateInstruction()
    45  		ssaConstInstr.AsF32const(1.1234)
    46  		ssaB.InsertInstruction(ssaConstInstr)
    47  
    48  		vr := m.lowerConstant(ssaConstInstr)
    49  		machInstr := getPendingInstr(m)
    50  		require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID())
    51  		require.Equal(t, regalloc.RegTypeFloat, vr.RegType())
    52  		require.Equal(t, loadFpuConst32, machInstr.kind)
    53  		require.Equal(t, uint64(math.Float32bits(1.1234)), machInstr.u1)
    54  
    55  		require.Equal(t, "ldr s128?, #8; b 8; data.f32 1.123400", formatEmittedInstructionsInCurrentBlock(m))
    56  	})
    57  
    58  	t.Run("TypeF64", func(t *testing.T) {
    59  		ssaB, m := newSetup()
    60  		ssaConstInstr := ssaB.AllocateInstruction()
    61  		ssaConstInstr.AsF64const(-9471.2)
    62  		ssaB.InsertInstruction(ssaConstInstr)
    63  
    64  		vr := m.lowerConstant(ssaConstInstr)
    65  		machInstr := getPendingInstr(m)
    66  		require.Equal(t, regalloc.VRegIDNonReservedBegin, vr.ID())
    67  		require.Equal(t, regalloc.RegTypeFloat, vr.RegType())
    68  		require.Equal(t, loadFpuConst64, machInstr.kind)
    69  		require.Equal(t, math.Float64bits(-9471.2), machInstr.u1)
    70  
    71  		require.Equal(t, "ldr d128?, #8; b 16; data.f64 -9471.200000", formatEmittedInstructionsInCurrentBlock(m))
    72  	})
    73  }
    74  
    75  func TestMachine_lowerConstantI32(t *testing.T) {
    76  	for _, tc := range []struct {
    77  		val uint32
    78  		exp []string
    79  	}{
    80  		{val: 0, exp: []string{"movz w0, #0x0, lsl 0"}},
    81  		{val: 0xffff, exp: []string{"movz w0, #0xffff, lsl 0"}},
    82  		{val: 0xffff_0000, exp: []string{"movz w0, #0xffff, lsl 16"}},
    83  		{val: 0xffff_fffe, exp: []string{"movn w0, #0x1, lsl 0"}},
    84  		{val: 0x2, exp: []string{"orr w0, wzr, #0x2"}},
    85  		{val: 0x80000001, exp: []string{
    86  			"movz w0, #0x1, lsl 0",
    87  			"movk w0, #0x8000, lsl 16",
    88  		}},
    89  		{val: 0xf00000f, exp: []string{
    90  			"movz w0, #0xf, lsl 0",
    91  			"movk w0, #0xf00, lsl 16",
    92  		}},
    93  	} {
    94  		tc := tc
    95  		t.Run(fmt.Sprintf("%#x", tc.val), func(t *testing.T) {
    96  			_, m := newSetup()
    97  			m.lowerConstantI32(regToVReg(x0), int32(tc.val))
    98  			exp := strings.Join(tc.exp, "\n")
    99  			require.Equal(t, exp, formatEmittedInstructionsInCurrentBlock(m))
   100  		})
   101  	}
   102  }
   103  
   104  func TestMachine_lowerConstantI64(t *testing.T) {
   105  	invert := func(v uint64) uint64 { return ^v }
   106  	for _, tc := range []struct {
   107  		val uint64
   108  		exp []string
   109  	}{
   110  		{val: 0x0, exp: []string{"movz x0, #0x0, lsl 0"}},
   111  		{val: 0x1, exp: []string{"orr x0, xzr, #0x1"}},
   112  		{val: 0x3, exp: []string{"orr x0, xzr, #0x3"}},
   113  		{val: 0xfff000, exp: []string{"orr x0, xzr, #0xfff000"}},
   114  		{val: 0x8001 << 16, exp: []string{"movz x0, #0x8001, lsl 16"}},
   115  		{val: 0x8001 << 32, exp: []string{"movz x0, #0x8001, lsl 32"}},
   116  		{val: 0x8001 << 48, exp: []string{"movz x0, #0x8001, lsl 48"}},
   117  		{val: invert(0x8001 << 16), exp: []string{"movn x0, #0x8001, lsl 16"}},
   118  		{val: invert(0x8001 << 32), exp: []string{"movn x0, #0x8001, lsl 32"}},
   119  		{val: invert(0x8001 << 48), exp: []string{"movn x0, #0x8001, lsl 48"}},
   120  		{val: 0x80000001 << 16, exp: []string{
   121  			"movz x0, #0x1, lsl 16",
   122  			"movk x0, #0x8000, lsl 32",
   123  		}},
   124  		{val: 0x40000001, exp: []string{
   125  			"movz x0, #0x1, lsl 0",
   126  			"movk x0, #0x4000, lsl 16",
   127  		}},
   128  		{val: 0xffffffffff001000, exp: []string{
   129  			"movn x0, #0xefff, lsl 0",
   130  			"movk x0, #0xff00, lsl 16",
   131  		}},
   132  		{val: 0xffff0000c466361f, exp: []string{
   133  			"movz x0, #0x361f, lsl 0",
   134  			"movk x0, #0xc466, lsl 16",
   135  			"movk x0, #0xffff, lsl 48",
   136  		}},
   137  		{val: 0x89705f4136b4a598, exp: []string{
   138  			"movz x0, #0xa598, lsl 0",
   139  			"movk x0, #0x36b4, lsl 16",
   140  			"movk x0, #0x5f41, lsl 32",
   141  			"movk x0, #0x8970, lsl 48",
   142  		}},
   143  		{val: 0xffff_0001_0001_0001, exp: []string{
   144  			"movn x0, #0xfffe, lsl 0",
   145  			"movk x0, #0x1, lsl 16",
   146  			"movk x0, #0x1, lsl 32",
   147  		}},
   148  	} {
   149  		tc := tc
   150  		t.Run(fmt.Sprintf("%#x", tc.val), func(t *testing.T) {
   151  			_, m := newSetup()
   152  			m.lowerConstantI64(regToVReg(x0), int64(tc.val))
   153  			exp := strings.Join(tc.exp, "\n")
   154  			require.Equal(t, exp, formatEmittedInstructionsInCurrentBlock(m))
   155  		})
   156  	}
   157  }