diff --git a/src/builtins.ts b/src/builtins.ts index eb6e4f60f6..d1d498358d 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -1126,8 +1126,8 @@ function builtin_popcnt(ctx: BuiltinContext): ExpressionRef { var type = compiler.currentType; if (type.isValue) { switch (compiler.currentType.kind) { - case TypeKind.BOOL: // not wrapped - case TypeKind.I8: + case TypeKind.BOOL: return arg0; + case TypeKind.I8: // not wrapped case TypeKind.U8: case TypeKind.I16: case TypeKind.U16: @@ -1171,14 +1171,27 @@ function builtin_rotl(ctx: BuiltinContext): ExpressionRef { if (type.isValue) { let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); switch (type.kind) { + case TypeKind.BOOL: return arg0; case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - return compiler.ensureSmallIntegerWrap( - module.binary(BinaryOp.RotlI32, arg0, arg1), - type + case TypeKind.U16: { + // (value << (shift & mask)) | (value >>> ((0 - shift) & mask)) + return module.binary(BinaryOp.OrI32, + module.binary( + BinaryOp.ShlI32, + arg0, + module.binary(BinaryOp.AndI32, arg1, module.i32(type.size - 1)) + ), + module.binary( + BinaryOp.ShrU32, + arg0, + module.binary( + BinaryOp.AndI32, + module.binary(BinaryOp.SubI32, module.i32(0), arg1), + module.i32(type.size - 1) + ) + ) ); } case TypeKind.I32: @@ -1221,14 +1234,27 @@ function builtin_rotr(ctx: BuiltinContext): ExpressionRef { if (type.isValue) { let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); switch (type.kind) { + case TypeKind.BOOL: return arg0; case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - return compiler.ensureSmallIntegerWrap( - module.binary(BinaryOp.RotrI32, arg0, arg1), - type + case TypeKind.U16: { + // (value >>> (shift & mask)) | (value << ((0 - shift) & mask)) + return module.binary(BinaryOp.OrI32, + module.binary( + BinaryOp.ShrU32, + arg0, + module.binary(BinaryOp.AndI32, arg1, module.i32(type.size - 1)) + ), + module.binary( + BinaryOp.ShlI32, + arg0, + module.binary( + BinaryOp.AndI32, + module.binary(BinaryOp.SubI32, module.i32(0), arg1), + module.i32(type.size - 1) + ) + ) ); } case TypeKind.I32: @@ -2129,7 +2155,7 @@ function builtin_add(ctx: BuiltinContext): ExpressionRef { { op = BinaryOp.AddI32; break; - } + } case TypeKind.I64: case TypeKind.U64: { op = BinaryOp.AddI64; @@ -2220,7 +2246,7 @@ function builtin_sub(ctx: BuiltinContext): ExpressionRef { { op = BinaryOp.SubI32; break; - } + } case TypeKind.I64: case TypeKind.U64: { op = BinaryOp.SubI64; @@ -2311,7 +2337,7 @@ function builtin_mul(ctx: BuiltinContext): ExpressionRef { { op = BinaryOp.MulI32; break; - } + } case TypeKind.I64: case TypeKind.U64: { op = BinaryOp.MulI64; @@ -3041,7 +3067,7 @@ function builtin_assert(ctx: BuiltinContext): ExpressionRef { case TypeKind.EXTERNREF: case TypeKind.EXNREF: case TypeKind.ANYREF: return module.if(module.ref_is_null(arg0), abort); - + } } else { compiler.currentType = type.nonNullableType; diff --git a/tests/compiler/builtins.optimized.wat b/tests/compiler/builtins.optimized.wat index e522385f05..e22480aec7 100644 --- a/tests/compiler/builtins.optimized.wat +++ b/tests/compiler/builtins.optimized.wat @@ -503,7 +503,7 @@ if i32.const 0 i32.const 1088 - i32.const 294 + i32.const 298 i32.const 1 call $~lib/builtins/abort unreachable @@ -518,7 +518,7 @@ if i32.const 0 i32.const 1088 - i32.const 295 + i32.const 299 i32.const 1 call $~lib/builtins/abort unreachable @@ -530,7 +530,7 @@ if i32.const 0 i32.const 1088 - i32.const 296 + i32.const 300 i32.const 1 call $~lib/builtins/abort unreachable @@ -542,7 +542,7 @@ if i32.const 0 i32.const 1088 - i32.const 299 + i32.const 303 i32.const 1 call $~lib/builtins/abort unreachable @@ -621,7 +621,7 @@ if i32.const 0 i32.const 1088 - i32.const 475 + i32.const 479 i32.const 1 call $~lib/builtins/abort unreachable @@ -633,7 +633,7 @@ if i32.const 0 i32.const 1088 - i32.const 476 + i32.const 480 i32.const 1 call $~lib/builtins/abort unreachable @@ -645,7 +645,7 @@ if i32.const 0 i32.const 1088 - i32.const 477 + i32.const 481 i32.const 1 call $~lib/builtins/abort unreachable @@ -655,7 +655,7 @@ if i32.const 0 i32.const 1088 - i32.const 478 + i32.const 482 i32.const 1 call $~lib/builtins/abort unreachable @@ -667,7 +667,7 @@ if i32.const 0 i32.const 1088 - i32.const 479 + i32.const 483 i32.const 1 call $~lib/builtins/abort unreachable @@ -677,7 +677,7 @@ if i32.const 0 i32.const 1088 - i32.const 480 + i32.const 484 i32.const 1 call $~lib/builtins/abort unreachable @@ -687,7 +687,7 @@ if i32.const 0 i32.const 1088 - i32.const 481 + i32.const 485 i32.const 1 call $~lib/builtins/abort unreachable @@ -707,7 +707,7 @@ if i32.const 0 i32.const 1088 - i32.const 498 + i32.const 502 i32.const 3 call $~lib/builtins/abort unreachable @@ -719,7 +719,7 @@ if i32.const 0 i32.const 1088 - i32.const 499 + i32.const 503 i32.const 3 call $~lib/builtins/abort unreachable @@ -731,7 +731,7 @@ if i32.const 0 i32.const 1088 - i32.const 500 + i32.const 504 i32.const 3 call $~lib/builtins/abort unreachable @@ -743,7 +743,7 @@ if i32.const 0 i32.const 1088 - i32.const 501 + i32.const 505 i32.const 3 call $~lib/builtins/abort unreachable @@ -755,7 +755,7 @@ if i32.const 0 i32.const 1088 - i32.const 502 + i32.const 506 i32.const 3 call $~lib/builtins/abort unreachable @@ -767,7 +767,7 @@ if i32.const 0 i32.const 1088 - i32.const 503 + i32.const 507 i32.const 3 call $~lib/builtins/abort unreachable @@ -779,7 +779,7 @@ if i32.const 0 i32.const 1088 - i32.const 504 + i32.const 508 i32.const 3 call $~lib/builtins/abort unreachable @@ -791,7 +791,7 @@ if i32.const 0 i32.const 1088 - i32.const 505 + i32.const 509 i32.const 3 call $~lib/builtins/abort unreachable @@ -803,7 +803,7 @@ if i32.const 0 i32.const 1088 - i32.const 506 + i32.const 510 i32.const 3 call $~lib/builtins/abort unreachable @@ -815,7 +815,7 @@ if i32.const 0 i32.const 1088 - i32.const 507 + i32.const 511 i32.const 3 call $~lib/builtins/abort unreachable @@ -827,7 +827,7 @@ if i32.const 0 i32.const 1088 - i32.const 508 + i32.const 512 i32.const 3 call $~lib/builtins/abort unreachable @@ -839,7 +839,7 @@ if i32.const 0 i32.const 1088 - i32.const 509 + i32.const 513 i32.const 3 call $~lib/builtins/abort unreachable @@ -851,7 +851,7 @@ if i32.const 0 i32.const 1088 - i32.const 510 + i32.const 514 i32.const 3 call $~lib/builtins/abort unreachable @@ -863,7 +863,7 @@ if i32.const 0 i32.const 1088 - i32.const 511 + i32.const 515 i32.const 3 call $~lib/builtins/abort unreachable @@ -875,7 +875,7 @@ if i32.const 0 i32.const 1088 - i32.const 512 + i32.const 516 i32.const 3 call $~lib/builtins/abort unreachable @@ -887,7 +887,7 @@ if i32.const 0 i32.const 1088 - i32.const 513 + i32.const 517 i32.const 3 call $~lib/builtins/abort unreachable @@ -899,7 +899,7 @@ if i32.const 0 i32.const 1088 - i32.const 514 + i32.const 518 i32.const 3 call $~lib/builtins/abort unreachable @@ -911,7 +911,7 @@ if i32.const 0 i32.const 1088 - i32.const 515 + i32.const 519 i32.const 3 call $~lib/builtins/abort unreachable @@ -923,7 +923,7 @@ if i32.const 0 i32.const 1088 - i32.const 516 + i32.const 520 i32.const 3 call $~lib/builtins/abort unreachable @@ -935,7 +935,7 @@ if i32.const 0 i32.const 1088 - i32.const 517 + i32.const 521 i32.const 3 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/builtins.ts b/tests/compiler/builtins.ts index 0f5217de42..8288498b94 100644 --- a/tests/compiler/builtins.ts +++ b/tests/compiler/builtins.ts @@ -52,6 +52,10 @@ l = add(1, 2); assert(l == 3); l = sub(2, 1); assert(l == 1); l = mul(1, 2); assert(l == 2); +var v: u8; +v = rotl(0b10001111, 3); assert(v == 0b01111100); +v = rotr(0b10101010, 1); assert(v == 0b01010101); + // integers var i: i32; @@ -149,9 +153,9 @@ abs(1.25); ceil(1.25); copysign(1.25, 2.5); floor(1.25); -add(1.5, 2.5); -sub(2.5, 1.5); -mul(1.5, 2.0); +add(1.5, 2.5); +sub(2.5, 1.5); +mul(1.5, 2.0); max(1.25, 2.5); min(1.25, 2.5); nearest(1.25); diff --git a/tests/compiler/builtins.untouched.wat b/tests/compiler/builtins.untouched.wat index 481b988d19..08e414acfd 100644 --- a/tests/compiler/builtins.untouched.wat +++ b/tests/compiler/builtins.untouched.wat @@ -40,6 +40,7 @@ (elem (i32.const 1) $start:builtins~anonymous|0 $start:builtins~anonymous|1 $start:builtins~anonymous|2) (global $builtins/b (mut i32) (i32.const 0)) (global $builtins/l (mut i32) (i32.const 0)) + (global $builtins/v (mut i32) (i32.const 0)) (global $builtins/i (mut i32) (i32.const 0)) (global $builtins/I (mut i64) (i64.const 0)) (global $builtins/f (mut f32) (f32.const 0)) @@ -500,6 +501,62 @@ call $~lib/builtins/abort unreachable end + i32.const 143 + i32.const 3 + i32.const 7 + i32.and + i32.shl + i32.const 143 + i32.const 0 + i32.const 3 + i32.sub + i32.const 7 + i32.and + i32.shr_u + i32.or + i32.const 255 + i32.and + global.set $builtins/v + global.get $builtins/v + i32.const 124 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 80 + i32.const 56 + i32.const 34 + call $~lib/builtins/abort + unreachable + end + i32.const 170 + i32.const 1 + i32.const 7 + i32.and + i32.shr_u + i32.const 170 + i32.const 0 + i32.const 1 + i32.sub + i32.const 7 + i32.and + i32.shl + i32.or + i32.const 255 + i32.and + global.set $builtins/v + global.get $builtins/v + i32.const 85 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 80 + i32.const 57 + i32.const 34 + call $~lib/builtins/abort + unreachable + end i32.const 1 i32.clz drop @@ -591,7 +648,7 @@ if i32.const 0 i32.const 80 - i32.const 76 + i32.const 80 i32.const 20 call $~lib/builtins/abort unreachable @@ -612,7 +669,7 @@ if i32.const 0 i32.const 80 - i32.const 77 + i32.const 81 i32.const 21 call $~lib/builtins/abort unreachable @@ -633,7 +690,7 @@ if i32.const 0 i32.const 80 - i32.const 78 + i32.const 82 i32.const 21 call $~lib/builtins/abort unreachable @@ -649,7 +706,7 @@ if i32.const 0 i32.const 80 - i32.const 79 + i32.const 83 i32.const 21 call $~lib/builtins/abort unreachable @@ -665,7 +722,7 @@ if i32.const 0 i32.const 80 - i32.const 80 + i32.const 84 i32.const 21 call $~lib/builtins/abort unreachable @@ -681,7 +738,7 @@ if i32.const 0 i32.const 80 - i32.const 81 + i32.const 85 i32.const 21 call $~lib/builtins/abort unreachable @@ -747,7 +804,7 @@ if i32.const 0 i32.const 80 - i32.const 96 + i32.const 100 i32.const 20 call $~lib/builtins/abort unreachable @@ -768,7 +825,7 @@ if i32.const 0 i32.const 80 - i32.const 97 + i32.const 101 i32.const 21 call $~lib/builtins/abort unreachable @@ -789,7 +846,7 @@ if i32.const 0 i32.const 80 - i32.const 98 + i32.const 102 i32.const 21 call $~lib/builtins/abort unreachable @@ -805,7 +862,7 @@ if i32.const 0 i32.const 80 - i32.const 99 + i32.const 103 i32.const 21 call $~lib/builtins/abort unreachable @@ -821,7 +878,7 @@ if i32.const 0 i32.const 80 - i32.const 100 + i32.const 104 i32.const 21 call $~lib/builtins/abort unreachable @@ -837,7 +894,7 @@ if i32.const 0 i32.const 80 - i32.const 101 + i32.const 105 i32.const 21 call $~lib/builtins/abort unreachable @@ -955,7 +1012,7 @@ if i32.const 0 i32.const 80 - i32.const 131 + i32.const 135 i32.const 25 call $~lib/builtins/abort unreachable @@ -971,7 +1028,7 @@ if i32.const 0 i32.const 80 - i32.const 132 + i32.const 136 i32.const 25 call $~lib/builtins/abort unreachable @@ -987,7 +1044,7 @@ if i32.const 0 i32.const 80 - i32.const 133 + i32.const 137 i32.const 25 call $~lib/builtins/abort unreachable @@ -1003,7 +1060,7 @@ if i32.const 0 i32.const 80 - i32.const 134 + i32.const 138 i32.const 26 call $~lib/builtins/abort unreachable @@ -1162,7 +1219,7 @@ if i32.const 0 i32.const 80 - i32.const 173 + i32.const 177 i32.const 25 call $~lib/builtins/abort unreachable @@ -1178,7 +1235,7 @@ if i32.const 0 i32.const 80 - i32.const 174 + i32.const 178 i32.const 25 call $~lib/builtins/abort unreachable @@ -1194,7 +1251,7 @@ if i32.const 0 i32.const 80 - i32.const 175 + i32.const 179 i32.const 25 call $~lib/builtins/abort unreachable @@ -1517,7 +1574,7 @@ if i32.const 0 i32.const 80 - i32.const 294 + i32.const 298 i32.const 1 call $~lib/builtins/abort unreachable @@ -1533,7 +1590,7 @@ if i32.const 0 i32.const 80 - i32.const 295 + i32.const 299 i32.const 1 call $~lib/builtins/abort unreachable @@ -1547,7 +1604,7 @@ if i32.const 0 i32.const 80 - i32.const 296 + i32.const 300 i32.const 1 call $~lib/builtins/abort unreachable @@ -1560,7 +1617,7 @@ if i32.const 0 i32.const 80 - i32.const 297 + i32.const 301 i32.const 1 call $~lib/builtins/abort unreachable @@ -1573,7 +1630,7 @@ if i32.const 0 i32.const 80 - i32.const 298 + i32.const 302 i32.const 1 call $~lib/builtins/abort unreachable @@ -1587,7 +1644,7 @@ if i32.const 0 i32.const 80 - i32.const 299 + i32.const 303 i32.const 1 call $~lib/builtins/abort unreachable @@ -2111,7 +2168,7 @@ if i32.const 0 i32.const 80 - i32.const 475 + i32.const 479 i32.const 1 call $~lib/builtins/abort unreachable @@ -2124,7 +2181,7 @@ if i32.const 0 i32.const 80 - i32.const 476 + i32.const 480 i32.const 1 call $~lib/builtins/abort unreachable @@ -2137,7 +2194,7 @@ if i32.const 0 i32.const 80 - i32.const 477 + i32.const 481 i32.const 1 call $~lib/builtins/abort unreachable @@ -2150,7 +2207,7 @@ if i32.const 0 i32.const 80 - i32.const 478 + i32.const 482 i32.const 1 call $~lib/builtins/abort unreachable @@ -2163,7 +2220,7 @@ if i32.const 0 i32.const 80 - i32.const 479 + i32.const 483 i32.const 1 call $~lib/builtins/abort unreachable @@ -2176,7 +2233,7 @@ if i32.const 0 i32.const 80 - i32.const 480 + i32.const 484 i32.const 1 call $~lib/builtins/abort unreachable @@ -2189,7 +2246,7 @@ if i32.const 0 i32.const 80 - i32.const 481 + i32.const 485 i32.const 1 call $~lib/builtins/abort unreachable @@ -2224,7 +2281,7 @@ if i32.const 288 i32.const 80 - i32.const 491 + i32.const 495 i32.const 3 call $~lib/builtins/abort unreachable @@ -2236,7 +2293,7 @@ if i32.const 0 i32.const 80 - i32.const 492 + i32.const 496 i32.const 3 call $~lib/builtins/abort unreachable @@ -2248,7 +2305,7 @@ if i32.const 0 i32.const 80 - i32.const 493 + i32.const 497 i32.const 3 call $~lib/builtins/abort unreachable @@ -2260,7 +2317,7 @@ if i32.const 0 i32.const 80 - i32.const 494 + i32.const 498 i32.const 3 call $~lib/builtins/abort unreachable @@ -2272,7 +2329,7 @@ if i32.const 0 i32.const 80 - i32.const 498 + i32.const 502 i32.const 3 call $~lib/builtins/abort unreachable @@ -2284,7 +2341,7 @@ if i32.const 0 i32.const 80 - i32.const 499 + i32.const 503 i32.const 3 call $~lib/builtins/abort unreachable @@ -2296,7 +2353,7 @@ if i32.const 0 i32.const 80 - i32.const 500 + i32.const 504 i32.const 3 call $~lib/builtins/abort unreachable @@ -2308,7 +2365,7 @@ if i32.const 0 i32.const 80 - i32.const 501 + i32.const 505 i32.const 3 call $~lib/builtins/abort unreachable @@ -2320,7 +2377,7 @@ if i32.const 0 i32.const 80 - i32.const 502 + i32.const 506 i32.const 3 call $~lib/builtins/abort unreachable @@ -2332,7 +2389,7 @@ if i32.const 0 i32.const 80 - i32.const 503 + i32.const 507 i32.const 3 call $~lib/builtins/abort unreachable @@ -2344,7 +2401,7 @@ if i32.const 0 i32.const 80 - i32.const 504 + i32.const 508 i32.const 3 call $~lib/builtins/abort unreachable @@ -2356,7 +2413,7 @@ if i32.const 0 i32.const 80 - i32.const 505 + i32.const 509 i32.const 3 call $~lib/builtins/abort unreachable @@ -2368,7 +2425,7 @@ if i32.const 0 i32.const 80 - i32.const 506 + i32.const 510 i32.const 3 call $~lib/builtins/abort unreachable @@ -2380,7 +2437,7 @@ if i32.const 0 i32.const 80 - i32.const 507 + i32.const 511 i32.const 3 call $~lib/builtins/abort unreachable @@ -2392,7 +2449,7 @@ if i32.const 0 i32.const 80 - i32.const 508 + i32.const 512 i32.const 3 call $~lib/builtins/abort unreachable @@ -2404,7 +2461,7 @@ if i32.const 0 i32.const 80 - i32.const 509 + i32.const 513 i32.const 3 call $~lib/builtins/abort unreachable @@ -2416,7 +2473,7 @@ if i32.const 0 i32.const 80 - i32.const 510 + i32.const 514 i32.const 3 call $~lib/builtins/abort unreachable @@ -2428,7 +2485,7 @@ if i32.const 0 i32.const 80 - i32.const 511 + i32.const 515 i32.const 3 call $~lib/builtins/abort unreachable @@ -2440,7 +2497,7 @@ if i32.const 0 i32.const 80 - i32.const 512 + i32.const 516 i32.const 3 call $~lib/builtins/abort unreachable @@ -2452,7 +2509,7 @@ if i32.const 0 i32.const 80 - i32.const 513 + i32.const 517 i32.const 3 call $~lib/builtins/abort unreachable @@ -2464,7 +2521,7 @@ if i32.const 0 i32.const 80 - i32.const 514 + i32.const 518 i32.const 3 call $~lib/builtins/abort unreachable @@ -2476,7 +2533,7 @@ if i32.const 0 i32.const 80 - i32.const 515 + i32.const 519 i32.const 3 call $~lib/builtins/abort unreachable @@ -2488,7 +2545,7 @@ if i32.const 0 i32.const 80 - i32.const 516 + i32.const 520 i32.const 3 call $~lib/builtins/abort unreachable @@ -2500,7 +2557,7 @@ if i32.const 0 i32.const 80 - i32.const 517 + i32.const 521 i32.const 3 call $~lib/builtins/abort unreachable