github.com/AR1011/wazero@v1.0.5/internal/wazeroir/signature.go (about) 1 package wazeroir 2 3 import ( 4 "fmt" 5 6 "github.com/AR1011/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 }