From 3980e53bb786c136c5455a35793bb25abfa48dbc Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Fri, 12 Jan 2018 05:03:25 +0100 Subject: [PATCH] Let the optimizer decide what it takes to become a select --- src/ast.ts | 2 +- src/builtins.ts | 34 +-- src/compiler.ts | 226 ++++++++---------- src/glue/binaryen-c.d.ts | 7 + src/tokenizer.ts | 6 +- src/types.ts | 4 +- tests/compiler.js | 2 +- tests/compiler/game-of-life.optimized.wast | 10 +- tests/compiler/game-of-life.wast | 14 +- tests/compiler/logical.wast | 60 ++--- tests/compiler/memcpy.optimized.wast | 4 +- tests/compiler/memcpy.wast | 8 +- .../compiler/showcase.optimized-inlined.wast | 4 +- tests/compiler/showcase.optimized.wast | 4 +- tests/compiler/showcase.wast | 68 +++--- tests/compiler/std/heap.optimized.wast | 4 +- tests/compiler/std/heap.wast | 8 +- tests/parser.js | 2 +- 18 files changed, 225 insertions(+), 242 deletions(-) diff --git a/src/ast.ts b/src/ast.ts index 738e3778..a4e32897 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -2248,7 +2248,7 @@ export function mangleInternalName(declaration: DeclarationStatement): string { function builderEndsWith(sb: string[], code: CharCode): bool { if (sb.length) { var last = sb[sb.length - 1]; - return select(last.charCodeAt(last.length - 1) == code, false, last.length > 0); + return last.length > 0 ? last.charCodeAt(last.length - 1) == code : false; } return false; } diff --git a/src/builtins.ts b/src/builtins.ts index ec2d592d..a26c04ac 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -194,8 +194,8 @@ export function compileGetConstant(compiler: Compiler, global: Global, reportNod /** Compiles a call to a built-in function. */ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, typeArguments: Type[] | null, operands: Expression[], contextualType: Type, reportNode: Node): ExpressionRef { var module = compiler.module; - var usizeType = select(Type.usize64, Type.usize32, compiler.options.target == Target.WASM64); - var nativeUsizeType = select(NativeType.I64, NativeType.I32, compiler.options.target == Target.WASM64); + var usizeType = compiler.options.target == Target.WASM64 ? Type.usize64 : Type.usize32; + var nativeUsizeType = compiler.options.target == Target.WASM64 ? NativeType.I64 : NativeType.I32; var arg0: ExpressionRef, arg1: ExpressionRef, @@ -365,7 +365,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty } // fall-through case TypeKind.ISIZE: - ret = module.createUnary(select(UnaryOp.ClzI64, UnaryOp.ClzI32, compiler.options.target == Target.WASM64), arg0); + ret = module.createUnary(compiler.options.target == Target.WASM64 ? UnaryOp.ClzI64 : UnaryOp.ClzI32, arg0); break; case TypeKind.I64: @@ -418,7 +418,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty } // fall-through case TypeKind.ISIZE: - ret = module.createUnary(select(UnaryOp.CtzI64, UnaryOp.CtzI32, compiler.options.target == Target.WASM64), arg0); + ret = module.createUnary(compiler.options.target == Target.WASM64 ? UnaryOp.CtzI64 : UnaryOp.CtzI32, arg0); break; case TypeKind.I64: @@ -471,7 +471,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty } // fall-through case TypeKind.ISIZE: - ret = module.createUnary(select(UnaryOp.PopcntI64, UnaryOp.PopcntI32, compiler.options.target == Target.WASM64), arg0); + ret = module.createUnary(compiler.options.target == Target.WASM64 ? UnaryOp.PopcntI64 : UnaryOp.PopcntI32, arg0); break; case TypeKind.I64: @@ -533,7 +533,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty } // fall-through case TypeKind.ISIZE: - ret = module.createBinary(select(BinaryOp.RotlI64, BinaryOp.RotlI32, compiler.options.target == Target.WASM64), arg0, arg1); + ret = module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.RotlI64 : BinaryOp.RotlI32, arg0, arg1); break; case TypeKind.I64: @@ -594,7 +594,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty } // fall-through case TypeKind.ISIZE: - ret = module.createBinary(select(BinaryOp.RotrI64, BinaryOp.RotrI32, compiler.options.target == Target.WASM64), arg0, arg1); + ret = module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.RotrI64 : BinaryOp.RotrI32, arg0, arg1); break; case TypeKind.I64: @@ -656,11 +656,11 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(usizeType); ret = module.createSelect( module.createTeeLocal(tempLocal0.index, arg0), - module.createBinary(select(BinaryOp.SubI64, BinaryOp.SubI32, compiler.options.target == Target.WASM64), + module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.SubI64 : BinaryOp.SubI32, usizeType.toNativeZero(module), module.createGetLocal(tempLocal0.index, nativeUsizeType) ), - module.createBinary(select(BinaryOp.GtI64, BinaryOp.GtI32, compiler.options.target == Target.WASM64), + module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.GtI64 : BinaryOp.GtI32, module.createGetLocal(tempLocal0.index, nativeUsizeType), usizeType.toNativeZero(module) ) @@ -809,7 +809,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty ret = module.createSelect( module.createTeeLocal(tempLocal0.index, arg0), module.createTeeLocal(tempLocal1.index, arg1), - module.createBinary(select(BinaryOp.GtI64, BinaryOp.GtI32, compiler.options.target == Target.WASM64), + module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.GtI64 : BinaryOp.GtI32, module.createGetLocal(tempLocal0.index, nativeUsizeType), module.createGetLocal(tempLocal1.index, nativeUsizeType) ) @@ -828,7 +828,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty ret = module.createSelect( module.createTeeLocal(tempLocal0.index, arg0), module.createTeeLocal(tempLocal1.index, arg1), - module.createBinary(select(BinaryOp.GtU64, BinaryOp.GtU32, compiler.options.target == Target.WASM64), + module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.GtU64 : BinaryOp.GtU32, module.createGetLocal(tempLocal0.index, nativeUsizeType), module.createGetLocal(tempLocal1.index, nativeUsizeType) ) @@ -943,7 +943,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty ret = module.createSelect( module.createTeeLocal(tempLocal0.index, arg0), module.createTeeLocal(tempLocal1.index, arg1), - module.createBinary(select(BinaryOp.LtI64, BinaryOp.LtI32, compiler.options.target == Target.WASM64), + module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.LtI64 : BinaryOp.LtI32, module.createGetLocal(tempLocal0.index, nativeUsizeType), module.createGetLocal(tempLocal1.index, nativeUsizeType) ) @@ -962,7 +962,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty ret = module.createSelect( module.createTeeLocal(tempLocal0.index, arg0), module.createTeeLocal(tempLocal1.index, arg1), - module.createBinary(select(BinaryOp.LtU64, BinaryOp.LtU32, compiler.options.target == Target.WASM64), + module.createBinary(compiler.options.target == Target.WASM64 ? BinaryOp.LtU64 : BinaryOp.LtU32, module.createGetLocal(tempLocal0.index, nativeUsizeType), module.createGetLocal(tempLocal1.index, nativeUsizeType) ) @@ -1603,7 +1603,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty case TypeKind.ISIZE: case TypeKind.USIZE: ret = module.createIf( - module.createUnary(select(UnaryOp.EqzI64, UnaryOp.EqzI32, compiler.options.target == Target.WASM64), + module.createUnary(compiler.options.target == Target.WASM64 ? UnaryOp.EqzI64 : UnaryOp.EqzI32, arg0 ), module.createUnreachable() @@ -1668,7 +1668,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty case TypeKind.USIZE: tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(usizeType); ret = module.createIf( - module.createUnary(select(UnaryOp.EqzI64, UnaryOp.EqzI32, compiler.options.target == Target.WASM64), + module.createUnary(compiler.options.target == Target.WASM64 ? UnaryOp.EqzI64 : UnaryOp.EqzI32, module.createTeeLocal(tempLocal0.index, arg0) ), module.createUnreachable(), @@ -1755,10 +1755,10 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty compiler.error(DiagnosticCode.Type_0_is_not_generic, reportNode.range, prototype.internalName); if (operands.length != 1) { compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "1", operands.length.toString(10)); - compiler.currentType = select(Type.isize64, Type.isize32, compiler.options.target == Target.WASM64); + compiler.currentType = compiler.options.target == Target.WASM64 ? Type.isize64 : Type.isize32; return module.createUnreachable(); } - return compiler.compileExpression(operands[0], select(Type.isize64, Type.isize32, compiler.options.target == Target.WASM64), ConversionKind.EXPLICIT); + return compiler.compileExpression(operands[0], compiler.options.target == Target.WASM64 ? Type.isize64 : Type.isize32, ConversionKind.EXPLICIT); case "u8": if (typeArguments) diff --git a/src/compiler.ts b/src/compiler.ts index e4193d11..ce7f5aec 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -576,7 +576,7 @@ export class Compiler extends DiagnosticEmitter { var signatureNameParts = new Array(numParametersInclThis + 1); if (instance.instanceMethodOf) { - nativeParamTypes[paramIndex] = select(NativeType.I64, NativeType.I32, this.options.target == Target.WASM64); + nativeParamTypes[paramIndex] = this.options.target == Target.WASM64 ? NativeType.I64 : NativeType.I32; signatureNameParts[paramIndex++] = instance.instanceMethodOf.type.toSignatureString(); } for (var i = 0; i < numParameters; ++i) { @@ -1278,19 +1278,19 @@ export class Compiler extends DiagnosticEmitter { if (toType.kind == TypeKind.F32) { if (fromType.is(TypeFlags.LONG)) { losesInformation = true; - expr = mod.createUnary(select(UnaryOp.ConvertI64ToF32, UnaryOp.ConvertU64ToF32, fromType.is(TypeFlags.SIGNED)), expr); + expr = mod.createUnary(fromType.is(TypeFlags.SIGNED) ? UnaryOp.ConvertI64ToF32 : UnaryOp.ConvertU64ToF32, expr); } else { losesInformation = !fromType.is(TypeFlags.SMALL); - expr = mod.createUnary(select(UnaryOp.ConvertI32ToF32, UnaryOp.ConvertU32ToF32, fromType.is(TypeFlags.SIGNED)), expr); + expr = mod.createUnary(fromType.is(TypeFlags.SIGNED) ? UnaryOp.ConvertI32ToF32 : UnaryOp.ConvertU32ToF32, expr); } // int to f64 } else { if (fromType.is(TypeFlags.LONG)) { losesInformation = true; - expr = mod.createUnary(select(UnaryOp.ConvertI64ToF64, UnaryOp.ConvertU64ToF64, fromType.is(TypeFlags.SIGNED)), expr); + expr = mod.createUnary(fromType.is(TypeFlags.SIGNED) ? UnaryOp.ConvertI64ToF64 : UnaryOp.ConvertU64ToF64, expr); } else - expr = mod.createUnary(select(UnaryOp.ConvertI32ToF64, UnaryOp.ConvertU32ToF64, fromType.is(TypeFlags.SIGNED)), expr); + expr = mod.createUnary(fromType.is(TypeFlags.SIGNED) ? UnaryOp.ConvertI32ToF64 : UnaryOp.ConvertU32ToF64, expr); } // int to int @@ -1307,7 +1307,7 @@ export class Compiler extends DiagnosticEmitter { // i32 to i64 } else if (toType.is(TypeFlags.LONG)) { - expr = mod.createUnary(select(UnaryOp.ExtendI32, UnaryOp.ExtendU32, toType.is(TypeFlags.SIGNED)), expr); + expr = mod.createUnary(toType.is(TypeFlags.SIGNED) ? UnaryOp.ExtendI32 : UnaryOp.ExtendU32, expr); // i32 or smaller to even smaller or same size int with change of sign } else if (toType.is(TypeFlags.SMALL) && (fromType.size > toType.size || (fromType.size == toType.size && fromType.is(TypeFlags.SIGNED) != toType.is(TypeFlags.SIGNED)))) { @@ -1344,7 +1344,7 @@ export class Compiler extends DiagnosticEmitter { switch (expression.operator) { case Token.LESSTHAN: - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType); switch (this.currentType.kind) { @@ -1360,7 +1360,7 @@ export class Compiler extends DiagnosticEmitter { break; case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.LtI64, BinaryOp.LtI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.LtI64 : BinaryOp.LtI32, left, right); break; case TypeKind.U8: @@ -1372,7 +1372,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload - expr = this.module.createBinary(select(BinaryOp.LtU64, BinaryOp.LtU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.LtU64 : BinaryOp.LtU32, left, right); break; case TypeKind.U64: @@ -1395,7 +1395,7 @@ export class Compiler extends DiagnosticEmitter { break; case Token.GREATERTHAN: - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType); switch (this.currentType.kind) { @@ -1407,7 +1407,7 @@ export class Compiler extends DiagnosticEmitter { break; case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.GtI64, BinaryOp.GtI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.GtI64 : BinaryOp.GtI32, left, right); break; case TypeKind.I64: @@ -1423,7 +1423,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload - expr = this.module.createBinary(select(BinaryOp.GtU64, BinaryOp.GtU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.GtU64 : BinaryOp.GtU32, left, right); break; case TypeKind.U64: @@ -1446,7 +1446,7 @@ export class Compiler extends DiagnosticEmitter { break; case Token.LESSTHAN_EQUALS: - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType); switch (this.currentType.kind) { @@ -1458,7 +1458,7 @@ export class Compiler extends DiagnosticEmitter { break; case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.LeI64, BinaryOp.LeI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.LeI64 : BinaryOp.LeI32, left, right); break; case TypeKind.I64: @@ -1474,7 +1474,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload - expr = this.module.createBinary(select(BinaryOp.LeU64, BinaryOp.LeU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.LeU64 : BinaryOp.LeU32, left, right); break; case TypeKind.U64: @@ -1497,7 +1497,7 @@ export class Compiler extends DiagnosticEmitter { break; case Token.GREATERTHAN_EQUALS: - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType); switch (this.currentType.kind) { @@ -1509,7 +1509,7 @@ export class Compiler extends DiagnosticEmitter { break; case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.GeI64, BinaryOp.GeI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.GeI64 : BinaryOp.GeI32, left, right); break; case TypeKind.I64: @@ -1525,7 +1525,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload - expr = this.module.createBinary(select(BinaryOp.GeU64, BinaryOp.GeU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.GeU64 : BinaryOp.GeU32, left, right); break; case TypeKind.U64: @@ -1555,7 +1555,7 @@ export class Compiler extends DiagnosticEmitter { // checking for a possible use of unary EQZ. while the most classic of all optimizations, // that's not what the source told us to do. for reference, `!left` emits unary EQZ. - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType); switch (this.currentType.kind) { @@ -1573,7 +1573,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.EqI64, BinaryOp.EqI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.EqI64 : BinaryOp.EqI32, left, right); break; case TypeKind.I64: @@ -1599,7 +1599,7 @@ export class Compiler extends DiagnosticEmitter { case Token.EXCLAMATION_EQUALS_EQUALS: // TODO? case Token.EXCLAMATION_EQUALS: - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType); switch (this.currentType.kind) { @@ -1617,7 +1617,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.NeI64, BinaryOp.NeI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.NeI64 : BinaryOp.NeI32, left, right); break; case TypeKind.I64: @@ -1646,7 +1646,7 @@ export class Compiler extends DiagnosticEmitter { case Token.PLUS_EQUALS: compound = true; case Token.PLUS: // retains low bits of small integers - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -1665,7 +1665,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.AddI64, BinaryOp.AddI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.AddI64 : BinaryOp.AddI32, left, right); break; case TypeKind.I64: @@ -1689,7 +1689,7 @@ export class Compiler extends DiagnosticEmitter { case Token.MINUS_EQUALS: compound = true; case Token.MINUS: // retains low bits of small integers - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -1708,7 +1708,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.SubI64, BinaryOp.SubI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.SubI64 : BinaryOp.SubI32, left, right); break; case TypeKind.I64: @@ -1733,7 +1733,7 @@ export class Compiler extends DiagnosticEmitter { case Token.ASTERISK_EQUALS: compound = true; case Token.ASTERISK: // retains low bits of small integers - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -1753,7 +1753,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.MulI64, BinaryOp.MulI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.MulI64 : BinaryOp.MulI32, left, right); break; case TypeKind.I64: @@ -1778,7 +1778,7 @@ export class Compiler extends DiagnosticEmitter { case Token.SLASH_EQUALS: compound = true; case Token.SLASH: // TODO: when can division remain unwrapped? does it overflow? - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT); switch (this.currentType.kind) { @@ -1791,7 +1791,7 @@ export class Compiler extends DiagnosticEmitter { break; case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.DivI64, BinaryOp.DivI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.DivI64 : BinaryOp.DivI32, left, right); break; case TypeKind.I64: @@ -1808,7 +1808,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload - expr = this.module.createBinary(select(BinaryOp.DivU64, BinaryOp.DivU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.DivU64 : BinaryOp.DivU32, left, right); break; case TypeKind.U64: @@ -1832,7 +1832,7 @@ export class Compiler extends DiagnosticEmitter { case Token.PERCENT_EQUALS: compound = true; case Token.PERCENT: // TODO: when can remainder remain unwrapped? may it overflow? - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT); switch (this.currentType.kind) { @@ -1844,7 +1844,7 @@ export class Compiler extends DiagnosticEmitter { break; case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.RemI64, BinaryOp.RemI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.RemI64 : BinaryOp.RemI32, left, right); break; case TypeKind.I64: @@ -1860,7 +1860,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload - expr = this.module.createBinary(select(BinaryOp.RemU64, BinaryOp.RemU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.RemU64 : BinaryOp.RemU32, left, right); break; case TypeKind.U64: @@ -1883,7 +1883,7 @@ export class Compiler extends DiagnosticEmitter { case Token.LESSTHAN_LESSTHAN_EQUALS: compound = true; case Token.LESSTHAN_LESSTHAN: // retains low bits of small integers - left = this.compileExpression(expression.left, select(Type.i64, select(Type.i32, contextualType, contextualType == Type.void), contextualType.is(TypeFlags.FLOAT)), ConversionKind.NONE, false); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType.is(TypeFlags.FLOAT) ? Type.i64 : contextualType, ConversionKind.NONE, false); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -1906,7 +1906,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.ShlI64, BinaryOp.ShlI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.ShlI64 : BinaryOp.ShlI32, left, right); break; case TypeKind.VOID: @@ -1918,7 +1918,7 @@ export class Compiler extends DiagnosticEmitter { case Token.GREATERTHAN_GREATERTHAN_EQUALS: compound = true; case Token.GREATERTHAN_GREATERTHAN: // must wrap small integers - left = this.compileExpression(expression.left, select(Type.i64, select(Type.i32, contextualType, contextualType == Type.void), contextualType.is(TypeFlags.FLOAT)), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType.is(TypeFlags.FLOAT) ? Type.i64 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT); switch (this.currentType.kind) { @@ -1933,7 +1933,7 @@ export class Compiler extends DiagnosticEmitter { break; case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.ShrI64, BinaryOp.ShrI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.ShrI64 : BinaryOp.ShrI32, left, right); break; case TypeKind.U8: @@ -1950,7 +1950,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload - expr = this.module.createBinary(select(BinaryOp.ShrU64, BinaryOp.ShrU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.ShrU64 : BinaryOp.ShrU32, left, right); break; case TypeKind.VOID: @@ -1962,7 +1962,7 @@ export class Compiler extends DiagnosticEmitter { case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: compound = true; case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: // modifies low bits of small integers if unsigned - left = this.compileExpression(expression.left, select(Type.u64, select(Type.i32, contextualType, contextualType == Type.void), contextualType.is(TypeFlags.FLOAT)), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType == Type.void ? Type.u64 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT); switch (this.currentType.kind) { @@ -1984,7 +1984,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.ShrU64, BinaryOp.ShrU32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.ShrU64 : BinaryOp.ShrU32, left, right); break; case TypeKind.VOID: @@ -1996,7 +1996,7 @@ export class Compiler extends DiagnosticEmitter { case Token.AMPERSAND_EQUALS: compound = true; case Token.AMPERSAND: // retains low bits of small integers - left = this.compileExpression(expression.left, select(Type.i64, select(Type.i32, contextualType, contextualType == Type.void), contextualType.is(TypeFlags.FLOAT)), ConversionKind.NONE, false); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType.is(TypeFlags.FLOAT) ? Type.i64 : contextualType, ConversionKind.NONE, false); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -2019,7 +2019,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.AndI64, BinaryOp.AndI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.AndI64 : BinaryOp.AndI32, left, right); break; case TypeKind.VOID: @@ -2031,7 +2031,7 @@ export class Compiler extends DiagnosticEmitter { case Token.BAR_EQUALS: compound = true; case Token.BAR: // retains low bits of small integers - left = this.compileExpression(expression.left, select(Type.i64, select(Type.i32, contextualType, contextualType == Type.void), contextualType.is(TypeFlags.FLOAT)), ConversionKind.NONE, false); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType.is(TypeFlags.FLOAT) ? Type.i64 : contextualType, ConversionKind.NONE, false); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -2054,7 +2054,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.OrI64, BinaryOp.OrI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.OrI64 : BinaryOp.OrI32, left, right); break; case TypeKind.VOID: @@ -2066,7 +2066,7 @@ export class Compiler extends DiagnosticEmitter { case Token.CARET_EQUALS: compound = true; case Token.CARET: // retains low bits of small integers - left = this.compileExpression(expression.left, select(Type.i64, select(Type.i32, contextualType, contextualType == Type.void), contextualType.is(TypeFlags.FLOAT)), ConversionKind.NONE, false); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType.is(TypeFlags.FLOAT) ? Type.i64 : contextualType, ConversionKind.NONE, false); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -2089,7 +2089,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.XorI64, BinaryOp.XorI32, this.options.target == Target.WASM64), left, right); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.XorI64 : BinaryOp.XorI32, left, right); break; case TypeKind.VOID: @@ -2101,7 +2101,7 @@ export class Compiler extends DiagnosticEmitter { // logical (no overloading) case Token.AMPERSAND_AMPERSAND: // left && right - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); // clone left if free of side effects while tolerating one level of nesting @@ -2119,26 +2119,15 @@ export class Compiler extends DiagnosticEmitter { condition = makeEqualsZero(left, this.currentType, this.module); // simplify when cloning left without side effects was successful - if (expr) { - - // if right is also free of side effects, do a select - if (left = this.module.cloneExpression(right, true, 1)) { - expr = this.module.createSelect( - expr, // then cloned left - left, // else cloned right, actually - condition // if !left - ); - - // otherwise make it an if - } else - expr = this.module.createIf( - condition, // if !left - expr, // then cloned left - right // else right - ); + if (expr) + expr = this.module.createIf( + condition, // if !left + expr, // then cloned left + right // else right + ); // otherwise make use of the temp. local - } else { + else { assert(tempLocal); expr = this.module.createIf( condition, // if !left @@ -2149,7 +2138,7 @@ export class Compiler extends DiagnosticEmitter { break; case Token.BAR_BAR: // left || right - left = this.compileExpression(expression.left, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + left = this.compileExpression(expression.left, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType, ConversionKind.IMPLICIT, false); // clone left if free of side effects while tolerating one level of nesting @@ -2167,26 +2156,15 @@ export class Compiler extends DiagnosticEmitter { condition = makeEqualsZero(left, this.currentType, this.module); // simplify when cloning left without side effects was successful - if (expr) { - - // if right is also free of side effects, do a select - if (left = this.module.cloneExpression(right, true, 1)) { - expr = this.module.createSelect( - left, // else cloned right, actually - expr, // then cloned left - condition // if !left - ); - - // otherwise make it an if - } else - expr = this.module.createIf( - condition, // if !left - right, // then right - expr // else cloned left - ); + if (expr) + expr = this.module.createIf( + condition, // if !left + right, // then right + expr // else cloned left + ); // otherwise make use of the temp. local - } else { + else { assert(tempLocal); expr = this.module.createIf( condition, // if !left @@ -2263,7 +2241,7 @@ export class Compiler extends DiagnosticEmitter { switch (element.kind) { case ElementKind.LOCAL: - this.currentType = select((element).type, Type.void, tee); + this.currentType = tee ? (element).type : Type.void; if ((element).isConstant) { this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (element).internalName); return this.module.createUnreachable(); @@ -2276,7 +2254,7 @@ export class Compiler extends DiagnosticEmitter { if (!this.compileGlobal(element)) // reports; not yet compiled if a static field compiled as a global return this.module.createUnreachable(); assert((element).type != Type.void); - this.currentType = select((element).type, Type.void, tee); + this.currentType = tee ? (element).type : Type.void; if ((element).isConstant) { this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (element).internalName); return this.module.createUnreachable(); @@ -2295,8 +2273,9 @@ export class Compiler extends DiagnosticEmitter { return this.module.createUnreachable(); } assert(resolved.targetExpression != null); - targetExpr = this.compileExpression(resolved.targetExpression, Type.usize32); - this.currentType = select((element).type, Type.void, tee); + targetExpr = this.compileExpression(resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32, ConversionKind.NONE); + assert(this.currentType.classType); + this.currentType = tee ? (element).type : Type.void; var elementNativeType = (element).type.toNativeType(); if (!tee) return this.module.createStore((element).type.byteSize, targetExpr, valueWithCorrectType, elementNativeType, (element).memoryOffset); @@ -2316,7 +2295,8 @@ export class Compiler extends DiagnosticEmitter { if (!tee) { if (setterInstance.isInstance) { assert(resolved.targetExpression != null); - targetExpr = this.compileExpression(resolved.targetExpression, select(Type.usize64, Type.usize32, this.options.target == Target.WASM64)); + targetExpr = this.compileExpression(resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32, ConversionKind.NONE); + assert(this.currentType.classType); this.currentType = Type.void; return this.makeCall(setterInstance, [ targetExpr, valueWithCorrectType ]); } else { @@ -2329,20 +2309,20 @@ export class Compiler extends DiagnosticEmitter { var getterInstance = (getterPrototype).resolve(); // reports if (getterInstance) { assert(getterInstance.parameters.length == 0); - this.currentType = getterInstance.returnType; if (setterInstance.isInstance) { assert(resolved.targetExpression != null); - targetExpr = this.compileExpression(resolved.targetExpression, select(Type.usize64, Type.usize32, this.options.target == Target.WASM64)); + targetExpr = this.compileExpression(resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32, ConversionKind.NONE); + assert(this.currentType.classType); tempLocal = this.currentFunction.getAndFreeTempLocal(getterInstance.returnType); return this.module.createBlock(null, [ this.makeCall(setterInstance, [ this.module.createTeeLocal(tempLocal.index, targetExpr), valueWithCorrectType ]), this.makeCall(getterInstance, [ this.module.createGetLocal(tempLocal.index, tempLocal.type.toNativeType()) ]) - ], getterInstance.returnType.toNativeType()); + ], (this.currentType = getterInstance.returnType).toNativeType()); } else return this.module.createBlock(null, [ this.makeCall(setterInstance, [ valueWithCorrectType ]), this.makeCall(getterInstance) - ], getterInstance.returnType.toNativeType()); + ], (this.currentType = getterInstance.returnType).toNativeType()); } } } else @@ -2395,7 +2375,7 @@ export class Compiler extends DiagnosticEmitter { return this.module.createUnreachable(); var numArguments = expression.arguments.length; - var numArgumentsInclThis = select(numArguments + 1, numArguments, functionInstance.instanceMethodOf != null); + var numArgumentsInclThis = functionInstance.instanceMethodOf != null ? numArguments + 1 : numArguments; var argumentIndex = 0; var args = new Array(numArgumentsInclThis); @@ -2418,9 +2398,9 @@ export class Compiler extends DiagnosticEmitter { var parameters = functionInstance.parameters; var numParameters = parameters.length; - var numParametersInclThis = select(numParameters + 1, numParameters, functionInstance.instanceMethodOf != null); + var numParametersInclThis = functionInstance.instanceMethodOf != null ? numParameters + 1 : numParameters; var numArgumentsInclThis = argumentExpressions.length; - var numArguments = select(numArgumentsInclThis - 1, numArgumentsInclThis, functionInstance.instanceMethodOf != null); + var numArguments = functionInstance.instanceMethodOf != null ? numArgumentsInclThis - 1 : numArgumentsInclThis; if (numArgumentsInclThis > numParametersInclThis) { // too many arguments this.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, @@ -2523,8 +2503,8 @@ export class Compiler extends DiagnosticEmitter { this.currentType = this.currentFunction.instanceMethodOf.type; return this.module.createGetLocal(0, this.currentType.toNativeType()); } - this.currentType = select(Type.usize64, Type.usize32, this.options.target == Target.WASM64); this.error(DiagnosticCode._this_cannot_be_referenced_in_current_location, expression.range); + this.currentType = this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32; return this.module.createUnreachable(); case NodeKind.SUPER: @@ -2532,8 +2512,8 @@ export class Compiler extends DiagnosticEmitter { this.currentType = this.currentFunction.instanceMethodOf.base.type; return this.module.createGetLocal(0, this.currentType.toNativeType()); } - this.currentType = select(Type.usize64, Type.usize32, this.options.target == Target.WASM64); this.error(DiagnosticCode._super_can_only_be_referenced_in_a_derived_class, expression.range); + this.currentType = this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32; return this.module.createUnreachable(); } @@ -2582,7 +2562,7 @@ export class Compiler extends DiagnosticEmitter { case LiteralKind.INTEGER: var intValue = (expression).value; if (contextualType == Type.bool && (intValue.isZero || intValue.isOne)) - return this.module.createI32(select(0, 1, intValue.isZero)); + return this.module.createI32(intValue.isZero ? 0 : 1); if (contextualType == Type.f64) return this.module.createF64(intValue.toF64()); if (contextualType == Type.f32) @@ -2590,23 +2570,19 @@ export class Compiler extends DiagnosticEmitter { if (contextualType.is(TypeFlags.LONG | TypeFlags.INTEGER)) return this.module.createI64(intValue.lo, intValue.hi); if (!intValue.fitsInI32) { - this.currentType = select(Type.i64, Type.u64, contextualType.is(TypeFlags.SIGNED)); + this.currentType = contextualType.is(TypeFlags.SIGNED) ? Type.i64 : Type.u64; return this.module.createI64(intValue.lo, intValue.hi); } if (contextualType.is(TypeFlags.SMALL | TypeFlags.INTEGER)) { var shift = contextualType.computeSmallIntegerShift(Type.i32); var mask = contextualType.computeSmallIntegerMask(Type.i32); - return this.module.createI32(select( - intValue.lo << shift >> shift, - intValue.lo & mask, - contextualType.is(TypeFlags.SIGNED) - )); + return this.module.createI32(contextualType.is(TypeFlags.SIGNED) ? intValue.lo << shift >> shift : intValue.lo & mask); } if (contextualType == Type.void && !intValue.fitsInI32) { this.currentType = Type.i64; return this.module.createI64(intValue.lo, intValue.hi); } - this.currentType = select(Type.i32, Type.u32, contextualType.is(TypeFlags.SIGNED)); + this.currentType = contextualType.is(TypeFlags.SIGNED) ? Type.i32 : Type.u32; return this.module.createI32(intValue.toI32()); // case LiteralKind.OBJECT: @@ -2657,7 +2633,7 @@ export class Compiler extends DiagnosticEmitter { assert(resolved.target != null); assert(resolved.targetExpression != null); assert((element).memoryOffset >= 0); - targetExpr = this.compileExpression(resolved.targetExpression, select(Type.usize64, Type.usize32, this.options.target == Target.WASM64)); + targetExpr = this.compileExpression(resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32); this.currentType = (element).type; return this.module.createLoad((element).type.byteSize, (element).type.is(TypeFlags.SIGNED | TypeFlags.INTEGER), targetExpr, @@ -2674,7 +2650,7 @@ export class Compiler extends DiagnosticEmitter { assert(getterInstance.parameters.length == 0); this.currentType = getterInstance.returnType; if (getterInstance.isInstance) { - var targetExpr = this.compileExpression(resolved.targetExpression, select(Type.usize64, Type.usize32, this.options.target == Target.WASM64)) + var targetExpr = this.compileExpression(resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32) return this.makeCall(getterInstance, [ targetExpr ]); } else return this.makeCall(getterInstance); @@ -2694,7 +2670,7 @@ export class Compiler extends DiagnosticEmitter { var operator = expression.operator; // make a getter for the expression (also obtains the type) - var getValue = this.compileExpression(expression.operand, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + var getValue = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); var op: BinaryOp; var nativeType: NativeType; @@ -2721,8 +2697,8 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - op = select(BinaryOp.AddI64, BinaryOp.AddI32, this.options.target == Target.WASM64); - nativeType = select(NativeType.I64, NativeType.I32, this.options.target == Target.WASM64); + op = this.options.target == Target.WASM64 ? BinaryOp.AddI64 : BinaryOp.AddI32; + nativeType = this.options.target == Target.WASM64 ? NativeType.I64 : NativeType.I32; nativeOne = this.currentType.toNativeOne(this.module); break; @@ -2769,8 +2745,8 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.USIZE: // TODO: check operator overload case TypeKind.ISIZE: - op = select(BinaryOp.SubI64, BinaryOp.SubI32, this.options.target == Target.WASM64); - nativeType = select(NativeType.I64, NativeType.I32, this.options.target == Target.WASM64); + op = this.options.target == Target.WASM64 ? BinaryOp.SubI64 : BinaryOp.SubI32; + nativeType = this.options.target == Target.WASM64 ? NativeType.I64 : NativeType.I32; nativeOne = this.currentType.toNativeOne(this.module); break; @@ -2845,12 +2821,12 @@ export class Compiler extends DiagnosticEmitter { this.error(DiagnosticCode.Operation_not_supported, expression.range); return this.module.createUnreachable(); } - expr = this.compileExpression(expression.operand, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); // if operand already did break; case Token.MINUS: - expr = this.compileExpression(expression.operand, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); switch (this.currentType.kind) { @@ -2870,7 +2846,7 @@ export class Compiler extends DiagnosticEmitter { return this.module.createUnreachable(); } case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.SubI64, BinaryOp.SubI32, this.options.target == Target.WASM64), this.currentType.toNativeZero(this.module), expr); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.SubI64 : BinaryOp.SubI32, this.currentType.toNativeZero(this.module), expr); break; case TypeKind.I64: @@ -2890,7 +2866,7 @@ export class Compiler extends DiagnosticEmitter { case Token.PLUS_PLUS: compound = true; - expr = this.compileExpression(expression.operand, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); switch (this.currentType.kind) { @@ -2911,7 +2887,7 @@ export class Compiler extends DiagnosticEmitter { } // fall-through case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.AddI64, BinaryOp.AddI32, this.options.target == Target.WASM64), expr, this.currentType.toNativeOne(this.module)); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.AddI64 : BinaryOp.AddI32, expr, this.currentType.toNativeOne(this.module)); break; case TypeKind.I64: @@ -2931,7 +2907,7 @@ export class Compiler extends DiagnosticEmitter { case Token.MINUS_MINUS: compound = true; - expr = this.compileExpression(expression.operand, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE, false); + expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE, false); switch (this.currentType.kind) { @@ -2953,7 +2929,7 @@ export class Compiler extends DiagnosticEmitter { } // fall-through case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.SubI64, BinaryOp.SubI32, this.options.target == Target.WASM64), expr, this.currentType.toNativeOne(this.module)); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.SubI64 : BinaryOp.SubI32, expr, this.currentType.toNativeOne(this.module)); break; case TypeKind.I64: @@ -2972,13 +2948,13 @@ export class Compiler extends DiagnosticEmitter { break; case Token.EXCLAMATION: // must wrap small integers - expr = this.compileExpression(expression.operand, select(Type.i32, contextualType, contextualType == Type.void), ConversionKind.NONE); + expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType, ConversionKind.NONE); expr = makeEqualsZero(expr, this.currentType, this.module); this.currentType = Type.bool; break; case Token.TILDE: // retains low bits of small integers - expr = this.compileExpression(expression.operand, select(Type.i64, select(Type.i32, contextualType, contextualType == Type.void), contextualType.is(TypeFlags.FLOAT)), select(ConversionKind.NONE, ConversionKind.IMPLICIT, contextualType == Type.void), false); + expr = this.compileExpression(expression.operand, contextualType == Type.void ? Type.i32 : contextualType.is(TypeFlags.FLOAT) ? Type.i64 : contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT, false); switch (this.currentType.kind) { @@ -2999,7 +2975,7 @@ export class Compiler extends DiagnosticEmitter { } // fall-through case TypeKind.ISIZE: - expr = this.module.createBinary(select(BinaryOp.XorI64, BinaryOp.XorI32, this.options.target == Target.WASM64), expr, this.currentType.toNativeNegOne(this.module)); + expr = this.module.createBinary(this.options.target == Target.WASM64 ? BinaryOp.XorI64 : BinaryOp.XorI32, expr, this.currentType.toNativeNegOne(this.module)); break; case TypeKind.I64: @@ -3152,7 +3128,7 @@ export function makeEqualsZero(expr: ExpressionRef, type: Type, module: Module): case TypeKind.ISIZE: case TypeKind.USIZE: - expr = module.createUnary(select(UnaryOp.EqzI64, UnaryOp.EqzI32, type.size == 64), expr); + expr = module.createUnary(type.size == 64 ? UnaryOp.EqzI64 : UnaryOp.EqzI32, expr); break; case TypeKind.F32: diff --git a/src/glue/binaryen-c.d.ts b/src/glue/binaryen-c.d.ts index 1928ccf6..699128dc 100644 --- a/src/glue/binaryen-c.d.ts +++ b/src/glue/binaryen-c.d.ts @@ -429,4 +429,11 @@ declare function _RelooperAddBlockWithSwitch(relooper: RelooperRef, code: Binary declare function _RelooperAddBranchForSwitch(from: RelooperBlockRef, to: RelooperBlockRef, indexes: usize, numIndexes: BinaryenIndex, code: BinaryenExpressionRef): void; declare function _RelooperRenderAndDispose(relooper: RelooperRef, entry: RelooperBlockRef, labelHelper: BinaryenIndex, module: BinaryenModuleRef): BinaryenExpressionRef; +declare function _BinaryenGetOptimizeLevel(): i32; +declare function _BinaryenSetOptimizeLevel(level: i32): void; +declare function _BinaryenGetShrinkLevel(): i32; +declare function _BinaryenSetShrinkLevel(level: i32): void; +declare function _BinaryenGetDebugInfo(): bool; +declare function _BinaryenSetDebugInfo(on: bool): void; + declare function _BinaryenSetAPITracing(on: i32): void; diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 89a6b61b..ef5d2b3e 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -943,13 +943,13 @@ export class Tokenizer extends DiagnosticEmitter { // make sure each supported flag is unique case CharCode.g: - flags |= select(1, -1, !(flags & 1)); + flags |= flags & 1 ? -1 : 1; break; case CharCode.i: - flags |= select(2, -1, !(flags & 2)); + flags |= flags & 2 ? -1 : 2; break; case CharCode.m: - flags |= select(4, -1, !(flags & 4)); + flags |= flags & 4 ? -1 : 4; break; default: diff --git a/src/types.ts b/src/types.ts index 6d4dcfbd..a83be9e7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -188,7 +188,7 @@ export class Type { case TypeKind.ISIZE: case TypeKind.USIZE: - return select(NativeType.I64, NativeType.I32, this.size == 64); + return this.size == 64 ? NativeType.I64 : NativeType.I32; case TypeKind.F32: return NativeType.F32; @@ -298,7 +298,7 @@ export class Type { case TypeKind.ISIZE: case TypeKind.USIZE: - return select("I", "i", this.size == 64); + return this.size == 64 ? "I" : "i"; case TypeKind.F32: return "f"; diff --git a/tests/compiler.js b/tests/compiler.js index acd7b3f3..9cfec7be 100644 --- a/tests/compiler.js +++ b/tests/compiler.js @@ -150,4 +150,4 @@ if (failures) { process.exitCode = 1; console.log(chalk.red("ERROR: ") + failures + " compiler tests failed"); } else - console.log(chalk.whiteBright("SUCCESS")); + console.log("[ " + chalk.whiteBright("SUCCESS") + " ]"); diff --git a/tests/compiler/game-of-life.optimized.wast b/tests/compiler/game-of-life.optimized.wast index e3b8f282..459b18bc 100644 --- a/tests/compiler/game-of-life.optimized.wast +++ b/tests/compiler/game-of-life.optimized.wast @@ -210,7 +210,11 @@ ) (if (i32.and - (select + (if (result i32) + (i32.ge_u + (get_local $2) + (i32.const 2) + ) (i32.gt_u (get_local $2) (i32.const 3) @@ -219,10 +223,6 @@ (get_local $2) (i32.const 2) ) - (i32.ge_u - (get_local $2) - (i32.const 2) - ) ) (i32.const 1) ) diff --git a/tests/compiler/game-of-life.wast b/tests/compiler/game-of-life.wast index 459eec86..7c0b0adf 100644 --- a/tests/compiler/game-of-life.wast +++ b/tests/compiler/game-of-life.wast @@ -236,7 +236,13 @@ ) (if (i32.and - (select + (if (result i32) + (i32.eqz + (i32.lt_u + (get_local $8) + (i32.const 2) + ) + ) (i32.gt_u (get_local $8) (i32.const 3) @@ -245,12 +251,6 @@ (get_local $8) (i32.const 2) ) - (i32.eqz - (i32.lt_u - (get_local $8) - (i32.const 2) - ) - ) ) (i32.const 1) ) diff --git a/tests/compiler/logical.wast b/tests/compiler/logical.wast index 15b509ca..2fcf969b 100644 --- a/tests/compiler/logical.wast +++ b/tests/compiler/logical.wast @@ -53,12 +53,12 @@ (if (result i32) (i32.eqz (tee_local $0 - (select - (i32.const 1) - (i32.const 2) + (if (result i32) (i32.eqz (i32.const 1) ) + (i32.const 1) + (i32.const 2) ) ) ) @@ -70,13 +70,13 @@ (if (result f64) (f64.eq (tee_local $1 - (select - (f64.const 1) - (f64.const 2) + (if (result f64) (f64.eq (f64.const 1) (f64.const 0) ) + (f64.const 1) + (f64.const 2) ) ) (f64.const 0) @@ -86,12 +86,12 @@ ) ) (set_global $logical/i - (select - (i32.const 1) - (i32.const 2) + (if (result i32) (i32.eqz (i32.const 1) ) + (i32.const 1) + (i32.const 2) ) ) (if @@ -104,12 +104,12 @@ (unreachable) ) (set_global $logical/i - (select - (i32.const 1) - (i32.const 0) + (if (result i32) (i32.eqz (i32.const 0) ) + (i32.const 1) + (i32.const 0) ) ) (if @@ -122,12 +122,12 @@ (unreachable) ) (set_global $logical/I - (select - (i64.const 1) - (i64.const 2) + (if (result i64) (i64.eqz (i64.const 1) ) + (i64.const 1) + (i64.const 2) ) ) (if @@ -140,12 +140,12 @@ (unreachable) ) (set_global $logical/I - (select - (i64.const 1) - (i64.const 0) + (if (result i64) (i64.eqz (i64.const 0) ) + (i64.const 1) + (i64.const 0) ) ) (if @@ -158,13 +158,13 @@ (unreachable) ) (set_global $logical/f - (select - (f32.const 1) - (f32.const 2) + (if (result f32) (f32.eq (f32.const 1) (f32.const 0) ) + (f32.const 1) + (f32.const 2) ) ) (if @@ -177,13 +177,13 @@ (unreachable) ) (set_global $logical/f - (select - (f32.const 1) - (f32.const 0) + (if (result f32) (f32.eq (f32.const 0) (f32.const 0) ) + (f32.const 1) + (f32.const 0) ) ) (if @@ -196,13 +196,13 @@ (unreachable) ) (set_global $logical/F - (select - (f64.const 1) - (f64.const 2) + (if (result f64) (f64.eq (f64.const 1) (f64.const 0) ) + (f64.const 1) + (f64.const 2) ) ) (if @@ -215,13 +215,13 @@ (unreachable) ) (set_global $logical/F - (select - (f64.const 1) - (f64.const 0) + (if (result f64) (f64.eq (f64.const 0) (f64.const 0) ) + (f64.const 1) + (f64.const 0) ) ) (if diff --git a/tests/compiler/memcpy.optimized.wast b/tests/compiler/memcpy.optimized.wast index 9702bae9..3edef66f 100644 --- a/tests/compiler/memcpy.optimized.wast +++ b/tests/compiler/memcpy.optimized.wast @@ -18,13 +18,13 @@ ) (loop $continue|0 (if - (select + (if (result i32) + (get_local $2) (i32.rem_u (get_local $3) (i32.const 4) ) (get_local $2) - (get_local $2) ) (block (set_local $4 diff --git a/tests/compiler/memcpy.wast b/tests/compiler/memcpy.wast index 35465c2e..5301ef07 100644 --- a/tests/compiler/memcpy.wast +++ b/tests/compiler/memcpy.wast @@ -26,15 +26,15 @@ (block $break|0 (loop $continue|0 (if - (select + (if (result i32) + (i32.eqz + (get_local $2) + ) (get_local $2) (i32.rem_u (get_local $4) (i32.const 4) ) - (i32.eqz - (get_local $2) - ) ) (block (block diff --git a/tests/compiler/showcase.optimized-inlined.wast b/tests/compiler/showcase.optimized-inlined.wast index e8b98af9..69bdbde7 100644 --- a/tests/compiler/showcase.optimized-inlined.wast +++ b/tests/compiler/showcase.optimized-inlined.wast @@ -65,13 +65,13 @@ ) (loop $continue|0 (if - (select + (if (result i32) + (get_local $2) (i32.rem_u (get_local $3) (i32.const 4) ) (get_local $2) - (get_local $2) ) (block (set_local $4 diff --git a/tests/compiler/showcase.optimized.wast b/tests/compiler/showcase.optimized.wast index 9db1dfac..aeda3181 100644 --- a/tests/compiler/showcase.optimized.wast +++ b/tests/compiler/showcase.optimized.wast @@ -86,13 +86,13 @@ ) (loop $continue|0 (if - (select + (if (result i32) + (get_local $2) (i32.rem_u (get_local $3) (i32.const 4) ) (get_local $2) - (get_local $2) ) (block (set_local $4 diff --git a/tests/compiler/showcase.wast b/tests/compiler/showcase.wast index d2c767ac..056b4f78 100644 --- a/tests/compiler/showcase.wast +++ b/tests/compiler/showcase.wast @@ -134,15 +134,15 @@ (block $break|0 (loop $continue|0 (if - (select + (if (result i32) + (i32.eqz + (get_local $2) + ) (get_local $2) (i32.rem_u (get_local $4) (i32.const 4) ) - (i32.eqz - (get_local $2) - ) ) (block (block @@ -4271,12 +4271,12 @@ (if (result i32) (i32.eqz (tee_local $0 - (select - (i32.const 1) - (i32.const 2) + (if (result i32) (i32.eqz (i32.const 1) ) + (i32.const 1) + (i32.const 2) ) ) ) @@ -4288,13 +4288,13 @@ (if (result f64) (f64.eq (tee_local $3 - (select - (f64.const 1) - (f64.const 2) + (if (result f64) (f64.eq (f64.const 1) (f64.const 0) ) + (f64.const 1) + (f64.const 2) ) ) (f64.const 0) @@ -4304,12 +4304,12 @@ ) ) (set_global $logical/i - (select - (i32.const 1) - (i32.const 2) + (if (result i32) (i32.eqz (i32.const 1) ) + (i32.const 1) + (i32.const 2) ) ) (if @@ -4322,12 +4322,12 @@ (unreachable) ) (set_global $logical/i - (select - (i32.const 1) - (i32.const 0) + (if (result i32) (i32.eqz (i32.const 0) ) + (i32.const 1) + (i32.const 0) ) ) (if @@ -4340,12 +4340,12 @@ (unreachable) ) (set_global $logical/I - (select - (i64.const 1) - (i64.const 2) + (if (result i64) (i64.eqz (i64.const 1) ) + (i64.const 1) + (i64.const 2) ) ) (if @@ -4358,12 +4358,12 @@ (unreachable) ) (set_global $logical/I - (select - (i64.const 1) - (i64.const 0) + (if (result i64) (i64.eqz (i64.const 0) ) + (i64.const 1) + (i64.const 0) ) ) (if @@ -4376,13 +4376,13 @@ (unreachable) ) (set_global $logical/f - (select - (f32.const 1) - (f32.const 2) + (if (result f32) (f32.eq (f32.const 1) (f32.const 0) ) + (f32.const 1) + (f32.const 2) ) ) (if @@ -4395,13 +4395,13 @@ (unreachable) ) (set_global $logical/f - (select - (f32.const 1) - (f32.const 0) + (if (result f32) (f32.eq (f32.const 0) (f32.const 0) ) + (f32.const 1) + (f32.const 0) ) ) (if @@ -4414,13 +4414,13 @@ (unreachable) ) (set_global $logical/F - (select - (f64.const 1) - (f64.const 2) + (if (result f64) (f64.eq (f64.const 1) (f64.const 0) ) + (f64.const 1) + (f64.const 2) ) ) (if @@ -4433,13 +4433,13 @@ (unreachable) ) (set_global $logical/F - (select - (f64.const 1) - (f64.const 0) + (if (result f64) (f64.eq (f64.const 0) (f64.const 0) ) + (f64.const 1) + (f64.const 0) ) ) (if diff --git a/tests/compiler/std/heap.optimized.wast b/tests/compiler/std/heap.optimized.wast index 33ca90f5..d9de4fb8 100644 --- a/tests/compiler/std/heap.optimized.wast +++ b/tests/compiler/std/heap.optimized.wast @@ -472,13 +472,13 @@ ) (loop $continue|0 (if - (select + (if (result i32) + (get_local $2) (i32.rem_u (get_local $1) (i32.const 4) ) (get_local $2) - (get_local $2) ) (block (set_local $4 diff --git a/tests/compiler/std/heap.wast b/tests/compiler/std/heap.wast index af88ec58..adeeee37 100644 --- a/tests/compiler/std/heap.wast +++ b/tests/compiler/std/heap.wast @@ -527,15 +527,15 @@ (block $break|0 (loop $continue|0 (if - (select + (if (result i32) + (i32.eqz + (get_local $2) + ) (get_local $2) (i32.rem_u (get_local $1) (i32.const 4) ) - (i32.eqz - (get_local $2) - ) ) (block (block diff --git a/tests/parser.js b/tests/parser.js index 8a14482a..330017fe 100644 --- a/tests/parser.js +++ b/tests/parser.js @@ -53,4 +53,4 @@ if (failures) { process.exitCode = 1; console.log(chalk.red("ERROR: ") + failures + " parser tests failed"); } else - console.log(chalk.whiteBright("SUCCESS")); + console.log("[ " + chalk.whiteBright("SUCCESS") + " ]");