github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/wazeroir/signature.go (about)

     1  package wazeroir
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/wasilibs/wazerox/internal/wasm"
     7  )
     8  
     9  // signature represents how a Wasm opcode
    10  // manipulates the value stacks in terms of value types.
    11  type signature struct {
    12  	in, out []UnsignedType
    13  }
    14  
    15  var (
    16  	signature_None_None    = &signature{}
    17  	signature_Unknown_None = &signature{
    18  		in: []UnsignedType{UnsignedTypeUnknown},
    19  	}
    20  	signature_None_I32 = &signature{
    21  		out: []UnsignedType{UnsignedTypeI32},
    22  	}
    23  	signature_None_I64 = &signature{
    24  		out: []UnsignedType{UnsignedTypeI64},
    25  	}
    26  	signature_None_V128 = &signature{
    27  		out: []UnsignedType{UnsignedTypeV128},
    28  	}
    29  	signature_None_F32 = &signature{
    30  		out: []UnsignedType{UnsignedTypeF32},
    31  	}
    32  	signature_None_F64 = &signature{
    33  		out: []UnsignedType{UnsignedTypeF64},
    34  	}
    35  	signature_I32_None = &signature{
    36  		in: []UnsignedType{UnsignedTypeI32},
    37  	}
    38  	signature_I64_None = &signature{
    39  		in: []UnsignedType{UnsignedTypeI64},
    40  	}
    41  	signature_F32_None = &signature{
    42  		in: []UnsignedType{UnsignedTypeF32},
    43  	}
    44  	signature_F64_None = &signature{
    45  		in: []UnsignedType{UnsignedTypeF64},
    46  	}
    47  	signature_V128_None = &signature{
    48  		in: []UnsignedType{UnsignedTypeV128},
    49  	}
    50  	signature_I32_I32 = &signature{
    51  		in:  []UnsignedType{UnsignedTypeI32},
    52  		out: []UnsignedType{UnsignedTypeI32},
    53  	}
    54  	signature_I32_I64 = &signature{
    55  		in:  []UnsignedType{UnsignedTypeI32},
    56  		out: []UnsignedType{UnsignedTypeI64},
    57  	}
    58  	signature_I64_I64 = &signature{
    59  		in:  []UnsignedType{UnsignedTypeI64},
    60  		out: []UnsignedType{UnsignedTypeI64},
    61  	}
    62  	signature_I32_F32 = &signature{
    63  		in:  []UnsignedType{UnsignedTypeI32},
    64  		out: []UnsignedType{UnsignedTypeF32},
    65  	}
    66  	signature_I32_F64 = &signature{
    67  		in:  []UnsignedType{UnsignedTypeI32},
    68  		out: []UnsignedType{UnsignedTypeF64},
    69  	}
    70  	signature_I64_I32 = &signature{
    71  		in:  []UnsignedType{UnsignedTypeI64},
    72  		out: []UnsignedType{UnsignedTypeI32},
    73  	}
    74  	signature_I64_F32 = &signature{
    75  		in:  []UnsignedType{UnsignedTypeI64},
    76  		out: []UnsignedType{UnsignedTypeF32},
    77  	}
    78  	signature_I64_F64 = &signature{
    79  		in:  []UnsignedType{UnsignedTypeI64},
    80  		out: []UnsignedType{UnsignedTypeF64},
    81  	}
    82  	signature_F32_I32 = &signature{
    83  		in:  []UnsignedType{UnsignedTypeF32},
    84  		out: []UnsignedType{UnsignedTypeI32},
    85  	}
    86  	signature_F32_I64 = &signature{
    87  		in:  []UnsignedType{UnsignedTypeF32},
    88  		out: []UnsignedType{UnsignedTypeI64},
    89  	}
    90  	signature_F32_F64 = &signature{
    91  		in:  []UnsignedType{UnsignedTypeF32},
    92  		out: []UnsignedType{UnsignedTypeF64},
    93  	}
    94  	signature_F32_F32 = &signature{
    95  		in:  []UnsignedType{UnsignedTypeF32},
    96  		out: []UnsignedType{UnsignedTypeF32},
    97  	}
    98  	signature_F64_I32 = &signature{
    99  		in:  []UnsignedType{UnsignedTypeF64},
   100  		out: []UnsignedType{UnsignedTypeI32},
   101  	}
   102  	signature_F64_F32 = &signature{
   103  		in:  []UnsignedType{UnsignedTypeF64},
   104  		out: []UnsignedType{UnsignedTypeF32},
   105  	}
   106  	signature_F64_I64 = &signature{
   107  		in:  []UnsignedType{UnsignedTypeF64},
   108  		out: []UnsignedType{UnsignedTypeI64},
   109  	}
   110  	signature_F64_F64 = &signature{
   111  		in:  []UnsignedType{UnsignedTypeF64},
   112  		out: []UnsignedType{UnsignedTypeF64},
   113  	}
   114  	signature_I32I32_None = &signature{
   115  		in: []UnsignedType{UnsignedTypeI32, UnsignedTypeI32},
   116  	}
   117  
   118  	signature_I32I32_I32 = &signature{
   119  		in:  []UnsignedType{UnsignedTypeI32, UnsignedTypeI32},
   120  		out: []UnsignedType{UnsignedTypeI32},
   121  	}
   122  	signature_I32I64_None = &signature{
   123  		in: []UnsignedType{UnsignedTypeI32, UnsignedTypeI64},
   124  	}
   125  	signature_I32F32_None = &signature{
   126  		in: []UnsignedType{UnsignedTypeI32, UnsignedTypeF32},
   127  	}
   128  	signature_I32F64_None = &signature{
   129  		in: []UnsignedType{UnsignedTypeI32, UnsignedTypeF64},
   130  	}
   131  	signature_I64I32_I32 = &signature{
   132  		in:  []UnsignedType{UnsignedTypeI64, UnsignedTypeI32},
   133  		out: []UnsignedType{UnsignedTypeI32},
   134  	}
   135  	signature_I64I64_I32 = &signature{
   136  		in:  []UnsignedType{UnsignedTypeI64, UnsignedTypeI64},
   137  		out: []UnsignedType{UnsignedTypeI32},
   138  	}
   139  	signature_I64I64_I64 = &signature{
   140  		in:  []UnsignedType{UnsignedTypeI64, UnsignedTypeI64},
   141  		out: []UnsignedType{UnsignedTypeI64},
   142  	}
   143  	signature_F32F32_I32 = &signature{
   144  		in:  []UnsignedType{UnsignedTypeF32, UnsignedTypeF32},
   145  		out: []UnsignedType{UnsignedTypeI32},
   146  	}
   147  	signature_F32F32_F32 = &signature{
   148  		in:  []UnsignedType{UnsignedTypeF32, UnsignedTypeF32},
   149  		out: []UnsignedType{UnsignedTypeF32},
   150  	}
   151  	signature_F64F64_I32 = &signature{
   152  		in:  []UnsignedType{UnsignedTypeF64, UnsignedTypeF64},
   153  		out: []UnsignedType{UnsignedTypeI32},
   154  	}
   155  	signature_F64F64_F64 = &signature{
   156  		in:  []UnsignedType{UnsignedTypeF64, UnsignedTypeF64},
   157  		out: []UnsignedType{UnsignedTypeF64},
   158  	}
   159  	signature_I32I32I32_None = &signature{
   160  		in: []UnsignedType{UnsignedTypeI32, UnsignedTypeI32, UnsignedTypeI32},
   161  	}
   162  	signature_I32I64I32_None = &signature{
   163  		in: []UnsignedType{UnsignedTypeI32, UnsignedTypeI64, UnsignedTypeI32},
   164  	}
   165  	signature_UnknownUnknownI32_Unknown = &signature{
   166  		in:  []UnsignedType{UnsignedTypeUnknown, UnsignedTypeUnknown, UnsignedTypeI32},
   167  		out: []UnsignedType{UnsignedTypeUnknown},
   168  	}
   169  	signature_V128V128_V128 = &signature{
   170  		in:  []UnsignedType{UnsignedTypeV128, UnsignedTypeV128},
   171  		out: []UnsignedType{UnsignedTypeV128},
   172  	}
   173  	signature_V128V128V128_V32 = &signature{
   174  		in:  []UnsignedType{UnsignedTypeV128, UnsignedTypeV128, UnsignedTypeV128},
   175  		out: []UnsignedType{UnsignedTypeV128},
   176  	}
   177  	signature_I32_V128 = &signature{
   178  		in:  []UnsignedType{UnsignedTypeI32},
   179  		out: []UnsignedType{UnsignedTypeV128},
   180  	}
   181  	signature_I32V128_None = &signature{
   182  		in: []UnsignedType{UnsignedTypeI32, UnsignedTypeV128},
   183  	}
   184  	signature_I32V128_V128 = &signature{
   185  		in:  []UnsignedType{UnsignedTypeI32, UnsignedTypeV128},
   186  		out: []UnsignedType{UnsignedTypeV128},
   187  	}
   188  	signature_V128I32_V128 = &signature{
   189  		in:  []UnsignedType{UnsignedTypeV128, UnsignedTypeI32},
   190  		out: []UnsignedType{UnsignedTypeV128},
   191  	}
   192  	signature_V128I64_V128 = &signature{
   193  		in:  []UnsignedType{UnsignedTypeV128, UnsignedTypeI64},
   194  		out: []UnsignedType{UnsignedTypeV128},
   195  	}
   196  	signature_V128F32_V128 = &signature{
   197  		in:  []UnsignedType{UnsignedTypeV128, UnsignedTypeF32},
   198  		out: []UnsignedType{UnsignedTypeV128},
   199  	}
   200  	signature_V128F64_V128 = &signature{
   201  		in:  []UnsignedType{UnsignedTypeV128, UnsignedTypeF64},
   202  		out: []UnsignedType{UnsignedTypeV128},
   203  	}
   204  	signature_V128_I32 = &signature{
   205  		in:  []UnsignedType{UnsignedTypeV128},
   206  		out: []UnsignedType{UnsignedTypeI32},
   207  	}
   208  	signature_V128_I64 = &signature{
   209  		in:  []UnsignedType{UnsignedTypeV128},
   210  		out: []UnsignedType{UnsignedTypeI64},
   211  	}
   212  	signature_V128_F32 = &signature{
   213  		in:  []UnsignedType{UnsignedTypeV128},
   214  		out: []UnsignedType{UnsignedTypeF32},
   215  	}
   216  	signature_V128_F64 = &signature{
   217  		in:  []UnsignedType{UnsignedTypeV128},
   218  		out: []UnsignedType{UnsignedTypeF64},
   219  	}
   220  	signature_V128_V128 = &signature{
   221  		in:  []UnsignedType{UnsignedTypeV128},
   222  		out: []UnsignedType{UnsignedTypeV128},
   223  	}
   224  	signature_I64_V128 = &signature{
   225  		in:  []UnsignedType{UnsignedTypeI64},
   226  		out: []UnsignedType{UnsignedTypeV128},
   227  	}
   228  	signature_F32_V128 = &signature{
   229  		in:  []UnsignedType{UnsignedTypeF32},
   230  		out: []UnsignedType{UnsignedTypeV128},
   231  	}
   232  	signature_F64_V128 = &signature{
   233  		in:  []UnsignedType{UnsignedTypeF64},
   234  		out: []UnsignedType{UnsignedTypeV128},
   235  	}
   236  	signature_I32I64_I64 = &signature{
   237  		in:  []UnsignedType{UnsignedTypeI32, UnsignedTypeI64},
   238  		out: []UnsignedType{UnsignedTypeI64},
   239  	}
   240  	signature_I32I32I64_I32 = &signature{
   241  		in:  []UnsignedType{UnsignedTypeI32, UnsignedTypeI32, UnsignedTypeI64},
   242  		out: []UnsignedType{UnsignedTypeI32},
   243  	}
   244  	signature_I32I64I64_I32 = &signature{
   245  		in:  []UnsignedType{UnsignedTypeI32, UnsignedTypeI64, UnsignedTypeI64},
   246  		out: []UnsignedType{UnsignedTypeI32},
   247  	}
   248  	signature_I32I32I32_I32 = &signature{
   249  		in:  []UnsignedType{UnsignedTypeI32, UnsignedTypeI32, UnsignedTypeI32},
   250  		out: []UnsignedType{UnsignedTypeI32},
   251  	}
   252  	signature_I32I64I64_I64 = &signature{
   253  		in:  []UnsignedType{UnsignedTypeI32, UnsignedTypeI64, UnsignedTypeI64},
   254  		out: []UnsignedType{UnsignedTypeI64},
   255  	}
   256  )
   257  
   258  // wasmOpcodeSignature returns the signature of given Wasm opcode.
   259  // Note that some of opcodes' signature vary depending on
   260  // the function instance (for example, local types).
   261  // "index" parameter is not used by most of opcodes.
   262  // The returned signature is used for stack validation when lowering Wasm's opcodes to wazeroir.
   263  func (c *Compiler) wasmOpcodeSignature(op wasm.Opcode, index uint32) (*signature, error) {
   264  	switch op {
   265  	case wasm.OpcodeUnreachable, wasm.OpcodeNop, wasm.OpcodeBlock, wasm.OpcodeLoop:
   266  		return signature_None_None, nil
   267  	case wasm.OpcodeIf:
   268  		return signature_I32_None, nil
   269  	case wasm.OpcodeElse, wasm.OpcodeEnd, wasm.OpcodeBr:
   270  		return signature_None_None, nil
   271  	case wasm.OpcodeBrIf, wasm.OpcodeBrTable:
   272  		return signature_I32_None, nil
   273  	case wasm.OpcodeReturn:
   274  		return signature_None_None, nil
   275  	case wasm.OpcodeCall:
   276  		return c.funcTypeToSigs.get(c.funcs[index], false /* direct */), nil
   277  	case wasm.OpcodeCallIndirect:
   278  		return c.funcTypeToSigs.get(index, true /* call_indirect */), nil
   279  	case wasm.OpcodeDrop:
   280  		return signature_Unknown_None, nil
   281  	case wasm.OpcodeSelect, wasm.OpcodeTypedSelect:
   282  		return signature_UnknownUnknownI32_Unknown, nil
   283  	case wasm.OpcodeLocalGet:
   284  		inputLen := uint32(len(c.sig.Params))
   285  		if l := uint32(len(c.localTypes)) + inputLen; index >= l {
   286  			return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l)
   287  		}
   288  		var t wasm.ValueType
   289  		if index < inputLen {
   290  			t = c.sig.Params[index]
   291  		} else {
   292  			t = c.localTypes[index-inputLen]
   293  		}
   294  		return wasmValueTypeToUnsignedOutSignature(t), nil
   295  	case wasm.OpcodeLocalSet:
   296  		inputLen := uint32(len(c.sig.Params))
   297  		if l := uint32(len(c.localTypes)) + inputLen; index >= l {
   298  			return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l)
   299  		}
   300  		var t wasm.ValueType
   301  		if index < inputLen {
   302  			t = c.sig.Params[index]
   303  		} else {
   304  			t = c.localTypes[index-inputLen]
   305  		}
   306  		return wasmValueTypeToUnsignedInSignature(t), nil
   307  	case wasm.OpcodeLocalTee:
   308  		inputLen := uint32(len(c.sig.Params))
   309  		if l := uint32(len(c.localTypes)) + inputLen; index >= l {
   310  			return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l)
   311  		}
   312  		var t wasm.ValueType
   313  		if index < inputLen {
   314  			t = c.sig.Params[index]
   315  		} else {
   316  			t = c.localTypes[index-inputLen]
   317  		}
   318  		return wasmValueTypeToUnsignedInOutSignature(t), nil
   319  	case wasm.OpcodeGlobalGet:
   320  		if len(c.globals) <= int(index) {
   321  			return nil, fmt.Errorf("invalid global index for global.get %d >= %d", index, len(c.globals))
   322  		}
   323  		return wasmValueTypeToUnsignedOutSignature(c.globals[index].ValType), nil
   324  	case wasm.OpcodeGlobalSet:
   325  		if len(c.globals) <= int(index) {
   326  			return nil, fmt.Errorf("invalid global index for global.get %d >= %d", index, len(c.globals))
   327  		}
   328  		return wasmValueTypeToUnsignedInSignature(c.globals[index].ValType), nil
   329  	case wasm.OpcodeI32Load:
   330  		return signature_I32_I32, nil
   331  	case wasm.OpcodeI64Load:
   332  		return signature_I32_I64, nil
   333  	case wasm.OpcodeF32Load:
   334  		return signature_I32_F32, nil
   335  	case wasm.OpcodeF64Load:
   336  		return signature_I32_F64, nil
   337  	case wasm.OpcodeI32Load8S, wasm.OpcodeI32Load8U, wasm.OpcodeI32Load16S, wasm.OpcodeI32Load16U:
   338  		return signature_I32_I32, nil
   339  	case wasm.OpcodeI64Load8S, wasm.OpcodeI64Load8U, wasm.OpcodeI64Load16S, wasm.OpcodeI64Load16U,
   340  		wasm.OpcodeI64Load32S, wasm.OpcodeI64Load32U:
   341  		return signature_I32_I64, nil
   342  	case wasm.OpcodeI32Store:
   343  		return signature_I32I32_None, nil
   344  	case wasm.OpcodeI64Store:
   345  		return signature_I32I64_None, nil
   346  	case wasm.OpcodeF32Store:
   347  		return signature_I32F32_None, nil
   348  	case wasm.OpcodeF64Store:
   349  		return signature_I32F64_None, nil
   350  	case wasm.OpcodeI32Store8:
   351  		return signature_I32I32_None, nil
   352  	case wasm.OpcodeI32Store16:
   353  		return signature_I32I32_None, nil
   354  	case wasm.OpcodeI64Store8:
   355  		return signature_I32I64_None, nil
   356  	case wasm.OpcodeI64Store16:
   357  		return signature_I32I64_None, nil
   358  	case wasm.OpcodeI64Store32:
   359  		return signature_I32I64_None, nil
   360  	case wasm.OpcodeMemorySize:
   361  		return signature_None_I32, nil
   362  	case wasm.OpcodeMemoryGrow:
   363  		return signature_I32_I32, nil
   364  	case wasm.OpcodeI32Const:
   365  		return signature_None_I32, nil
   366  	case wasm.OpcodeI64Const:
   367  		return signature_None_I64, nil
   368  	case wasm.OpcodeF32Const:
   369  		return signature_None_F32, nil
   370  	case wasm.OpcodeF64Const:
   371  		return signature_None_F64, nil
   372  	case wasm.OpcodeI32Eqz:
   373  		return signature_I32_I32, nil
   374  	case wasm.OpcodeI32Eq, wasm.OpcodeI32Ne, wasm.OpcodeI32LtS,
   375  		wasm.OpcodeI32LtU, wasm.OpcodeI32GtS, wasm.OpcodeI32GtU,
   376  		wasm.OpcodeI32LeS, wasm.OpcodeI32LeU, wasm.OpcodeI32GeS,
   377  		wasm.OpcodeI32GeU:
   378  		return signature_I32I32_I32, nil
   379  	case wasm.OpcodeI64Eqz:
   380  		return signature_I64_I32, nil
   381  	case wasm.OpcodeI64Eq, wasm.OpcodeI64Ne, wasm.OpcodeI64LtS,
   382  		wasm.OpcodeI64LtU, wasm.OpcodeI64GtS, wasm.OpcodeI64GtU,
   383  		wasm.OpcodeI64LeS, wasm.OpcodeI64LeU, wasm.OpcodeI64GeS,
   384  		wasm.OpcodeI64GeU:
   385  		return signature_I64I64_I32, nil
   386  	case wasm.OpcodeF32Eq, wasm.OpcodeF32Ne, wasm.OpcodeF32Lt,
   387  		wasm.OpcodeF32Gt, wasm.OpcodeF32Le, wasm.OpcodeF32Ge:
   388  		return signature_F32F32_I32, nil
   389  	case wasm.OpcodeF64Eq, wasm.OpcodeF64Ne, wasm.OpcodeF64Lt,
   390  		wasm.OpcodeF64Gt, wasm.OpcodeF64Le, wasm.OpcodeF64Ge:
   391  		return signature_F64F64_I32, nil
   392  	case wasm.OpcodeI32Clz, wasm.OpcodeI32Ctz, wasm.OpcodeI32Popcnt:
   393  		return signature_I32_I32, nil
   394  	case wasm.OpcodeI32Add, wasm.OpcodeI32Sub, wasm.OpcodeI32Mul,
   395  		wasm.OpcodeI32DivS, wasm.OpcodeI32DivU, wasm.OpcodeI32RemS,
   396  		wasm.OpcodeI32RemU, wasm.OpcodeI32And, wasm.OpcodeI32Or,
   397  		wasm.OpcodeI32Xor, wasm.OpcodeI32Shl, wasm.OpcodeI32ShrS,
   398  		wasm.OpcodeI32ShrU, wasm.OpcodeI32Rotl, wasm.OpcodeI32Rotr:
   399  		return signature_I32I32_I32, nil
   400  	case wasm.OpcodeI64Clz, wasm.OpcodeI64Ctz, wasm.OpcodeI64Popcnt:
   401  		return signature_I64_I64, nil
   402  	case wasm.OpcodeI64Add, wasm.OpcodeI64Sub, wasm.OpcodeI64Mul,
   403  		wasm.OpcodeI64DivS, wasm.OpcodeI64DivU, wasm.OpcodeI64RemS,
   404  		wasm.OpcodeI64RemU, wasm.OpcodeI64And, wasm.OpcodeI64Or,
   405  		wasm.OpcodeI64Xor, wasm.OpcodeI64Shl, wasm.OpcodeI64ShrS,
   406  		wasm.OpcodeI64ShrU, wasm.OpcodeI64Rotl, wasm.OpcodeI64Rotr:
   407  		return signature_I64I64_I64, nil
   408  	case wasm.OpcodeF32Abs, wasm.OpcodeF32Neg, wasm.OpcodeF32Ceil,
   409  		wasm.OpcodeF32Floor, wasm.OpcodeF32Trunc, wasm.OpcodeF32Nearest,
   410  		wasm.OpcodeF32Sqrt:
   411  		return signature_F32_F32, nil
   412  	case wasm.OpcodeF32Add, wasm.OpcodeF32Sub, wasm.OpcodeF32Mul,
   413  		wasm.OpcodeF32Div, wasm.OpcodeF32Min, wasm.OpcodeF32Max,
   414  		wasm.OpcodeF32Copysign:
   415  		return signature_F32F32_F32, nil
   416  	case wasm.OpcodeF64Abs, wasm.OpcodeF64Neg, wasm.OpcodeF64Ceil,
   417  		wasm.OpcodeF64Floor, wasm.OpcodeF64Trunc, wasm.OpcodeF64Nearest,
   418  		wasm.OpcodeF64Sqrt:
   419  		return signature_F64_F64, nil
   420  	case wasm.OpcodeF64Add, wasm.OpcodeF64Sub, wasm.OpcodeF64Mul,
   421  		wasm.OpcodeF64Div, wasm.OpcodeF64Min, wasm.OpcodeF64Max,
   422  		wasm.OpcodeF64Copysign:
   423  		return signature_F64F64_F64, nil
   424  	case wasm.OpcodeI32WrapI64:
   425  		return signature_I64_I32, nil
   426  	case wasm.OpcodeI32TruncF32S, wasm.OpcodeI32TruncF32U:
   427  		return signature_F32_I32, nil
   428  	case wasm.OpcodeI32TruncF64S, wasm.OpcodeI32TruncF64U:
   429  		return signature_F64_I32, nil
   430  	case wasm.OpcodeI64ExtendI32S, wasm.OpcodeI64ExtendI32U:
   431  		return signature_I32_I64, nil
   432  	case wasm.OpcodeI64TruncF32S, wasm.OpcodeI64TruncF32U:
   433  		return signature_F32_I64, nil
   434  	case wasm.OpcodeI64TruncF64S, wasm.OpcodeI64TruncF64U:
   435  		return signature_F64_I64, nil
   436  	case wasm.OpcodeF32ConvertI32S, wasm.OpcodeF32ConvertI32U:
   437  		return signature_I32_F32, nil
   438  	case wasm.OpcodeF32ConvertI64S, wasm.OpcodeF32ConvertI64U:
   439  		return signature_I64_F32, nil
   440  	case wasm.OpcodeF32DemoteF64:
   441  		return signature_F64_F32, nil
   442  	case wasm.OpcodeF64ConvertI32S, wasm.OpcodeF64ConvertI32U:
   443  		return signature_I32_F64, nil
   444  	case wasm.OpcodeF64ConvertI64S, wasm.OpcodeF64ConvertI64U:
   445  		return signature_I64_F64, nil
   446  	case wasm.OpcodeF64PromoteF32:
   447  		return signature_F32_F64, nil
   448  	case wasm.OpcodeI32ReinterpretF32:
   449  		return signature_F32_I32, nil
   450  	case wasm.OpcodeI64ReinterpretF64:
   451  		return signature_F64_I64, nil
   452  	case wasm.OpcodeF32ReinterpretI32:
   453  		return signature_I32_F32, nil
   454  	case wasm.OpcodeF64ReinterpretI64:
   455  		return signature_I64_F64, nil
   456  	case wasm.OpcodeI32Extend8S, wasm.OpcodeI32Extend16S:
   457  		return signature_I32_I32, nil
   458  	case wasm.OpcodeI64Extend8S, wasm.OpcodeI64Extend16S, wasm.OpcodeI64Extend32S:
   459  		return signature_I64_I64, nil
   460  	case wasm.OpcodeTableGet:
   461  		// table.get takes table's offset and pushes the ref type value of opaque pointer as i64 value onto the stack.
   462  		return signature_I32_I64, nil
   463  	case wasm.OpcodeTableSet:
   464  		// table.set takes table's offset and the ref type value of opaque pointer as i64 value.
   465  		return signature_I32I64_None, nil
   466  	case wasm.OpcodeRefFunc:
   467  		// ref.func is translated as pushing the compiled function's opaque pointer (uint64) at wazeroir layer.
   468  		return signature_None_I64, nil
   469  	case wasm.OpcodeRefIsNull:
   470  		// ref.is_null is translated as checking if the uint64 on the top of the stack (opaque pointer) is zero or not.
   471  		return signature_I64_I32, nil
   472  	case wasm.OpcodeRefNull:
   473  		// ref.null is translated as i64.const 0.
   474  		return signature_None_I64, nil
   475  	case wasm.OpcodeMiscPrefix:
   476  		switch miscOp := c.body[c.pc+1]; miscOp {
   477  		case wasm.OpcodeMiscI32TruncSatF32S, wasm.OpcodeMiscI32TruncSatF32U:
   478  			return signature_F32_I32, nil
   479  		case wasm.OpcodeMiscI32TruncSatF64S, wasm.OpcodeMiscI32TruncSatF64U:
   480  			return signature_F64_I32, nil
   481  		case wasm.OpcodeMiscI64TruncSatF32S, wasm.OpcodeMiscI64TruncSatF32U:
   482  			return signature_F32_I64, nil
   483  		case wasm.OpcodeMiscI64TruncSatF64S, wasm.OpcodeMiscI64TruncSatF64U:
   484  			return signature_F64_I64, nil
   485  		case wasm.OpcodeMiscMemoryInit, wasm.OpcodeMiscMemoryCopy, wasm.OpcodeMiscMemoryFill,
   486  			wasm.OpcodeMiscTableInit, wasm.OpcodeMiscTableCopy:
   487  			return signature_I32I32I32_None, nil
   488  		case wasm.OpcodeMiscDataDrop, wasm.OpcodeMiscElemDrop:
   489  			return signature_None_None, nil
   490  		case wasm.OpcodeMiscTableGrow:
   491  			return signature_I64I32_I32, nil
   492  		case wasm.OpcodeMiscTableSize:
   493  			return signature_None_I32, nil
   494  		case wasm.OpcodeMiscTableFill:
   495  			return signature_I32I64I32_None, nil
   496  		default:
   497  			return nil, fmt.Errorf("unsupported misc instruction in wazeroir: 0x%x", op)
   498  		}
   499  	case wasm.OpcodeVecPrefix:
   500  		switch vecOp := c.body[c.pc+1]; vecOp {
   501  		case wasm.OpcodeVecV128Const:
   502  			return signature_None_V128, nil
   503  		case wasm.OpcodeVecV128Load, wasm.OpcodeVecV128Load8x8s, wasm.OpcodeVecV128Load8x8u,
   504  			wasm.OpcodeVecV128Load16x4s, wasm.OpcodeVecV128Load16x4u, wasm.OpcodeVecV128Load32x2s,
   505  			wasm.OpcodeVecV128Load32x2u, wasm.OpcodeVecV128Load8Splat, wasm.OpcodeVecV128Load16Splat,
   506  			wasm.OpcodeVecV128Load32Splat, wasm.OpcodeVecV128Load64Splat, wasm.OpcodeVecV128Load32zero,
   507  			wasm.OpcodeVecV128Load64zero:
   508  			return signature_I32_V128, nil
   509  		case wasm.OpcodeVecV128Load8Lane, wasm.OpcodeVecV128Load16Lane,
   510  			wasm.OpcodeVecV128Load32Lane, wasm.OpcodeVecV128Load64Lane:
   511  			return signature_I32V128_V128, nil
   512  		case wasm.OpcodeVecV128Store,
   513  			wasm.OpcodeVecV128Store8Lane,
   514  			wasm.OpcodeVecV128Store16Lane,
   515  			wasm.OpcodeVecV128Store32Lane,
   516  			wasm.OpcodeVecV128Store64Lane:
   517  			return signature_I32V128_None, nil
   518  		case wasm.OpcodeVecI8x16ExtractLaneS,
   519  			wasm.OpcodeVecI8x16ExtractLaneU,
   520  			wasm.OpcodeVecI16x8ExtractLaneS,
   521  			wasm.OpcodeVecI16x8ExtractLaneU,
   522  			wasm.OpcodeVecI32x4ExtractLane:
   523  			return signature_V128_I32, nil
   524  		case wasm.OpcodeVecI64x2ExtractLane:
   525  			return signature_V128_I64, nil
   526  		case wasm.OpcodeVecF32x4ExtractLane:
   527  			return signature_V128_F32, nil
   528  		case wasm.OpcodeVecF64x2ExtractLane:
   529  			return signature_V128_F64, nil
   530  		case wasm.OpcodeVecI8x16ReplaceLane, wasm.OpcodeVecI16x8ReplaceLane, wasm.OpcodeVecI32x4ReplaceLane,
   531  			wasm.OpcodeVecI8x16Shl, wasm.OpcodeVecI8x16ShrS, wasm.OpcodeVecI8x16ShrU,
   532  			wasm.OpcodeVecI16x8Shl, wasm.OpcodeVecI16x8ShrS, wasm.OpcodeVecI16x8ShrU,
   533  			wasm.OpcodeVecI32x4Shl, wasm.OpcodeVecI32x4ShrS, wasm.OpcodeVecI32x4ShrU,
   534  			wasm.OpcodeVecI64x2Shl, wasm.OpcodeVecI64x2ShrS, wasm.OpcodeVecI64x2ShrU:
   535  			return signature_V128I32_V128, nil
   536  		case wasm.OpcodeVecI64x2ReplaceLane:
   537  			return signature_V128I64_V128, nil
   538  		case wasm.OpcodeVecF32x4ReplaceLane:
   539  			return signature_V128F32_V128, nil
   540  		case wasm.OpcodeVecF64x2ReplaceLane:
   541  			return signature_V128F64_V128, nil
   542  		case wasm.OpcodeVecI8x16Splat,
   543  			wasm.OpcodeVecI16x8Splat,
   544  			wasm.OpcodeVecI32x4Splat:
   545  			return signature_I32_V128, nil
   546  		case wasm.OpcodeVecI64x2Splat:
   547  			return signature_I64_V128, nil
   548  		case wasm.OpcodeVecF32x4Splat:
   549  			return signature_F32_V128, nil
   550  		case wasm.OpcodeVecF64x2Splat:
   551  			return signature_F64_V128, nil
   552  		case wasm.OpcodeVecV128i8x16Shuffle, wasm.OpcodeVecI8x16Swizzle, wasm.OpcodeVecV128And, wasm.OpcodeVecV128Or, wasm.OpcodeVecV128Xor, wasm.OpcodeVecV128AndNot:
   553  			return signature_V128V128_V128, nil
   554  		case wasm.OpcodeVecI8x16AllTrue, wasm.OpcodeVecI16x8AllTrue, wasm.OpcodeVecI32x4AllTrue, wasm.OpcodeVecI64x2AllTrue,
   555  			wasm.OpcodeVecV128AnyTrue,
   556  			wasm.OpcodeVecI8x16BitMask, wasm.OpcodeVecI16x8BitMask, wasm.OpcodeVecI32x4BitMask, wasm.OpcodeVecI64x2BitMask:
   557  			return signature_V128_I32, nil
   558  		case wasm.OpcodeVecV128Not, wasm.OpcodeVecI8x16Neg, wasm.OpcodeVecI16x8Neg, wasm.OpcodeVecI32x4Neg, wasm.OpcodeVecI64x2Neg,
   559  			wasm.OpcodeVecF32x4Neg, wasm.OpcodeVecF64x2Neg, wasm.OpcodeVecF32x4Sqrt, wasm.OpcodeVecF64x2Sqrt,
   560  			wasm.OpcodeVecI8x16Abs, wasm.OpcodeVecI8x16Popcnt, wasm.OpcodeVecI16x8Abs, wasm.OpcodeVecI32x4Abs, wasm.OpcodeVecI64x2Abs,
   561  			wasm.OpcodeVecF32x4Abs, wasm.OpcodeVecF64x2Abs,
   562  			wasm.OpcodeVecF32x4Ceil, wasm.OpcodeVecF32x4Floor, wasm.OpcodeVecF32x4Trunc, wasm.OpcodeVecF32x4Nearest,
   563  			wasm.OpcodeVecF64x2Ceil, wasm.OpcodeVecF64x2Floor, wasm.OpcodeVecF64x2Trunc, wasm.OpcodeVecF64x2Nearest,
   564  			wasm.OpcodeVecI16x8ExtendLowI8x16S, wasm.OpcodeVecI16x8ExtendHighI8x16S, wasm.OpcodeVecI16x8ExtendLowI8x16U, wasm.OpcodeVecI16x8ExtendHighI8x16U,
   565  			wasm.OpcodeVecI32x4ExtendLowI16x8S, wasm.OpcodeVecI32x4ExtendHighI16x8S, wasm.OpcodeVecI32x4ExtendLowI16x8U, wasm.OpcodeVecI32x4ExtendHighI16x8U,
   566  			wasm.OpcodeVecI64x2ExtendLowI32x4S, wasm.OpcodeVecI64x2ExtendHighI32x4S, wasm.OpcodeVecI64x2ExtendLowI32x4U, wasm.OpcodeVecI64x2ExtendHighI32x4U,
   567  			wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S, wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U, wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S, wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U,
   568  			wasm.OpcodeVecF64x2PromoteLowF32x4Zero, wasm.OpcodeVecF32x4DemoteF64x2Zero,
   569  			wasm.OpcodeVecF32x4ConvertI32x4S, wasm.OpcodeVecF32x4ConvertI32x4U,
   570  			wasm.OpcodeVecF64x2ConvertLowI32x4S, wasm.OpcodeVecF64x2ConvertLowI32x4U,
   571  			wasm.OpcodeVecI32x4TruncSatF32x4S, wasm.OpcodeVecI32x4TruncSatF32x4U,
   572  			wasm.OpcodeVecI32x4TruncSatF64x2SZero, wasm.OpcodeVecI32x4TruncSatF64x2UZero:
   573  			return signature_V128_V128, nil
   574  		case wasm.OpcodeVecV128Bitselect:
   575  			return signature_V128V128V128_V32, nil
   576  		case wasm.OpcodeVecI8x16Eq, wasm.OpcodeVecI8x16Ne, wasm.OpcodeVecI8x16LtS, wasm.OpcodeVecI8x16LtU, wasm.OpcodeVecI8x16GtS,
   577  			wasm.OpcodeVecI8x16GtU, wasm.OpcodeVecI8x16LeS, wasm.OpcodeVecI8x16LeU, wasm.OpcodeVecI8x16GeS, wasm.OpcodeVecI8x16GeU,
   578  			wasm.OpcodeVecI16x8Eq, wasm.OpcodeVecI16x8Ne, wasm.OpcodeVecI16x8LtS, wasm.OpcodeVecI16x8LtU, wasm.OpcodeVecI16x8GtS,
   579  			wasm.OpcodeVecI16x8GtU, wasm.OpcodeVecI16x8LeS, wasm.OpcodeVecI16x8LeU, wasm.OpcodeVecI16x8GeS, wasm.OpcodeVecI16x8GeU,
   580  			wasm.OpcodeVecI32x4Eq, wasm.OpcodeVecI32x4Ne, wasm.OpcodeVecI32x4LtS, wasm.OpcodeVecI32x4LtU, wasm.OpcodeVecI32x4GtS,
   581  			wasm.OpcodeVecI32x4GtU, wasm.OpcodeVecI32x4LeS, wasm.OpcodeVecI32x4LeU, wasm.OpcodeVecI32x4GeS, wasm.OpcodeVecI32x4GeU,
   582  			wasm.OpcodeVecI64x2Eq, wasm.OpcodeVecI64x2Ne, wasm.OpcodeVecI64x2LtS, wasm.OpcodeVecI64x2GtS, wasm.OpcodeVecI64x2LeS,
   583  			wasm.OpcodeVecI64x2GeS, wasm.OpcodeVecF32x4Eq, wasm.OpcodeVecF32x4Ne, wasm.OpcodeVecF32x4Lt, wasm.OpcodeVecF32x4Gt,
   584  			wasm.OpcodeVecF32x4Le, wasm.OpcodeVecF32x4Ge, wasm.OpcodeVecF64x2Eq, wasm.OpcodeVecF64x2Ne, wasm.OpcodeVecF64x2Lt,
   585  			wasm.OpcodeVecF64x2Gt, wasm.OpcodeVecF64x2Le, wasm.OpcodeVecF64x2Ge,
   586  			wasm.OpcodeVecI8x16Add, wasm.OpcodeVecI8x16AddSatS, wasm.OpcodeVecI8x16AddSatU, wasm.OpcodeVecI8x16Sub,
   587  			wasm.OpcodeVecI8x16SubSatS, wasm.OpcodeVecI8x16SubSatU,
   588  			wasm.OpcodeVecI16x8Add, wasm.OpcodeVecI16x8AddSatS, wasm.OpcodeVecI16x8AddSatU, wasm.OpcodeVecI16x8Sub,
   589  			wasm.OpcodeVecI16x8SubSatS, wasm.OpcodeVecI16x8SubSatU, wasm.OpcodeVecI16x8Mul,
   590  			wasm.OpcodeVecI32x4Add, wasm.OpcodeVecI32x4Sub, wasm.OpcodeVecI32x4Mul,
   591  			wasm.OpcodeVecI64x2Add, wasm.OpcodeVecI64x2Sub, wasm.OpcodeVecI64x2Mul,
   592  			wasm.OpcodeVecF32x4Add, wasm.OpcodeVecF32x4Sub, wasm.OpcodeVecF32x4Mul, wasm.OpcodeVecF32x4Div,
   593  			wasm.OpcodeVecF64x2Add, wasm.OpcodeVecF64x2Sub, wasm.OpcodeVecF64x2Mul, wasm.OpcodeVecF64x2Div,
   594  			wasm.OpcodeVecI8x16MinS, wasm.OpcodeVecI8x16MinU, wasm.OpcodeVecI8x16MaxS, wasm.OpcodeVecI8x16MaxU, wasm.OpcodeVecI8x16AvgrU,
   595  			wasm.OpcodeVecI16x8MinS, wasm.OpcodeVecI16x8MinU, wasm.OpcodeVecI16x8MaxS, wasm.OpcodeVecI16x8MaxU, wasm.OpcodeVecI16x8AvgrU,
   596  			wasm.OpcodeVecI32x4MinS, wasm.OpcodeVecI32x4MinU, wasm.OpcodeVecI32x4MaxS, wasm.OpcodeVecI32x4MaxU,
   597  			wasm.OpcodeVecF32x4Min, wasm.OpcodeVecF32x4Max, wasm.OpcodeVecF64x2Min, wasm.OpcodeVecF64x2Max,
   598  			wasm.OpcodeVecF32x4Pmin, wasm.OpcodeVecF32x4Pmax, wasm.OpcodeVecF64x2Pmin, wasm.OpcodeVecF64x2Pmax,
   599  			wasm.OpcodeVecI16x8Q15mulrSatS,
   600  			wasm.OpcodeVecI16x8ExtMulLowI8x16S, wasm.OpcodeVecI16x8ExtMulHighI8x16S, wasm.OpcodeVecI16x8ExtMulLowI8x16U, wasm.OpcodeVecI16x8ExtMulHighI8x16U,
   601  			wasm.OpcodeVecI32x4ExtMulLowI16x8S, wasm.OpcodeVecI32x4ExtMulHighI16x8S, wasm.OpcodeVecI32x4ExtMulLowI16x8U, wasm.OpcodeVecI32x4ExtMulHighI16x8U,
   602  			wasm.OpcodeVecI64x2ExtMulLowI32x4S, wasm.OpcodeVecI64x2ExtMulHighI32x4S, wasm.OpcodeVecI64x2ExtMulLowI32x4U, wasm.OpcodeVecI64x2ExtMulHighI32x4U,
   603  			wasm.OpcodeVecI32x4DotI16x8S,
   604  			wasm.OpcodeVecI8x16NarrowI16x8S, wasm.OpcodeVecI8x16NarrowI16x8U, wasm.OpcodeVecI16x8NarrowI32x4S, wasm.OpcodeVecI16x8NarrowI32x4U:
   605  			return signature_V128V128_V128, nil
   606  		default:
   607  			return nil, fmt.Errorf("unsupported vector instruction in wazeroir: %s", wasm.VectorInstructionName(vecOp))
   608  		}
   609  	case wasm.OpcodeAtomicPrefix:
   610  		switch atomicOp := c.body[c.pc+1]; atomicOp {
   611  		case wasm.OpcodeAtomicMemoryNotify:
   612  			return signature_I32I32_I32, nil
   613  		case wasm.OpcodeAtomicMemoryWait32:
   614  			return signature_I32I32I64_I32, nil
   615  		case wasm.OpcodeAtomicMemoryWait64:
   616  			return signature_I32I64I64_I32, nil
   617  		case wasm.OpcodeAtomicFence:
   618  			return signature_None_None, nil
   619  		case wasm.OpcodeAtomicI32Load, wasm.OpcodeAtomicI32Load8U, wasm.OpcodeAtomicI32Load16U:
   620  			return signature_I32_I32, nil
   621  		case wasm.OpcodeAtomicI64Load, wasm.OpcodeAtomicI64Load8U, wasm.OpcodeAtomicI64Load16U, wasm.OpcodeAtomicI64Load32U:
   622  			return signature_I32_I64, nil
   623  		case wasm.OpcodeAtomicI32Store, wasm.OpcodeAtomicI32Store8, wasm.OpcodeAtomicI32Store16:
   624  			return signature_I32I32_None, nil
   625  		case wasm.OpcodeAtomicI64Store, wasm.OpcodeAtomicI64Store8, wasm.OpcodeAtomicI64Store16, wasm.OpcodeAtomicI64Store32:
   626  			return signature_I32I64_None, nil
   627  		case wasm.OpcodeAtomicI32RmwAdd, wasm.OpcodeAtomicI32RmwSub, wasm.OpcodeAtomicI32RmwAnd, wasm.OpcodeAtomicI32RmwOr, wasm.OpcodeAtomicI32RmwXor, wasm.OpcodeAtomicI32RmwXchg,
   628  			wasm.OpcodeAtomicI32Rmw8AddU, wasm.OpcodeAtomicI32Rmw8SubU, wasm.OpcodeAtomicI32Rmw8AndU, wasm.OpcodeAtomicI32Rmw8OrU, wasm.OpcodeAtomicI32Rmw8XorU, wasm.OpcodeAtomicI32Rmw8XchgU,
   629  			wasm.OpcodeAtomicI32Rmw16AddU, wasm.OpcodeAtomicI32Rmw16SubU, wasm.OpcodeAtomicI32Rmw16AndU, wasm.OpcodeAtomicI32Rmw16OrU, wasm.OpcodeAtomicI32Rmw16XorU, wasm.OpcodeAtomicI32Rmw16XchgU:
   630  			return signature_I32I32_I32, nil
   631  		case wasm.OpcodeAtomicI64RmwAdd, wasm.OpcodeAtomicI64RmwSub, wasm.OpcodeAtomicI64RmwAnd, wasm.OpcodeAtomicI64RmwOr, wasm.OpcodeAtomicI64RmwXor, wasm.OpcodeAtomicI64RmwXchg,
   632  			wasm.OpcodeAtomicI64Rmw8AddU, wasm.OpcodeAtomicI64Rmw8SubU, wasm.OpcodeAtomicI64Rmw8AndU, wasm.OpcodeAtomicI64Rmw8OrU, wasm.OpcodeAtomicI64Rmw8XorU, wasm.OpcodeAtomicI64Rmw8XchgU,
   633  			wasm.OpcodeAtomicI64Rmw16AddU, wasm.OpcodeAtomicI64Rmw16SubU, wasm.OpcodeAtomicI64Rmw16AndU, wasm.OpcodeAtomicI64Rmw16OrU, wasm.OpcodeAtomicI64Rmw16XorU, wasm.OpcodeAtomicI64Rmw16XchgU,
   634  			wasm.OpcodeAtomicI64Rmw32AddU, wasm.OpcodeAtomicI64Rmw32SubU, wasm.OpcodeAtomicI64Rmw32AndU, wasm.OpcodeAtomicI64Rmw32OrU, wasm.OpcodeAtomicI64Rmw32XorU, wasm.OpcodeAtomicI64Rmw32XchgU:
   635  			return signature_I32I64_I64, nil
   636  		case wasm.OpcodeAtomicI32RmwCmpxchg, wasm.OpcodeAtomicI32Rmw8CmpxchgU, wasm.OpcodeAtomicI32Rmw16CmpxchgU:
   637  			return signature_I32I32I32_I32, nil
   638  		case wasm.OpcodeAtomicI64RmwCmpxchg, wasm.OpcodeAtomicI64Rmw8CmpxchgU, wasm.OpcodeAtomicI64Rmw16CmpxchgU, wasm.OpcodeAtomicI64Rmw32CmpxchgU:
   639  			return signature_I32I64I64_I64, nil
   640  		default:
   641  			return nil, fmt.Errorf("unsupported atomic instruction in wazeroir: %s", wasm.AtomicInstructionName(atomicOp))
   642  		}
   643  	default:
   644  		return nil, fmt.Errorf("unsupported instruction in wazeroir: 0x%x", op)
   645  	}
   646  }
   647  
   648  // funcTypeToIRSignatures is the central cache for a module to get the *signature
   649  // for function calls.
   650  type funcTypeToIRSignatures struct {
   651  	directCalls   []*signature
   652  	indirectCalls []*signature
   653  	wasmTypes     []wasm.FunctionType
   654  }
   655  
   656  // get returns the *signature for the direct or indirect function call against functions whose type is at `typeIndex`.
   657  func (f *funcTypeToIRSignatures) get(typeIndex wasm.Index, indirect bool) *signature {
   658  	var sig *signature
   659  	if indirect {
   660  		sig = f.indirectCalls[typeIndex]
   661  	} else {
   662  		sig = f.directCalls[typeIndex]
   663  	}
   664  	if sig != nil {
   665  		return sig
   666  	}
   667  
   668  	tp := &f.wasmTypes[typeIndex]
   669  	if indirect {
   670  		sig = &signature{
   671  			in:  make([]UnsignedType, 0, len(tp.Params)+1), // +1 to reserve space for call indirect index.
   672  			out: make([]UnsignedType, 0, len(tp.Results)),
   673  		}
   674  	} else {
   675  		sig = &signature{
   676  			in:  make([]UnsignedType, 0, len(tp.Params)),
   677  			out: make([]UnsignedType, 0, len(tp.Results)),
   678  		}
   679  	}
   680  
   681  	for _, vt := range tp.Params {
   682  		sig.in = append(sig.in, wasmValueTypeToUnsignedType(vt))
   683  	}
   684  	for _, vt := range tp.Results {
   685  		sig.out = append(sig.out, wasmValueTypeToUnsignedType(vt))
   686  	}
   687  
   688  	if indirect {
   689  		sig.in = append(sig.in, UnsignedTypeI32)
   690  		f.indirectCalls[typeIndex] = sig
   691  	} else {
   692  		f.directCalls[typeIndex] = sig
   693  	}
   694  	return sig
   695  }
   696  
   697  func wasmValueTypeToUnsignedType(vt wasm.ValueType) UnsignedType {
   698  	switch vt {
   699  	case wasm.ValueTypeI32:
   700  		return UnsignedTypeI32
   701  	case wasm.ValueTypeI64,
   702  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   703  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   704  		return UnsignedTypeI64
   705  	case wasm.ValueTypeF32:
   706  		return UnsignedTypeF32
   707  	case wasm.ValueTypeF64:
   708  		return UnsignedTypeF64
   709  	case wasm.ValueTypeV128:
   710  		return UnsignedTypeV128
   711  	}
   712  	panic("unreachable")
   713  }
   714  
   715  func wasmValueTypeToUnsignedOutSignature(vt wasm.ValueType) *signature {
   716  	switch vt {
   717  	case wasm.ValueTypeI32:
   718  		return signature_None_I32
   719  	case wasm.ValueTypeI64,
   720  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   721  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   722  		return signature_None_I64
   723  	case wasm.ValueTypeF32:
   724  		return signature_None_F32
   725  	case wasm.ValueTypeF64:
   726  		return signature_None_F64
   727  	case wasm.ValueTypeV128:
   728  		return signature_None_V128
   729  	}
   730  	panic("unreachable")
   731  }
   732  
   733  func wasmValueTypeToUnsignedInSignature(vt wasm.ValueType) *signature {
   734  	switch vt {
   735  	case wasm.ValueTypeI32:
   736  		return signature_I32_None
   737  	case wasm.ValueTypeI64,
   738  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   739  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   740  		return signature_I64_None
   741  	case wasm.ValueTypeF32:
   742  		return signature_F32_None
   743  	case wasm.ValueTypeF64:
   744  		return signature_F64_None
   745  	case wasm.ValueTypeV128:
   746  		return signature_V128_None
   747  	}
   748  	panic("unreachable")
   749  }
   750  
   751  func wasmValueTypeToUnsignedInOutSignature(vt wasm.ValueType) *signature {
   752  	switch vt {
   753  	case wasm.ValueTypeI32:
   754  		return signature_I32_I32
   755  	case wasm.ValueTypeI64,
   756  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   757  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   758  		return signature_I64_I64
   759  	case wasm.ValueTypeF32:
   760  		return signature_F32_F32
   761  	case wasm.ValueTypeF64:
   762  		return signature_F64_F64
   763  	case wasm.ValueTypeV128:
   764  		return signature_V128_V128
   765  	}
   766  	panic("unreachable")
   767  }