...

Source file src/github.com/tetratelabs/wazero/internal/wazeroir/signature.go

Documentation: github.com/tetratelabs/wazero/internal/wazeroir

     1  package wazeroir
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/tetratelabs/wazero/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  )
   237  
   238  // wasmOpcodeSignature returns the signature of given Wasm opcode.
   239  // Note that some of opcodes' signature vary depending on
   240  // the function instance (for example, local types).
   241  // "index" parameter is not used by most of opcodes.
   242  // The returned signature is used for stack validation when lowering Wasm's opcodes to wazeroir.
   243  func (c *Compiler) wasmOpcodeSignature(op wasm.Opcode, index uint32) (*signature, error) {
   244  	switch op {
   245  	case wasm.OpcodeUnreachable, wasm.OpcodeNop, wasm.OpcodeBlock, wasm.OpcodeLoop:
   246  		return signature_None_None, nil
   247  	case wasm.OpcodeIf:
   248  		return signature_I32_None, nil
   249  	case wasm.OpcodeElse, wasm.OpcodeEnd, wasm.OpcodeBr:
   250  		return signature_None_None, nil
   251  	case wasm.OpcodeBrIf, wasm.OpcodeBrTable:
   252  		return signature_I32_None, nil
   253  	case wasm.OpcodeReturn:
   254  		return signature_None_None, nil
   255  	case wasm.OpcodeCall:
   256  		return c.funcTypeToSigs.get(c.funcs[index], false /* direct */), nil
   257  	case wasm.OpcodeCallIndirect:
   258  		return c.funcTypeToSigs.get(index, true /* call_indirect */), nil
   259  	case wasm.OpcodeDrop:
   260  		return signature_Unknown_None, nil
   261  	case wasm.OpcodeSelect, wasm.OpcodeTypedSelect:
   262  		return signature_UnknownUnknownI32_Unknown, nil
   263  	case wasm.OpcodeLocalGet:
   264  		inputLen := uint32(len(c.sig.Params))
   265  		if l := uint32(len(c.localTypes)) + inputLen; index >= l {
   266  			return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l)
   267  		}
   268  		var t wasm.ValueType
   269  		if index < inputLen {
   270  			t = c.sig.Params[index]
   271  		} else {
   272  			t = c.localTypes[index-inputLen]
   273  		}
   274  		return wasmValueTypeToUnsignedOutSignature(t), nil
   275  	case wasm.OpcodeLocalSet:
   276  		inputLen := uint32(len(c.sig.Params))
   277  		if l := uint32(len(c.localTypes)) + inputLen; index >= l {
   278  			return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l)
   279  		}
   280  		var t wasm.ValueType
   281  		if index < inputLen {
   282  			t = c.sig.Params[index]
   283  		} else {
   284  			t = c.localTypes[index-inputLen]
   285  		}
   286  		return wasmValueTypeToUnsignedInSignature(t), nil
   287  	case wasm.OpcodeLocalTee:
   288  		inputLen := uint32(len(c.sig.Params))
   289  		if l := uint32(len(c.localTypes)) + inputLen; index >= l {
   290  			return nil, fmt.Errorf("invalid local index for local.get %d >= %d", index, l)
   291  		}
   292  		var t wasm.ValueType
   293  		if index < inputLen {
   294  			t = c.sig.Params[index]
   295  		} else {
   296  			t = c.localTypes[index-inputLen]
   297  		}
   298  		return wasmValueTypeToUnsignedInOutSignature(t), nil
   299  	case wasm.OpcodeGlobalGet:
   300  		if len(c.globals) <= int(index) {
   301  			return nil, fmt.Errorf("invalid global index for global.get %d >= %d", index, len(c.globals))
   302  		}
   303  		return wasmValueTypeToUnsignedOutSignature(c.globals[index].ValType), nil
   304  	case wasm.OpcodeGlobalSet:
   305  		if len(c.globals) <= int(index) {
   306  			return nil, fmt.Errorf("invalid global index for global.get %d >= %d", index, len(c.globals))
   307  		}
   308  		return wasmValueTypeToUnsignedInSignature(c.globals[index].ValType), nil
   309  	case wasm.OpcodeI32Load:
   310  		return signature_I32_I32, nil
   311  	case wasm.OpcodeI64Load:
   312  		return signature_I32_I64, nil
   313  	case wasm.OpcodeF32Load:
   314  		return signature_I32_F32, nil
   315  	case wasm.OpcodeF64Load:
   316  		return signature_I32_F64, nil
   317  	case wasm.OpcodeI32Load8S, wasm.OpcodeI32Load8U, wasm.OpcodeI32Load16S, wasm.OpcodeI32Load16U:
   318  		return signature_I32_I32, nil
   319  	case wasm.OpcodeI64Load8S, wasm.OpcodeI64Load8U, wasm.OpcodeI64Load16S, wasm.OpcodeI64Load16U,
   320  		wasm.OpcodeI64Load32S, wasm.OpcodeI64Load32U:
   321  		return signature_I32_I64, nil
   322  	case wasm.OpcodeI32Store:
   323  		return signature_I32I32_None, nil
   324  	case wasm.OpcodeI64Store:
   325  		return signature_I32I64_None, nil
   326  	case wasm.OpcodeF32Store:
   327  		return signature_I32F32_None, nil
   328  	case wasm.OpcodeF64Store:
   329  		return signature_I32F64_None, nil
   330  	case wasm.OpcodeI32Store8:
   331  		return signature_I32I32_None, nil
   332  	case wasm.OpcodeI32Store16:
   333  		return signature_I32I32_None, nil
   334  	case wasm.OpcodeI64Store8:
   335  		return signature_I32I64_None, nil
   336  	case wasm.OpcodeI64Store16:
   337  		return signature_I32I64_None, nil
   338  	case wasm.OpcodeI64Store32:
   339  		return signature_I32I64_None, nil
   340  	case wasm.OpcodeMemorySize:
   341  		return signature_None_I32, nil
   342  	case wasm.OpcodeMemoryGrow:
   343  		return signature_I32_I32, nil
   344  	case wasm.OpcodeI32Const:
   345  		return signature_None_I32, nil
   346  	case wasm.OpcodeI64Const:
   347  		return signature_None_I64, nil
   348  	case wasm.OpcodeF32Const:
   349  		return signature_None_F32, nil
   350  	case wasm.OpcodeF64Const:
   351  		return signature_None_F64, nil
   352  	case wasm.OpcodeI32Eqz:
   353  		return signature_I32_I32, nil
   354  	case wasm.OpcodeI32Eq, wasm.OpcodeI32Ne, wasm.OpcodeI32LtS,
   355  		wasm.OpcodeI32LtU, wasm.OpcodeI32GtS, wasm.OpcodeI32GtU,
   356  		wasm.OpcodeI32LeS, wasm.OpcodeI32LeU, wasm.OpcodeI32GeS,
   357  		wasm.OpcodeI32GeU:
   358  		return signature_I32I32_I32, nil
   359  	case wasm.OpcodeI64Eqz:
   360  		return signature_I64_I32, nil
   361  	case wasm.OpcodeI64Eq, wasm.OpcodeI64Ne, wasm.OpcodeI64LtS,
   362  		wasm.OpcodeI64LtU, wasm.OpcodeI64GtS, wasm.OpcodeI64GtU,
   363  		wasm.OpcodeI64LeS, wasm.OpcodeI64LeU, wasm.OpcodeI64GeS,
   364  		wasm.OpcodeI64GeU:
   365  		return signature_I64I64_I32, nil
   366  	case wasm.OpcodeF32Eq, wasm.OpcodeF32Ne, wasm.OpcodeF32Lt,
   367  		wasm.OpcodeF32Gt, wasm.OpcodeF32Le, wasm.OpcodeF32Ge:
   368  		return signature_F32F32_I32, nil
   369  	case wasm.OpcodeF64Eq, wasm.OpcodeF64Ne, wasm.OpcodeF64Lt,
   370  		wasm.OpcodeF64Gt, wasm.OpcodeF64Le, wasm.OpcodeF64Ge:
   371  		return signature_F64F64_I32, nil
   372  	case wasm.OpcodeI32Clz, wasm.OpcodeI32Ctz, wasm.OpcodeI32Popcnt:
   373  		return signature_I32_I32, nil
   374  	case wasm.OpcodeI32Add, wasm.OpcodeI32Sub, wasm.OpcodeI32Mul,
   375  		wasm.OpcodeI32DivS, wasm.OpcodeI32DivU, wasm.OpcodeI32RemS,
   376  		wasm.OpcodeI32RemU, wasm.OpcodeI32And, wasm.OpcodeI32Or,
   377  		wasm.OpcodeI32Xor, wasm.OpcodeI32Shl, wasm.OpcodeI32ShrS,
   378  		wasm.OpcodeI32ShrU, wasm.OpcodeI32Rotl, wasm.OpcodeI32Rotr:
   379  		return signature_I32I32_I32, nil
   380  	case wasm.OpcodeI64Clz, wasm.OpcodeI64Ctz, wasm.OpcodeI64Popcnt:
   381  		return signature_I64_I64, nil
   382  	case wasm.OpcodeI64Add, wasm.OpcodeI64Sub, wasm.OpcodeI64Mul,
   383  		wasm.OpcodeI64DivS, wasm.OpcodeI64DivU, wasm.OpcodeI64RemS,
   384  		wasm.OpcodeI64RemU, wasm.OpcodeI64And, wasm.OpcodeI64Or,
   385  		wasm.OpcodeI64Xor, wasm.OpcodeI64Shl, wasm.OpcodeI64ShrS,
   386  		wasm.OpcodeI64ShrU, wasm.OpcodeI64Rotl, wasm.OpcodeI64Rotr:
   387  		return signature_I64I64_I64, nil
   388  	case wasm.OpcodeF32Abs, wasm.OpcodeF32Neg, wasm.OpcodeF32Ceil,
   389  		wasm.OpcodeF32Floor, wasm.OpcodeF32Trunc, wasm.OpcodeF32Nearest,
   390  		wasm.OpcodeF32Sqrt:
   391  		return signature_F32_F32, nil
   392  	case wasm.OpcodeF32Add, wasm.OpcodeF32Sub, wasm.OpcodeF32Mul,
   393  		wasm.OpcodeF32Div, wasm.OpcodeF32Min, wasm.OpcodeF32Max,
   394  		wasm.OpcodeF32Copysign:
   395  		return signature_F32F32_F32, nil
   396  	case wasm.OpcodeF64Abs, wasm.OpcodeF64Neg, wasm.OpcodeF64Ceil,
   397  		wasm.OpcodeF64Floor, wasm.OpcodeF64Trunc, wasm.OpcodeF64Nearest,
   398  		wasm.OpcodeF64Sqrt:
   399  		return signature_F64_F64, nil
   400  	case wasm.OpcodeF64Add, wasm.OpcodeF64Sub, wasm.OpcodeF64Mul,
   401  		wasm.OpcodeF64Div, wasm.OpcodeF64Min, wasm.OpcodeF64Max,
   402  		wasm.OpcodeF64Copysign:
   403  		return signature_F64F64_F64, nil
   404  	case wasm.OpcodeI32WrapI64:
   405  		return signature_I64_I32, nil
   406  	case wasm.OpcodeI32TruncF32S, wasm.OpcodeI32TruncF32U:
   407  		return signature_F32_I32, nil
   408  	case wasm.OpcodeI32TruncF64S, wasm.OpcodeI32TruncF64U:
   409  		return signature_F64_I32, nil
   410  	case wasm.OpcodeI64ExtendI32S, wasm.OpcodeI64ExtendI32U:
   411  		return signature_I32_I64, nil
   412  	case wasm.OpcodeI64TruncF32S, wasm.OpcodeI64TruncF32U:
   413  		return signature_F32_I64, nil
   414  	case wasm.OpcodeI64TruncF64S, wasm.OpcodeI64TruncF64U:
   415  		return signature_F64_I64, nil
   416  	case wasm.OpcodeF32ConvertI32S, wasm.OpcodeF32ConvertI32U:
   417  		return signature_I32_F32, nil
   418  	case wasm.OpcodeF32ConvertI64S, wasm.OpcodeF32ConvertI64U:
   419  		return signature_I64_F32, nil
   420  	case wasm.OpcodeF32DemoteF64:
   421  		return signature_F64_F32, nil
   422  	case wasm.OpcodeF64ConvertI32S, wasm.OpcodeF64ConvertI32U:
   423  		return signature_I32_F64, nil
   424  	case wasm.OpcodeF64ConvertI64S, wasm.OpcodeF64ConvertI64U:
   425  		return signature_I64_F64, nil
   426  	case wasm.OpcodeF64PromoteF32:
   427  		return signature_F32_F64, nil
   428  	case wasm.OpcodeI32ReinterpretF32:
   429  		return signature_F32_I32, nil
   430  	case wasm.OpcodeI64ReinterpretF64:
   431  		return signature_F64_I64, nil
   432  	case wasm.OpcodeF32ReinterpretI32:
   433  		return signature_I32_F32, nil
   434  	case wasm.OpcodeF64ReinterpretI64:
   435  		return signature_I64_F64, nil
   436  	case wasm.OpcodeI32Extend8S, wasm.OpcodeI32Extend16S:
   437  		return signature_I32_I32, nil
   438  	case wasm.OpcodeI64Extend8S, wasm.OpcodeI64Extend16S, wasm.OpcodeI64Extend32S:
   439  		return signature_I64_I64, nil
   440  	case wasm.OpcodeTableGet:
   441  		// table.get takes table's offset and pushes the ref type value of opaque pointer as i64 value onto the stack.
   442  		return signature_I32_I64, nil
   443  	case wasm.OpcodeTableSet:
   444  		// table.set takes table's offset and the ref type value of opaque pointer as i64 value.
   445  		return signature_I32I64_None, nil
   446  	case wasm.OpcodeRefFunc:
   447  		// ref.func is translated as pushing the compiled function's opaque pointer (uint64) at wazeroir layer.
   448  		return signature_None_I64, nil
   449  	case wasm.OpcodeRefIsNull:
   450  		// ref.is_null is translated as checking if the uint64 on the top of the stack (opaque pointer) is zero or not.
   451  		return signature_I64_I32, nil
   452  	case wasm.OpcodeRefNull:
   453  		// ref.null is translated as i64.const 0.
   454  		return signature_None_I64, nil
   455  	case wasm.OpcodeMiscPrefix:
   456  		switch miscOp := c.body[c.pc+1]; miscOp {
   457  		case wasm.OpcodeMiscI32TruncSatF32S, wasm.OpcodeMiscI32TruncSatF32U:
   458  			return signature_F32_I32, nil
   459  		case wasm.OpcodeMiscI32TruncSatF64S, wasm.OpcodeMiscI32TruncSatF64U:
   460  			return signature_F64_I32, nil
   461  		case wasm.OpcodeMiscI64TruncSatF32S, wasm.OpcodeMiscI64TruncSatF32U:
   462  			return signature_F32_I64, nil
   463  		case wasm.OpcodeMiscI64TruncSatF64S, wasm.OpcodeMiscI64TruncSatF64U:
   464  			return signature_F64_I64, nil
   465  		case wasm.OpcodeMiscMemoryInit, wasm.OpcodeMiscMemoryCopy, wasm.OpcodeMiscMemoryFill,
   466  			wasm.OpcodeMiscTableInit, wasm.OpcodeMiscTableCopy:
   467  			return signature_I32I32I32_None, nil
   468  		case wasm.OpcodeMiscDataDrop, wasm.OpcodeMiscElemDrop:
   469  			return signature_None_None, nil
   470  		case wasm.OpcodeMiscTableGrow:
   471  			return signature_I64I32_I32, nil
   472  		case wasm.OpcodeMiscTableSize:
   473  			return signature_None_I32, nil
   474  		case wasm.OpcodeMiscTableFill:
   475  			return signature_I32I64I32_None, nil
   476  		default:
   477  			return nil, fmt.Errorf("unsupported misc instruction in wazeroir: 0x%x", op)
   478  		}
   479  	case wasm.OpcodeVecPrefix:
   480  		switch vecOp := c.body[c.pc+1]; vecOp {
   481  		case wasm.OpcodeVecV128Const:
   482  			return signature_None_V128, nil
   483  		case wasm.OpcodeVecV128Load, wasm.OpcodeVecV128Load8x8s, wasm.OpcodeVecV128Load8x8u,
   484  			wasm.OpcodeVecV128Load16x4s, wasm.OpcodeVecV128Load16x4u, wasm.OpcodeVecV128Load32x2s,
   485  			wasm.OpcodeVecV128Load32x2u, wasm.OpcodeVecV128Load8Splat, wasm.OpcodeVecV128Load16Splat,
   486  			wasm.OpcodeVecV128Load32Splat, wasm.OpcodeVecV128Load64Splat, wasm.OpcodeVecV128Load32zero,
   487  			wasm.OpcodeVecV128Load64zero:
   488  			return signature_I32_V128, nil
   489  		case wasm.OpcodeVecV128Load8Lane, wasm.OpcodeVecV128Load16Lane,
   490  			wasm.OpcodeVecV128Load32Lane, wasm.OpcodeVecV128Load64Lane:
   491  			return signature_I32V128_V128, nil
   492  		case wasm.OpcodeVecV128Store,
   493  			wasm.OpcodeVecV128Store8Lane,
   494  			wasm.OpcodeVecV128Store16Lane,
   495  			wasm.OpcodeVecV128Store32Lane,
   496  			wasm.OpcodeVecV128Store64Lane:
   497  			return signature_I32V128_None, nil
   498  		case wasm.OpcodeVecI8x16ExtractLaneS,
   499  			wasm.OpcodeVecI8x16ExtractLaneU,
   500  			wasm.OpcodeVecI16x8ExtractLaneS,
   501  			wasm.OpcodeVecI16x8ExtractLaneU,
   502  			wasm.OpcodeVecI32x4ExtractLane:
   503  			return signature_V128_I32, nil
   504  		case wasm.OpcodeVecI64x2ExtractLane:
   505  			return signature_V128_I64, nil
   506  		case wasm.OpcodeVecF32x4ExtractLane:
   507  			return signature_V128_F32, nil
   508  		case wasm.OpcodeVecF64x2ExtractLane:
   509  			return signature_V128_F64, nil
   510  		case wasm.OpcodeVecI8x16ReplaceLane, wasm.OpcodeVecI16x8ReplaceLane, wasm.OpcodeVecI32x4ReplaceLane,
   511  			wasm.OpcodeVecI8x16Shl, wasm.OpcodeVecI8x16ShrS, wasm.OpcodeVecI8x16ShrU,
   512  			wasm.OpcodeVecI16x8Shl, wasm.OpcodeVecI16x8ShrS, wasm.OpcodeVecI16x8ShrU,
   513  			wasm.OpcodeVecI32x4Shl, wasm.OpcodeVecI32x4ShrS, wasm.OpcodeVecI32x4ShrU,
   514  			wasm.OpcodeVecI64x2Shl, wasm.OpcodeVecI64x2ShrS, wasm.OpcodeVecI64x2ShrU:
   515  			return signature_V128I32_V128, nil
   516  		case wasm.OpcodeVecI64x2ReplaceLane:
   517  			return signature_V128I64_V128, nil
   518  		case wasm.OpcodeVecF32x4ReplaceLane:
   519  			return signature_V128F32_V128, nil
   520  		case wasm.OpcodeVecF64x2ReplaceLane:
   521  			return signature_V128F64_V128, nil
   522  		case wasm.OpcodeVecI8x16Splat,
   523  			wasm.OpcodeVecI16x8Splat,
   524  			wasm.OpcodeVecI32x4Splat:
   525  			return signature_I32_V128, nil
   526  		case wasm.OpcodeVecI64x2Splat:
   527  			return signature_I64_V128, nil
   528  		case wasm.OpcodeVecF32x4Splat:
   529  			return signature_F32_V128, nil
   530  		case wasm.OpcodeVecF64x2Splat:
   531  			return signature_F64_V128, nil
   532  		case wasm.OpcodeVecV128i8x16Shuffle, wasm.OpcodeVecI8x16Swizzle, wasm.OpcodeVecV128And, wasm.OpcodeVecV128Or, wasm.OpcodeVecV128Xor, wasm.OpcodeVecV128AndNot:
   533  			return signature_V128V128_V128, nil
   534  		case wasm.OpcodeVecI8x16AllTrue, wasm.OpcodeVecI16x8AllTrue, wasm.OpcodeVecI32x4AllTrue, wasm.OpcodeVecI64x2AllTrue,
   535  			wasm.OpcodeVecV128AnyTrue,
   536  			wasm.OpcodeVecI8x16BitMask, wasm.OpcodeVecI16x8BitMask, wasm.OpcodeVecI32x4BitMask, wasm.OpcodeVecI64x2BitMask:
   537  			return signature_V128_I32, nil
   538  		case wasm.OpcodeVecV128Not, wasm.OpcodeVecI8x16Neg, wasm.OpcodeVecI16x8Neg, wasm.OpcodeVecI32x4Neg, wasm.OpcodeVecI64x2Neg,
   539  			wasm.OpcodeVecF32x4Neg, wasm.OpcodeVecF64x2Neg, wasm.OpcodeVecF32x4Sqrt, wasm.OpcodeVecF64x2Sqrt,
   540  			wasm.OpcodeVecI8x16Abs, wasm.OpcodeVecI8x16Popcnt, wasm.OpcodeVecI16x8Abs, wasm.OpcodeVecI32x4Abs, wasm.OpcodeVecI64x2Abs,
   541  			wasm.OpcodeVecF32x4Abs, wasm.OpcodeVecF64x2Abs,
   542  			wasm.OpcodeVecF32x4Ceil, wasm.OpcodeVecF32x4Floor, wasm.OpcodeVecF32x4Trunc, wasm.OpcodeVecF32x4Nearest,
   543  			wasm.OpcodeVecF64x2Ceil, wasm.OpcodeVecF64x2Floor, wasm.OpcodeVecF64x2Trunc, wasm.OpcodeVecF64x2Nearest,
   544  			wasm.OpcodeVecI16x8ExtendLowI8x16S, wasm.OpcodeVecI16x8ExtendHighI8x16S, wasm.OpcodeVecI16x8ExtendLowI8x16U, wasm.OpcodeVecI16x8ExtendHighI8x16U,
   545  			wasm.OpcodeVecI32x4ExtendLowI16x8S, wasm.OpcodeVecI32x4ExtendHighI16x8S, wasm.OpcodeVecI32x4ExtendLowI16x8U, wasm.OpcodeVecI32x4ExtendHighI16x8U,
   546  			wasm.OpcodeVecI64x2ExtendLowI32x4S, wasm.OpcodeVecI64x2ExtendHighI32x4S, wasm.OpcodeVecI64x2ExtendLowI32x4U, wasm.OpcodeVecI64x2ExtendHighI32x4U,
   547  			wasm.OpcodeVecI16x8ExtaddPairwiseI8x16S, wasm.OpcodeVecI16x8ExtaddPairwiseI8x16U, wasm.OpcodeVecI32x4ExtaddPairwiseI16x8S, wasm.OpcodeVecI32x4ExtaddPairwiseI16x8U,
   548  			wasm.OpcodeVecF64x2PromoteLowF32x4Zero, wasm.OpcodeVecF32x4DemoteF64x2Zero,
   549  			wasm.OpcodeVecF32x4ConvertI32x4S, wasm.OpcodeVecF32x4ConvertI32x4U,
   550  			wasm.OpcodeVecF64x2ConvertLowI32x4S, wasm.OpcodeVecF64x2ConvertLowI32x4U,
   551  			wasm.OpcodeVecI32x4TruncSatF32x4S, wasm.OpcodeVecI32x4TruncSatF32x4U,
   552  			wasm.OpcodeVecI32x4TruncSatF64x2SZero, wasm.OpcodeVecI32x4TruncSatF64x2UZero:
   553  			return signature_V128_V128, nil
   554  		case wasm.OpcodeVecV128Bitselect:
   555  			return signature_V128V128V128_V32, nil
   556  		case wasm.OpcodeVecI8x16Eq, wasm.OpcodeVecI8x16Ne, wasm.OpcodeVecI8x16LtS, wasm.OpcodeVecI8x16LtU, wasm.OpcodeVecI8x16GtS,
   557  			wasm.OpcodeVecI8x16GtU, wasm.OpcodeVecI8x16LeS, wasm.OpcodeVecI8x16LeU, wasm.OpcodeVecI8x16GeS, wasm.OpcodeVecI8x16GeU,
   558  			wasm.OpcodeVecI16x8Eq, wasm.OpcodeVecI16x8Ne, wasm.OpcodeVecI16x8LtS, wasm.OpcodeVecI16x8LtU, wasm.OpcodeVecI16x8GtS,
   559  			wasm.OpcodeVecI16x8GtU, wasm.OpcodeVecI16x8LeS, wasm.OpcodeVecI16x8LeU, wasm.OpcodeVecI16x8GeS, wasm.OpcodeVecI16x8GeU,
   560  			wasm.OpcodeVecI32x4Eq, wasm.OpcodeVecI32x4Ne, wasm.OpcodeVecI32x4LtS, wasm.OpcodeVecI32x4LtU, wasm.OpcodeVecI32x4GtS,
   561  			wasm.OpcodeVecI32x4GtU, wasm.OpcodeVecI32x4LeS, wasm.OpcodeVecI32x4LeU, wasm.OpcodeVecI32x4GeS, wasm.OpcodeVecI32x4GeU,
   562  			wasm.OpcodeVecI64x2Eq, wasm.OpcodeVecI64x2Ne, wasm.OpcodeVecI64x2LtS, wasm.OpcodeVecI64x2GtS, wasm.OpcodeVecI64x2LeS,
   563  			wasm.OpcodeVecI64x2GeS, wasm.OpcodeVecF32x4Eq, wasm.OpcodeVecF32x4Ne, wasm.OpcodeVecF32x4Lt, wasm.OpcodeVecF32x4Gt,
   564  			wasm.OpcodeVecF32x4Le, wasm.OpcodeVecF32x4Ge, wasm.OpcodeVecF64x2Eq, wasm.OpcodeVecF64x2Ne, wasm.OpcodeVecF64x2Lt,
   565  			wasm.OpcodeVecF64x2Gt, wasm.OpcodeVecF64x2Le, wasm.OpcodeVecF64x2Ge,
   566  			wasm.OpcodeVecI8x16Add, wasm.OpcodeVecI8x16AddSatS, wasm.OpcodeVecI8x16AddSatU, wasm.OpcodeVecI8x16Sub,
   567  			wasm.OpcodeVecI8x16SubSatS, wasm.OpcodeVecI8x16SubSatU,
   568  			wasm.OpcodeVecI16x8Add, wasm.OpcodeVecI16x8AddSatS, wasm.OpcodeVecI16x8AddSatU, wasm.OpcodeVecI16x8Sub,
   569  			wasm.OpcodeVecI16x8SubSatS, wasm.OpcodeVecI16x8SubSatU, wasm.OpcodeVecI16x8Mul,
   570  			wasm.OpcodeVecI32x4Add, wasm.OpcodeVecI32x4Sub, wasm.OpcodeVecI32x4Mul,
   571  			wasm.OpcodeVecI64x2Add, wasm.OpcodeVecI64x2Sub, wasm.OpcodeVecI64x2Mul,
   572  			wasm.OpcodeVecF32x4Add, wasm.OpcodeVecF32x4Sub, wasm.OpcodeVecF32x4Mul, wasm.OpcodeVecF32x4Div,
   573  			wasm.OpcodeVecF64x2Add, wasm.OpcodeVecF64x2Sub, wasm.OpcodeVecF64x2Mul, wasm.OpcodeVecF64x2Div,
   574  			wasm.OpcodeVecI8x16MinS, wasm.OpcodeVecI8x16MinU, wasm.OpcodeVecI8x16MaxS, wasm.OpcodeVecI8x16MaxU, wasm.OpcodeVecI8x16AvgrU,
   575  			wasm.OpcodeVecI16x8MinS, wasm.OpcodeVecI16x8MinU, wasm.OpcodeVecI16x8MaxS, wasm.OpcodeVecI16x8MaxU, wasm.OpcodeVecI16x8AvgrU,
   576  			wasm.OpcodeVecI32x4MinS, wasm.OpcodeVecI32x4MinU, wasm.OpcodeVecI32x4MaxS, wasm.OpcodeVecI32x4MaxU,
   577  			wasm.OpcodeVecF32x4Min, wasm.OpcodeVecF32x4Max, wasm.OpcodeVecF64x2Min, wasm.OpcodeVecF64x2Max,
   578  			wasm.OpcodeVecF32x4Pmin, wasm.OpcodeVecF32x4Pmax, wasm.OpcodeVecF64x2Pmin, wasm.OpcodeVecF64x2Pmax,
   579  			wasm.OpcodeVecI16x8Q15mulrSatS,
   580  			wasm.OpcodeVecI16x8ExtMulLowI8x16S, wasm.OpcodeVecI16x8ExtMulHighI8x16S, wasm.OpcodeVecI16x8ExtMulLowI8x16U, wasm.OpcodeVecI16x8ExtMulHighI8x16U,
   581  			wasm.OpcodeVecI32x4ExtMulLowI16x8S, wasm.OpcodeVecI32x4ExtMulHighI16x8S, wasm.OpcodeVecI32x4ExtMulLowI16x8U, wasm.OpcodeVecI32x4ExtMulHighI16x8U,
   582  			wasm.OpcodeVecI64x2ExtMulLowI32x4S, wasm.OpcodeVecI64x2ExtMulHighI32x4S, wasm.OpcodeVecI64x2ExtMulLowI32x4U, wasm.OpcodeVecI64x2ExtMulHighI32x4U,
   583  			wasm.OpcodeVecI32x4DotI16x8S,
   584  			wasm.OpcodeVecI8x16NarrowI16x8S, wasm.OpcodeVecI8x16NarrowI16x8U, wasm.OpcodeVecI16x8NarrowI32x4S, wasm.OpcodeVecI16x8NarrowI32x4U:
   585  			return signature_V128V128_V128, nil
   586  		default:
   587  			return nil, fmt.Errorf("unsupported vector instruction in wazeroir: %s", wasm.VectorInstructionName(vecOp))
   588  		}
   589  	default:
   590  		return nil, fmt.Errorf("unsupported instruction in wazeroir: 0x%x", op)
   591  	}
   592  }
   593  
   594  // funcTypeToIRSignatures is the central cache for a module to get the *signature
   595  // for function calls.
   596  type funcTypeToIRSignatures struct {
   597  	directCalls   []*signature
   598  	indirectCalls []*signature
   599  	wasmTypes     []wasm.FunctionType
   600  }
   601  
   602  // get returns the *signature for the direct or indirect function call against functions whose type is at `typeIndex`.
   603  func (f *funcTypeToIRSignatures) get(typeIndex wasm.Index, indirect bool) *signature {
   604  	var sig *signature
   605  	if indirect {
   606  		sig = f.indirectCalls[typeIndex]
   607  	} else {
   608  		sig = f.directCalls[typeIndex]
   609  	}
   610  	if sig != nil {
   611  		return sig
   612  	}
   613  
   614  	tp := &f.wasmTypes[typeIndex]
   615  	if indirect {
   616  		sig = &signature{
   617  			in:  make([]UnsignedType, 0, len(tp.Params)+1), // +1 to reserve space for call indirect index.
   618  			out: make([]UnsignedType, 0, len(tp.Results)),
   619  		}
   620  	} else {
   621  		sig = &signature{
   622  			in:  make([]UnsignedType, 0, len(tp.Params)),
   623  			out: make([]UnsignedType, 0, len(tp.Results)),
   624  		}
   625  	}
   626  
   627  	for _, vt := range tp.Params {
   628  		sig.in = append(sig.in, wasmValueTypeToUnsignedType(vt))
   629  	}
   630  	for _, vt := range tp.Results {
   631  		sig.out = append(sig.out, wasmValueTypeToUnsignedType(vt))
   632  	}
   633  
   634  	if indirect {
   635  		sig.in = append(sig.in, UnsignedTypeI32)
   636  		f.indirectCalls[typeIndex] = sig
   637  	} else {
   638  		f.directCalls[typeIndex] = sig
   639  	}
   640  	return sig
   641  }
   642  
   643  func wasmValueTypeToUnsignedType(vt wasm.ValueType) UnsignedType {
   644  	switch vt {
   645  	case wasm.ValueTypeI32:
   646  		return UnsignedTypeI32
   647  	case wasm.ValueTypeI64,
   648  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   649  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   650  		return UnsignedTypeI64
   651  	case wasm.ValueTypeF32:
   652  		return UnsignedTypeF32
   653  	case wasm.ValueTypeF64:
   654  		return UnsignedTypeF64
   655  	case wasm.ValueTypeV128:
   656  		return UnsignedTypeV128
   657  	}
   658  	panic("unreachable")
   659  }
   660  
   661  func wasmValueTypeToUnsignedOutSignature(vt wasm.ValueType) *signature {
   662  	switch vt {
   663  	case wasm.ValueTypeI32:
   664  		return signature_None_I32
   665  	case wasm.ValueTypeI64,
   666  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   667  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   668  		return signature_None_I64
   669  	case wasm.ValueTypeF32:
   670  		return signature_None_F32
   671  	case wasm.ValueTypeF64:
   672  		return signature_None_F64
   673  	case wasm.ValueTypeV128:
   674  		return signature_None_V128
   675  	}
   676  	panic("unreachable")
   677  }
   678  
   679  func wasmValueTypeToUnsignedInSignature(vt wasm.ValueType) *signature {
   680  	switch vt {
   681  	case wasm.ValueTypeI32:
   682  		return signature_I32_None
   683  	case wasm.ValueTypeI64,
   684  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   685  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   686  		return signature_I64_None
   687  	case wasm.ValueTypeF32:
   688  		return signature_F32_None
   689  	case wasm.ValueTypeF64:
   690  		return signature_F64_None
   691  	case wasm.ValueTypeV128:
   692  		return signature_V128_None
   693  	}
   694  	panic("unreachable")
   695  }
   696  
   697  func wasmValueTypeToUnsignedInOutSignature(vt wasm.ValueType) *signature {
   698  	switch vt {
   699  	case wasm.ValueTypeI32:
   700  		return signature_I32_I32
   701  	case wasm.ValueTypeI64,
   702  		// From wazeroir layer, ref type values are opaque 64-bit pointers.
   703  		wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
   704  		return signature_I64_I64
   705  	case wasm.ValueTypeF32:
   706  		return signature_F32_F32
   707  	case wasm.ValueTypeF64:
   708  		return signature_F64_F64
   709  	case wasm.ValueTypeV128:
   710  		return signature_V128_V128
   711  	}
   712  	panic("unreachable")
   713  }
   714  

View as plain text