diff --git a/src/builtins.ts b/src/builtins.ts index 359950b739..810aea92e1 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -1158,15 +1158,8 @@ function builtin_clz(ctx: BuiltinContext): ExpressionRef { case TypeKind.U16: case TypeKind.I32: case TypeKind.U32: return module.unary(UnaryOp.ClzI32, arg0); - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.unary( - compiler.options.isWasm64 - ? UnaryOp.ClzI64 - : UnaryOp.ClzI32, - arg0 - ); - } + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.unary(UnaryOp.ClzSize, arg0); case TypeKind.I64: case TypeKind.U64: return module.unary(UnaryOp.ClzI64, arg0); } @@ -1202,15 +1195,8 @@ function builtin_ctz(ctx: BuiltinContext): ExpressionRef { case TypeKind.U16: case TypeKind.I32: case TypeKind.U32: return module.unary(UnaryOp.CtzI32, arg0); - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.unary( - compiler.options.isWasm64 - ? UnaryOp.CtzI64 - : UnaryOp.CtzI32, - arg0 - ); - } + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.unary(UnaryOp.CtzSize, arg0); case TypeKind.I64: case TypeKind.U64: return module.unary(UnaryOp.CtzI64, arg0); } @@ -1249,14 +1235,7 @@ function builtin_popcnt(ctx: BuiltinContext): ExpressionRef { case TypeKind.I64: case TypeKind.U64: return module.unary(UnaryOp.PopcntI64, arg0); case TypeKind.ISIZE: - case TypeKind.USIZE: { - return module.unary( - compiler.options.isWasm64 - ? UnaryOp.PopcntI64 - : UnaryOp.PopcntI32, - arg0 - ); - } + case TypeKind.USIZE: return module.unary(UnaryOp.PopcntSize, arg0); } } compiler.error( @@ -1327,17 +1306,10 @@ function builtin_rotl(ctx: BuiltinContext): ExpressionRef { } case TypeKind.I32: case TypeKind.U32: return module.binary(BinaryOp.RotlI32, arg0, arg1); - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - compiler.options.isWasm64 - ? BinaryOp.RotlI64 - : BinaryOp.RotlI32, - arg0, arg1 - ); - } case TypeKind.I64: case TypeKind.U64: return module.binary(BinaryOp.RotlI64, arg0, arg1); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.RotlSize, arg0, arg1); } } compiler.error( @@ -1408,17 +1380,10 @@ function builtin_rotr(ctx: BuiltinContext): ExpressionRef { } case TypeKind.I32: case TypeKind.U32: return module.binary(BinaryOp.RotrI32, arg0, arg1); - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - compiler.options.isWasm64 - ? BinaryOp.RotrI64 - : BinaryOp.RotrI32, - arg0, arg1 - ); - } case TypeKind.I64: case TypeKind.U64: return module.binary(BinaryOp.RotrI64, arg0, arg1); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.RotrSize, arg0, arg1); } } compiler.error( @@ -1445,6 +1410,12 @@ function builtin_abs(ctx: BuiltinContext): ExpressionRef { var type = compiler.currentType; if (type.isValue) { switch (type.kind) { + case TypeKind.BOOL: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: return arg0; case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: { @@ -1475,17 +1446,18 @@ function builtin_abs(ctx: BuiltinContext): ExpressionRef { case TypeKind.ISIZE: { let options = compiler.options; let flow = compiler.currentFlow; - let isWasm64 = options.isWasm64; let temp1 = flow.getTempLocal(options.usizeType); let temp2 = flow.getTempLocal(options.usizeType); - let ret = module.binary(isWasm64 ? BinaryOp.XorI64 : BinaryOp.XorI32, - module.binary(isWasm64 ? BinaryOp.AddI64 : BinaryOp.AddI32, + let ret = module.binary(BinaryOp.XorSize, + module.binary(BinaryOp.AddSize, module.local_tee( temp2.index, - module.binary(isWasm64 ? BinaryOp.ShrI64 : BinaryOp.ShrI32, + module.binary(BinaryOp.ShrISize, module.local_tee(temp1.index, arg0, false), // i32/i64 - isWasm64 ? module.i64(63) : module.i32(31) + compiler.options.isWasm64 + ? module.i64(63) + : module.i32(31) ), false // i32/i64 ), @@ -1521,12 +1493,6 @@ function builtin_abs(ctx: BuiltinContext): ExpressionRef { flow.freeTempLocal(temp1); return ret; } - case TypeKind.USIZE: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.U32: - case TypeKind.U64: - case TypeKind.BOOL: return arg0; case TypeKind.F32: return module.unary(UnaryOp.AbsF32, arg0); case TypeKind.F64: return module.unary(UnaryOp.AbsF64, arg0); } @@ -1568,25 +1534,15 @@ function builtin_max(ctx: BuiltinContext): ExpressionRef { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: - case TypeKind.I32: { op = BinaryOp.GtI32; break; } + case TypeKind.I32: { op = BinaryOp.GtI32; break; } + case TypeKind.BOOL: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { op = BinaryOp.GtU32; break; } - case TypeKind.I64: { op = BinaryOp.GtI64; break; } - case TypeKind.U64: { op = BinaryOp.GtU64; break; } - case TypeKind.ISIZE: { - op = compiler.options.isWasm64 - ? BinaryOp.GtI64 - : BinaryOp.GtI32; - break; - } - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? BinaryOp.GtU64 - : BinaryOp.GtU32; - break; - } + case TypeKind.U32: { op = BinaryOp.GtU32; break; } + case TypeKind.I64: { op = BinaryOp.GtI64; break; } + case TypeKind.U64: { op = BinaryOp.GtU64; break; } + case TypeKind.ISIZE: { op = BinaryOp.GtISize; break; } + case TypeKind.USIZE: { op = BinaryOp.GtUSize; break; } case TypeKind.F32: return module.binary(BinaryOp.MaxF32, arg0, arg1); case TypeKind.F64: return module.binary(BinaryOp.MaxF64, arg0, arg1); } @@ -1648,25 +1604,15 @@ function builtin_min(ctx: BuiltinContext): ExpressionRef { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: - case TypeKind.I32: { op = BinaryOp.LtI32; break; } + case TypeKind.I32: { op = BinaryOp.LtI32; break; } + case TypeKind.BOOL: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { op = BinaryOp.LtU32; break; } - case TypeKind.I64: { op = BinaryOp.LtI64; break; } - case TypeKind.U64: { op = BinaryOp.LtU64; break; } - case TypeKind.ISIZE: { - op = compiler.options.isWasm64 - ? BinaryOp.LtI64 - : BinaryOp.LtI32; - break; - } - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? BinaryOp.LtU64 - : BinaryOp.LtU32; - break; - } + case TypeKind.U32: { op = BinaryOp.LtU32; break; } + case TypeKind.I64: { op = BinaryOp.LtI64; break; } + case TypeKind.U64: { op = BinaryOp.LtU64; break; } + case TypeKind.ISIZE: { op = BinaryOp.LtISize; break; } + case TypeKind.USIZE: { op = BinaryOp.LtUSize; break; } case TypeKind.F32: return module.binary(BinaryOp.MinF32, arg0, arg1); case TypeKind.F64: return module.binary(BinaryOp.MinF64, arg0, arg1); } @@ -1715,6 +1661,7 @@ function builtin_ceil(ctx: BuiltinContext): ExpressionRef { var type = compiler.currentType; if (type.isValue) { switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: @@ -1724,8 +1671,7 @@ function builtin_ceil(ctx: BuiltinContext): ExpressionRef { case TypeKind.U16: case TypeKind.U32: case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.BOOL: return arg0; // considered rounded + case TypeKind.USIZE: return arg0; // considered rounded case TypeKind.F32: return module.unary(UnaryOp.CeilF32, arg0); case TypeKind.F64: return module.unary(UnaryOp.CeilF64, arg0); } @@ -1754,6 +1700,7 @@ function builtin_floor(ctx: BuiltinContext): ExpressionRef { var type = compiler.currentType; if (type.isValue) { switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: @@ -1763,8 +1710,7 @@ function builtin_floor(ctx: BuiltinContext): ExpressionRef { case TypeKind.U16: case TypeKind.U32: case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.BOOL: return arg0; // considered rounded + case TypeKind.USIZE: return arg0; // considered rounded case TypeKind.F32: return module.unary(UnaryOp.FloorF32, arg0); case TypeKind.F64: return module.unary(UnaryOp.FloorF64, arg0); } @@ -1823,6 +1769,7 @@ function builtin_nearest(ctx: BuiltinContext): ExpressionRef { var type = compiler.currentType; if (type.isValue) { switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: @@ -1832,8 +1779,7 @@ function builtin_nearest(ctx: BuiltinContext): ExpressionRef { case TypeKind.U16: case TypeKind.U32: case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.BOOL: return arg0; + case TypeKind.USIZE: return arg0; case TypeKind.F32: return module.unary(UnaryOp.NearestF32, arg0); case TypeKind.F64: return module.unary(UnaryOp.NearestF64, arg0); } @@ -1873,15 +1819,14 @@ function builtin_reinterpret(ctx: BuiltinContext): ExpressionRef { } case TypeKind.ISIZE: case TypeKind.USIZE: { + let isWasm64 = compiler.options.isWasm64; let arg0 = compiler.compileExpression(operands[0], - compiler.options.isWasm64 - ? Type.f64 - : Type.f32, + isWasm64 ? Type.f64 : Type.f32, Constraints.CONV_IMPLICIT ); compiler.currentType = type; return module.unary( - compiler.options.isWasm64 + isWasm64 ? UnaryOp.ReinterpretF64ToI64 : UnaryOp.ReinterpretF32ToI32, arg0 @@ -1952,6 +1897,7 @@ function builtin_trunc(ctx: BuiltinContext): ExpressionRef { var type = compiler.currentType; if (type.isValue) { switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: @@ -1961,8 +1907,7 @@ function builtin_trunc(ctx: BuiltinContext): ExpressionRef { case TypeKind.U16: case TypeKind.U32: case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.BOOL: return arg0; // considered truncated + case TypeKind.USIZE: return arg0; // considered truncated case TypeKind.F32: return module.unary(UnaryOp.TruncF32, arg0); case TypeKind.F64: return module.unary(UnaryOp.TruncF64, arg0); } @@ -3321,27 +3266,17 @@ function builtin_assert(ctx: BuiltinContext): ExpressionRef { if (contextualType == Type.void) { // simplify if dropped anyway compiler.currentType = Type.void; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: return module.if(module.unary(UnaryOp.EqzI32, arg0), abort); + case TypeKind.U32: return module.if(module.unary(UnaryOp.EqzI32, arg0), abort); case TypeKind.I64: case TypeKind.U64: return module.if(module.unary(UnaryOp.EqzI64, arg0), abort); case TypeKind.ISIZE: - case TypeKind.USIZE: { - return module.if( - module.unary( - compiler.options.isWasm64 - ? UnaryOp.EqzI64 - : UnaryOp.EqzI32, - arg0 - ), - abort - ); - } + case TypeKind.USIZE: return module.if(module.unary(UnaryOp.EqzSize, arg0), abort); // TODO: also check for NaN in float assertions, as in `Boolean(NaN) -> false`? case TypeKind.F32: return module.if(module.binary(BinaryOp.EqF32, arg0, module.f32(0)), abort); case TypeKind.F64: return module.if(module.binary(BinaryOp.EqF64, arg0, module.f64(0)), abort); @@ -3357,13 +3292,13 @@ function builtin_assert(ctx: BuiltinContext): ExpressionRef { compiler.currentType = type.nonNullableType; let flow = compiler.currentFlow; switch (compiler.currentType.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { + case TypeKind.U32: { let temp = flow.getTempLocal(type); flow.setLocalFlag(temp.index, LocalFlags.WRAPPED); // arg0 is wrapped let ret = module.if( @@ -3392,9 +3327,7 @@ function builtin_assert(ctx: BuiltinContext): ExpressionRef { let temp = flow.getTempLocal(compiler.options.usizeType); let ret = module.if( module.unary( - compiler.options.isWasm64 - ? UnaryOp.EqzI64 - : UnaryOp.EqzI32, + UnaryOp.EqzSize, module.local_tee(temp.index, arg0, type.isManaged) ), abort, @@ -4499,7 +4432,16 @@ function builtin_v128_load_zero(ctx: BuiltinContext): ExpressionRef { case TypeKind.U64: case TypeKind.F64: return module.simd_load(SIMDLoadOp.Load64Zero, arg0, immOffset, immAlign); case TypeKind.ISIZE: - case TypeKind.USIZE: return module.simd_load(compiler.options.isWasm64 ? SIMDLoadOp.Load64Zero : SIMDLoadOp.Load32Zero, arg0, immOffset, immAlign); + case TypeKind.USIZE: { + return module.simd_load( + compiler.options.isWasm64 + ? SIMDLoadOp.Load64Zero + : SIMDLoadOp.Load32Zero, + arg0, + immOffset, + immAlign + ); + } } } compiler.error( @@ -4574,7 +4516,18 @@ function builtin_v128_load_lane(ctx: BuiltinContext): ExpressionRef { case TypeKind.U64: case TypeKind.F64: return module.simd_loadstorelane(SIMDLoadStoreLaneOp.Load64Lane, arg0, immOffset, immAlign, idx, arg1); case TypeKind.ISIZE: - case TypeKind.USIZE: return module.simd_loadstorelane(compiler.options.isWasm64 ? SIMDLoadStoreLaneOp.Load64Lane : SIMDLoadStoreLaneOp.Load32Lane, arg0, immOffset, immAlign, idx, arg1); + case TypeKind.USIZE: { + return module.simd_loadstorelane( + compiler.options.isWasm64 + ? SIMDLoadStoreLaneOp.Load64Lane + : SIMDLoadStoreLaneOp.Load32Lane, + arg0, + immOffset, + immAlign, + idx, + arg1 + ); + } } } compiler.error( @@ -4649,7 +4602,18 @@ function builtin_v128_store_lane(ctx: BuiltinContext): ExpressionRef { case TypeKind.U64: case TypeKind.F64: return module.simd_loadstorelane(SIMDLoadStoreLaneOp.Store64Lane, arg0, immOffset, immAlign, idx, arg1); case TypeKind.ISIZE: - case TypeKind.USIZE: return module.simd_loadstorelane(compiler.options.isWasm64 ? SIMDLoadStoreLaneOp.Store64Lane : SIMDLoadStoreLaneOp.Store32Lane, arg0, immOffset, immAlign, idx, arg1); + case TypeKind.USIZE: { + return module.simd_loadstorelane( + compiler.options.isWasm64 + ? SIMDLoadStoreLaneOp.Store64Lane + : SIMDLoadStoreLaneOp.Store32Lane, + arg0, + immOffset, + immAlign, + idx, + arg1 + ); + } } } compiler.error( @@ -6102,7 +6066,12 @@ function builtin_v128_all_true(ctx: BuiltinContext): ExpressionRef { case TypeKind.U64: return module.unary(UnaryOp.AllTrueI64x2, arg0); case TypeKind.ISIZE: case TypeKind.USIZE: { - return module.unary(compiler.options.isWasm64 ? UnaryOp.AllTrueI64x2 : UnaryOp.AllTrueI32x4, arg0); + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.AllTrueI64x2 + : UnaryOp.AllTrueI32x4, + arg0 + ); } } } @@ -6141,7 +6110,14 @@ function builtin_v128_bitmask(ctx: BuiltinContext): ExpressionRef { case TypeKind.I64: case TypeKind.U64: return module.unary(UnaryOp.BitmaskI64x2, arg0); case TypeKind.ISIZE: - case TypeKind.USIZE: return module.unary(compiler.options.isWasm64 ? UnaryOp.BitmaskI64x2 : UnaryOp.BitmaskI32x4, arg0); + case TypeKind.USIZE: { + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.BitmaskI64x2 + : UnaryOp.BitmaskI32x4, + arg0 + ); + } } } compiler.error( diff --git a/src/compiler.ts b/src/compiler.ts index c5741d2436..0ebc4aac19 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -489,11 +489,11 @@ export class Compiler extends DiagnosticEmitter { // add mutable data, heap and rtti offset dummies if (options.isWasm64) { - module.addGlobal(BuiltinNames.data_end, TypeRef.I64, true, module.i64(0)); + module.addGlobal(BuiltinNames.data_end, TypeRef.I64, true, module.i64(0)); module.addGlobal(BuiltinNames.heap_base, TypeRef.I64, true, module.i64(0)); module.addGlobal(BuiltinNames.rtti_base, TypeRef.I64, true, module.i64(0)); } else { - module.addGlobal(BuiltinNames.data_end, TypeRef.I32, true, module.i32(0)); + module.addGlobal(BuiltinNames.data_end, TypeRef.I32, true, module.i32(0)); module.addGlobal(BuiltinNames.heap_base, TypeRef.I32, true, module.i32(0)); module.addGlobal(BuiltinNames.rtti_base, TypeRef.I32, true, module.i32(0)); } @@ -957,7 +957,7 @@ export class Compiler extends DiagnosticEmitter { element.identifierNode.range ); } - + // files /** Compiles the file matching the specified path. */ @@ -4622,53 +4622,25 @@ export class Compiler extends DiagnosticEmitter { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.I32: { - return module.binary(BinaryOp.LtI32, leftExpr, rightExpr); - } - case TypeKind.I64: { - return module.binary(BinaryOp.LtI64, leftExpr, rightExpr); - } - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.LtI64 - : BinaryOp.LtI32, - leftExpr, - rightExpr - ); - } + case TypeKind.I32: return module.binary(BinaryOp.LtI32, leftExpr, rightExpr); + case TypeKind.I64: return module.binary(BinaryOp.LtI64, leftExpr, rightExpr); + case TypeKind.ISIZE: return module.binary(BinaryOp.LtISize, leftExpr, rightExpr); + case TypeKind.BOOL: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.U32: { - return module.binary(BinaryOp.LtU32, leftExpr, rightExpr); - } - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.LtU64 - : BinaryOp.LtU32, - leftExpr, - rightExpr - ); - } - case TypeKind.U64: { - return module.binary(BinaryOp.LtU64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.LtF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.LtF64, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.LtU32, leftExpr, rightExpr); + case TypeKind.U64: return module.binary(BinaryOp.LtU64, leftExpr, rightExpr); + case TypeKind.USIZE: return module.binary(BinaryOp.LtUSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.LtF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.LtF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -4680,53 +4652,25 @@ export class Compiler extends DiagnosticEmitter { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.I32: { - return module.binary(BinaryOp.GtI32, leftExpr, rightExpr); - } - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.GtI64 - : BinaryOp.GtI32, - leftExpr, - rightExpr - ); - } - case TypeKind.I64: { - return module.binary(BinaryOp.GtI64, leftExpr, rightExpr); - } + case TypeKind.I32: return module.binary(BinaryOp.GtI32, leftExpr, rightExpr); + case TypeKind.I64: return module.binary(BinaryOp.GtI64, leftExpr, rightExpr); + case TypeKind.ISIZE: return module.binary(BinaryOp.GtISize, leftExpr, rightExpr); + case TypeKind.BOOL: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.U32: { - return module.binary(BinaryOp.GtU32, leftExpr, rightExpr); - } - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.GtU64 - : BinaryOp.GtU32, - leftExpr, - rightExpr - ); - } - case TypeKind.U64: { - return module.binary(BinaryOp.GtU64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.GtF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.GtF64, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.GtU32, leftExpr, rightExpr); + case TypeKind.U64: return module.binary(BinaryOp.GtU64, leftExpr, rightExpr); + case TypeKind.USIZE: return module.binary(BinaryOp.GtUSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.GtF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.GtF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -4738,53 +4682,25 @@ export class Compiler extends DiagnosticEmitter { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.I32: { - return module.binary(BinaryOp.LeI32, leftExpr, rightExpr); - } - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.LeI64 - : BinaryOp.LeI32, - leftExpr, - rightExpr - ); - } - case TypeKind.I64: { - return module.binary(BinaryOp.LeI64, leftExpr, rightExpr); - } + case TypeKind.I32: return module.binary(BinaryOp.LeI32, leftExpr, rightExpr); + case TypeKind.I64: return module.binary(BinaryOp.LeI64, leftExpr, rightExpr); + case TypeKind.ISIZE: return module.binary(BinaryOp.LeISize, leftExpr, rightExpr); + case TypeKind.BOOL: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.U32: { - return module.binary(BinaryOp.LeU32, leftExpr, rightExpr); - } - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.LeU64 - : BinaryOp.LeU32, - leftExpr, - rightExpr - ); - } - case TypeKind.U64: { - return module.binary(BinaryOp.LeU64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.LeF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.LeF64, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.LeU32, leftExpr, rightExpr); + case TypeKind.U64: return module.binary(BinaryOp.LeU64, leftExpr, rightExpr); + case TypeKind.USIZE: return module.binary(BinaryOp.LeUSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.LeF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.LeF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -4796,53 +4712,25 @@ export class Compiler extends DiagnosticEmitter { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.I32: { - return module.binary(BinaryOp.GeI32, leftExpr, rightExpr); - } - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.GeI64 - : BinaryOp.GeI32, - leftExpr, - rightExpr - ); - } - case TypeKind.I64: { - return module.binary(BinaryOp.GeI64, leftExpr, rightExpr); - } + case TypeKind.I32: return module.binary(BinaryOp.GeI32, leftExpr, rightExpr); + case TypeKind.I64: return module.binary(BinaryOp.GeI64, leftExpr, rightExpr); + case TypeKind.ISIZE: return module.binary(BinaryOp.GeISize, leftExpr, rightExpr); + case TypeKind.BOOL: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.U32: { - return module.binary(BinaryOp.GeU32, leftExpr, rightExpr); - } - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.GeU64 - : BinaryOp.GeU32, - leftExpr, - rightExpr - ); - } - case TypeKind.U64: { - return module.binary(BinaryOp.GeU64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.GeF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.GeF64, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.GeU32, leftExpr, rightExpr); + case TypeKind.U64: return module.binary(BinaryOp.GeU64, leftExpr, rightExpr); + case TypeKind.USIZE: return module.binary(BinaryOp.GeUSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.GeF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.GeF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -4852,39 +4740,23 @@ export class Compiler extends DiagnosticEmitter { // Cares about garbage bits var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.EqI32, leftExpr, rightExpr); - } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.EqI64 - : BinaryOp.EqI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U32: return module.binary(BinaryOp.EqI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.EqI64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.EqF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.EqF64, leftExpr, rightExpr); - } + case TypeKind.U64: return module.binary(BinaryOp.EqI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.EqSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.EqF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.EqF64, leftExpr, rightExpr); case TypeKind.V128: { return module.unary(UnaryOp.AllTrueI8x16, module.binary(BinaryOp.EqI8x16, leftExpr, rightExpr) @@ -4892,9 +4764,7 @@ export class Compiler extends DiagnosticEmitter { } case TypeKind.EQREF: case TypeKind.I31REF: - case TypeKind.DATAREF: { - return module.ref_eq(leftExpr, rightExpr); - } + case TypeKind.DATAREF: return module.ref_eq(leftExpr, rightExpr); case TypeKind.FUNCREF: case TypeKind.EXTERNREF: case TypeKind.ANYREF: { @@ -4915,39 +4785,23 @@ export class Compiler extends DiagnosticEmitter { // Cares about garbage bits var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.NeI32, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.NeI64 - : BinaryOp.NeI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U32: return module.binary(BinaryOp.NeI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.NeI64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.NeF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.NeF64, leftExpr, rightExpr); - } + case TypeKind.U64: return module.binary(BinaryOp.NeI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.NeSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.NeF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.NeF64, leftExpr, rightExpr); case TypeKind.V128: { return module.unary(UnaryOp.AnyTrueV128, module.binary(BinaryOp.NeI8x16, leftExpr, rightExpr) @@ -4980,35 +4834,19 @@ export class Compiler extends DiagnosticEmitter { // Does not care about garbage bits or signedness var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: case TypeKind.U16: - case TypeKind.BOOL: case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.AddI32, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.AddI64 - : BinaryOp.AddI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U32: return module.binary(BinaryOp.AddI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.AddI64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.AddF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.AddF64, leftExpr, rightExpr); - } + case TypeKind.U64: return module.binary(BinaryOp.AddI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.AddSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.AddF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.AddF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5018,35 +4856,19 @@ export class Compiler extends DiagnosticEmitter { // Does not care about garbage bits or signedness var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: case TypeKind.U16: - case TypeKind.BOOL: case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.SubI32, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.SubI64 - : BinaryOp.SubI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U32: return module.binary(BinaryOp.SubI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.SubI64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.SubF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.SubF64, leftExpr, rightExpr); - } + case TypeKind.U64: return module.binary(BinaryOp.SubI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.SubSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.SubF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.SubF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5056,35 +4878,19 @@ export class Compiler extends DiagnosticEmitter { // Does not care about garbage bits or signedness var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: case TypeKind.U16: - case TypeKind.BOOL: case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.MulI32, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.MulI64 - : BinaryOp.MulI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U32: return module.binary(BinaryOp.MulI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.MulI64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.MulF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.MulF64, leftExpr, rightExpr); - } + case TypeKind.U64: return module.binary(BinaryOp.MulI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.MulSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.MulF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.MulF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5106,7 +4912,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.U8: case TypeKind.I16: case TypeKind.U16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } @@ -5116,10 +4922,10 @@ export class Compiler extends DiagnosticEmitter { // Precompute power if LHS and RHS constants // TODO: move this optimization to AIR if ( - getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(leftExpr) == ExpressionId.Const && getExpressionId(rightExpr) == ExpressionId.Const ) { - let leftValue = getConstValueI32(leftExpr); + let leftValue = getConstValueI32(leftExpr); let rightValue = getConstValueI32(rightExpr); this.currentType = type; return module.i32(i64_low(i64_pow( @@ -5197,13 +5003,13 @@ export class Compiler extends DiagnosticEmitter { getExpressionId(rightExpr) == ExpressionId.Const ) { if (isWasm64) { - let leftValue = i64_new(getConstValueI64Low(leftExpr), getConstValueI64High(leftExpr)); + let leftValue = i64_new(getConstValueI64Low(leftExpr), getConstValueI64High(leftExpr)); let rightValue = i64_new(getConstValueI64Low(rightExpr), getConstValueI64High(rightExpr)); let result = i64_pow(leftValue, rightValue); this.currentType = type; return module.i64(i64_low(result), i64_high(result)); } else { - let leftValue = getConstValueI32(leftExpr); + let leftValue = getConstValueI32(leftExpr); let rightValue = getConstValueI32(rightExpr); this.currentType = type; return module.i32(i64_low(i64_pow( @@ -5213,9 +5019,14 @@ export class Compiler extends DiagnosticEmitter { } } } - let instance = isWasm64 ? this.i64PowInstance : this.i32PowInstance; + let instance = isWasm64 + ? this.i64PowInstance + : this.i32PowInstance; if (!instance) { - let prototype = this.program.lookup(isWasm64 ? CommonNames.ipow64 : CommonNames.ipow32); + let prototype = this.program.lookup(isWasm64 + ? CommonNames.ipow64 + : CommonNames.ipow32 + ); if (!prototype) { this.error( DiagnosticCode.Cannot_find_name_0, @@ -5241,10 +5052,10 @@ export class Compiler extends DiagnosticEmitter { // Precompute power if LHS and RHS constants // TODO: move this optimization to AIR if ( - getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(leftExpr) == ExpressionId.Const && getExpressionId(rightExpr) == ExpressionId.Const ) { - let leftValue = getConstValueF32(leftExpr); + let leftValue = getConstValueF32(leftExpr); let rightValue = getConstValueF32(rightExpr); this.currentType = type; return module.f32(f32(accuratePow64(leftValue, rightValue))); @@ -5283,10 +5094,10 @@ export class Compiler extends DiagnosticEmitter { // Precompute power if LHS and RHS constants // TODO: move this optimization to AIR if ( - getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(leftExpr) == ExpressionId.Const && getExpressionId(rightExpr) == ExpressionId.Const ) { - let leftValue = getConstValueF64(leftExpr); + let leftValue = getConstValueF64(leftExpr); let rightValue = getConstValueF64(rightExpr); this.currentType = type; return module.f64(accuratePow64(leftValue, rightValue)); @@ -5330,53 +5141,25 @@ export class Compiler extends DiagnosticEmitter { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.I32: { - return module.binary(BinaryOp.DivI32, leftExpr, rightExpr); - } - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.DivI64 - : BinaryOp.DivI32, - leftExpr, - rightExpr - ); - } - case TypeKind.I64: { - return module.binary(BinaryOp.DivI64, leftExpr, rightExpr); - } + case TypeKind.I32: return module.binary(BinaryOp.DivI32, leftExpr, rightExpr); + case TypeKind.I64: return module.binary(BinaryOp.DivI64, leftExpr, rightExpr); + case TypeKind.ISIZE: return module.binary(BinaryOp.DivISize, leftExpr, rightExpr); + case TypeKind.BOOL: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.U32: { - return module.binary(BinaryOp.DivU32, leftExpr, rightExpr); - } - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.DivU64 - : BinaryOp.DivU32, - leftExpr, - rightExpr - ); - } - case TypeKind.U64: { - return module.binary(BinaryOp.DivU64, leftExpr, rightExpr); - } - case TypeKind.F32: { - return module.binary(BinaryOp.DivF32, leftExpr, rightExpr); - } - case TypeKind.F64: { - return module.binary(BinaryOp.DivF64, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.DivU32, leftExpr, rightExpr); + case TypeKind.U64: return module.binary(BinaryOp.DivU64, leftExpr, rightExpr); + case TypeKind.USIZE: return module.binary(BinaryOp.DivUSize, leftExpr, rightExpr); + case TypeKind.F32: return module.binary(BinaryOp.DivF32, leftExpr, rightExpr); + case TypeKind.F64: return module.binary(BinaryOp.DivF64, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5388,47 +5171,23 @@ export class Compiler extends DiagnosticEmitter { switch (type.kind) { case TypeKind.I8: case TypeKind.I16: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.I32: { - return module.binary(BinaryOp.RemI32, leftExpr, rightExpr); - } - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.RemI64 - : BinaryOp.RemI32, - leftExpr, - rightExpr - ); - } - case TypeKind.I64: { - return module.binary(BinaryOp.RemI64, leftExpr, rightExpr); - } + case TypeKind.I32: return module.binary(BinaryOp.RemI32, leftExpr, rightExpr); + case TypeKind.I64: return module.binary(BinaryOp.RemI64, leftExpr, rightExpr); + case TypeKind.ISIZE: return module.binary(BinaryOp.RemISize, leftExpr, rightExpr); + case TypeKind.BOOL: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); + case TypeKind.U16: { + leftExpr = this.ensureSmallIntegerWrap(leftExpr, type); rightExpr = this.ensureSmallIntegerWrap(rightExpr, type); // falls through } - case TypeKind.U32: { - return module.binary(BinaryOp.RemU32, leftExpr, rightExpr); - } - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.RemU64 - : BinaryOp.RemU32, - leftExpr, - rightExpr - ); - } - case TypeKind.U64: { - return module.binary(BinaryOp.RemU64, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.RemU32, leftExpr, rightExpr); + case TypeKind.U64: return module.binary(BinaryOp.RemU64, leftExpr, rightExpr); + case TypeKind.USIZE: return module.binary(BinaryOp.RemUSize, leftExpr, rightExpr); case TypeKind.F32: { let instance = this.f32ModInstance; if (!instance) { @@ -5503,27 +5262,19 @@ export class Compiler extends DiagnosticEmitter { return module.binary( BinaryOp.ShlI32, leftExpr, - module.binary(BinaryOp.AndI32, rightExpr, module.i32(type.size - 1)) + module.binary( + BinaryOp.AndI32, + rightExpr, + module.i32(type.size - 1) + ) ); } case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.ShlI32, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.ShlI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.ShlI64, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.ShlI64 - : BinaryOp.ShlI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U64: return module.binary(BinaryOp.ShlI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.ShlSize, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5541,7 +5292,11 @@ export class Compiler extends DiagnosticEmitter { return module.binary( BinaryOp.ShrI32, this.ensureSmallIntegerWrap(leftExpr, type), - module.binary(BinaryOp.AndI32, rightExpr, module.i32(type.size - 1)) + module.binary( + BinaryOp.AndI32, + rightExpr, + module.i32(type.size - 1) + ) ); } case TypeKind.U8: @@ -5550,39 +5305,19 @@ export class Compiler extends DiagnosticEmitter { 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); - } - case TypeKind.I64: { - return module.binary(BinaryOp.ShrI64, leftExpr, rightExpr); - } - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.ShrI64 - : BinaryOp.ShrI32, - leftExpr, - rightExpr - ); - } - case TypeKind.U32: { - return module.binary(BinaryOp.ShrU32, leftExpr, rightExpr); - } - case TypeKind.U64: { - return module.binary(BinaryOp.ShrU64, leftExpr, rightExpr); - } - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.ShrU64 - : BinaryOp.ShrU32, - leftExpr, - rightExpr + module.binary( + BinaryOp.AndI32, + rightExpr, + module.i32(type.size - 1) + ) ); } + case TypeKind.I32: return module.binary(BinaryOp.ShrI32, leftExpr, rightExpr); + case TypeKind.I64: return module.binary(BinaryOp.ShrI64, leftExpr, rightExpr); + case TypeKind.ISIZE: return module.binary(BinaryOp.ShrISize, leftExpr, rightExpr); + case TypeKind.U32: return module.binary(BinaryOp.ShrU32, leftExpr, rightExpr); + case TypeKind.U64: return module.binary(BinaryOp.ShrU64, leftExpr, rightExpr); + case TypeKind.USIZE: return module.binary(BinaryOp.ShrUSize, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5601,27 +5336,19 @@ export class Compiler extends DiagnosticEmitter { return module.binary( BinaryOp.ShrU32, this.ensureSmallIntegerWrap(leftExpr, type), - module.binary(BinaryOp.AndI32, rightExpr, module.i32(type.size - 1)) + module.binary( + BinaryOp.AndI32, + rightExpr, + module.i32(type.size - 1) + ) ); } case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.ShrU32, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.ShrU32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.ShrU64, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.ShrU64 - : BinaryOp.ShrU32, - leftExpr, - rightExpr - ); - } + case TypeKind.U64: return module.binary(BinaryOp.ShrU64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.ShrUSize, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5631,29 +5358,17 @@ export class Compiler extends DiagnosticEmitter { // Does not care about garbage bits or signedness var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.BOOL: - case TypeKind.U32: { - return module.binary(BinaryOp.AndI32, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.AndI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.AndI64, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.AndI64 - : BinaryOp.AndI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U64: return module.binary(BinaryOp.AndI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.AndSize, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5663,31 +5378,17 @@ export class Compiler extends DiagnosticEmitter { // Does not care about garbage bits or signedness var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - return module.binary(BinaryOp.OrI32, leftExpr, rightExpr); - } + case TypeKind.U16: return module.binary(BinaryOp.OrI32, leftExpr, rightExpr); case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.OrI32, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.OrI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.OrI64, leftExpr, rightExpr); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.OrI64 - : BinaryOp.OrI32, - leftExpr, - rightExpr - ); - } + case TypeKind.U64: return module.binary(BinaryOp.OrI64, leftExpr, rightExpr); + case TypeKind.ISIZE: + case TypeKind.USIZE: return module.binary(BinaryOp.OrSize, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -5697,31 +5398,17 @@ export class Compiler extends DiagnosticEmitter { // Does not care about garbage bits or signedness var module = this.module; switch (type.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - return module.binary(BinaryOp.XorI32, leftExpr, rightExpr); - } + case TypeKind.U16: return module.binary(BinaryOp.XorI32, leftExpr, rightExpr); case TypeKind.I32: - case TypeKind.U32: { - return module.binary(BinaryOp.XorI32, leftExpr, rightExpr); - } + case TypeKind.U32: return module.binary(BinaryOp.XorI32, leftExpr, rightExpr); case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.XorI64, leftExpr, rightExpr); - } + case TypeKind.U64: return module.binary(BinaryOp.XorI64, leftExpr, rightExpr); case TypeKind.ISIZE: - case TypeKind.USIZE: { - return module.binary( - this.options.isWasm64 - ? BinaryOp.XorI64 - : BinaryOp.XorI32, - leftExpr, - rightExpr - ); - } + case TypeKind.USIZE: return module.binary(BinaryOp.XorSize, leftExpr, rightExpr); } assert(false); return module.unreachable(); @@ -8695,6 +8382,7 @@ export class Compiler extends DiagnosticEmitter { switch (fieldType.kind) { // Number Types (and Number alias types) + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: @@ -8705,7 +8393,6 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.U32: case TypeKind.U64: case TypeKind.USIZE: - case TypeKind.BOOL: case TypeKind.F32: case TypeKind.F64: { exprs.push( @@ -9293,13 +8980,13 @@ export class Compiler extends DiagnosticEmitter { } switch (this.currentType.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { + case TypeKind.U32: { expr = module.binary( BinaryOp.AddI32, getValue, @@ -9307,24 +8994,21 @@ export class Compiler extends DiagnosticEmitter { ); break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - let options = this.options; + case TypeKind.I64: + case TypeKind.U64: { expr = module.binary( - options.isWasm64 - ? BinaryOp.AddI64 - : BinaryOp.AddI32, + BinaryOp.AddI64, getValue, - this.makeOne(this.currentType) + module.i64(1) ); break; } - case TypeKind.I64: - case TypeKind.U64: { + case TypeKind.ISIZE: + case TypeKind.USIZE: { expr = module.binary( - BinaryOp.AddI64, + BinaryOp.AddSize, getValue, - module.i64(1) + this.makeOne(this.currentType) ); break; } @@ -9382,13 +9066,13 @@ export class Compiler extends DiagnosticEmitter { } switch (this.currentType.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { + case TypeKind.U32: { expr = module.binary( BinaryOp.SubI32, getValue, @@ -9396,24 +9080,21 @@ export class Compiler extends DiagnosticEmitter { ); break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - let options = this.options; + case TypeKind.I64: + case TypeKind.U64: { expr = module.binary( - options.isWasm64 - ? BinaryOp.SubI64 - : BinaryOp.SubI32, + BinaryOp.SubI64, getValue, - this.makeOne(this.currentType) + module.i64(1) ); break; } - case TypeKind.I64: - case TypeKind.U64: { + case TypeKind.ISIZE: + case TypeKind.USIZE: { expr = module.binary( - BinaryOp.SubI64, + BinaryOp.SubSize, getValue, - module.i64(1) + this.makeOne(this.currentType) ); break; } @@ -9555,32 +9236,30 @@ export class Compiler extends DiagnosticEmitter { } switch (this.currentType.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { + case TypeKind.U32: { expr = module.binary(BinaryOp.SubI32, module.i32(0), expr); break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { + case TypeKind.I64: + case TypeKind.U64: { + expr = module.binary(BinaryOp.SubI64, module.i64(0), expr); + break; + } + case TypeKind.ISIZE: + case TypeKind.USIZE: { expr = module.binary( - this.options.isWasm64 - ? BinaryOp.SubI64 - : BinaryOp.SubI32, + BinaryOp.SubSize, this.makeZero(this.currentType), expr ); break; } - case TypeKind.I64: - case TypeKind.U64: { - expr = module.binary(BinaryOp.SubI64, module.i64(0), expr); - break; - } case TypeKind.F32: { expr = module.unary(UnaryOp.NegF32, expr); break; @@ -9626,32 +9305,30 @@ export class Compiler extends DiagnosticEmitter { } switch (this.currentType.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { + case TypeKind.U32: { expr = module.binary(BinaryOp.AddI32, expr, this.module.i32(1)); break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { + case TypeKind.I64: + case TypeKind.U64: { + expr = module.binary(BinaryOp.AddI64, expr, module.i64(1)); + break; + } + case TypeKind.ISIZE: + case TypeKind.USIZE: { expr = module.binary( - this.options.isWasm64 - ? BinaryOp.AddI64 - : BinaryOp.AddI32, + BinaryOp.AddSize, expr, this.makeOne(this.currentType) ); break; } - case TypeKind.I64: - case TypeKind.U64: { - expr = module.binary(BinaryOp.AddI64, expr, module.i64(1)); - break; - } case TypeKind.F32: { expr = module.binary(BinaryOp.AddF32, expr, module.f32(1)); break; @@ -9697,32 +9374,30 @@ export class Compiler extends DiagnosticEmitter { } switch (this.currentType.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { + case TypeKind.U32: { expr = module.binary(BinaryOp.SubI32, expr, module.i32(1)); break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { + case TypeKind.I64: + case TypeKind.U64: { + expr = module.binary(BinaryOp.SubI64, expr, module.i64(1)); + break; + } + case TypeKind.ISIZE: + case TypeKind.USIZE: { expr = module.binary( - this.options.isWasm64 - ? BinaryOp.SubI64 - : BinaryOp.SubI32, + BinaryOp.SubSize, expr, this.makeOne(this.currentType) ); break; } - case TypeKind.I64: - case TypeKind.U64: { - expr = module.binary(BinaryOp.SubI64, expr, module.i64(1)); - break; - } case TypeKind.F32: { expr = module.binary(BinaryOp.SubF32, expr, module.f32(1)); break; @@ -9788,32 +9463,30 @@ export class Compiler extends DiagnosticEmitter { expr = this.convertExpression(expr, this.currentType, this.currentType.intType, false, expression.operand); switch (this.currentType.kind) { + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: { + case TypeKind.U32: { expr = module.binary(BinaryOp.XorI32, expr, module.i32(-1)); break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { + case TypeKind.I64: + case TypeKind.U64: { + expr = module.binary(BinaryOp.XorI64, expr, module.i64(-1, -1)); + break; + } + case TypeKind.ISIZE: + case TypeKind.USIZE: { expr = module.binary( - this.options.isWasm64 - ? BinaryOp.XorI64 - : BinaryOp.XorI32, + BinaryOp.XorSize, expr, this.makeNegOne(this.currentType) ); break; } - case TypeKind.I64: - case TypeKind.U64: { - expr = module.binary(BinaryOp.XorI64, expr, module.i64(-1, -1)); - break; - } default: { this.error( DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1, @@ -9943,6 +9616,16 @@ export class Compiler extends DiagnosticEmitter { var module = this.module; var flow = this.currentFlow; switch (type.kind) { + case TypeKind.BOOL: { + if (flow.canOverflow(expr, type)) { + // bool is special in that it compares to 0 instead of masking with 0x1 + expr = module.binary(BinaryOp.NeI32, + expr, + module.i32(0) + ); + } + break; + } case TypeKind.I8: { if (flow.canOverflow(expr, type)) { expr = this.options.hasFeature(Feature.SIGN_EXTENSION) @@ -9989,16 +9672,6 @@ export class Compiler extends DiagnosticEmitter { } break; } - case TypeKind.BOOL: { - if (flow.canOverflow(expr, type)) { - // bool is special in that it compares to 0 instead of masking with 0x1 - expr = module.binary(BinaryOp.NeI32, - expr, - module.i32(0) - ); - } - break; - } } return expr; } @@ -10125,13 +9798,13 @@ export class Compiler extends DiagnosticEmitter { var module = this.module; switch (type.kind) { default: assert(false); + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: return module.i32(0); + case TypeKind.U32: return module.i32(0); case TypeKind.ISIZE: case TypeKind.USIZE: if (type.size != 64) return module.i32(0); case TypeKind.I64: @@ -10153,13 +9826,13 @@ export class Compiler extends DiagnosticEmitter { var module = this.module; switch (type.kind) { default: assert(false); + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: return module.i32(1); + case TypeKind.U32: return module.i32(1); case TypeKind.ISIZE: case TypeKind.USIZE: if (type.size != 64) return module.i32(1); case TypeKind.I64: @@ -10204,15 +9877,11 @@ export class Compiler extends DiagnosticEmitter { } case TypeKind.BOOL: // not a mask, just != 0 case TypeKind.I32: - case TypeKind.U32: { - return expr; - } + case TypeKind.U32: return expr; case TypeKind.I64: - case TypeKind.U64: { - return module.binary(BinaryOp.NeI64, expr, module.i64(0)); - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { + case TypeKind.U64: return module.binary(BinaryOp.NeI64, expr, module.i64(0)); + case TypeKind.ISIZE: + case TypeKind.USIZE: { return type.size == 64 ? module.binary(BinaryOp.NeI64, expr, module.i64(0)) : expr; diff --git a/src/flow.ts b/src/flow.ts index 6214f026c4..511764a477 100644 --- a/src/flow.ts +++ b/src/flow.ts @@ -1417,11 +1417,11 @@ export class Flow { default: assert(false); } switch (type.kind) { - case TypeKind.I8: return value < i8.MIN_VALUE || value > i8.MAX_VALUE; - case TypeKind.I16: return value < i16.MIN_VALUE || value > i16.MAX_VALUE; - case TypeKind.U8: return value < 0 || value > u8.MAX_VALUE; - case TypeKind.U16: return value < 0 || value > u16.MAX_VALUE; case TypeKind.BOOL: return (value & ~1) != 0; + case TypeKind.I8: return value < i8.MIN_VALUE || value > i8.MAX_VALUE; + case TypeKind.I16: return value < i16.MIN_VALUE || value > i16.MAX_VALUE; + case TypeKind.U8: return value < 0 || value > u8.MAX_VALUE; + case TypeKind.U16: return value < 0 || value > u16.MAX_VALUE; } break; } diff --git a/src/resolver.ts b/src/resolver.ts index 46d5d16570..9c1b298dd4 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -1551,6 +1551,10 @@ export class Resolver extends DiagnosticEmitter { if (ctxType.isValue) { // compile to contextual type if matching switch (ctxType.kind) { + case TypeKind.BOOL: { + if (i64_is_bool(intValue)) return Type.bool; + break; + } case TypeKind.I8: { if (i64_is_i8(intValue)) return Type.i8; break; @@ -1575,10 +1579,6 @@ export class Resolver extends DiagnosticEmitter { if (i64_is_u32(intValue)) return Type.u32; break; } - case TypeKind.BOOL: { - if (i64_is_bool(intValue)) return Type.bool; - break; - } case TypeKind.ISIZE: { if (!this.program.options.isWasm64) { if (i64_is_i32(intValue)) return Type.isize32; diff --git a/src/types.ts b/src/types.ts index e8a77844fc..2d683ff38f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -16,6 +16,8 @@ import { /** Indicates the kind of a type. */ export const enum TypeKind { + /** A 1-bit unsigned integer. */ + BOOL, // signed integers @@ -42,8 +44,6 @@ export const enum TypeKind { U64, /** A 32-bit/64-bit unsigned integer, depending on the target. Also the base of class types. */ USIZE, - /** A 1-bit unsigned integer. */ - BOOL, // sic // floats @@ -145,19 +145,19 @@ export class Type { get intType(): Type { if (this == Type.auto) return this; // keep auto as a hint switch (this.kind) { - case TypeKind.I8: return Type.i8; - case TypeKind.I16: return Type.i16; - case TypeKind.F32: - case TypeKind.I32: return Type.i32; + case TypeKind.BOOL: + case TypeKind.I32: + case TypeKind.F32: return Type.i32; + case TypeKind.I8: return Type.i8; + case TypeKind.I16: return Type.i16; case TypeKind.F64: - case TypeKind.I64: return Type.i64; + case TypeKind.I64: return Type.i64; case TypeKind.ISIZE: return this.size == 64 ? Type.isize64 : Type.isize32; - case TypeKind.U8: return Type.u8; - case TypeKind.U16: return Type.u16; - case TypeKind.U32: return Type.u32; - case TypeKind.U64: return Type.u64; + case TypeKind.U8: return Type.u8; + case TypeKind.U16: return Type.u16; + case TypeKind.U32: return Type.u32; + case TypeKind.U64: return Type.u64; case TypeKind.USIZE: return this.size == 64 ? Type.usize64 : Type.usize32; - case TypeKind.BOOL: default: return Type.i32; } } @@ -488,6 +488,7 @@ export class Type { } } switch (this.kind) { + case TypeKind.BOOL: return "bool"; case TypeKind.I8: return "i8"; case TypeKind.I16: return "i16"; case TypeKind.I32: return "i32"; @@ -498,7 +499,6 @@ export class Type { case TypeKind.U32: return "u32"; case TypeKind.U64: return "u64"; case TypeKind.USIZE: return "usize"; - case TypeKind.BOOL: return "bool"; case TypeKind.F32: return "f32"; case TypeKind.F64: return "f64"; case TypeKind.V128: return "v128"; @@ -519,19 +519,19 @@ export class Type { toRef(): TypeRef { switch (this.kind) { default: assert(false); + case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: case TypeKind.U8: case TypeKind.U16: - case TypeKind.U32: - case TypeKind.BOOL: return TypeRef.I32; + case TypeKind.U32: return TypeRef.I32; case TypeKind.ISIZE: case TypeKind.USIZE: if (this.size != 64) return TypeRef.I32; case TypeKind.I64: - case TypeKind.U64: return TypeRef.I64; - case TypeKind.F32: return TypeRef.F32; - case TypeKind.F64: return TypeRef.F64; + case TypeKind.U64: return TypeRef.I64; + case TypeKind.F32: return TypeRef.F32; + case TypeKind.F64: return TypeRef.F64; case TypeKind.V128: return TypeRef.V128; // TODO: nullable/non-nullable refs have different type refs case TypeKind.FUNCREF: return TypeRef.Funcref;