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