github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/backend/abi_test.go (about)

     1  package backend
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
     7  	"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
     8  	"github.com/tetratelabs/wazero/internal/testing/require"
     9  )
    10  
    11  const (
    12  	x0 = regalloc.RealRegInvalid + 1 + iota
    13  	x1
    14  	x2
    15  	x3
    16  	x4
    17  	x5
    18  	x6
    19  	x7
    20  	x8
    21  	x9
    22  	v0
    23  	v1
    24  	v2
    25  	v3
    26  	v4
    27  	v5
    28  	v6
    29  	v7
    30  	v8
    31  	v9
    32  )
    33  
    34  var (
    35  	x0VReg = regalloc.FromRealReg(x0, regalloc.RegTypeInt)
    36  	x1VReg = regalloc.FromRealReg(x1, regalloc.RegTypeInt)
    37  	x2VReg = regalloc.FromRealReg(x2, regalloc.RegTypeInt)
    38  	x3VReg = regalloc.FromRealReg(x3, regalloc.RegTypeInt)
    39  	x4VReg = regalloc.FromRealReg(x4, regalloc.RegTypeInt)
    40  	x5VReg = regalloc.FromRealReg(x5, regalloc.RegTypeInt)
    41  	x6VReg = regalloc.FromRealReg(x6, regalloc.RegTypeInt)
    42  	x7VReg = regalloc.FromRealReg(x7, regalloc.RegTypeInt)
    43  
    44  	v0VReg = regalloc.FromRealReg(v0, regalloc.RegTypeFloat)
    45  	v1VReg = regalloc.FromRealReg(v1, regalloc.RegTypeFloat)
    46  	v2VReg = regalloc.FromRealReg(v2, regalloc.RegTypeFloat)
    47  	v3VReg = regalloc.FromRealReg(v3, regalloc.RegTypeFloat)
    48  	v4VReg = regalloc.FromRealReg(v4, regalloc.RegTypeFloat)
    49  	v5VReg = regalloc.FromRealReg(v5, regalloc.RegTypeFloat)
    50  	v6VReg = regalloc.FromRealReg(v6, regalloc.RegTypeFloat)
    51  	v7VReg = regalloc.FromRealReg(v7, regalloc.RegTypeFloat)
    52  
    53  	intParamResultRegs   = []regalloc.RealReg{x0, x1, x2, x3, x4, x5, x6, x7}
    54  	floatParamResultRegs = []regalloc.RealReg{v0, v1, v2, v3, v4, v5, v6, v7}
    55  )
    56  
    57  func TestAbiImpl_init(t *testing.T) {
    58  	for _, tc := range []struct {
    59  		name string
    60  		sig  *ssa.Signature
    61  		exp  FunctionABI
    62  	}{
    63  		{
    64  			name: "empty sig",
    65  			sig:  &ssa.Signature{},
    66  			exp:  FunctionABI{},
    67  		},
    68  		{
    69  			name: "small sig",
    70  			sig: &ssa.Signature{
    71  				Params:  []ssa.Type{ssa.TypeI32, ssa.TypeF32, ssa.TypeI32},
    72  				Results: []ssa.Type{ssa.TypeI64, ssa.TypeF64},
    73  			},
    74  			exp: FunctionABI{
    75  				Args: []ABIArg{
    76  					{Index: 0, Kind: ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
    77  					{Index: 1, Kind: ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF32},
    78  					{Index: 2, Kind: ABIArgKindReg, Reg: x1VReg, Type: ssa.TypeI32},
    79  				},
    80  				Rets: []ABIArg{
    81  					{Index: 0, Kind: ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI64},
    82  					{Index: 1, Kind: ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF64},
    83  				},
    84  				ArgIntRealRegs: 2, ArgFloatRealRegs: 1,
    85  				RetIntRealRegs: 1, RetFloatRealRegs: 1,
    86  			},
    87  		},
    88  		{
    89  			name: "regs stack mix and match",
    90  			sig: &ssa.Signature{
    91  				Params: []ssa.Type{
    92  					ssa.TypeI32, ssa.TypeF32,
    93  					ssa.TypeI64, ssa.TypeF64,
    94  					ssa.TypeI32, ssa.TypeF32,
    95  					ssa.TypeI64, ssa.TypeF64,
    96  					ssa.TypeI32, ssa.TypeF32,
    97  					ssa.TypeI64, ssa.TypeF64,
    98  					ssa.TypeI32, ssa.TypeF32,
    99  					ssa.TypeI64, ssa.TypeF64,
   100  					ssa.TypeI32, ssa.TypeF32,
   101  					ssa.TypeI64, ssa.TypeF64,
   102  					ssa.TypeI32, ssa.TypeF32,
   103  					ssa.TypeI64, ssa.TypeF64,
   104  					ssa.TypeI32, ssa.TypeF32,
   105  					ssa.TypeI64, ssa.TypeF64,
   106  					ssa.TypeI32, ssa.TypeF32,
   107  					ssa.TypeI64, ssa.TypeF64,
   108  				},
   109  				Results: []ssa.Type{
   110  					ssa.TypeI32, ssa.TypeF32,
   111  					ssa.TypeI64, ssa.TypeF64,
   112  					ssa.TypeI32, ssa.TypeF32,
   113  					ssa.TypeI64, ssa.TypeF64,
   114  					ssa.TypeI32, ssa.TypeF32,
   115  					ssa.TypeI64, ssa.TypeF64,
   116  					ssa.TypeI32, ssa.TypeF32,
   117  					ssa.TypeI64, ssa.TypeF64,
   118  					ssa.TypeI32, ssa.TypeF32,
   119  					ssa.TypeI64, ssa.TypeF64,
   120  					ssa.TypeI32, ssa.TypeF32,
   121  					ssa.TypeI64, ssa.TypeF64,
   122  					ssa.TypeI32, ssa.TypeF32,
   123  					ssa.TypeI64, ssa.TypeF64,
   124  					ssa.TypeI32, ssa.TypeF32,
   125  					ssa.TypeI64, ssa.TypeF64,
   126  				},
   127  			},
   128  			exp: FunctionABI{
   129  				ArgStackSize: 128, RetStackSize: 128,
   130  				Args: []ABIArg{
   131  					{Index: 0, Kind: ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
   132  					{Index: 1, Kind: ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF32},
   133  					{Index: 2, Kind: ABIArgKindReg, Reg: x1VReg, Type: ssa.TypeI64},
   134  					{Index: 3, Kind: ABIArgKindReg, Reg: v1VReg, Type: ssa.TypeF64},
   135  					{Index: 4, Kind: ABIArgKindReg, Reg: x2VReg, Type: ssa.TypeI32},
   136  					{Index: 5, Kind: ABIArgKindReg, Reg: v2VReg, Type: ssa.TypeF32},
   137  					{Index: 6, Kind: ABIArgKindReg, Reg: x3VReg, Type: ssa.TypeI64},
   138  					{Index: 7, Kind: ABIArgKindReg, Reg: v3VReg, Type: ssa.TypeF64},
   139  					{Index: 8, Kind: ABIArgKindReg, Reg: x4VReg, Type: ssa.TypeI32},
   140  					{Index: 9, Kind: ABIArgKindReg, Reg: v4VReg, Type: ssa.TypeF32},
   141  					{Index: 10, Kind: ABIArgKindReg, Reg: x5VReg, Type: ssa.TypeI64},
   142  					{Index: 11, Kind: ABIArgKindReg, Reg: v5VReg, Type: ssa.TypeF64},
   143  					{Index: 12, Kind: ABIArgKindReg, Reg: x6VReg, Type: ssa.TypeI32},
   144  					{Index: 13, Kind: ABIArgKindReg, Reg: v6VReg, Type: ssa.TypeF32},
   145  					{Index: 14, Kind: ABIArgKindReg, Reg: x7VReg, Type: ssa.TypeI64},
   146  					{Index: 15, Kind: ABIArgKindReg, Reg: v7VReg, Type: ssa.TypeF64},
   147  					{Index: 16, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 0},
   148  					{Index: 17, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 8},
   149  					{Index: 18, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 16},
   150  					{Index: 19, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 24},
   151  					{Index: 20, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 32},
   152  					{Index: 21, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 40},
   153  					{Index: 22, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 48},
   154  					{Index: 23, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 56},
   155  					{Index: 24, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 64},
   156  					{Index: 25, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 72},
   157  					{Index: 26, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 80},
   158  					{Index: 27, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 88},
   159  					{Index: 28, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 96},
   160  					{Index: 29, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 104},
   161  					{Index: 30, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 112},
   162  					{Index: 31, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 120},
   163  				},
   164  				Rets: []ABIArg{
   165  					{Index: 0, Kind: ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
   166  					{Index: 1, Kind: ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF32},
   167  					{Index: 2, Kind: ABIArgKindReg, Reg: x1VReg, Type: ssa.TypeI64},
   168  					{Index: 3, Kind: ABIArgKindReg, Reg: v1VReg, Type: ssa.TypeF64},
   169  					{Index: 4, Kind: ABIArgKindReg, Reg: x2VReg, Type: ssa.TypeI32},
   170  					{Index: 5, Kind: ABIArgKindReg, Reg: v2VReg, Type: ssa.TypeF32},
   171  					{Index: 6, Kind: ABIArgKindReg, Reg: x3VReg, Type: ssa.TypeI64},
   172  					{Index: 7, Kind: ABIArgKindReg, Reg: v3VReg, Type: ssa.TypeF64},
   173  					{Index: 8, Kind: ABIArgKindReg, Reg: x4VReg, Type: ssa.TypeI32},
   174  					{Index: 9, Kind: ABIArgKindReg, Reg: v4VReg, Type: ssa.TypeF32},
   175  					{Index: 10, Kind: ABIArgKindReg, Reg: x5VReg, Type: ssa.TypeI64},
   176  					{Index: 11, Kind: ABIArgKindReg, Reg: v5VReg, Type: ssa.TypeF64},
   177  					{Index: 12, Kind: ABIArgKindReg, Reg: x6VReg, Type: ssa.TypeI32},
   178  					{Index: 13, Kind: ABIArgKindReg, Reg: v6VReg, Type: ssa.TypeF32},
   179  					{Index: 14, Kind: ABIArgKindReg, Reg: x7VReg, Type: ssa.TypeI64},
   180  					{Index: 15, Kind: ABIArgKindReg, Reg: v7VReg, Type: ssa.TypeF64},
   181  					{Index: 16, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 0},
   182  					{Index: 17, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 8},
   183  					{Index: 18, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 16},
   184  					{Index: 19, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 24},
   185  					{Index: 20, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 32},
   186  					{Index: 21, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 40},
   187  					{Index: 22, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 48},
   188  					{Index: 23, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 56},
   189  					{Index: 24, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 64},
   190  					{Index: 25, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 72},
   191  					{Index: 26, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 80},
   192  					{Index: 27, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 88},
   193  					{Index: 28, Kind: ABIArgKindStack, Type: ssa.TypeI32, Offset: 96},
   194  					{Index: 29, Kind: ABIArgKindStack, Type: ssa.TypeF32, Offset: 104},
   195  					{Index: 30, Kind: ABIArgKindStack, Type: ssa.TypeI64, Offset: 112},
   196  					{Index: 31, Kind: ABIArgKindStack, Type: ssa.TypeF64, Offset: 120},
   197  				},
   198  				ArgIntRealRegs: 8, ArgFloatRealRegs: 8,
   199  				RetIntRealRegs: 8, RetFloatRealRegs: 8,
   200  			},
   201  		},
   202  		{
   203  			name: "all regs",
   204  			sig: &ssa.Signature{
   205  				Params: []ssa.Type{
   206  					ssa.TypeI32, ssa.TypeF32,
   207  					ssa.TypeI64, ssa.TypeF64,
   208  					ssa.TypeI32, ssa.TypeF32,
   209  					ssa.TypeI64, ssa.TypeF64,
   210  					ssa.TypeI32, ssa.TypeF32,
   211  					ssa.TypeI64, ssa.TypeF64,
   212  					ssa.TypeI32, ssa.TypeF32,
   213  					ssa.TypeI64, ssa.TypeF64,
   214  				},
   215  				Results: []ssa.Type{
   216  					ssa.TypeI32, ssa.TypeF32,
   217  					ssa.TypeI64, ssa.TypeF64,
   218  					ssa.TypeI32, ssa.TypeF32,
   219  					ssa.TypeI64, ssa.TypeF64,
   220  					ssa.TypeI32, ssa.TypeF32,
   221  					ssa.TypeI64, ssa.TypeF64,
   222  					ssa.TypeI32, ssa.TypeF32,
   223  					ssa.TypeI64, ssa.TypeF64,
   224  				},
   225  			},
   226  			exp: FunctionABI{
   227  				Args: []ABIArg{
   228  					{Index: 0, Kind: ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
   229  					{Index: 1, Kind: ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF32},
   230  					{Index: 2, Kind: ABIArgKindReg, Reg: x1VReg, Type: ssa.TypeI64},
   231  					{Index: 3, Kind: ABIArgKindReg, Reg: v1VReg, Type: ssa.TypeF64},
   232  					{Index: 4, Kind: ABIArgKindReg, Reg: x2VReg, Type: ssa.TypeI32},
   233  					{Index: 5, Kind: ABIArgKindReg, Reg: v2VReg, Type: ssa.TypeF32},
   234  					{Index: 6, Kind: ABIArgKindReg, Reg: x3VReg, Type: ssa.TypeI64},
   235  					{Index: 7, Kind: ABIArgKindReg, Reg: v3VReg, Type: ssa.TypeF64},
   236  					{Index: 8, Kind: ABIArgKindReg, Reg: x4VReg, Type: ssa.TypeI32},
   237  					{Index: 9, Kind: ABIArgKindReg, Reg: v4VReg, Type: ssa.TypeF32},
   238  					{Index: 10, Kind: ABIArgKindReg, Reg: x5VReg, Type: ssa.TypeI64},
   239  					{Index: 11, Kind: ABIArgKindReg, Reg: v5VReg, Type: ssa.TypeF64},
   240  					{Index: 12, Kind: ABIArgKindReg, Reg: x6VReg, Type: ssa.TypeI32},
   241  					{Index: 13, Kind: ABIArgKindReg, Reg: v6VReg, Type: ssa.TypeF32},
   242  					{Index: 14, Kind: ABIArgKindReg, Reg: x7VReg, Type: ssa.TypeI64},
   243  					{Index: 15, Kind: ABIArgKindReg, Reg: v7VReg, Type: ssa.TypeF64},
   244  				},
   245  				Rets: []ABIArg{
   246  					{Index: 0, Kind: ABIArgKindReg, Reg: x0VReg, Type: ssa.TypeI32},
   247  					{Index: 1, Kind: ABIArgKindReg, Reg: v0VReg, Type: ssa.TypeF32},
   248  					{Index: 2, Kind: ABIArgKindReg, Reg: x1VReg, Type: ssa.TypeI64},
   249  					{Index: 3, Kind: ABIArgKindReg, Reg: v1VReg, Type: ssa.TypeF64},
   250  					{Index: 4, Kind: ABIArgKindReg, Reg: x2VReg, Type: ssa.TypeI32},
   251  					{Index: 5, Kind: ABIArgKindReg, Reg: v2VReg, Type: ssa.TypeF32},
   252  					{Index: 6, Kind: ABIArgKindReg, Reg: x3VReg, Type: ssa.TypeI64},
   253  					{Index: 7, Kind: ABIArgKindReg, Reg: v3VReg, Type: ssa.TypeF64},
   254  					{Index: 8, Kind: ABIArgKindReg, Reg: x4VReg, Type: ssa.TypeI32},
   255  					{Index: 9, Kind: ABIArgKindReg, Reg: v4VReg, Type: ssa.TypeF32},
   256  					{Index: 10, Kind: ABIArgKindReg, Reg: x5VReg, Type: ssa.TypeI64},
   257  					{Index: 11, Kind: ABIArgKindReg, Reg: v5VReg, Type: ssa.TypeF64},
   258  					{Index: 12, Kind: ABIArgKindReg, Reg: x6VReg, Type: ssa.TypeI32},
   259  					{Index: 13, Kind: ABIArgKindReg, Reg: v6VReg, Type: ssa.TypeF32},
   260  					{Index: 14, Kind: ABIArgKindReg, Reg: x7VReg, Type: ssa.TypeI64},
   261  					{Index: 15, Kind: ABIArgKindReg, Reg: v7VReg, Type: ssa.TypeF64},
   262  				},
   263  				ArgIntRealRegs: 8, ArgFloatRealRegs: 8,
   264  				RetIntRealRegs: 8, RetFloatRealRegs: 8,
   265  			},
   266  		},
   267  	} {
   268  		tc := tc
   269  		t.Run(tc.name, func(t *testing.T) {
   270  			abi := FunctionABI{}
   271  			abi.Init(tc.sig, intParamResultRegs, floatParamResultRegs)
   272  			require.Equal(t, tc.exp.Args, abi.Args)
   273  			require.Equal(t, tc.exp.Rets, abi.Rets)
   274  			require.Equal(t, tc.exp.ArgStackSize, abi.ArgStackSize)
   275  			require.Equal(t, tc.exp.RetStackSize, abi.RetStackSize)
   276  			require.Equal(t, tc.exp.RetIntRealRegs, abi.RetIntRealRegs)
   277  			require.Equal(t, tc.exp.RetFloatRealRegs, abi.RetFloatRealRegs)
   278  			require.Equal(t, tc.exp.ArgIntRealRegs, abi.ArgIntRealRegs)
   279  			require.Equal(t, tc.exp.ArgFloatRealRegs, abi.ArgFloatRealRegs)
   280  		})
   281  	}
   282  }