diff --git a/src/compiler.ts b/src/compiler.ts index 01914289ac..c8559eeba1 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -5128,7 +5128,7 @@ export class Compiler extends DiagnosticEmitter { module.binary(BinaryOp.EqI8x16, leftExpr, rightExpr) ); } - case TypeKind.FUNCREF: + case TypeKind.FUNCREF: case TypeKind.EXTERNREF: case TypeKind.EXNREF: case TypeKind.ANYREF: { @@ -5641,14 +5641,18 @@ export class Compiler extends DiagnosticEmitter { // Cares about garbage bits on the RHS, but only for types smaller than 5 bits var module = this.module; switch (type.kind) { - case TypeKind.BOOL: { - rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); - // falls through - } + case TypeKind.BOOL: return leftExpr; case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: - case TypeKind.U16: + case TypeKind.U16: { + // leftExpr << (rightExpr & (7|15)) + return module.binary( + BinaryOp.ShlI32, + leftExpr, + module.binary(BinaryOp.AndI32, rightExpr, module.i32(type.size - 1)) + ); + } case TypeKind.I32: case TypeKind.U32: { return module.binary(BinaryOp.ShlI32, leftExpr, rightExpr); @@ -5677,10 +5681,24 @@ export class Compiler extends DiagnosticEmitter { // and signedness var module = this.module; switch (type.kind) { + case TypeKind.BOOL: return leftExpr; case TypeKind.I8: case TypeKind.I16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); - // falls through + // leftExpr >> (rightExpr & (7|15)) + return module.binary( + BinaryOp.ShrI32, + this.ensureSmallIntegerWrap(leftExpr, type), + module.binary(BinaryOp.AndI32, rightExpr, module.i32(type.size - 1)) + ); + } + case TypeKind.U8: + case TypeKind.U16: { + // leftExpr >>> (rightExpr & (7|15)) + return module.binary( + BinaryOp.ShrU32, + this.ensureSmallIntegerWrap(leftExpr, type), + module.binary(BinaryOp.AndI32, rightExpr, module.i32(type.size - 1)) + ); } case TypeKind.I32: { return module.binary(BinaryOp.ShrI32, leftExpr, rightExpr); @@ -5697,15 +5715,6 @@ export class Compiler extends DiagnosticEmitter { rightExpr ); } - case TypeKind.BOOL: { - rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); - // falls through - } - case TypeKind.U8: - case TypeKind.U16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); - // falls through - } case TypeKind.U32: { return module.binary(BinaryOp.ShrU32, leftExpr, rightExpr); } @@ -5730,16 +5739,17 @@ export class Compiler extends DiagnosticEmitter { // Cares about garbage bits on the LHS, but on the RHS only for types smaller than 5 bits var module = this.module; switch (type.kind) { - case TypeKind.BOOL: { - rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); - // falls through - } + case TypeKind.BOOL: return leftExpr; case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: case TypeKind.U16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); - // falls through + // leftExpr >>> (rightExpr & (7|15)) + return module.binary( + BinaryOp.ShrU32, + this.ensureSmallIntegerWrap(leftExpr, type), + module.binary(BinaryOp.AndI32, rightExpr, module.i32(type.size - 1)) + ); } case TypeKind.I32: case TypeKind.U32: { diff --git a/tests/compiler/abi.untouched.wat b/tests/compiler/abi.untouched.wat index f540d255b1..d87a34b2b3 100644 --- a/tests/compiler/abi.untouched.wat +++ b/tests/compiler/abi.untouched.wat @@ -88,6 +88,8 @@ i32.const 24 i32.shr_s i32.const 24 + i32.const 7 + i32.and i32.shr_s local.set $0 else diff --git a/tests/compiler/retain-i32.ts b/tests/compiler/retain-i32.ts index 5484c06c1b..4065eb74da 100644 --- a/tests/compiler/retain-i32.ts +++ b/tests/compiler/retain-i32.ts @@ -7,7 +7,7 @@ function test(a: u32, b: u32): void { assert((a & b) == (a & b)); assert((a | b) == (a | b)); assert((a ^ b) == (a ^ b)); - assert((a << b) == (a << b)); + assert((a << (b & 7)) == (a << b)); // unsigned assert((a + b) == (a + b)); @@ -16,7 +16,7 @@ function test(a: u32, b: u32): void { assert((a & b) == (a & b)); assert((a | b) == (a | b)); assert((a ^ b) == (a ^ b)); - assert((a << b) == (a << b)); + assert((a << (b & 7)) == (a << b)); } // signed diff --git a/tests/compiler/retain-i32.untouched.wat b/tests/compiler/retain-i32.untouched.wat index a096fb55d4..215c53523c 100644 --- a/tests/compiler/retain-i32.untouched.wat +++ b/tests/compiler/retain-i32.untouched.wat @@ -167,6 +167,8 @@ end local.get $0 local.get $1 + i32.const 7 + i32.and i32.shl i32.const 24 i32.shl @@ -174,6 +176,8 @@ i32.shr_s local.get $0 local.get $1 + i32.const 7 + i32.and i32.shl i32.const 24 i32.shl @@ -311,11 +315,15 @@ end local.get $0 local.get $1 + i32.const 7 + i32.and i32.shl i32.const 255 i32.and local.get $0 local.get $1 + i32.const 7 + i32.and i32.shl i32.const 255 i32.and diff --git a/tests/compiler/std/dataview.untouched.wat b/tests/compiler/std/dataview.untouched.wat index cf9f905ef2..c7acb9845a 100644 --- a/tests/compiler/std/dataview.untouched.wat +++ b/tests/compiler/std/dataview.untouched.wat @@ -2124,6 +2124,8 @@ drop local.get $0 i32.const 8 + i32.const 15 + i32.and i32.shl local.get $0 i32.const 16 @@ -2131,6 +2133,8 @@ i32.const 16 i32.shr_s i32.const 8 + i32.const 15 + i32.and i32.shr_s i32.const 255 i32.and @@ -2344,11 +2348,15 @@ drop local.get $0 i32.const 8 + i32.const 15 + i32.and i32.shl local.get $0 i32.const 65535 i32.and i32.const 8 + i32.const 15 + i32.and i32.shr_u i32.const 255 i32.and diff --git a/tests/compiler/std/polyfills.untouched.wat b/tests/compiler/std/polyfills.untouched.wat index 966b7ef0aa..efe857cedb 100644 --- a/tests/compiler/std/polyfills.untouched.wat +++ b/tests/compiler/std/polyfills.untouched.wat @@ -54,11 +54,15 @@ drop local.get $0 i32.const 8 + i32.const 15 + i32.and i32.shl local.get $0 i32.const 65535 i32.and i32.const 8 + i32.const 15 + i32.and i32.shr_u i32.const 255 i32.and @@ -74,6 +78,8 @@ drop local.get $0 i32.const 8 + i32.const 15 + i32.and i32.shl local.get $0 i32.const 16 @@ -81,6 +87,8 @@ i32.const 16 i32.shr_s i32.const 8 + i32.const 15 + i32.and i32.shr_s i32.const 255 i32.and @@ -347,11 +355,15 @@ drop local.get $0 i32.const 8 + i32.const 15 + i32.and i32.shl local.get $0 i32.const 65535 i32.and i32.const 8 + i32.const 15 + i32.and i32.shr_u i32.const 255 i32.and @@ -374,6 +386,8 @@ drop local.get $0 i32.const 8 + i32.const 15 + i32.and i32.shl local.get $0 i32.const 16 @@ -381,6 +395,8 @@ i32.const 16 i32.shr_s i32.const 8 + i32.const 15 + i32.and i32.shr_s i32.const 255 i32.and