github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/wazeroir/signature_test.go (about)

     1  package wazeroir
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/bananabytelabs/wazero/internal/testing/require"
     7  	"github.com/bananabytelabs/wazero/internal/wasm"
     8  )
     9  
    10  func TestCompiler_wasmOpcodeSignature(t *testing.T) {
    11  	tests := []struct {
    12  		name string
    13  		body []byte
    14  		exp  *signature
    15  	}{
    16  		{
    17  			name: "i32.trunc_sat_f32_s",
    18  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF32S},
    19  			exp:  signature_F32_I32,
    20  		},
    21  		{
    22  			name: "i32.trunc_sat_f32_u",
    23  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF32U},
    24  			exp:  signature_F32_I32,
    25  		},
    26  		{
    27  			name: "i32.trunc_sat_f64_s",
    28  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF64S},
    29  			exp:  signature_F64_I32,
    30  		},
    31  		{
    32  			name: "i32.trunc_sat_f64_u",
    33  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI32TruncSatF64U},
    34  			exp:  signature_F64_I32,
    35  		},
    36  		{
    37  			name: "i64.trunc_sat_f32_s",
    38  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF32S},
    39  			exp:  signature_F32_I64,
    40  		},
    41  		{
    42  			name: "i64.trunc_sat_f32_u",
    43  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF32U},
    44  			exp:  signature_F32_I64,
    45  		},
    46  		{
    47  			name: "i64.trunc_sat_f64_s",
    48  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF64S},
    49  			exp:  signature_F64_I64,
    50  		},
    51  		{
    52  			name: "i64.trunc_sat_f64_u",
    53  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscI64TruncSatF64U},
    54  			exp:  signature_F64_I64,
    55  		},
    56  		{
    57  			name: "memory.init",
    58  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscMemoryInit},
    59  			exp:  signature_I32I32I32_None,
    60  		},
    61  		{
    62  			name: "data.drop",
    63  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscDataDrop},
    64  			exp:  signature_None_None,
    65  		},
    66  		{
    67  			name: "memory.copy",
    68  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscMemoryCopy},
    69  			exp:  signature_I32I32I32_None,
    70  		},
    71  		{
    72  			name: "memory.fill",
    73  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscMemoryFill},
    74  			exp:  signature_I32I32I32_None,
    75  		},
    76  		{
    77  			name: "table.init",
    78  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscTableInit},
    79  			exp:  signature_I32I32I32_None,
    80  		},
    81  		{
    82  			name: "elem.drop",
    83  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscElemDrop},
    84  			exp:  signature_None_None,
    85  		},
    86  		{
    87  			name: "table.copy",
    88  			body: []byte{wasm.OpcodeMiscPrefix, wasm.OpcodeMiscTableCopy},
    89  			exp:  signature_I32I32I32_None,
    90  		},
    91  		{
    92  			name: "i32.atomic.load8_u",
    93  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Load8U},
    94  			exp:  signature_I32_I32,
    95  		},
    96  		{
    97  			name: "i32.atomic.load16_u",
    98  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Load16U},
    99  			exp:  signature_I32_I32,
   100  		},
   101  		{
   102  			name: "i32.atomic.load",
   103  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Load},
   104  			exp:  signature_I32_I32,
   105  		},
   106  		{
   107  			name: "i64.atomic.load8_u",
   108  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Load8U},
   109  			exp:  signature_I32_I64,
   110  		},
   111  		{
   112  			name: "i64.atomic.load16_u",
   113  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Load16U},
   114  			exp:  signature_I32_I64,
   115  		},
   116  		{
   117  			name: "i64.atomic.load32_u",
   118  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Load32U},
   119  			exp:  signature_I32_I64,
   120  		},
   121  		{
   122  			name: "i64.atomic.load",
   123  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Load},
   124  			exp:  signature_I32_I64,
   125  		},
   126  		{
   127  			name: "i32.atomic.store8",
   128  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Store8},
   129  			exp:  signature_I32I32_None,
   130  		},
   131  		{
   132  			name: "i32.atomic.store16_u",
   133  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Store16},
   134  			exp:  signature_I32I32_None,
   135  		},
   136  		{
   137  			name: "i32.atomic.store",
   138  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Store},
   139  			exp:  signature_I32I32_None,
   140  		},
   141  		{
   142  			name: "i64.atomic.store8",
   143  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Store8},
   144  			exp:  signature_I32I64_None,
   145  		},
   146  		{
   147  			name: "i64.atomic.store16",
   148  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Store16},
   149  			exp:  signature_I32I64_None,
   150  		},
   151  		{
   152  			name: "i64.atomic.store32",
   153  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Store32},
   154  			exp:  signature_I32I64_None,
   155  		},
   156  		{
   157  			name: "i64.atomic.store",
   158  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Store},
   159  			exp:  signature_I32I64_None,
   160  		},
   161  		{
   162  			name: "i32.atomic.rmw8.add_u",
   163  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw8AddU},
   164  			exp:  signature_I32I32_I32,
   165  		},
   166  		{
   167  			name: "i32.atomic.rmw16.add_u",
   168  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw16AddU},
   169  			exp:  signature_I32I32_I32,
   170  		},
   171  		{
   172  			name: "i32.atomic.rmw.add",
   173  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32RmwAdd},
   174  			exp:  signature_I32I32_I32,
   175  		},
   176  		{
   177  			name: "i64.atomic.rmw8.add_u",
   178  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw8AddU},
   179  			exp:  signature_I32I64_I64,
   180  		},
   181  		{
   182  			name: "i64.atomic.rmw16.add_u",
   183  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw16AddU},
   184  			exp:  signature_I32I64_I64,
   185  		},
   186  		{
   187  			name: "i64.atomic.rmw32.add_u",
   188  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw32AddU},
   189  			exp:  signature_I32I64_I64,
   190  		},
   191  		{
   192  			name: "i64.atomic.rmw.add",
   193  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64RmwAdd},
   194  			exp:  signature_I32I64_I64,
   195  		},
   196  		{
   197  			name: "i32.atomic.rmw8.sub_u",
   198  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw8SubU},
   199  			exp:  signature_I32I32_I32,
   200  		},
   201  		{
   202  			name: "i32.atomic.rmw16.sub_u",
   203  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw16SubU},
   204  			exp:  signature_I32I32_I32,
   205  		},
   206  		{
   207  			name: "i32.atomic.rmw.sub",
   208  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32RmwSub},
   209  			exp:  signature_I32I32_I32,
   210  		},
   211  		{
   212  			name: "i64.atomic.rmw8.sub_u",
   213  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw8SubU},
   214  			exp:  signature_I32I64_I64,
   215  		},
   216  		{
   217  			name: "i64.atomic.rmw16.sub_u",
   218  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw16SubU},
   219  			exp:  signature_I32I64_I64,
   220  		},
   221  		{
   222  			name: "i64.atomic.rmw32.sub_u",
   223  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw32SubU},
   224  			exp:  signature_I32I64_I64,
   225  		},
   226  		{
   227  			name: "i64.atomic.rmw.sub",
   228  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64RmwSub},
   229  			exp:  signature_I32I64_I64,
   230  		},
   231  		{
   232  			name: "i32.atomic.rmw8.and_u",
   233  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw8AndU},
   234  			exp:  signature_I32I32_I32,
   235  		},
   236  		{
   237  			name: "i32.atomic.rmw16.and_u",
   238  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw16AndU},
   239  			exp:  signature_I32I32_I32,
   240  		},
   241  		{
   242  			name: "i32.atomic.rmw.and",
   243  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32RmwAnd},
   244  			exp:  signature_I32I32_I32,
   245  		},
   246  		{
   247  			name: "i64.atomic.rmw8.and_u",
   248  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw8AndU},
   249  			exp:  signature_I32I64_I64,
   250  		},
   251  		{
   252  			name: "i64.atomic.rmw16.and_u",
   253  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw16AndU},
   254  			exp:  signature_I32I64_I64,
   255  		},
   256  		{
   257  			name: "i64.atomic.rmw32.and_u",
   258  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw32AndU},
   259  			exp:  signature_I32I64_I64,
   260  		},
   261  		{
   262  			name: "i64.atomic.rmw.and",
   263  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64RmwAnd},
   264  			exp:  signature_I32I64_I64,
   265  		},
   266  		{
   267  			name: "i32.atomic.rmw8.or_u",
   268  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw8OrU},
   269  			exp:  signature_I32I32_I32,
   270  		},
   271  		{
   272  			name: "i32.atomic.rmw16.or_u",
   273  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw16OrU},
   274  			exp:  signature_I32I32_I32,
   275  		},
   276  		{
   277  			name: "i32.atomic.rmw.or",
   278  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32RmwOr},
   279  			exp:  signature_I32I32_I32,
   280  		},
   281  		{
   282  			name: "i64.atomic.rmw8.or_u",
   283  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw8OrU},
   284  			exp:  signature_I32I64_I64,
   285  		},
   286  		{
   287  			name: "i64.atomic.rmw16.or_u",
   288  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw16OrU},
   289  			exp:  signature_I32I64_I64,
   290  		},
   291  		{
   292  			name: "i64.atomic.rmw32.or_u",
   293  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw32OrU},
   294  			exp:  signature_I32I64_I64,
   295  		},
   296  		{
   297  			name: "i64.atomic.rmw.or",
   298  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64RmwOr},
   299  			exp:  signature_I32I64_I64,
   300  		},
   301  		{
   302  			name: "i32.atomic.rmw8.xor_u",
   303  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw8XorU},
   304  			exp:  signature_I32I32_I32,
   305  		},
   306  		{
   307  			name: "i32.atomic.rmw16.xor_u",
   308  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw16XorU},
   309  			exp:  signature_I32I32_I32,
   310  		},
   311  		{
   312  			name: "i32.atomic.rmw.xor",
   313  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32RmwXor},
   314  			exp:  signature_I32I32_I32,
   315  		},
   316  		{
   317  			name: "i64.atomic.rmw8.xor_u",
   318  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw8XorU},
   319  			exp:  signature_I32I64_I64,
   320  		},
   321  		{
   322  			name: "i64.atomic.rmw16.xor_u",
   323  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw16XorU},
   324  			exp:  signature_I32I64_I64,
   325  		},
   326  		{
   327  			name: "i64.atomic.rmw32.xor_u",
   328  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw32XorU},
   329  			exp:  signature_I32I64_I64,
   330  		},
   331  		{
   332  			name: "i64.atomic.rmw.xor",
   333  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64RmwXor},
   334  			exp:  signature_I32I64_I64,
   335  		},
   336  		{
   337  			name: "i32.atomic.rmw8.xchg_u",
   338  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw8XchgU},
   339  			exp:  signature_I32I32_I32,
   340  		},
   341  		{
   342  			name: "i32.atomic.rmw16.xchg_u",
   343  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw16XchgU},
   344  			exp:  signature_I32I32_I32,
   345  		},
   346  		{
   347  			name: "i32.atomic.rmw.xchg",
   348  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32RmwXchg},
   349  			exp:  signature_I32I32_I32,
   350  		},
   351  		{
   352  			name: "i64.atomic.rmw8.xchg_u",
   353  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw8XchgU},
   354  			exp:  signature_I32I64_I64,
   355  		},
   356  		{
   357  			name: "i64.atomic.rmw16.xchg_u",
   358  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw16XchgU},
   359  			exp:  signature_I32I64_I64,
   360  		},
   361  		{
   362  			name: "i64.atomic.rmw32.xchg_u",
   363  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw32XchgU},
   364  			exp:  signature_I32I64_I64,
   365  		},
   366  		{
   367  			name: "i64.atomic.rmw.xchg",
   368  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64RmwXchg},
   369  			exp:  signature_I32I64_I64,
   370  		},
   371  		{
   372  			name: "i32.atomic.rmw8.cmpxchg_u",
   373  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw8CmpxchgU},
   374  			exp:  signature_I32I32I32_I32,
   375  		},
   376  		{
   377  			name: "i32.atomic.rmw16.cmpxchg_u",
   378  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32Rmw16CmpxchgU},
   379  			exp:  signature_I32I32I32_I32,
   380  		},
   381  		{
   382  			name: "i32.atomic.rmw.cmpxchg",
   383  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI32RmwCmpxchg},
   384  			exp:  signature_I32I32I32_I32,
   385  		},
   386  		{
   387  			name: "i64.atomic.rmw8.cmpxchg_u",
   388  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw8CmpxchgU},
   389  			exp:  signature_I32I64I64_I64,
   390  		},
   391  		{
   392  			name: "i64.atomic.rmw16.cmpxchg_u",
   393  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw16CmpxchgU},
   394  			exp:  signature_I32I64I64_I64,
   395  		},
   396  		{
   397  			name: "i64.atomic.rmw32.cmpxchg_u",
   398  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64Rmw32CmpxchgU},
   399  			exp:  signature_I32I64I64_I64,
   400  		},
   401  		{
   402  			name: "i64.atomic.rmw.cmpxchg",
   403  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicI64RmwCmpxchg},
   404  			exp:  signature_I32I64I64_I64,
   405  		},
   406  		{
   407  			name: "memory.atomic.wait32",
   408  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicMemoryWait32},
   409  			exp:  signature_I32I32I64_I32,
   410  		},
   411  		{
   412  			name: "memory.atomic.wait64",
   413  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicMemoryWait64},
   414  			exp:  signature_I32I64I64_I32,
   415  		},
   416  		{
   417  			name: "memory.atomic.notify",
   418  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicMemoryNotify},
   419  			exp:  signature_I32I32_I32,
   420  		},
   421  		{
   422  			name: "memory.atomic.fence",
   423  			body: []byte{wasm.OpcodeAtomicPrefix, wasm.OpcodeAtomicFence},
   424  			exp:  signature_None_None,
   425  		},
   426  	}
   427  
   428  	for _, tt := range tests {
   429  		tc := tt
   430  		t.Run(tc.name, func(t *testing.T) {
   431  			c := &Compiler{body: tc.body}
   432  			actual, err := c.wasmOpcodeSignature(tc.body[0], 0)
   433  			require.NoError(t, err)
   434  			require.Equal(t, tc.exp, actual)
   435  		})
   436  	}
   437  }
   438  
   439  func Test_funcTypeToIRSignatures(t *testing.T) {
   440  	f := &funcTypeToIRSignatures{
   441  		wasmTypes:     []wasm.FunctionType{v_v, i32_i32, v_f64f64},
   442  		directCalls:   make([]*signature, 3),
   443  		indirectCalls: make([]*signature, 3),
   444  	}
   445  
   446  	require.Equal(t, &signature{in: make([]UnsignedType, 0), out: make([]UnsignedType, 0)}, f.get(0, false))
   447  	require.Equal(t, &signature{in: []UnsignedType{UnsignedTypeI32}, out: make([]UnsignedType, 0)}, f.get(0, true))
   448  	require.NotNil(t, f.directCalls[0])
   449  	require.NotNil(t, f.indirectCalls[0])
   450  	require.Equal(t, &signature{in: []UnsignedType{UnsignedTypeI32}, out: []UnsignedType{UnsignedTypeI32}}, f.get(1, false))
   451  	require.Equal(t, &signature{in: []UnsignedType{UnsignedTypeI32, UnsignedTypeI32}, out: []UnsignedType{UnsignedTypeI32}}, f.get(1, true))
   452  	require.NotNil(t, f.directCalls[1])
   453  	require.NotNil(t, f.indirectCalls[1])
   454  	require.Equal(t, &signature{in: make([]UnsignedType, 0), out: []UnsignedType{UnsignedTypeF64, UnsignedTypeF64}}, f.get(2, false))
   455  	require.Equal(t, &signature{in: []UnsignedType{UnsignedTypeI32}, out: []UnsignedType{UnsignedTypeF64, UnsignedTypeF64}}, f.get(2, true))
   456  	require.NotNil(t, f.directCalls[2])
   457  	require.NotNil(t, f.indirectCalls[2])
   458  }