From 4b86a4fcbe4b255e853a72f688a428690df87306 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 25 Sep 2019 17:40:50 +0200 Subject: [PATCH 1/4] Improve error messages --- src/builtins.ts | 2015 +++++++++++++-------------- src/compiler.ts | 4 +- src/diagnosticMessages.generated.ts | 34 +- src/diagnosticMessages.json | 19 +- src/parser.ts | 16 +- src/program.ts | 14 +- src/resolver.ts | 48 +- tests/compiler/unsafe.json | 48 +- 8 files changed, 1035 insertions(+), 1163 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index c6451a3861..1f200afc63 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -779,13 +779,22 @@ export function compileCall( checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsOptional(operands, 0, 1, reportNode, compiler) ) return module.unreachable(); - let typeArgument = typeArguments![0]; - let classType = typeArgument.classReference; - if (!(typeArgument.is(TypeFlags.REFERENCE) && classType !== null)) { + let type = typeArguments![0]; + let classType = type.classReference; + if (!(type.is(TypeFlags.REFERENCE) && classType !== null)) { compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "offsetof", type.toString() ); + if (compiler.options.isWasm64) { + if (contextualType.is(TypeFlags.INTEGER) && contextualType.size <= 32) { + compiler.currentType = Type.u32; + } + } else { + if (contextualType.is(TypeFlags.INTEGER) && contextualType.size == 64) { + compiler.currentType = Type.u64; + } + } return module.unreachable(); } let offset: i32; @@ -818,24 +827,21 @@ export function compileCall( if (contextualType.is(TypeFlags.INTEGER) && contextualType.size <= 32) { compiler.currentType = Type.u32; return module.i32(offset); - } else { - return module.i64(offset); } + return module.i64(offset); } else { // implicitly extend if contextual type is a 64-bit integer if (contextualType.is(TypeFlags.INTEGER) && contextualType.size == 64) { compiler.currentType = Type.u64; return module.i64(offset); - } else { - return module.i32(offset); } + return module.i32(offset); } } case BuiltinSymbols.nameof: { // Check to make sure a parameter or a type was passed to the builtin let resultType = evaluateConstantType(compiler, typeArguments, operands, reportNode); if (!resultType) return module.unreachable(); - let value: string; if (resultType.is(TypeFlags.REFERENCE)) { let classReference = resultType.classReference; @@ -865,21 +871,17 @@ export function compileCall( case TypeKind.ISIZE: { value = "isize"; break; } case TypeKind.USIZE: { value = "usize"; break; } case TypeKind.V128: { value = "v128"; break; } - // If the kind is not set properly, throw an error. - // The default case falls through to satisfy that value is always set, and never null. + case TypeKind.ANYREF: { value = "anyref"; break; } default: assert(false); case TypeKind.VOID: { value = "void"; break; } } } - return compiler.ensureStaticString(value); } // === Math =================================================================================== - case BuiltinSymbols.clz: // any_bitcount(value: T) -> T - case BuiltinSymbols.ctz: - case BuiltinSymbols.popcnt: { + case BuiltinSymbols.clz: { // clz(value: T) -> T if ( checkTypeOptional(typeArguments, reportNode, compiler, true) | checkArgsRequired(operands, 1, reportNode, compiler) @@ -888,87 +890,107 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let op: UnaryOp = -1; - switch (prototype.internalName) { - case BuiltinSymbols.clz: { - switch (type.kind) { - case TypeKind.BOOL: - case TypeKind.I8: - case TypeKind.U8: - case TypeKind.I16: - case TypeKind.U16: - case TypeKind.I32: - case TypeKind.U32: { op = UnaryOp.ClzI32; break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - op = compiler.options.isWasm64 + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.BOOL: // not wrapped + case TypeKind.I8: + case TypeKind.U8: + case TypeKind.I16: + 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; - break; - } - case TypeKind.I64: - case TypeKind.U64: { op = UnaryOp.ClzI64; break; } + : UnaryOp.ClzI32, + arg0 + ); } - break; + case TypeKind.I64: + case TypeKind.U64: return module.unary(UnaryOp.ClzI64, arg0); } - case BuiltinSymbols.ctz: { - switch (type.kind) { - case TypeKind.BOOL: - case TypeKind.I8: - case TypeKind.U8: - case TypeKind.I16: - case TypeKind.U16: - case TypeKind.I32: - case TypeKind.U32: { op = UnaryOp.CtzI32; break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - op = compiler.options.isWasm64 + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "clz", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.ctz: { // ctz(value: T) -> T + if ( + checkTypeOptional(typeArguments, reportNode, compiler, true) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) return module.unreachable(); + let arg0 = typeArguments + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); + let type = compiler.currentType; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.BOOL: // not wrapped + case TypeKind.I8: + case TypeKind.U8: + case TypeKind.I16: + 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; - break; - } - case TypeKind.I64: - case TypeKind.U64: { op = UnaryOp.CtzI64; break; } + : UnaryOp.CtzI32, + arg0 + ); } - break; + case TypeKind.I64: + case TypeKind.U64: return module.unary(UnaryOp.CtzI64, arg0); } - case BuiltinSymbols.popcnt: { - switch (compiler.currentType.kind) { - case TypeKind.BOOL: - case TypeKind.I8: - case TypeKind.U8: - case TypeKind.I16: - case TypeKind.U16: - case TypeKind.I32: - case TypeKind.U32: { op = UnaryOp.PopcntI32; break; } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - op = compiler.options.isWasm64 + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "ctz", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.popcnt: { // popcnt(value: T) -> T + if ( + checkTypeOptional(typeArguments, reportNode, compiler, true) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) return module.unreachable(); + let arg0 = typeArguments + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) + : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); + let type = compiler.currentType; + if (!type.is(TypeFlags.REFERENCE)) { + switch (compiler.currentType.kind) { + case TypeKind.BOOL: // not wrapped + case TypeKind.I8: + case TypeKind.U8: + case TypeKind.I16: + case TypeKind.U16: + case TypeKind.I32: + case TypeKind.U32: return module.unary(UnaryOp.PopcntI32, arg0); + case TypeKind.USIZE: + case TypeKind.ISIZE: { + return module.unary( + compiler.options.isWasm64 ? UnaryOp.PopcntI64 - : UnaryOp.PopcntI32; - break; - } - case TypeKind.I64: - case TypeKind.U64: { op = UnaryOp.PopcntI64; break; } + : UnaryOp.PopcntI32, + arg0 + ); } - break; + case TypeKind.I64: + case TypeKind.U64: return module.unary(UnaryOp.PopcntI64, arg0); } } - if (op == -1) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - return module.unary(op, arg0); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "popcnt", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.rotl: { // rotl(value: T, shift: T) -> T if ( @@ -979,57 +1001,39 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); - let expr: ExpressionRef; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - expr = compiler.ensureSmallIntegerWrap( - module.binary(BinaryOp.RotlI32, arg0, arg1), - type - ); - // fall-through - } - case TypeKind.I32: - case TypeKind.U32: { - expr = module.binary(BinaryOp.RotlI32, arg0, arg1); - break; - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - expr = module.binary( - compiler.options.isWasm64 - ? BinaryOp.RotlI64 - : BinaryOp.RotlI32, - arg0, arg1 - ); - break; - } - case TypeKind.I64: - case TypeKind.U64: { - expr = module.binary(BinaryOp.RotlI64, arg0, arg1); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = module.unreachable(); - break; + if (!type.is(TypeFlags.REFERENCE)) { + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.BOOL: { + return compiler.ensureSmallIntegerWrap( + module.binary(BinaryOp.RotlI32, arg0, arg1), + type + ); + } + case TypeKind.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); } } - return expr; // possibly overflows + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "rotl", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.rotr: { // rotr(value: T, shift: T) -> T if ( @@ -1040,57 +1044,39 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) : compiler.compileExpression(operands[0], Type.i32, Constraints.MUST_WRAP); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); - let expr: ExpressionRef; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.BOOL: { - expr = compiler.ensureSmallIntegerWrap( - module.binary(BinaryOp.RotrI32, arg0, arg1), - type - ); - break; - } - case TypeKind.I32: - case TypeKind.U32: { - expr = module.binary(BinaryOp.RotrI32, arg0, arg1); - break; - } - case TypeKind.USIZE: - case TypeKind.ISIZE: { - expr = module.binary( - compiler.options.isWasm64 - ? BinaryOp.RotrI64 - : BinaryOp.RotrI32, - arg0, arg1 - ); - break; - } - case TypeKind.I64: - case TypeKind.U64: { - expr = module.binary(BinaryOp.RotrI64, arg0, arg1); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = module.unreachable(); - break; + if (!type.is(TypeFlags.REFERENCE)) { + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.BOOL: { + return compiler.ensureSmallIntegerWrap( + module.binary(BinaryOp.RotrI32, arg0, arg1), + type + ); + } + case TypeKind.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); } } - return expr; // possibly overflowws + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "rotr", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.abs: { // abs(value: T) -> T if ( @@ -1101,121 +1087,96 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let expr: ExpressionRef; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.I32: { - let flow = compiler.currentFlow; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: { + let flow = compiler.currentFlow; - // possibly overflows, e.g. abs(-128) == 128 - let tempLocal1 = flow.getTempLocal(Type.i32); - let tempLocalIndex2 = flow.getAndFreeTempLocal(Type.i32).index; - let tempLocalIndex1 = tempLocal1.index; + // possibly overflows, e.g. abs(-128) == 128 + let tempLocal1 = flow.getTempLocal(Type.i32); + let tempLocalIndex2 = flow.getAndFreeTempLocal(Type.i32).index; + let tempLocalIndex1 = tempLocal1.index; + flow.freeTempLocal(tempLocal1); - // (x + (x >> 31)) ^ (x >> 31) - expr = module.binary(BinaryOp.XorI32, - module.binary(BinaryOp.AddI32, - module.local_tee( - tempLocalIndex2, - module.binary(BinaryOp.ShrI32, - module.local_tee(tempLocalIndex1, arg0), - module.i32(31) - ) + // (x + (x >> 31)) ^ (x >> 31) + return module.binary(BinaryOp.XorI32, + module.binary(BinaryOp.AddI32, + module.local_tee( + tempLocalIndex2, + module.binary(BinaryOp.ShrI32, + module.local_tee(tempLocalIndex1, arg0), + module.i32(31) + ) + ), + module.local_get(tempLocalIndex1, NativeType.I32) ), - module.local_get(tempLocalIndex1, NativeType.I32) - ), - module.local_get(tempLocalIndex2, NativeType.I32) - ); - - flow.freeTempLocal(tempLocal1); - break; - } - case TypeKind.ISIZE: { - let options = compiler.options; - let flow = compiler.currentFlow; - let wasm64 = options.isWasm64; + module.local_get(tempLocalIndex2, NativeType.I32) + ); + } + case TypeKind.ISIZE: { + let options = compiler.options; + let flow = compiler.currentFlow; + let wasm64 = options.isWasm64; - let tempLocal1 = flow.getTempLocal(options.usizeType); - let tempLocalIndex2 = flow.getAndFreeTempLocal(options.usizeType).index; - let tempLocalIndex1 = tempLocal1.index; + let tempLocal1 = flow.getTempLocal(options.usizeType); + let tempLocalIndex2 = flow.getAndFreeTempLocal(options.usizeType).index; + let tempLocalIndex1 = tempLocal1.index; + flow.freeTempLocal(tempLocal1); - expr = module.binary(wasm64 ? BinaryOp.XorI64 : BinaryOp.XorI32, - module.binary(wasm64 ? BinaryOp.AddI64 : BinaryOp.AddI32, - module.local_tee( - tempLocalIndex2, - module.binary(wasm64 ? BinaryOp.ShrI64 : BinaryOp.ShrI32, - module.local_tee(tempLocalIndex1, arg0), - wasm64 ? module.i64(63) : module.i32(31) - ) + return module.binary(wasm64 ? BinaryOp.XorI64 : BinaryOp.XorI32, + module.binary(wasm64 ? BinaryOp.AddI64 : BinaryOp.AddI32, + module.local_tee( + tempLocalIndex2, + module.binary(wasm64 ? BinaryOp.ShrI64 : BinaryOp.ShrI32, + module.local_tee(tempLocalIndex1, arg0), + wasm64 ? module.i64(63) : module.i32(31) + ) + ), + module.local_get(tempLocalIndex1, options.nativeSizeType) ), - module.local_get(tempLocalIndex1, options.nativeSizeType) - ), - module.local_get(tempLocalIndex2, options.nativeSizeType) - ); - - flow.freeTempLocal(tempLocal1); - break; - } - case TypeKind.I64: { - let flow = compiler.currentFlow; + module.local_get(tempLocalIndex2, options.nativeSizeType) + ); + } + case TypeKind.I64: { + let flow = compiler.currentFlow; - let tempLocal1 = flow.getTempLocal(Type.i64); - let tempLocalIndex2 = flow.getAndFreeTempLocal(Type.i64).index; - let tempLocalIndex1 = tempLocal1.index; + let tempLocal1 = flow.getTempLocal(Type.i64); + let tempLocalIndex2 = flow.getAndFreeTempLocal(Type.i64).index; + let tempLocalIndex1 = tempLocal1.index; + flow.freeTempLocal(tempLocal1); - // (x + (x >> 63)) ^ (x >> 63) - expr = module.binary(BinaryOp.XorI64, - module.binary(BinaryOp.AddI64, - module.local_tee( - tempLocalIndex2, - module.binary(BinaryOp.ShrI64, - module.local_tee(tempLocalIndex1, arg0), - module.i64(63) - ) + // (x + (x >> 63)) ^ (x >> 63) + return module.binary(BinaryOp.XorI64, + module.binary(BinaryOp.AddI64, + module.local_tee( + tempLocalIndex2, + module.binary(BinaryOp.ShrI64, + module.local_tee(tempLocalIndex1, arg0), + module.i64(63) + ) + ), + module.local_get(tempLocalIndex1, NativeType.I64) ), - module.local_get(tempLocalIndex1, NativeType.I64) - ), - module.local_get(tempLocalIndex2, NativeType.I64) - ); - - flow.freeTempLocal(tempLocal1); - break; - } - case TypeKind.USIZE: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.U32: - case TypeKind.U64: - case TypeKind.BOOL: { - expr = arg0; - break; - } - case TypeKind.F32: { - expr = module.unary(UnaryOp.AbsF32, arg0); - break; - } - case TypeKind.F64: { - expr = module.unary(UnaryOp.AbsF64, arg0); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = module.unreachable(); - break; + module.local_get(tempLocalIndex2, NativeType.I64) + ); + } + 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); } } - return expr; + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "abs", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.max: { // max(left: T, right: T) -> T if ( @@ -1226,66 +1187,57 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP); - let op: BinaryOp; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.I32: { op = BinaryOp.GtI32; break; } - 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.F32: { - return module.binary(BinaryOp.MaxF32, arg0, arg1); - } - case TypeKind.F64: { - return module.binary(BinaryOp.MaxF64, arg0, arg1); + if (!type.is(TypeFlags.REFERENCE)) { + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP); + let op: BinaryOp = -1; + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: { op = BinaryOp.GtI32; break; } + 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.F32: return module.binary(BinaryOp.MaxF32, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.MaxF64, arg0, arg1); } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + if (op != -1) { + let flow = compiler.currentFlow; + let nativeType = type.toNativeType(); + let tempLocal0 = flow.getTempLocal(type); + flow.setLocalFlag(tempLocal0.index, LocalFlags.WRAPPED); + let tempLocal1 = flow.getAndFreeTempLocal(type); + flow.setLocalFlag(tempLocal1.index, LocalFlags.WRAPPED); + flow.freeTempLocal(tempLocal0); + return module.select( + module.local_tee(tempLocal0.index, arg0), + module.local_tee(tempLocal1.index, arg1), + module.binary(op, + module.local_get(tempLocal0.index, nativeType), + module.local_get(tempLocal1.index, nativeType) + ) ); - return module.unreachable(); } } - let flow = compiler.currentFlow; - let nativeType = type.toNativeType(); - let tempLocal0 = flow.getTempLocal(type); - flow.setLocalFlag(tempLocal0.index, LocalFlags.WRAPPED); - let tempLocal1 = flow.getAndFreeTempLocal(type); - flow.setLocalFlag(tempLocal1.index, LocalFlags.WRAPPED); - flow.freeTempLocal(tempLocal0); - return module.select( - module.local_tee(tempLocal0.index, arg0), - module.local_tee(tempLocal1.index, arg1), - module.binary(op, - module.local_get(tempLocal0.index, nativeType), - module.local_get(tempLocal1.index, nativeType) - ) + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "max", type.toString() ); + return module.unreachable(); } case BuiltinSymbols.min: { // min(left: T, right: T) -> T if ( @@ -1296,66 +1248,57 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP) : compiler.compileExpression(operands[0], Type.f64, Constraints.MUST_WRAP); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP); - let op: BinaryOp; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.I32: { op = BinaryOp.LtI32; break; } - 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.F32: { - return module.binary(BinaryOp.MinF32, arg0, arg1); - } - case TypeKind.F64: { - return module.binary(BinaryOp.MinF64, arg0, arg1); + if (!type.is(TypeFlags.REFERENCE)) { + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP); + let op: BinaryOp = -1; + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: { op = BinaryOp.LtI32; break; } + 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.F32: return module.binary(BinaryOp.MinF32, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.MinF64, arg0, arg1); } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + if (op != -1) { + let flow = compiler.currentFlow; + let nativeType = type.toNativeType(); + let tempLocal0 = flow.getTempLocal(type); + flow.setLocalFlag(tempLocal0.index, LocalFlags.WRAPPED); + let tempLocal1 = flow.getAndFreeTempLocal(type); + flow.setLocalFlag(tempLocal1.index, LocalFlags.WRAPPED); + flow.freeTempLocal(tempLocal0); + return module.select( + module.local_tee(tempLocal0.index, arg0), + module.local_tee(tempLocal1.index, arg1), + module.binary(op, + module.local_get(tempLocal0.index, nativeType), + module.local_get(tempLocal1.index, nativeType) + ) ); - return module.unreachable(); } } - let flow = compiler.currentFlow; - let nativeType = type.toNativeType(); - let tempLocal0 = flow.getTempLocal(type); - flow.setLocalFlag(tempLocal0.index, LocalFlags.WRAPPED); - let tempLocal1 = flow.getAndFreeTempLocal(type); - flow.setLocalFlag(tempLocal1.index, LocalFlags.WRAPPED); - flow.freeTempLocal(tempLocal0); - return module.select( - module.local_tee(tempLocal0.index, arg0), - module.local_tee(tempLocal1.index, arg1), - module.binary(op, - module.local_get(tempLocal0.index, nativeType), - module.local_get(tempLocal1.index, nativeType) - ) + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "min", type.toString() ); + return module.unreachable(); } case BuiltinSymbols.ceil: // any_rounding(value: T) -> T case BuiltinSymbols.floor: { @@ -1367,47 +1310,29 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let op: UnaryOp; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.I32: - case TypeKind.I64: - case TypeKind.ISIZE: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.U32: - case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.BOOL: return arg0; // considered rounded - case TypeKind.F32: { - op = prototype.internalName == BuiltinSymbols.ceil - ? UnaryOp.CeilF32 - : UnaryOp.FloorF32; - break; - } - case TypeKind.F64: { - op = prototype.internalName == BuiltinSymbols.ceil - ? UnaryOp.CeilF64 - : UnaryOp.FloorF64; - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); + let isCeil = prototype.internalName == BuiltinSymbols.ceil; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: + case TypeKind.I64: + case TypeKind.ISIZE: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: + case TypeKind.BOOL: return arg0; // considered rounded + case TypeKind.F32: return module.unary(isCeil ? UnaryOp.CeilF32 : UnaryOp.FloorF32, arg0); + case TypeKind.F64: return module.unary(isCeil ? UnaryOp.CeilF64 : UnaryOp.FloorF64, arg0); } } - return module.unary(op, arg0); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, isCeil ? "ceil" : "floor", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.copysign: { // copysign(left: T, right: T) -> T if ( @@ -1418,28 +1343,19 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); - let op: BinaryOp; - switch (type.kind) { - // TODO: does an integer version make sense? - case TypeKind.F32: { op = BinaryOp.CopysignF32; break; } - case TypeKind.F64: { op = BinaryOp.CopysignF64; break; } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); + if (!type.is(TypeFlags.REFERENCE)) { + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); + switch (type.kind) { + // TODO: does an integer version make sense? + case TypeKind.F32: return module.binary(BinaryOp.CopysignF32, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.CopysignF64, arg0, arg1); } } - return module.binary(op, arg0, arg1); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "copysign", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.nearest: { // nearest(value: T) -> T if ( @@ -1450,47 +1366,28 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let expr: ExpressionRef; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.I32: - case TypeKind.I64: - case TypeKind.ISIZE: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.U32: - case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.BOOL: { - expr = arg0; - break; - } - case TypeKind.F32: { - expr = module.unary(UnaryOp.NearestF32, arg0); - break; - } - case TypeKind.F64: { - expr = module.unary(UnaryOp.NearestF64, arg0); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = module.unreachable(); - break; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: + case TypeKind.I64: + case TypeKind.ISIZE: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: + case TypeKind.BOOL: return arg0; + case TypeKind.F32: return module.unary(UnaryOp.NearestF32, arg0); + case TypeKind.F64: return module.unary(UnaryOp.NearestF64, arg0); } } - return expr; + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "nearest", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.reinterpret: { // reinterpret(value: *) -> T if ( @@ -1498,65 +1395,53 @@ export function compileCall( checkArgsRequired(operands, 1, reportNode, compiler) ) return module.unreachable(); let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.currentType = type; - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let expr: ExpressionRef; - switch (type.kind) { - case TypeKind.I32: - case TypeKind.U32: { - let arg0 = compiler.compileExpression(operands[0], Type.f32, Constraints.CONV_IMPLICIT); - expr = module.unary(UnaryOp.ReinterpretF32, arg0); - break; - } - case TypeKind.I64: - case TypeKind.U64: { - let arg0 = compiler.compileExpression(operands[0], Type.f64, Constraints.CONV_IMPLICIT); - expr = module.unary(UnaryOp.ReinterpretF64, arg0); - break; - } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - let arg0 = compiler.compileExpression(operands[0], - compiler.options.isWasm64 - ? Type.f64 - : Type.f32, - Constraints.CONV_IMPLICIT - ); - expr = module.unary( - compiler.options.isWasm64 - ? UnaryOp.ReinterpretF64 - : UnaryOp.ReinterpretF32, - arg0 - ); - break; - } - case TypeKind.F32: { - let arg0 = compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_IMPLICIT); - expr = module.unary(UnaryOp.ReinterpretI32, arg0); - break; - } - case TypeKind.F64: { - let arg0 = compiler.compileExpression(operands[0], Type.i64, Constraints.CONV_IMPLICIT); - expr = module.unary(UnaryOp.ReinterpretI64, arg0); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = module.unreachable(); - break; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I32: + case TypeKind.U32: { + let arg0 = compiler.compileExpression(operands[0], Type.f32, Constraints.CONV_IMPLICIT); + compiler.currentType = type; + return module.unary(UnaryOp.ReinterpretF32, arg0); + } + case TypeKind.I64: + case TypeKind.U64: { + let arg0 = compiler.compileExpression(operands[0], Type.f64, Constraints.CONV_IMPLICIT); + compiler.currentType = type; + return module.unary(UnaryOp.ReinterpretF64, arg0); + } + case TypeKind.ISIZE: + case TypeKind.USIZE: { + let arg0 = compiler.compileExpression(operands[0], + compiler.options.isWasm64 + ? Type.f64 + : Type.f32, + Constraints.CONV_IMPLICIT + ); + compiler.currentType = type; + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.ReinterpretF64 + : UnaryOp.ReinterpretF32, + arg0 + ); + } + case TypeKind.F32: { + let arg0 = compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.f32; + return module.unary(UnaryOp.ReinterpretI32, arg0); + } + case TypeKind.F64: { + let arg0 = compiler.compileExpression(operands[0], Type.i64, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.f64; + return module.unary(UnaryOp.ReinterpretI64, arg0); + } } } - compiler.currentType = type; - return expr; + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "reinterpret", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.sqrt: { // sqrt(value: T) -> T if ( @@ -1567,86 +1452,52 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.currentType = type; - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let expr: ExpressionRef; - switch (type.kind) { // TODO: integer versions (that return f64 or convert)? - case TypeKind.F32: { - expr = module.unary(UnaryOp.SqrtF32, arg0); - break; - } - case TypeKind.F64: { - expr = module.unary(UnaryOp.SqrtF64, arg0); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = module.unreachable(); - break; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + // TODO: integer versions (that return f64 or convert)? + case TypeKind.F32: return module.unary(UnaryOp.SqrtF32, arg0); + case TypeKind.F64: return module.unary(UnaryOp.SqrtF64, arg0); } } - return expr; - } - case BuiltinSymbols.trunc: { // trunc(value: T) -> T - if ( - checkTypeOptional(typeArguments, reportNode, compiler, true) | - checkArgsRequired(operands, 1, reportNode, compiler) - ) return module.unreachable(); - let arg0 = typeArguments - ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) - : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); - let type = compiler.currentType; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.range - ); - return module.unreachable(); - } - let expr: ExpressionRef; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.I32: - case TypeKind.I64: - case TypeKind.ISIZE: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.U32: - case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.BOOL: { - expr = arg0; - break; - } - // TODO: truncate to contextual type directly (if not void etc.)? - case TypeKind.F32: { - expr = module.unary(UnaryOp.TruncF32, arg0); - break; - } - case TypeKind.F64: { - expr = module.unary(UnaryOp.TruncF64, arg0); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = module.unreachable(); - break; + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "sqrt", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.trunc: { // trunc(value: T) -> T + if ( + checkTypeOptional(typeArguments, reportNode, compiler, true) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) return module.unreachable(); + let arg0 = typeArguments + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) + : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); + let type = compiler.currentType; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + // Nothing to do for integers + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: + case TypeKind.I64: + case TypeKind.ISIZE: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: + case TypeKind.BOOL: return arg0; + // TODO: truncate to contextual type directly? + case TypeKind.F32: return module.unary(UnaryOp.TruncF32, arg0); + case TypeKind.F64: return module.unary(UnaryOp.TruncF64, arg0); } } - return expr; + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "trunc", type.toString() + ); + return module.unreachable(); } // === Memory access ========================================================================== @@ -1800,8 +1651,8 @@ export function compileCall( ) ? contextualType : type; if (!type.is(TypeFlags.INTEGER)) { compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "atomic.load", type.toString() ); compiler.currentType = outType; return module.unreachable(); @@ -1831,10 +1682,10 @@ export function compileCall( checkArgsOptional(operands, 2, 3, reportNode, compiler) ) return module.unreachable(); let type = typeArguments![0]; - if (!type.is(TypeFlags.INTEGER) || type.size < 8) { + if (!type.is(TypeFlags.INTEGER)) { compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "atomic.store", type.toString() ); return module.unreachable(); } @@ -1891,9 +1742,19 @@ export function compileCall( ) return module.unreachable(); let type = typeArguments![0]; if (!type.is(TypeFlags.INTEGER) || type.size < 8) { + let opName: string; + switch (prototype.internalName) { + default: assert(false); + case BuiltinSymbols.atomic_add: { opName = "atomic.add"; break; } + case BuiltinSymbols.atomic_sub: { opName = "atomic.sub"; break; } + case BuiltinSymbols.atomic_and: { opName = "atomic.and"; break; } + case BuiltinSymbols.atomic_or: { opName = "atomic.or"; break; } + case BuiltinSymbols.atomic_xor: { opName = "atomic.xor"; break; } + case BuiltinSymbols.atomic_xchg: { opName = "atomic.xchg"; break; } + } compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, opName, type.toString() ); return module.unreachable(); } @@ -1944,9 +1805,7 @@ export function compileCall( case BuiltinSymbols.atomic_xchg: { op = AtomicRMWOp.Xchg; break; } } compiler.currentType = inType; - return module.atomic_rmw( - op, type.byteSize, immOffset, arg0, arg1, inType.toNativeType() - ); + return module.atomic_rmw(op, type.byteSize, immOffset, arg0, arg1, inType.toNativeType()); } case BuiltinSymbols.atomic_cmpxchg: { // cmpxchg(ptr: usize, expected: T, replacement: T, off?: usize) -> T if (!compiler.options.hasFeature(Feature.THREADS)) break; @@ -1957,8 +1816,8 @@ export function compileCall( let type = typeArguments![0]; if (!type.is(TypeFlags.INTEGER) || type.size < 8) { compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "atomic.cmpxchg", type.toString() ); return module.unreachable(); } @@ -2008,9 +1867,7 @@ export function compileCall( return module.unreachable(); } compiler.currentType = inType; - return module.atomic_cmpxchg( - type.byteSize, immOffset, arg0, arg1, arg2, inType.toNativeType() - ); + return module.atomic_cmpxchg(type.byteSize, immOffset, arg0, arg1, arg2, inType.toNativeType()); } case BuiltinSymbols.atomic_wait: { // wait(ptr: usize, expected: T, timeout: i64) -> i32 if (!compiler.options.hasFeature(Feature.THREADS)) break; @@ -2022,8 +1879,8 @@ export function compileCall( let type = typeArguments![0]; if (!type.is(TypeFlags.INTEGER) || type.size < 32) { compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "atomic.wait", type.toString() ); return module.unreachable(); } @@ -2082,8 +1939,8 @@ export function compileCall( let type = compiler.currentType; if (!type.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE)) { compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "select", type.toString() ); return module.unreachable(); } @@ -2178,8 +2035,8 @@ export function compileCall( compiler.currentType = toType; if (fromType.size != toType.size) { compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.range + DiagnosticCode.Type_0_cannot_be_changed_to_type_1, + reportNode.range, fromType.toString(), toType.toString() ); return module.unreachable(); } @@ -2260,7 +2117,6 @@ export function compileCall( // otherwise call abort if the assertion is false-ish let abort = compileAbort(compiler, operands.length == 2 ? operands[1] : null, reportNode); compiler.currentType = type.nonNullableType; - let expr: ExpressionRef; if (contextualType == Type.void) { // simplify if dropped anyway compiler.currentType = Type.void; switch (type.kind) { @@ -2270,24 +2126,12 @@ export function compileCall( case TypeKind.U8: case TypeKind.U16: case TypeKind.U32: - case TypeKind.BOOL: { - expr = module.if( - module.unary(UnaryOp.EqzI32, arg0), - abort - ); - break; - } + case TypeKind.BOOL: return module.if(module.unary(UnaryOp.EqzI32, arg0), abort); case TypeKind.I64: - case TypeKind.U64: { - expr = module.if( - module.unary(UnaryOp.EqzI64, arg0), - abort - ); - break; - } + case TypeKind.U64: return module.if(module.unary(UnaryOp.EqzI64, arg0), abort); case TypeKind.ISIZE: case TypeKind.USIZE: { - expr = module.if( + return module.if( module.unary( compiler.options.isWasm64 ? UnaryOp.EqzI64 @@ -2296,37 +2140,10 @@ export function compileCall( ), abort ); - break; } // TODO: also check for NaN in float assertions, as in `Boolean(NaN) -> false`? - case TypeKind.F32: { - expr = module.if( - module.binary(BinaryOp.EqF32, - arg0, - module.f32(0) - ), - abort - ); - break; - } - case TypeKind.F64: { - expr = module.if( - module.binary(BinaryOp.EqF64, - arg0, - module.f64(0) - ), - abort - ); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = abort; - break; - } + 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); } } else { compiler.currentType = type.nonNullableType; @@ -2341,29 +2158,27 @@ export function compileCall( let flow = compiler.currentFlow; let tempLocal = flow.getAndFreeTempLocal(type); flow.setLocalFlag(tempLocal.index, LocalFlags.WRAPPED); // arg0 is wrapped - expr = module.if( + return module.if( module.local_tee(tempLocal.index, arg0), module.local_get(tempLocal.index, NativeType.I32), abort ); - break; } case TypeKind.I64: case TypeKind.U64: { let tempLocal = compiler.currentFlow.getAndFreeTempLocal(Type.i64); - expr = module.if( + return module.if( module.unary(UnaryOp.EqzI64, module.local_tee(tempLocal.index, arg0) ), abort, module.local_get(tempLocal.index, NativeType.I64) ); - break; } case TypeKind.ISIZE: case TypeKind.USIZE: { let tempLocal = compiler.currentFlow.getAndFreeTempLocal(compiler.options.usizeType); - expr = module.if( + return module.if( module.unary( compiler.options.isWasm64 ? UnaryOp.EqzI64 @@ -2373,11 +2188,10 @@ export function compileCall( abort, module.local_get(tempLocal.index, compiler.options.nativeSizeType) ); - break; } case TypeKind.F32: { let tempLocal = compiler.currentFlow.getAndFreeTempLocal(Type.f32); - expr = module.if( + return module.if( module.binary(BinaryOp.EqF32, module.local_tee(tempLocal.index, arg0), module.f32(0) @@ -2385,11 +2199,10 @@ export function compileCall( abort, module.local_get(tempLocal.index, NativeType.F32) ); - break; } case TypeKind.F64: { let tempLocal = compiler.currentFlow.getAndFreeTempLocal(Type.f64); - expr = module.if( + return module.if( module.binary(BinaryOp.EqF64, module.local_tee(tempLocal.index, arg0), module.f64(0) @@ -2397,19 +2210,14 @@ export function compileCall( abort, module.local_get(tempLocal.index, NativeType.F64) ); - break; - } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - expr = abort; - break; } } } - return expr; + compiler.error( + DiagnosticCode.Not_implemented, + reportNode.typeArgumentsRange + ); + return abort; } case BuiltinSymbols.unchecked: { // unchecked(expr: *) -> * if ( @@ -2438,8 +2246,8 @@ export function compileCall( arg0Type.kind == TypeKind.U32 && arg0Type.signatureReference // or function reference )) { compiler.error( - DiagnosticCode.Operation_not_supported, - operands[0].range + DiagnosticCode.Type_0_is_not_a_function_index_or_function_reference, + operands[0].range, arg0Type.toString() ); return module.unreachable(); } @@ -2469,7 +2277,7 @@ export function compileCall( } } compiler.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_must_be_a_compile_time_constant, operands[0].range ); return module.unreachable(); @@ -2486,7 +2294,7 @@ export function compileCall( let classInstance = typeArgument.classReference; if (!(typeArgument.is(TypeFlags.REFERENCE) && classInstance !== null)) { compiler.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.This_expression_is_not_constructable, reportNode.typeArgumentsRange ); return module.unreachable(); @@ -2846,45 +2654,36 @@ export function compileCall( return module.unreachable(); } let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = Type.v128; - return module.unreachable(); - } - let op: UnaryOp; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = UnaryOp.SplatI8x16; break; } - case TypeKind.I16: - case TypeKind.U16: { op = UnaryOp.SplatI16x8; break; } - case TypeKind.I32: - case TypeKind.U32: { op = UnaryOp.SplatI32x4; break; } - case TypeKind.I64: - case TypeKind.U64: { op = UnaryOp.SplatI64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? UnaryOp.SplatI64x2 - : UnaryOp.SplatI32x4; - break; - } - case TypeKind.F32: { op = UnaryOp.SplatF32x4; break; } - case TypeKind.F64: { op = UnaryOp.SplatF64x2; break; } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = Type.v128; - return module.unreachable(); - } - } let arg0 = compiler.compileExpression(operands[0], type, Constraints.CONV_IMPLICIT); compiler.currentType = Type.v128; - return module.unary(op, arg0); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.unary(UnaryOp.SplatI8x16, arg0); + case TypeKind.I16: + case TypeKind.U16: return module.unary(UnaryOp.SplatI16x8, arg0); + case TypeKind.I32: + case TypeKind.U32: return module.unary(UnaryOp.SplatI32x4, arg0); + case TypeKind.I64: + case TypeKind.U64: return module.unary(UnaryOp.SplatI64x2, arg0); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.SplatI64x2 + : UnaryOp.SplatI32x4, + arg0 + ); + } + case TypeKind.F32: return module.unary(UnaryOp.SplatF32x4, arg0); + case TypeKind.F64: return module.unary(UnaryOp.SplatF64x2, arg0); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "splat", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.v128_extract_lane: { // extract_lane(x: v128, idx: u8) -> T if (!compiler.options.hasFeature(Feature.SIMD)) break; @@ -2893,63 +2692,55 @@ export function compileCall( checkArgsRequired(operands, 2, reportNode, compiler) ) return module.unreachable(); let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = type; - return module.unreachable(); - } - let op: SIMDExtractOp; - switch (type.kind) { - case TypeKind.I8: { op = SIMDExtractOp.ExtractLaneI8x16; break; } - case TypeKind.U8: { op = SIMDExtractOp.ExtractLaneU8x16; break; } - case TypeKind.I16: { op = SIMDExtractOp.ExtractLaneI16x8; break; } - case TypeKind.U16: { op = SIMDExtractOp.ExtractLaneU16x8; break; } - case TypeKind.I32: - case TypeKind.U32: { op = SIMDExtractOp.ExtractLaneI32x4; break; } - case TypeKind.I64: - case TypeKind.U64: { op = SIMDExtractOp.ExtractLaneI64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? SIMDExtractOp.ExtractLaneI64x2 - : SIMDExtractOp.ExtractLaneI32x4; - break; - } - case TypeKind.F32: { op = SIMDExtractOp.ExtractLaneF32x4; break; } - case TypeKind.F64: { op = SIMDExtractOp.ExtractLaneF64x2; break; } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = type; - return module.unreachable(); - } - } let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.precomputeExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT); compiler.currentType = type; - if (getExpressionId(arg1) != ExpressionId.Const) { + let idx = 0; + if (getExpressionId(arg1) == ExpressionId.Const) { + assert(getExpressionType(arg1) == NativeType.I32); + idx = getConstValueI32(arg1); + } else { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, operands[1].range ); - return module.unreachable(); } - assert(getExpressionType(arg1) == NativeType.I32); - let maxIdx = (16 / type.byteSize) - 1; - let idx = getConstValueI32(arg1); - if (idx < 0 || idx > maxIdx) { - compiler.error( - DiagnosticCode._0_must_be_a_value_between_1_and_2_inclusive, - operands[1].range, "Lane index", "0", maxIdx.toString() - ); - return module.unreachable(); + if (!type.is(TypeFlags.REFERENCE)) { + let maxIdx = (16 / assert(type.byteSize)) - 1; + if (idx < 0 || idx > maxIdx) { + compiler.error( + DiagnosticCode._0_must_be_a_value_between_1_and_2_inclusive, + operands[1].range, "Lane index", "0", maxIdx.toString() + ); + idx = 0; + } + switch (type.kind) { + case TypeKind.I8: return module.simd_extract(SIMDExtractOp.ExtractLaneI8x16, arg0, idx); + case TypeKind.U8: return module.simd_extract(SIMDExtractOp.ExtractLaneU8x16, arg0, idx); + case TypeKind.I16: return module.simd_extract(SIMDExtractOp.ExtractLaneI16x8, arg0, idx); + case TypeKind.U16: return module.simd_extract(SIMDExtractOp.ExtractLaneU16x8, arg0, idx); + case TypeKind.I32: + case TypeKind.U32: return module.simd_extract(SIMDExtractOp.ExtractLaneI32x4, arg0, idx); + case TypeKind.I64: + case TypeKind.U64: return module.simd_extract(SIMDExtractOp.ExtractLaneI64x2, arg0, idx); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.simd_extract( + compiler.options.isWasm64 + ? SIMDExtractOp.ExtractLaneI64x2 + : SIMDExtractOp.ExtractLaneI32x4, + arg0, idx + ); + } + case TypeKind.F32: return module.simd_extract(SIMDExtractOp.ExtractLaneF32x4, arg0, idx); + case TypeKind.F64: return module.simd_extract(SIMDExtractOp.ExtractLaneF64x2, arg0, idx); + } } - return module.simd_extract(op, arg0, idx); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "extract_lane", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.v128_replace_lane: { // replace_lane(x: v128, idx: u8, value: T) -> v128 if (!compiler.options.hasFeature(Feature.SIMD)) break; @@ -2961,65 +2752,56 @@ export function compileCall( return module.unreachable(); } let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = Type.v128; - return module.unreachable(); - } - let op: SIMDReplaceOp; - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = SIMDReplaceOp.ReplaceLaneI8x16; break; } - case TypeKind.I16: - case TypeKind.U16: { op = SIMDReplaceOp.ReplaceLaneI16x8; break; } - case TypeKind.I32: - case TypeKind.U32: { op = SIMDReplaceOp.ReplaceLaneI32x4; break; } - case TypeKind.I64: - case TypeKind.U64: { op = SIMDReplaceOp.ReplaceLaneI64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? SIMDReplaceOp.ReplaceLaneI64x2 - : SIMDReplaceOp.ReplaceLaneI32x4; - break; - } - case TypeKind.F32: { op = SIMDReplaceOp.ReplaceLaneF32x4; break; } - case TypeKind.F64: { op = SIMDReplaceOp.ReplaceLaneF64x2; break; } - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = Type.v128; - return module.unreachable(); - } - } let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.precomputeExpression(operands[1], Type.u8, Constraints.CONV_IMPLICIT); - if (getExpressionId(arg1) != ExpressionId.Const) { + let arg2 = compiler.compileExpression(operands[2], type, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.v128; + let idx = 0; + if (getExpressionId(arg1) == ExpressionId.Const) { + assert(getExpressionType(arg1) == NativeType.I32); + idx = getConstValueI32(arg1); + } else { compiler.error( DiagnosticCode.Expression_must_be_a_compile_time_constant, operands[1].range ); - compiler.currentType = Type.v128; - return module.unreachable(); } - assert(getExpressionType(arg1) == NativeType.I32); - let maxIdx = (16 / type.byteSize) - 1; - let idx = getConstValueI32(arg1); - if (idx < 0 || idx > maxIdx) { - compiler.error( - DiagnosticCode._0_must_be_a_value_between_1_and_2_inclusive, - operands[1].range, "Lane index", "0", maxIdx.toString() - ); - return module.unreachable(); + if (!type.is(TypeFlags.REFERENCE)) { + let maxIdx = (16 / assert(type.byteSize)) - 1; + if (idx < 0 || idx > maxIdx) { + compiler.error( + DiagnosticCode._0_must_be_a_value_between_1_and_2_inclusive, + operands[1].range, "Lane index", "0", maxIdx.toString() + ); + idx = 0; + } + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.simd_replace(SIMDReplaceOp.ReplaceLaneI8x16, arg0, idx, arg2); + case TypeKind.I16: + case TypeKind.U16: return module.simd_replace(SIMDReplaceOp.ReplaceLaneI16x8, arg0, idx, arg2); + case TypeKind.I32: + case TypeKind.U32: return module.simd_replace(SIMDReplaceOp.ReplaceLaneI32x4, arg0, idx, arg2); + case TypeKind.I64: + case TypeKind.U64: return module.simd_replace(SIMDReplaceOp.ReplaceLaneI64x2, arg0, idx, arg2); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.simd_replace( + compiler.options.isWasm64 + ? SIMDReplaceOp.ReplaceLaneI64x2 + : SIMDReplaceOp.ReplaceLaneI32x4, + arg0, idx, arg2 + ); + } + case TypeKind.F32: return module.simd_replace(SIMDReplaceOp.ReplaceLaneF32x4, arg0, idx, arg2); + case TypeKind.F64: return module.simd_replace(SIMDReplaceOp.ReplaceLaneF64x2, arg0, idx, arg2); + } } - let arg2 = compiler.compileExpression(operands[2], type, Constraints.CONV_IMPLICIT); - compiler.currentType = Type.v128; - return module.simd_replace(op, arg0, idx, arg2); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "replace_lane", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.v128_shuffle: { // shuffle(a: v128, b: v128, ...lanes: u8[]) -> v128 if (!compiler.options.hasFeature(Feature.SIMD)) break; @@ -3400,29 +3182,86 @@ export function compileCall( case TypeKind.I32: { op = BinaryOp.NarrowI32x4ToI16x8; break; } case TypeKind.U32: { op = BinaryOp.NarrowU32x4ToU16x8; break; } } - break; + break; + } + } + if (op == -1) { + compiler.error( + DiagnosticCode.Operation_not_supported, + reportNode.typeArgumentsRange + ); + compiler.currentType = Type.v128; + return module.unreachable(); + } + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.v128; + return module.binary(op, arg0, arg1); + } + case BuiltinSymbols.v128_neg: { + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.unary(UnaryOp.NegI8x16, arg0); + case TypeKind.I16: + case TypeKind.U16: return module.unary(UnaryOp.NegI16x8, arg0); + case TypeKind.I32: + case TypeKind.U32: return module.unary(UnaryOp.NegI32x4, arg0); + case TypeKind.I64: + case TypeKind.U64: return module.unary(UnaryOp.NegI64x2, arg0); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.NegI64x2 + : UnaryOp.NegI32x4, + arg0 + ); + } + case TypeKind.F32: return module.unary(UnaryOp.NegF32x4, arg0); + case TypeKind.F64: return module.unary(UnaryOp.NegF64x2, arg0); } } - if (op == -1) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "v128.neg", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_abs: { + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) { compiler.currentType = Type.v128; return module.unreachable(); } + let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); - compiler.currentType = Type.v128; - return module.binary(op, arg0, arg1); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.F32: return module.unary(UnaryOp.AbsF32x4, arg0); + case TypeKind.F64: return module.unary(UnaryOp.AbsF64x2, arg0); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "v128.abs", type.toString() + ); + return module.unreachable(); } - case BuiltinSymbols.v128_neg: // any_unary(a: v128) -> v128 - case BuiltinSymbols.v128_abs: - case BuiltinSymbols.v128_sqrt: - case BuiltinSymbols.v128_convert: - case BuiltinSymbols.v128_trunc_sat: - case BuiltinSymbols.v128_widen_low: - case BuiltinSymbols.v128_widen_high: { + case BuiltinSymbols.v128_sqrt: { if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( checkTypeRequired(typeArguments, reportNode, compiler) | @@ -3432,100 +3271,118 @@ export function compileCall( return module.unreachable(); } let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.range - ); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.F32: return module.unary(UnaryOp.SqrtF32x4, arg0); + case TypeKind.F64: return module.unary(UnaryOp.SqrtF64x2, arg0); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "v128.sqrt", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_convert: { + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) { compiler.currentType = Type.v128; return module.unreachable(); } - let op: UnaryOp = -1; - switch (prototype.internalName) { - case BuiltinSymbols.v128_neg: { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = UnaryOp.NegI8x16; break; } - case TypeKind.I16: - case TypeKind.U16: { op = UnaryOp.NegI16x8; break; } - case TypeKind.I32: - case TypeKind.U32: { op = UnaryOp.NegI32x4; break; } - case TypeKind.I64: - case TypeKind.U64: { op = UnaryOp.NegI64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? UnaryOp.NegI64x2 - : UnaryOp.NegI32x4; - break; - } - case TypeKind.F32: { op = UnaryOp.NegF32x4; break; } - case TypeKind.F64: { op = UnaryOp.NegF64x2; break; } - } - break; - } - case BuiltinSymbols.v128_abs: { - switch (type.kind) { - case TypeKind.F32: { op = UnaryOp.AbsF32x4; break; } - case TypeKind.F64: { op = UnaryOp.AbsF64x2; break; } - } - break; - } - case BuiltinSymbols.v128_sqrt: { - switch (type.kind) { - case TypeKind.F32: { op = UnaryOp.SqrtF32x4; break; } - case TypeKind.F64: { op = UnaryOp.SqrtF64x2; break; } - } - break; - } - case BuiltinSymbols.v128_convert: { - switch (type.kind) { - case TypeKind.I32: { op = UnaryOp.ConvertI32x4ToF32x4; break; } - case TypeKind.U32: { op = UnaryOp.ConvertU32x4ToF32x4; break; } - case TypeKind.I64: { op = UnaryOp.ConvertI64x2ToF64x2; break; } - case TypeKind.U64: { op = UnaryOp.ConvertU64x2ToF64x2; break; } - } - break; - } - case BuiltinSymbols.v128_trunc_sat: { - switch (type.kind) { - case TypeKind.I32: { op = UnaryOp.TruncSatF32x4ToI32x4; break; } - case TypeKind.U32: { op = UnaryOp.TruncSatF32x4ToU32x4; break; } - case TypeKind.I64: { op = UnaryOp.TruncSatF64x2ToI64x2; break; } - case TypeKind.U64: { op = UnaryOp.TruncSatF64x2ToU64x2; break; } - } - break; + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I32: return module.unary(UnaryOp.ConvertI32x4ToF32x4, arg0); + case TypeKind.U32: return module.unary(UnaryOp.ConvertU32x4ToF32x4, arg0); + case TypeKind.I64: return module.unary(UnaryOp.ConvertI64x2ToF64x2, arg0); + case TypeKind.U64: return module.unary(UnaryOp.ConvertU64x2ToF64x2, arg0); } - case BuiltinSymbols.v128_widen_low: { - switch (type.kind) { - case TypeKind.I8: { op = UnaryOp.WidenLowI8x16ToI16x8; break; } - case TypeKind.U8: { op = UnaryOp.WidenLowU8x16ToU16x8; break; } - case TypeKind.I16: { op = UnaryOp.WidenLowI16x8ToI32x4; break; } - case TypeKind.U16: { op = UnaryOp.WidenLowU16x8ToU32x4; break; } - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "v128.convert", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_trunc_sat: { + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I32: return module.unary(UnaryOp.TruncSatF32x4ToI32x4, arg0); + case TypeKind.U32: return module.unary(UnaryOp.TruncSatF32x4ToU32x4, arg0); + case TypeKind.I64: return module.unary(UnaryOp.TruncSatF64x2ToI64x2, arg0); + case TypeKind.U64: return module.unary(UnaryOp.TruncSatF64x2ToU64x2, arg0); } - case BuiltinSymbols.v128_widen_high: { - switch (type.kind) { - case TypeKind.I8: { op = UnaryOp.WidenHighI8x16ToI16x8; break; } - case TypeKind.U8: { op = UnaryOp.WidenHighU8x16ToU16x8; break; } - case TypeKind.I16: { op = UnaryOp.WidenHighI16x8ToI32x4; break; } - case TypeKind.U16: { op = UnaryOp.WidenHighU16x8ToU32x4; break; } - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "v128.trunc_sat", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_widen_low: { + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.unary(UnaryOp.WidenLowI8x16ToI16x8, arg0); + case TypeKind.U8: return module.unary(UnaryOp.WidenLowU8x16ToU16x8, arg0); + case TypeKind.I16: return module.unary(UnaryOp.WidenLowI16x8ToI32x4, arg0); + case TypeKind.U16: return module.unary(UnaryOp.WidenLowU16x8ToU32x4, arg0); } } - if (op == -1) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "v128.widen_low", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_widen_high: { + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) { compiler.currentType = Type.v128; return module.unreachable(); } + let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); - compiler.currentType = Type.v128; - return module.unary(op, arg0); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.unary(UnaryOp.WidenHighI8x16ToI16x8, arg0); + case TypeKind.U8: return module.unary(UnaryOp.WidenHighU8x16ToU16x8, arg0); + case TypeKind.I16: return module.unary(UnaryOp.WidenHighI16x8ToI32x4, arg0); + case TypeKind.U16: return module.unary(UnaryOp.WidenHighU16x8ToU32x4, arg0); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.range, "v128.widen_high", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.v128_shl: // any_shift(a: v128, b: i32) -> v128 case BuiltinSymbols.v128_shr: { @@ -3537,79 +3394,81 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } + let isShl = prototype.internalName == BuiltinSymbols.v128_shl; let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = Type.v128; - return module.unreachable(); - } - let op: SIMDShiftOp = -1; - switch (prototype.internalName) { - case BuiltinSymbols.v128_shl: { + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.i32, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.v128; + if (!type.is(TypeFlags.REFERENCE)) { + if (isShl) { switch (type.kind) { case TypeKind.I8: - case TypeKind.U8: { op = SIMDShiftOp.ShlI8x16; break; } + case TypeKind.U8: return module.simd_shift(SIMDShiftOp.ShlI8x16, arg0, arg1); case TypeKind.I16: - case TypeKind.U16: { op = SIMDShiftOp.ShlI16x8; break; } + case TypeKind.U16: return module.simd_shift(SIMDShiftOp.ShlI16x8, arg0, arg1); case TypeKind.I32: - case TypeKind.U32: { op = SIMDShiftOp.ShlI32x4; break; } + case TypeKind.U32: return module.simd_shift(SIMDShiftOp.ShlI32x4, arg0, arg1); case TypeKind.I64: - case TypeKind.U64: { op = SIMDShiftOp.ShlI64x2; break; } + case TypeKind.U64: return module.simd_shift(SIMDShiftOp.ShlI64x2, arg0, arg1); case TypeKind.ISIZE: case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? SIMDShiftOp.ShlI64x2 - : SIMDShiftOp.ShlI32x4; - break; + return module.simd_shift( + compiler.options.isWasm64 + ? SIMDShiftOp.ShlI64x2 + : SIMDShiftOp.ShlI32x4, + arg0, arg1 + ); } } - break; - } - case BuiltinSymbols.v128_shr: { + } else { switch (type.kind) { - case TypeKind.I8: { op = SIMDShiftOp.ShrI8x16; break; } - case TypeKind.U8: { op = SIMDShiftOp.ShrU8x16; break; } - case TypeKind.I16: { op = SIMDShiftOp.ShrI16x8; break; } - case TypeKind.U16: { op = SIMDShiftOp.ShrU16x8; break; } - case TypeKind.I32: { op = SIMDShiftOp.ShrI32x4; break; } - case TypeKind.U32: { op = SIMDShiftOp.ShrU32x4; break; } - case TypeKind.I64: { op = SIMDShiftOp.ShrI64x2; break; } - case TypeKind.U64: { op = SIMDShiftOp.ShrU64x2; break; } + case TypeKind.I8: return module.simd_shift(SIMDShiftOp.ShrI8x16, arg0, arg1); + case TypeKind.U8: return module.simd_shift(SIMDShiftOp.ShrU8x16, arg0, arg1); + case TypeKind.I16: return module.simd_shift(SIMDShiftOp.ShrI16x8, arg0, arg1); + case TypeKind.U16: return module.simd_shift(SIMDShiftOp.ShrU16x8, arg0, arg1); + case TypeKind.I32: return module.simd_shift(SIMDShiftOp.ShrI32x4, arg0, arg1); + case TypeKind.U32: return module.simd_shift(SIMDShiftOp.ShrU32x4, arg0, arg1); + case TypeKind.I64: return module.simd_shift(SIMDShiftOp.ShrI64x2, arg0, arg1); + case TypeKind.U64: return module.simd_shift(SIMDShiftOp.ShrU64x2, arg0, arg1); case TypeKind.ISIZE: { - op = compiler.options.isWasm64 - ? SIMDShiftOp.ShrI64x2 - : SIMDShiftOp.ShrI32x4; - break; + return module.simd_shift( + compiler.options.isWasm64 + ? SIMDShiftOp.ShrI64x2 + : SIMDShiftOp.ShrI32x4, + arg0, arg1 + ); } case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? SIMDShiftOp.ShrU64x2 - : SIMDShiftOp.ShrU32x4; - break; + return module.simd_shift( + compiler.options.isWasm64 + ? SIMDShiftOp.ShrU64x2 + : SIMDShiftOp.ShrU32x4, + arg0, arg1 + ); } } - break; } } - if (op == -1) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.range - ); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, isShl ? "shl" : "shr", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_and: { // and(a: v128) -> v128 + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeAbsent(typeArguments, reportNode, prototype) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { compiler.currentType = Type.v128; return module.unreachable(); } let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); - let arg1 = compiler.compileExpression(operands[1], Type.i32, Constraints.CONV_IMPLICIT); - compiler.currentType = Type.v128; - return module.simd_shift(op, arg0, arg1); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + return module.binary(BinaryOp.AndV128, arg0, arg1); } - case BuiltinSymbols.v128_and: // any_bitwise_binary(a: v128, b: v128) -> v128 - case BuiltinSymbols.v128_or: - case BuiltinSymbols.v128_xor: { + case BuiltinSymbols.v128_or: { // or(a: v128) -> v128 if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( checkTypeAbsent(typeArguments, reportNode, prototype) | @@ -3618,18 +3477,24 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let op: BinaryOp = -1; - switch (prototype.internalName) { - default: assert(false); - case BuiltinSymbols.v128_and: { op = BinaryOp.AndV128; break; } - case BuiltinSymbols.v128_or: { op = BinaryOp.OrV128; break; } - case BuiltinSymbols.v128_xor: { op = BinaryOp.XorV128; break; } + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + return module.binary(BinaryOp.OrV128, arg0, arg1); + } + case BuiltinSymbols.v128_xor: { // xor(a: v128) -> v128 + if (!compiler.options.hasFeature(Feature.SIMD)) break; + if ( + checkTypeAbsent(typeArguments, reportNode, prototype) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); } let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); - return module.binary(op, arg0, arg1); + return module.binary(BinaryOp.XorV128, arg0, arg1); } - case BuiltinSymbols.v128_not: { // any_bitwise_unary(a: v128) -> v128 + case BuiltinSymbols.v128_not: { // not(a: v128) -> v128 if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( checkTypeAbsent(typeArguments, reportNode, prototype) | @@ -3641,6 +3506,19 @@ export function compileCall( let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); return module.unary(UnaryOp.NotV128, arg0); } + // case BuiltinSymbols.v128_andnot: { // andnot(a: v128, b: v128) -> v128 + // if (!compiler.options.hasFeature(Feature.SIMD)) break; + // if ( + // checkTypeAbsent(typeArguments, reportNode, prototype) | + // checkArgsRequired(operands, 2, reportNode, compiler) + // ) { + // compiler.currentType = Type.v128; + // return module.unreachable(); + // } + // let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + // let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + // return module.binary(BinaryOp.AndnotV128, arg0); + // } case BuiltinSymbols.v128_bitselect: { // bitselect(v1: v128, v2: v128, c: v128) -> v128 if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( @@ -3665,69 +3543,58 @@ export function compileCall( compiler.currentType = Type.bool; return module.unreachable(); } + let isAnyTrue = prototype.internalName == BuiltinSymbols.v128_any_true; let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } - let op: UnaryOp = -1; - switch (prototype.internalName) { - default: assert(false); - case BuiltinSymbols.v128_any_true: { + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.bool; + if (!type.is(TypeFlags.REFERENCE)) { + if (isAnyTrue) { switch (type.kind) { case TypeKind.I8: - case TypeKind.U8: { op = UnaryOp.AnyTrueI8x16; break; } + case TypeKind.U8: return module.unary(UnaryOp.AnyTrueI8x16, arg0); case TypeKind.I16: - case TypeKind.U16: { op = UnaryOp.AnyTrueI16x8; break; } + case TypeKind.U16: return module.unary(UnaryOp.AnyTrueI16x8, arg0); case TypeKind.I32: - case TypeKind.U32: { op = UnaryOp.AnyTrueI32x4; break; } + case TypeKind.U32: return module.unary(UnaryOp.AnyTrueI32x4, arg0); case TypeKind.I64: - case TypeKind.U64: { op = UnaryOp.AnyTrueI64x2; break; } + case TypeKind.U64: return module.unary(UnaryOp.AnyTrueI64x2, arg0); case TypeKind.ISIZE: case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? UnaryOp.AnyTrueI64x2 - : UnaryOp.AnyTrueI32x4; - break; + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.AnyTrueI64x2 + : UnaryOp.AnyTrueI32x4, + arg0 + ); } } - break; - } - case BuiltinSymbols.v128_all_true: { + } else { switch (type.kind) { case TypeKind.I8: - case TypeKind.U8: { op = UnaryOp.AllTrueI8x16; break; } + case TypeKind.U8: return module.unary(UnaryOp.AllTrueI8x16, arg0); case TypeKind.I16: - case TypeKind.U16: { op = UnaryOp.AllTrueI16x8; break; } + case TypeKind.U16: return module.unary(UnaryOp.AllTrueI16x8, arg0); case TypeKind.I32: - case TypeKind.U32: { op = UnaryOp.AllTrueI32x4; break; } + case TypeKind.U32: return module.unary(UnaryOp.AllTrueI32x4, arg0); case TypeKind.I64: - case TypeKind.U64: { op = UnaryOp.AllTrueI64x2; break; } + case TypeKind.U64: return module.unary(UnaryOp.AllTrueI64x2, arg0); case TypeKind.ISIZE: case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? UnaryOp.AllTrueI64x2 - : UnaryOp.AllTrueI32x4; - break; + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.AllTrueI64x2 + : UnaryOp.AllTrueI32x4, + arg0 + ); } } - break; } } - if (op == -1) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = Type.bool; - return module.unreachable(); - } - let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); - compiler.currentType = Type.bool; - return module.unary(op, arg0); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, isAnyTrue ? "any_true" : "all_true", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.v128_qfma: // qfma(a: v128, b: v128, c: v128) -> v128 case BuiltinSymbols.v128_qfms: { // qfms(a: v128, b: v128, c: v128) -> v128 @@ -3739,27 +3606,29 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let op: SIMDTernaryOp; + let isQfma = prototype.internalName == BuiltinSymbols.v128_qfma; let type = typeArguments![0]; - if (type == Type.f32) { - op = prototype.internalName == BuiltinSymbols.v128_qfma - ? SIMDTernaryOp.QFMAF32x4 - : SIMDTernaryOp.QFMSF32x4; - } else if (type == Type.f64) { - op = prototype.internalName == BuiltinSymbols.v128_qfma - ? SIMDTernaryOp.QFMAF64x2 - : SIMDTernaryOp.QFMSF64x2; - } else { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - return module.unreachable(); - } let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); let arg2 = compiler.compileExpression(operands[2], Type.v128, Constraints.CONV_IMPLICIT); - return module.simd_ternary(op, arg0, arg1, arg2); + if (!type.is(TypeFlags.REFERENCE)) { + if (isQfma) { + switch (type.kind) { + case TypeKind.F32: return module.simd_ternary(SIMDTernaryOp.QFMAF32x4, arg0, arg1, arg2); + case TypeKind.F64: return module.simd_ternary(SIMDTernaryOp.QFMAF64x2, arg0, arg1, arg2); + } + } else { + switch (type.kind) { + case TypeKind.F32: return module.simd_ternary(SIMDTernaryOp.QFMSF32x4, arg0, arg1, arg2); + case TypeKind.F64: return module.simd_ternary(SIMDTernaryOp.QFMSF64x2, arg0, arg1, arg2); + } + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, isQfma ? "qfma" : "qfms", type.toString() + ); + return module.unreachable(); } // === Internal runtime ======================================================================= @@ -3779,8 +3648,8 @@ export function compileCall( } } compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange + DiagnosticCode.Type_0_is_not_a_class_or_function_type, + reportNode.typeArgumentsRange, type.toString() ); return module.unreachable(); } diff --git a/src/compiler.ts b/src/compiler.ts index a6301298de..57311276a0 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -6126,7 +6126,7 @@ export class Compiler extends DiagnosticEmitter { // Library files may always use unsafe features if (this.options.noUnsafe && !reportNode.range.source.isLibrary) { this.error( - DiagnosticCode.Expression_is_unsafe, + DiagnosticCode.Operation_is_unsafe, reportNode.range ); } @@ -7777,7 +7777,7 @@ export class Compiler extends DiagnosticEmitter { if (!target) return module.unreachable(); if (target.kind != ElementKind.CLASS_PROTOTYPE) { this.error( - DiagnosticCode.Cannot_use_new_with_an_expression_whose_type_lacks_a_construct_signature, + DiagnosticCode.This_expression_is_not_constructable, expression.expression.range ); return this.module.unreachable(); diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 5e6f076bbe..cc89de4046 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -10,32 +10,34 @@ export enum DiagnosticCode { Operation_not_supported = 100, Operation_is_unsafe = 101, User_defined_0 = 102, + Not_implemented = 103, Conversion_from_type_0_to_1_requires_an_explicit_cast = 200, Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201, Type_0_cannot_be_changed_to_type_1 = 202, - Type_0_cannot_be_reinterpreted_as_type_1 = 203, + Operation_0_cannot_be_applied_to_type_1 = 203, Basic_type_0_cannot_be_nullable = 204, Cannot_export_a_mutable_global = 205, Mutable_value_cannot_be_inlined = 206, Unmanaged_classes_cannot_extend_managed_classes_and_vice_versa = 207, Unmanaged_classes_cannot_implement_interfaces = 208, Invalid_regular_expression_flags = 209, - Implementation_0_must_match_the_signature_1 = 210, + Expression_is_never_null = 210, Class_0_is_sealed_and_cannot_be_extended = 211, Decorator_0_is_not_valid_here = 212, Duplicate_decorator = 213, - An_allocator_must_be_present_to_use_0 = 214, + Type_0_is_not_a_class_or_function_type = 214, Optional_parameter_must_have_an_initializer = 215, Constructor_of_class_0_must_not_require_any_arguments = 216, Function_0_cannot_be_inlined_into_itself = 217, Cannot_access_method_0_without_calling_it_as_it_requires_this_to_be_set = 218, Optional_properties_are_not_supported = 219, Expression_must_be_a_compile_time_constant = 220, - Module_cannot_have_multiple_start_functions = 221, + Type_0_is_not_a_function_index_or_function_reference = 221, _0_must_be_a_value_between_1_and_2_inclusive = 222, _0_must_be_a_power_of_two = 223, - Expression_is_unsafe = 224, - Expression_is_never_null = 225, + _0_is_not_a_valid_operator = 224, + Expression_cannot_be_represented_by_a_type = 225, + Type_0_is_illegal_in_this_context = 226, Unterminated_string_literal = 1002, Identifier_expected = 1003, _0_expected = 1005, @@ -105,7 +107,7 @@ export enum DiagnosticCode { Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors = 2337, Property_0_does_not_exist_on_type_1 = 2339, Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures = 2349, - Cannot_use_new_with_an_expression_whose_type_lacks_a_construct_signature = 2351, + This_expression_is_not_constructable = 2351, A_function_whose_declared_type_is_not_void_must_return_a_value = 2355, The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access = 2357, The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access = 2364, @@ -147,35 +149,37 @@ export enum DiagnosticCode { /** Translates a diagnostic code to its respective string. */ export function diagnosticCodeToString(code: DiagnosticCode): string { switch (code) { - case 100: return "Operation not supported."; + case 100: return "Operation not supported"; case 101: return "Operation is unsafe."; case 102: return "User-defined: {0}"; + case 103: return "Not implemented."; case 200: return "Conversion from type '{0}' to '{1}' requires an explicit cast."; case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit."; case 202: return "Type '{0}' cannot be changed to type '{1}'."; - case 203: return "Type '{0}' cannot be reinterpreted as type '{1}'."; + case 203: return "Operation '{0}' cannot be applied to type '{1}'."; case 204: return "Basic type '{0}' cannot be nullable."; case 205: return "Cannot export a mutable global."; case 206: return "Mutable value cannot be inlined."; case 207: return "Unmanaged classes cannot extend managed classes and vice-versa."; case 208: return "Unmanaged classes cannot implement interfaces."; case 209: return "Invalid regular expression flags."; - case 210: return "Implementation '{0}' must match the signature '{1}'."; + case 210: return "Expression is never 'null'."; case 211: return "Class '{0}' is sealed and cannot be extended."; case 212: return "Decorator '{0}' is not valid here."; case 213: return "Duplicate decorator."; - case 214: return "An allocator must be present to use '{0}'."; + case 214: return "Type '{0}' is not a class or function type."; case 215: return "Optional parameter must have an initializer."; case 216: return "Constructor of class '{0}' must not require any arguments."; case 217: return "Function '{0}' cannot be inlined into itself."; case 218: return "Cannot access method '{0}' without calling it as it requires 'this' to be set."; case 219: return "Optional properties are not supported."; case 220: return "Expression must be a compile-time constant."; - case 221: return "Module cannot have multiple start functions."; + case 221: return "Type '{0}' is not a function index or function reference."; case 222: return "'{0}' must be a value between '{1}' and '{2}' inclusive."; case 223: return "'{0}' must be a power of two."; - case 224: return "Expression is unsafe."; - case 225: return "Expression is never 'null'."; + case 224: return "'{0}' is not a valid operator."; + case 225: return "Expression cannot be represented by a type."; + case 226: return "Type '{0}' is illegal in this context."; case 1002: return "Unterminated string literal."; case 1003: return "Identifier expected."; case 1005: return "'{0}' expected."; @@ -245,7 +249,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2337: return "Super calls are not permitted outside constructors or in nested functions inside constructors."; case 2339: return "Property '{0}' does not exist on type '{1}'."; case 2349: return "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures."; - case 2351: return "Cannot use 'new' with an expression whose type lacks a construct signature."; + case 2351: return "This expression is not constructable."; case 2355: return "A function whose declared type is not 'void' must return a value."; case 2357: return "The operand of an increment or decrement operator must be a variable or a property access."; case 2364: return "The left-hand side of an assignment expression must be a variable or a property access."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 17c832cee4..7898eb2aa2 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -1,33 +1,36 @@ { - "Operation not supported.": 100, + "Operation not supported": 100, "Operation is unsafe.": 101, "User-defined: {0}": 102, + "Not implemented.": 103, + "Conversion from type '{0}' to '{1}' requires an explicit cast.": 200, "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201, "Type '{0}' cannot be changed to type '{1}'.": 202, - "Type '{0}' cannot be reinterpreted as type '{1}'.": 203, + "Operation '{0}' cannot be applied to type '{1}'.": 203, "Basic type '{0}' cannot be nullable.": 204, "Cannot export a mutable global.": 205, "Mutable value cannot be inlined.": 206, "Unmanaged classes cannot extend managed classes and vice-versa.": 207, "Unmanaged classes cannot implement interfaces.": 208, "Invalid regular expression flags.": 209, - "Implementation '{0}' must match the signature '{1}'.": 210, + "Expression is never 'null'.": 210, "Class '{0}' is sealed and cannot be extended.": 211, "Decorator '{0}' is not valid here.": 212, "Duplicate decorator.": 213, - "An allocator must be present to use '{0}'.": 214, + "Type '{0}' is not a class or function type.": 214, "Optional parameter must have an initializer.": 215, "Constructor of class '{0}' must not require any arguments.": 216, "Function '{0}' cannot be inlined into itself.": 217, "Cannot access method '{0}' without calling it as it requires 'this' to be set.": 218, "Optional properties are not supported.": 219, "Expression must be a compile-time constant.": 220, - "Module cannot have multiple start functions.": 221, + "Type '{0}' is not a function index or function reference.": 221, "'{0}' must be a value between '{1}' and '{2}' inclusive.": 222, "'{0}' must be a power of two.": 223, - "Expression is unsafe.": 224, - "Expression is never 'null'.": 225, + "'{0}' is not a valid operator.": 224, + "Expression cannot be represented by a type.": 225, + "Type '{0}' is illegal in this context.": 226, "Unterminated string literal.": 1002, "Identifier expected.": 1003, @@ -99,7 +102,7 @@ "Super calls are not permitted outside constructors or in nested functions inside constructors.": 2337, "Property '{0}' does not exist on type '{1}'.": 2339, "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures.": 2349, - "Cannot use 'new' with an expression whose type lacks a construct signature.": 2351, + "This expression is not constructable.": 2351, "A function whose declared type is not 'void' must return a value.": 2355, "The operand of an increment or decrement operator must be a variable or a property access.": 2357, "The left-hand side of an assignment expression must be a variable or a property access.": 2364, diff --git a/src/parser.ts b/src/parser.ts index 5466a06287..c12d964ee1 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -647,7 +647,7 @@ export class Parser extends DiagnosticEmitter { if (!t) return null; if (t.kind != NodeKind.NAMEDTYPE) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Identifier_expected, t.range ); this.tryParseSignatureIsSignature = true; @@ -1085,7 +1085,7 @@ export class Parser extends DiagnosticEmitter { if (!t) return null; if (t.kind != NodeKind.NAMEDTYPE) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Identifier_expected, t.range ); return null; @@ -1098,7 +1098,7 @@ export class Parser extends DiagnosticEmitter { if (!t) return null; if (t.kind != NodeKind.NAMEDTYPE) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Identifier_expected, t.range ); return null; @@ -1145,7 +1145,7 @@ export class Parser extends DiagnosticEmitter { this.parseParametersThis = thisType; } else { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Identifier_expected, thisType.range ); } @@ -1605,7 +1605,7 @@ export class Parser extends DiagnosticEmitter { if (!t) return null; if (t.kind != NodeKind.NAMEDTYPE) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Identifier_expected, t.range ); return null; @@ -2504,7 +2504,7 @@ export class Parser extends DiagnosticEmitter { if (tn.skip(Token.COMMA)) { // TODO: default + star, default + members this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, tn.range() ); return null; @@ -3276,8 +3276,8 @@ export class Parser extends DiagnosticEmitter { ); } else { this.error( - DiagnosticCode.Operation_not_supported, - tn.range() + DiagnosticCode.This_expression_is_not_constructable, + operand.range ); } return null; diff --git a/src/program.ts b/src/program.ts index 3c59790641..3bdd75a847 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1262,8 +1262,8 @@ export class Program extends DiagnosticEmitter { } else if (numImplementsTypes) { // remember classes that implement interfaces for (let i = 0; i < numImplementsTypes; ++i) { - this.warning( // TODO: not yet supported - DiagnosticCode.Operation_not_supported, + this.warning( + DiagnosticCode.Not_implemented, implementsTypes[i].range ); } @@ -1387,14 +1387,12 @@ export class Program extends DiagnosticEmitter { firstArg.kind == NodeKind.LITERAL && (firstArg).literalKind == LiteralKind.STRING ) { - let kind = OperatorKind.fromDecorator( - decorator.decoratorKind, - (firstArg).value - ); + let text = (firstArg).value; + let kind = OperatorKind.fromDecorator(decorator.decoratorKind, text); if (kind == OperatorKind.INVALID) { this.error( - DiagnosticCode.Operation_not_supported, - firstArg.range + DiagnosticCode._0_is_not_a_valid_operator, + firstArg.range, text ); } else { let overloads = classPrototype.overloadPrototypes; diff --git a/src/resolver.ts b/src/resolver.ts index 3b7b8827df..550806c5e2 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -922,7 +922,7 @@ export class Resolver extends DiagnosticEmitter { } if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, node.range ); } @@ -1046,7 +1046,7 @@ export class Resolver extends DiagnosticEmitter { } if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, node.range ); } @@ -1132,7 +1132,7 @@ export class Resolver extends DiagnosticEmitter { if (!type) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_cannot_be_represented_by_a_type, node.range ); } @@ -1359,7 +1359,7 @@ export class Resolver extends DiagnosticEmitter { if (!type) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_cannot_be_represented_by_a_type, node.range ); } @@ -1418,7 +1418,7 @@ export class Resolver extends DiagnosticEmitter { if (!type) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_cannot_be_represented_by_a_type, node.range ); } @@ -1515,8 +1515,8 @@ export class Resolver extends DiagnosticEmitter { if (element) return element; if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, - node.range + DiagnosticCode.Type_0_is_illegal_in_this_context, + node.range, type.toString() ); } this.currentThisExpression = null; @@ -1716,11 +1716,10 @@ export class Resolver extends DiagnosticEmitter { } return type; } - default: assert(false); } if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, node.range ); } @@ -1744,8 +1743,8 @@ export class Resolver extends DiagnosticEmitter { if (element) return element; // otherwise void if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, - node.range + DiagnosticCode.Type_0_is_illegal_in_this_context, + node.range, type.toString() ); } return null; @@ -1942,10 +1941,9 @@ export class Resolver extends DiagnosticEmitter { return this.resolveExpression(left, ctxFlow, ctxType, reportMode); } } - if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, node.range ); } @@ -2003,7 +2001,7 @@ export class Resolver extends DiagnosticEmitter { if (!type) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_cannot_be_represented_by_a_type, node.range ); } @@ -2062,7 +2060,7 @@ export class Resolver extends DiagnosticEmitter { if (!type) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_cannot_be_represented_by_a_type, node.range ); } @@ -2111,7 +2109,7 @@ export class Resolver extends DiagnosticEmitter { } if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, node.range ); } @@ -2135,7 +2133,7 @@ export class Resolver extends DiagnosticEmitter { if (!type) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_cannot_be_represented_by_a_type, node.range ); } @@ -2160,8 +2158,8 @@ export class Resolver extends DiagnosticEmitter { if (!element) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, - node.range + DiagnosticCode.Type_0_is_illegal_in_this_context, + node.range, type.toString() ); } } @@ -2299,8 +2297,8 @@ export class Resolver extends DiagnosticEmitter { if (!element) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, - node.range + DiagnosticCode.Type_0_is_illegal_in_this_context, + node.range, type.toString() ); } } @@ -2359,7 +2357,7 @@ export class Resolver extends DiagnosticEmitter { } if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Cannot_use_new_with_an_expression_whose_type_lacks_a_construct_signature, + DiagnosticCode.This_expression_is_not_constructable, node.range ); } @@ -2383,7 +2381,7 @@ export class Resolver extends DiagnosticEmitter { if (!type) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Expression_cannot_be_represented_by_a_type, node.range ); } @@ -2408,8 +2406,8 @@ export class Resolver extends DiagnosticEmitter { if (!element) { if (reportMode == ReportMode.REPORT) { this.error( - DiagnosticCode.Operation_not_supported, - node.range + DiagnosticCode.Type_0_is_illegal_in_this_context, + node.range, type.toString() ); } } diff --git a/tests/compiler/unsafe.json b/tests/compiler/unsafe.json index 64cda034fb..044af5cc1e 100644 --- a/tests/compiler/unsafe.json +++ b/tests/compiler/unsafe.json @@ -5,30 +5,30 @@ ], "stderr": [ "AS212: Decorator '@unsafe' is not valid here.", - "AS224: Expression is unsafe.", "f1();", - "AS224: Expression is unsafe.", "f2();", - "AS224: Expression is unsafe.", "= new Foo();", - "AS224: Expression is unsafe.", "super();", - "AS224: Expression is unsafe.", ": Foo = {};", - "AS224: Expression is unsafe.", "= instantiate()", - "AS224: Expression is unsafe.", "Foo.bar();", - "AS224: Expression is unsafe.", "foo.bar();", - "AS224: Expression is unsafe.", " = Foo.foo;", - "AS224: Expression is unsafe.", "Foo.foo = 1;", - "AS224: Expression is unsafe.", "Foo.foo++;", - "AS224: Expression is unsafe.", "Foo.foo += 1;", - "AS224: Expression is unsafe.", " = foo.foo;", - "AS224: Expression is unsafe.", "foo.foo = 1;", - "AS224: Expression is unsafe.", "foo.foo++;", - "AS224: Expression is unsafe.", "foo.foo += 1;", - "AS224: Expression is unsafe.", "= Foo.baz;", - "AS224: Expression is unsafe.", "Foo.baz = 1;", - "AS224: Expression is unsafe.", "Foo.baz++;", - "AS224: Expression is unsafe.", "Foo.baz += 1;", - "AS224: Expression is unsafe.", "= foo.baz;", - "AS224: Expression is unsafe.", "foo.baz = 1;", - "AS224: Expression is unsafe.", "foo.baz++;", - "AS224: Expression is unsafe.", "foo.baz += 1;", + "AS101: Operation is unsafe.", "f1();", + "AS101: Operation is unsafe.", "f2();", + "AS101: Operation is unsafe.", "= new Foo();", + "AS101: Operation is unsafe.", "super();", + "AS101: Operation is unsafe.", ": Foo = {};", + "AS101: Operation is unsafe.", "= instantiate()", + "AS101: Operation is unsafe.", "Foo.bar();", + "AS101: Operation is unsafe.", "foo.bar();", + "AS101: Operation is unsafe.", " = Foo.foo;", + "AS101: Operation is unsafe.", "Foo.foo = 1;", + "AS101: Operation is unsafe.", "Foo.foo++;", + "AS101: Operation is unsafe.", "Foo.foo += 1;", + "AS101: Operation is unsafe.", " = foo.foo;", + "AS101: Operation is unsafe.", "foo.foo = 1;", + "AS101: Operation is unsafe.", "foo.foo++;", + "AS101: Operation is unsafe.", "foo.foo += 1;", + "AS101: Operation is unsafe.", "= Foo.baz;", + "AS101: Operation is unsafe.", "Foo.baz = 1;", + "AS101: Operation is unsafe.", "Foo.baz++;", + "AS101: Operation is unsafe.", "Foo.baz += 1;", + "AS101: Operation is unsafe.", "= foo.baz;", + "AS101: Operation is unsafe.", "foo.baz = 1;", + "AS101: Operation is unsafe.", "foo.baz++;", + "AS101: Operation is unsafe.", "foo.baz += 1;", "EOF" ] } \ No newline at end of file From 0b319b4d3f15e252de9ba44f6e6e2cded6ad8cc5 Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 26 Sep 2019 03:31:34 +0200 Subject: [PATCH 2/4] more --- src/builtins.ts | 1446 ++++++++++++++++----------- src/common.ts | 2 +- src/compiler.ts | 84 +- src/diagnosticMessages.generated.ts | 12 +- src/diagnosticMessages.json | 6 +- src/diagnostics.ts | 2 +- std/assembly/shared/feature.ts | 17 + 7 files changed, 911 insertions(+), 658 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index 1f200afc63..831b301783 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -75,6 +75,7 @@ import { import { CommonFlags, Feature, + featureToString, TypeinfoFlags } from "./common"; @@ -1638,8 +1639,8 @@ export function compileCall( // === Atomics ================================================================================ case BuiltinSymbols.atomic_load: { // load(offset: usize, immOffset?: usize) -> T* - if (!compiler.options.hasFeature(Feature.THREADS)) break; if ( + checkFeatureEnabled(Feature.THREADS, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler, true) | checkArgsOptional(operands, 1, 2, reportNode, compiler) ) return module.unreachable(); @@ -1675,9 +1676,8 @@ export function compileCall( ); } case BuiltinSymbols.atomic_store: { // store(offset: usize, value: T*, immOffset?: usize) -> void - if (!compiler.options.hasFeature(Feature.THREADS)) break; - compiler.currentType = Type.void; if ( + checkFeatureEnabled(Feature.THREADS, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsOptional(operands, 2, 3, reportNode, compiler) ) return module.unreachable(); @@ -1687,6 +1687,7 @@ export function compileCall( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, reportNode.typeArgumentsRange, "atomic.store", type.toString() ); + compiler.currentType = Type.void; return module.unreachable(); } let arg0 = compiler.compileExpression(operands[0], @@ -1735,8 +1736,8 @@ export function compileCall( case BuiltinSymbols.atomic_or: case BuiltinSymbols.atomic_xor: case BuiltinSymbols.atomic_xchg: { - if (!compiler.options.hasFeature(Feature.THREADS)) break; if ( + checkFeatureEnabled(Feature.THREADS, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler, true) | checkArgsOptional(operands, 2, 3, reportNode, compiler) ) return module.unreachable(); @@ -1808,8 +1809,8 @@ export function compileCall( return module.atomic_rmw(op, type.byteSize, immOffset, arg0, arg1, inType.toNativeType()); } case BuiltinSymbols.atomic_cmpxchg: { // cmpxchg(ptr: usize, expected: T, replacement: T, off?: usize) -> T - if (!compiler.options.hasFeature(Feature.THREADS)) break; if ( + checkFeatureEnabled(Feature.THREADS, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler, true) | checkArgsOptional(operands, 3, 4, reportNode, compiler) ) return module.unreachable(); @@ -1870,56 +1871,51 @@ export function compileCall( return module.atomic_cmpxchg(type.byteSize, immOffset, arg0, arg1, arg2, inType.toNativeType()); } case BuiltinSymbols.atomic_wait: { // wait(ptr: usize, expected: T, timeout: i64) -> i32 - if (!compiler.options.hasFeature(Feature.THREADS)) break; - compiler.currentType = Type.i32; if ( + checkFeatureEnabled(Feature.THREADS, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 3, reportNode, compiler) - ) return module.unreachable(); - let type = typeArguments![0]; - if (!type.is(TypeFlags.INTEGER) || type.size < 32) { - compiler.error( - DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "atomic.wait", type.toString() - ); + ) { + compiler.currentType = Type.i32; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], - compiler.options.usizeType, - Constraints.CONV_IMPLICIT - ); - let arg1 = compiler.compileExpression(operands[1], type, - Constraints.CONV_IMPLICIT - ); - let arg2 = compiler.compileExpression(operands[2], - Type.i64, - Constraints.CONV_IMPLICIT - ); + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], type, Constraints.CONV_IMPLICIT); + let arg2 = compiler.compileExpression(operands[2], Type.i64, Constraints.CONV_IMPLICIT); compiler.currentType = Type.i32; - return module.atomic_wait(arg0, arg1, arg2, type.toNativeType()); + switch (type.kind) { + case TypeKind.I32: + case TypeKind.I64: + case TypeKind.ISIZE: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: return module.atomic_wait(arg0, arg1, arg2, type.toNativeType()); + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "atomic.wait", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.atomic_notify: { // notify(ptr: usize, count: i32) -> i32 - if (!compiler.options.hasFeature(Feature.THREADS)) break; - compiler.currentType = Type.i32; if ( + checkFeatureEnabled(Feature.THREADS, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 2, reportNode, compiler) - ) return module.unreachable(); - let arg0 = compiler.compileExpression(operands[0], - compiler.options.usizeType, - Constraints.CONV_IMPLICIT - ); - let arg1 = compiler.compileExpression(operands[1], - Type.i32, - Constraints.CONV_IMPLICIT - ); + ) { + compiler.currentType = Type.i32; + return module.unreachable(); + } + let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.i32, Constraints.CONV_IMPLICIT); compiler.currentType = Type.i32; return module.atomic_notify(arg0, arg1); } case BuiltinSymbols.atomic_fence: { // fence() -> void - if (!compiler.options.hasFeature(Feature.THREADS)) break; compiler.currentType = Type.void; if ( + checkFeatureEnabled(Feature.THREADS, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 0, reportNode, compiler) ) return module.unreachable(); @@ -2469,8 +2465,8 @@ export function compileCall( case BuiltinSymbols.v128: // alias for now case BuiltinSymbols.i8x16: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 16, reportNode, compiler) ) { @@ -2498,8 +2494,8 @@ export function compileCall( return module.v128(bytes); } case BuiltinSymbols.i16x8: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 8, reportNode, compiler) ) { @@ -2527,8 +2523,8 @@ export function compileCall( return module.v128(bytes); } case BuiltinSymbols.i32x4: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 4, reportNode, compiler) ) { @@ -2556,8 +2552,8 @@ export function compileCall( return module.v128(bytes); } case BuiltinSymbols.i64x2: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 2, reportNode, compiler) ) { @@ -2587,8 +2583,8 @@ export function compileCall( return module.v128(bytes); } case BuiltinSymbols.f32x4: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 4, reportNode, compiler) ) { @@ -2616,8 +2612,8 @@ export function compileCall( return module.v128(bytes); } case BuiltinSymbols.f64x2: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 2, reportNode, compiler) ) { @@ -2645,8 +2641,8 @@ export function compileCall( return module.v128(bytes); } case BuiltinSymbols.v128_splat: { // splat(x: T) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -2686,8 +2682,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_extract_lane: { // extract_lane(x: v128, idx: u8) -> T - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler, true) | checkArgsRequired(operands, 2, reportNode, compiler) ) return module.unreachable(); @@ -2743,8 +2739,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_replace_lane: { // replace_lane(x: v128, idx: u8, value: T) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 3, reportNode, compiler) ) { @@ -2804,135 +2800,233 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_shuffle: { // shuffle(a: v128, b: v128, ...lanes: u8[]) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) ) { compiler.currentType = Type.v128; return module.unreachable(); } let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); + if (!type.is(TypeFlags.REFERENCE)) { + let laneWidth = type.byteSize; + let laneCount = 16 / laneWidth; + assert(isInteger(laneCount) && isPowerOf2(laneCount)); + if ( + checkArgsRequired(operands, 2 + laneCount, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: + case TypeKind.I64: + case TypeKind.ISIZE: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: + case TypeKind.F32: + case TypeKind.F64: { + let mask = new Uint8Array(16); + let maxIdx = (laneCount << 1) - 1; + for (let i = 0; i < laneCount; ++i) { + let operand = operands[2 + i]; + let argN = compiler.precomputeExpression(operand, Type.u8, Constraints.CONV_IMPLICIT); + if (getExpressionId(argN) != ExpressionId.Const) { + compiler.error( + DiagnosticCode.Expression_must_be_a_compile_time_constant, + operand.range + ); + compiler.currentType = Type.v128; + return module.unreachable(); + } + assert(getExpressionType(argN) == NativeType.I32); + let idx = getConstValueI32(argN); + if (idx < 0 || idx > maxIdx) { + compiler.error( + DiagnosticCode._0_must_be_a_value_between_1_and_2_inclusive, + operand.range, "Lane index", "0", maxIdx.toString() + ); + compiler.currentType = Type.v128; + return module.unreachable(); + } + switch (laneWidth) { + case 1: { + writeI8(idx, mask, i); + break; + } + case 2: { + let off8 = i << 1; + let idx8 = idx << 1; + writeI8(idx8 , mask, off8); + writeI8(idx8 + 1, mask, off8 + 1); + break; + } + case 4: { + let off8 = i << 2; + let idx8 = idx << 2; + writeI8(idx8 , mask, off8); + writeI8(idx8 + 1, mask, off8 + 1); + writeI8(idx8 + 2, mask, off8 + 2); + writeI8(idx8 + 3, mask, off8 + 3); + break; + } + case 8: { + let off8 = i << 3; + let idx8 = idx << 3; + writeI8(idx8 , mask, off8); + writeI8(idx8 + 1, mask, off8 + 1); + writeI8(idx8 + 2, mask, off8 + 2); + writeI8(idx8 + 3, mask, off8 + 3); + writeI8(idx8 + 4, mask, off8 + 4); + writeI8(idx8 + 5, mask, off8 + 5); + writeI8(idx8 + 6, mask, off8 + 6); + writeI8(idx8 + 7, mask, off8 + 7); + break; + } + default: assert(false); + } + } + compiler.currentType = Type.v128; + return module.simd_shuffle(arg0, arg1, mask); + } + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "shuffle", type.toString() + ); + compiler.currentType = Type.v128; + return module.unreachable(); + } + case BuiltinSymbols.v128_add: { // add(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { compiler.currentType = Type.v128; return module.unreachable(); } - let laneWidth = type.byteSize; - let laneCount = 16 / laneWidth; - assert(isInteger(laneCount) && isPowerOf2(laneCount)); + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.binary(BinaryOp.AddI8x16, arg0, arg1); + case TypeKind.I16: + case TypeKind.U16: return module.binary(BinaryOp.AddI16x8, arg0, arg1); + case TypeKind.I32: + case TypeKind.U32: return module.binary(BinaryOp.AddI32x4, arg0, arg1); + case TypeKind.I64: + case TypeKind.U64: return module.binary(BinaryOp.AddI64x2, arg0, arg1); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.binary( + compiler.options.isWasm64 + ? BinaryOp.AddI64x2 + : BinaryOp.AddI32x4, + arg0, arg1 + ); + } + case TypeKind.F32: return module.binary(BinaryOp.AddF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.AddF64x2, arg0, arg1); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "add", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_sub: { // sub(a: v128, b: v128) -> v128 if ( - checkArgsRequired(operands, 2 + laneCount, reportNode, compiler) + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) ) { compiler.currentType = Type.v128; return module.unreachable(); } - switch (type.kind) { - case TypeKind.I8: - case TypeKind.I16: - case TypeKind.I32: - case TypeKind.I64: - case TypeKind.ISIZE: - case TypeKind.U8: - case TypeKind.U16: - case TypeKind.U32: - case TypeKind.U64: - case TypeKind.USIZE: - case TypeKind.F32: - case TypeKind.F64: break; - default: { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); - compiler.currentType = Type.v128; - return module.unreachable(); + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.binary(BinaryOp.SubI8x16, arg0, arg1); + case TypeKind.I16: + case TypeKind.U16: return module.binary(BinaryOp.SubI16x8, arg0, arg1); + case TypeKind.I32: + case TypeKind.U32: return module.binary(BinaryOp.SubI32x4, arg0, arg1); + case TypeKind.I64: + case TypeKind.U64: return module.binary(BinaryOp.SubI64x2, arg0, arg1); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.binary( + compiler.options.isWasm64 + ? BinaryOp.SubI64x2 + : BinaryOp.SubI32x4, + arg0, arg1 + ); + } + case TypeKind.F32: return module.binary(BinaryOp.SubF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.SubF64x2, arg0, arg1); } } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "sub", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_mul: { // mul(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); - let mask = new Uint8Array(16); - let maxIdx = (laneCount << 1) - 1; - for (let i = 0; i < laneCount; ++i) { - let operand = operands[2 + i]; - let argN = compiler.precomputeExpression(operand, Type.u8, Constraints.CONV_IMPLICIT); - if (getExpressionId(argN) != ExpressionId.Const) { - compiler.error( - DiagnosticCode.Expression_must_be_a_compile_time_constant, - operand.range - ); - compiler.currentType = Type.v128; - return module.unreachable(); - } - assert(getExpressionType(argN) == NativeType.I32); - let idx = getConstValueI32(argN); - if (idx < 0 || idx > maxIdx) { - compiler.error( - DiagnosticCode._0_must_be_a_value_between_1_and_2_inclusive, - operand.range, "Lane index", "0", maxIdx.toString() - ); - compiler.currentType = Type.v128; - return module.unreachable(); - } - switch (laneWidth) { - case 1: { - writeI8(idx, mask, i); - break; - } - case 2: { - let off8 = i << 1; - let idx8 = idx << 1; - writeI8(idx8 , mask, off8); - writeI8(idx8 + 1, mask, off8 + 1); - break; - } - case 4: { - let off8 = i << 2; - let idx8 = idx << 2; - writeI8(idx8 , mask, off8); - writeI8(idx8 + 1, mask, off8 + 1); - writeI8(idx8 + 2, mask, off8 + 2); - writeI8(idx8 + 3, mask, off8 + 3); - break; - } - case 8: { - let off8 = i << 3; - let idx8 = idx << 3; - writeI8(idx8 , mask, off8); - writeI8(idx8 + 1, mask, off8 + 1); - writeI8(idx8 + 2, mask, off8 + 2); - writeI8(idx8 + 3, mask, off8 + 3); - writeI8(idx8 + 4, mask, off8 + 4); - writeI8(idx8 + 5, mask, off8 + 5); - writeI8(idx8 + 6, mask, off8 + 6); - writeI8(idx8 + 7, mask, off8 + 7); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.binary(BinaryOp.MulI8x16, arg0, arg1); + case TypeKind.I16: + case TypeKind.U16: return module.binary(BinaryOp.MulI16x8, arg0, arg1); + case TypeKind.I32: + case TypeKind.U32: return module.binary(BinaryOp.MulI32x4, arg0, arg1); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.MulI32x4, arg0, arg1); + } break; } - default: assert(false); + case TypeKind.F32: return module.binary(BinaryOp.MulF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.MulF64x2, arg0, arg1); } } - compiler.currentType = Type.v128; - return module.simd_shuffle(arg0, arg1, mask); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "mul", type.toString() + ); + return module.unreachable(); } - case BuiltinSymbols.v128_add: // any_binary(a: v128, b: v128) -> v128 - case BuiltinSymbols.v128_sub: - case BuiltinSymbols.v128_mul: - case BuiltinSymbols.v128_div: - case BuiltinSymbols.v128_add_saturate: - case BuiltinSymbols.v128_sub_saturate: - case BuiltinSymbols.v128_min: - case BuiltinSymbols.v128_max: - case BuiltinSymbols.v128_eq: - case BuiltinSymbols.v128_ne: - case BuiltinSymbols.v128_lt: - case BuiltinSymbols.v128_le: - case BuiltinSymbols.v128_gt: - case BuiltinSymbols.v128_ge: - case BuiltinSymbols.v128_narrow: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; + case BuiltinSymbols.v128_div: { // div(a: v128, b: v128) -> v128 if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 2, reportNode, compiler) ) { @@ -2940,267 +3034,391 @@ export function compileCall( return module.unreachable(); } let type = typeArguments![0]; - if (type.is(TypeFlags.REFERENCE)) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.F32: return module.binary(BinaryOp.DivF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.DivF64x2, arg0, arg1); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "div", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_add_saturate: { // add_saturate(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { compiler.currentType = Type.v128; return module.unreachable(); } - let op: BinaryOp = -1; - switch (prototype.internalName) { - case BuiltinSymbols.v128_add: { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = BinaryOp.AddI8x16; break; } - case TypeKind.I16: - case TypeKind.U16: { op = BinaryOp.AddI16x8; break; } - case TypeKind.I32: - case TypeKind.U32: { op = BinaryOp.AddI32x4; break; } - case TypeKind.I64: - case TypeKind.U64: { op = BinaryOp.AddI64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? BinaryOp.AddI64x2 - : BinaryOp.AddI32x4; - break; - } - case TypeKind.F32: { op = BinaryOp.AddF32x4; break; } - case TypeKind.F64: { op = BinaryOp.AddF64x2; break; } - } - break; + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.binary(BinaryOp.AddSatI8x16, arg0, arg1); + case TypeKind.U8: return module.binary(BinaryOp.AddSatU8x16, arg0, arg1); + case TypeKind.I16: return module.binary(BinaryOp.AddSatI16x8, arg0, arg1); + case TypeKind.U16: return module.binary(BinaryOp.AddSatU16x8, arg0, arg1); } - case BuiltinSymbols.v128_sub: { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = BinaryOp.SubI8x16; break; } - case TypeKind.I16: - case TypeKind.U16: { op = BinaryOp.SubI16x8; break; } - case TypeKind.I32: - case TypeKind.U32: { op = BinaryOp.SubI32x4; break; } - case TypeKind.I64: - case TypeKind.U64: { op = BinaryOp.SubI64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - op = compiler.options.isWasm64 - ? BinaryOp.SubI64x2 - : BinaryOp.SubI32x4; - break; - } - case TypeKind.F32: { op = BinaryOp.SubF32x4; break; } - case TypeKind.F64: { op = BinaryOp.SubF64x2; break; } - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "add_saturate", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_sub_saturate: { // sub_saturate(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.binary(BinaryOp.SubSatI8x16, arg0, arg1); + case TypeKind.U8: return module.binary(BinaryOp.SubSatU8x16, arg0, arg1); + case TypeKind.I16: return module.binary(BinaryOp.SubSatI16x8, arg0, arg1); + case TypeKind.U16: return module.binary(BinaryOp.SubSatU16x8, arg0, arg1); } - case BuiltinSymbols.v128_mul: { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = BinaryOp.MulI8x16; break; } - case TypeKind.I16: - case TypeKind.U16: { op = BinaryOp.MulI16x8; break; } - case TypeKind.I32: - case TypeKind.U32: { op = BinaryOp.MulI32x4; break; } - case TypeKind.F32: { op = BinaryOp.MulF32x4; break; } - case TypeKind.F64: { op = BinaryOp.MulF64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - if (!compiler.options.isWasm64) op = BinaryOp.MulI32x4; - break; - } - } - break; - } - case BuiltinSymbols.v128_div: { - switch (type.kind) { - case TypeKind.F32: { op = BinaryOp.DivF32x4; break; } - case TypeKind.F64: { op = BinaryOp.DivF64x2; break; } - } - break; - } - case BuiltinSymbols.v128_add_saturate: { - switch (type.kind) { - case TypeKind.I8: { op = BinaryOp.AddSatI8x16; break; } - case TypeKind.U8: { op = BinaryOp.AddSatU8x16; break; } - case TypeKind.I16: { op = BinaryOp.AddSatI16x8; break; } - case TypeKind.U16: { op = BinaryOp.AddSatU16x8; break; } - } - break; - } - case BuiltinSymbols.v128_sub_saturate: { - switch (type.kind) { - case TypeKind.I8: { op = BinaryOp.SubSatI8x16; break; } - case TypeKind.U8: { op = BinaryOp.SubSatU8x16; break; } - case TypeKind.I16: { op = BinaryOp.SubSatI16x8; break; } - case TypeKind.U16: { op = BinaryOp.SubSatU16x8; break; } - } - break; - } - case BuiltinSymbols.v128_min: { - switch (type.kind) { - case TypeKind.F32: { op = BinaryOp.MinF32x4; break; } - case TypeKind.F64: { op = BinaryOp.MinF64x2; break; } - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "sub_saturate", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_min: { // min(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.F32: return module.binary(BinaryOp.MinF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.MinF64x2, arg0, arg1); } - case BuiltinSymbols.v128_max: { - switch (type.kind) { - case TypeKind.F32: { op = BinaryOp.MaxF32x4; break; } - case TypeKind.F64: { op = BinaryOp.MaxF64x2; break; } - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "min", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_max: { // max(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.F32: return module.binary(BinaryOp.MaxF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.MaxF64x2, arg0, arg1); } - case BuiltinSymbols.v128_eq: { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = BinaryOp.EqI8x16; break; } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "max", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_eq: { // eq(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.binary(BinaryOp.EqI8x16, arg0, arg1); case TypeKind.I16: - case TypeKind.U16: { op = BinaryOp.EqI16x8; break; } + case TypeKind.U16: return module.binary(BinaryOp.EqI16x8, arg0, arg1); case TypeKind.I32: - case TypeKind.U32: { op = BinaryOp.EqI32x4; break; } - case TypeKind.F32: { op = BinaryOp.EqF32x4; break; } - case TypeKind.F64: { op = BinaryOp.EqF64x2; break; } + case TypeKind.U32: return module.binary(BinaryOp.EqI32x4, arg0, arg1); case TypeKind.ISIZE: case TypeKind.USIZE: { - if (!compiler.options.isWasm64) op = BinaryOp.EqI32x4; + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.EqI32x4, arg0, arg1); + } break; } - } - break; + case TypeKind.F32: return module.binary(BinaryOp.EqF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.EqF64x2, arg0, arg1); } - case BuiltinSymbols.v128_ne: { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: { op = BinaryOp.NeI8x16; break; } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "eq", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_ne: { // ne(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.binary(BinaryOp.NeI8x16, arg0, arg1); case TypeKind.I16: - case TypeKind.U16: { op = BinaryOp.NeI16x8; break; } + case TypeKind.U16: return module.binary(BinaryOp.NeI16x8, arg0, arg1); case TypeKind.I32: - case TypeKind.U32: { op = BinaryOp.NeI32x4; break; } - case TypeKind.F32: { op = BinaryOp.NeF32x4; break; } - case TypeKind.F64: { op = BinaryOp.NeF64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - if (!compiler.options.isWasm64) op = BinaryOp.NeI32x4; - break; - } - } - break; - } - case BuiltinSymbols.v128_lt: { - switch (type.kind) { - case TypeKind.I8: { op = BinaryOp.LtI8x16; break; } - case TypeKind.U8: { op = BinaryOp.LtU8x16; break; } - case TypeKind.I16: { op = BinaryOp.LtI16x8; break; } - case TypeKind.U16: { op = BinaryOp.LtU16x8; break; } - case TypeKind.I32: { op = BinaryOp.LtI32x4; break; } - case TypeKind.U32: { op = BinaryOp.LtU32x4; break; } - case TypeKind.F32: { op = BinaryOp.LtF32x4; break; } - case TypeKind.F64: { op = BinaryOp.LtF64x2; break; } + case TypeKind.U32: return module.binary(BinaryOp.NeI32x4, arg0, arg1); case TypeKind.ISIZE: case TypeKind.USIZE: { if (!compiler.options.isWasm64) { - op = type.kind == TypeKind.ISIZE - ? BinaryOp.LtI32x4 - : BinaryOp.LtU32x4; + return module.binary(BinaryOp.NeI32x4, arg0, arg1); } break; } - } - break; + case TypeKind.F32: return module.binary(BinaryOp.NeF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.NeF64x2, arg0, arg1); } - case BuiltinSymbols.v128_le: { - switch (type.kind) { - case TypeKind.I8: { op = BinaryOp.LeI8x16; break; } - case TypeKind.U8: { op = BinaryOp.LeU8x16; break; } - case TypeKind.I16: { op = BinaryOp.LeI16x8; break; } - case TypeKind.U16: { op = BinaryOp.LeU16x8; break; } - case TypeKind.I32: { op = BinaryOp.LeI32x4; break; } - case TypeKind.U32: { op = BinaryOp.LeU32x4; break; } - case TypeKind.F32: { op = BinaryOp.LeF32x4; break; } - case TypeKind.F64: { op = BinaryOp.LeF64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - if (!compiler.options.isWasm64) { - op = type.kind == TypeKind.ISIZE - ? BinaryOp.LeI32x4 - : BinaryOp.LeU32x4; - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "ne", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_lt: { // lt(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.binary(BinaryOp.LtI8x16, arg0, arg1); + case TypeKind.U8: return module.binary(BinaryOp.LtU8x16, arg0, arg1); + case TypeKind.I16: return module.binary(BinaryOp.LtI16x8, arg0, arg1); + case TypeKind.U16: return module.binary(BinaryOp.LtU16x8, arg0, arg1); + case TypeKind.I32: return module.binary(BinaryOp.LtI32x4, arg0, arg1); + case TypeKind.U32: return module.binary(BinaryOp.LtU32x4, arg0, arg1); + case TypeKind.ISIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.LtI32x4, arg0, arg1); } + break; } - break; + case TypeKind.USIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.LtU32x4, arg0, arg1); + } + break; + } + case TypeKind.F32: return module.binary(BinaryOp.LtF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.LtF64x2, arg0, arg1); } - case BuiltinSymbols.v128_gt: { - switch (type.kind) { - case TypeKind.I8: { op = BinaryOp.GtI8x16; break; } - case TypeKind.U8: { op = BinaryOp.GtU8x16; break; } - case TypeKind.I16: { op = BinaryOp.GtI16x8; break; } - case TypeKind.U16: { op = BinaryOp.GtU16x8; break; } - case TypeKind.I32: { op = BinaryOp.GtI32x4; break; } - case TypeKind.U32: { op = BinaryOp.GtU32x4; break; } - case TypeKind.F32: { op = BinaryOp.GtF32x4; break; } - case TypeKind.F64: { op = BinaryOp.GtF64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - if (!compiler.options.isWasm64) { - op = type.kind == TypeKind.ISIZE - ? BinaryOp.GtI32x4 - : BinaryOp.GtU32x4; - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "lt", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_le: { // le(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.binary(BinaryOp.LeI8x16, arg0, arg1); + case TypeKind.U8: return module.binary(BinaryOp.LeU8x16, arg0, arg1); + case TypeKind.I16: return module.binary(BinaryOp.LeI16x8, arg0, arg1); + case TypeKind.U16: return module.binary(BinaryOp.LeU16x8, arg0, arg1); + case TypeKind.I32: return module.binary(BinaryOp.LeI32x4, arg0, arg1); + case TypeKind.U32: return module.binary(BinaryOp.LeU32x4, arg0, arg1); + case TypeKind.ISIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.LeI32x4, arg0, arg1); } + break; } - break; + case TypeKind.USIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.LeU32x4, arg0, arg1); + } + break; + } + case TypeKind.F32: return module.binary(BinaryOp.LeF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.LeF64x2, arg0, arg1); } - case BuiltinSymbols.v128_ge: { - switch (type.kind) { - case TypeKind.I8: { op = BinaryOp.GeI8x16; break; } - case TypeKind.U8: { op = BinaryOp.GeU8x16; break; } - case TypeKind.I16: { op = BinaryOp.GeI16x8; break; } - case TypeKind.U16: { op = BinaryOp.GeU16x8; break; } - case TypeKind.I32: { op = BinaryOp.GeI32x4; break; } - case TypeKind.U32: { op = BinaryOp.GeU32x4; break; } - case TypeKind.F32: { op = BinaryOp.GeF32x4; break; } - case TypeKind.F64: { op = BinaryOp.GeF64x2; break; } - case TypeKind.ISIZE: - case TypeKind.USIZE: { - if (!compiler.options.isWasm64) { - op = type.kind == TypeKind.ISIZE - ? BinaryOp.GeI32x4 - : BinaryOp.GeU32x4; - } - break; + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "le", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_gt: { // gt(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.binary(BinaryOp.GtI8x16, arg0, arg1); + case TypeKind.U8: return module.binary(BinaryOp.GtU8x16, arg0, arg1); + case TypeKind.I16: return module.binary(BinaryOp.GtI16x8, arg0, arg1); + case TypeKind.U16: return module.binary(BinaryOp.GtU16x8, arg0, arg1); + case TypeKind.I32: return module.binary(BinaryOp.GtI32x4, arg0, arg1); + case TypeKind.U32: return module.binary(BinaryOp.GtU32x4, arg0, arg1); + case TypeKind.ISIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.GtI32x4, arg0, arg1); } + break; } - break; + case TypeKind.USIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.GtU32x4, arg0, arg1); + } + break; + } + case TypeKind.F32: return module.binary(BinaryOp.GtF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.GtF64x2, arg0, arg1); } - case BuiltinSymbols.v128_narrow: { - switch (type.kind) { - case TypeKind.I16: { op = BinaryOp.NarrowI16x8ToI8x16; break; } - case TypeKind.U16: { op = BinaryOp.NarrowU16x8ToU8x16; break; } - case TypeKind.I32: { op = BinaryOp.NarrowI32x4ToI16x8; break; } - case TypeKind.U32: { op = BinaryOp.NarrowU32x4ToU16x8; break; } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "gt", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_ge: { // ge(a: v128, b: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.binary(BinaryOp.GeI8x16, arg0, arg1); + case TypeKind.U8: return module.binary(BinaryOp.GeU8x16, arg0, arg1); + case TypeKind.I16: return module.binary(BinaryOp.GeI16x8, arg0, arg1); + case TypeKind.U16: return module.binary(BinaryOp.GeU16x8, arg0, arg1); + case TypeKind.I32: return module.binary(BinaryOp.GeI32x4, arg0, arg1); + case TypeKind.U32: return module.binary(BinaryOp.GeU32x4, arg0, arg1); + case TypeKind.ISIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.GeI32x4, arg0, arg1); + } + break; + } + case TypeKind.USIZE: { + if (!compiler.options.isWasm64) { + return module.binary(BinaryOp.GeU32x4, arg0, arg1); + } + break; } - break; + case TypeKind.F32: return module.binary(BinaryOp.GeF32x4, arg0, arg1); + case TypeKind.F64: return module.binary(BinaryOp.GeF64x2, arg0, arg1); } } - if (op == -1) { - compiler.error( - DiagnosticCode.Operation_not_supported, - reportNode.typeArgumentsRange - ); + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "ge", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_narrow: { + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { compiler.currentType = Type.v128; return module.unreachable(); } + let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); - compiler.currentType = Type.v128; - return module.binary(op, arg0, arg1); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I16: return module.binary(BinaryOp.NarrowI16x8ToI8x16, arg0, arg1); + case TypeKind.U16: return module.binary(BinaryOp.NarrowU16x8ToU8x16, arg0, arg1); + case TypeKind.I32: return module.binary(BinaryOp.NarrowI32x4ToI16x8, arg0, arg1); + case TypeKind.U32: return module.binary(BinaryOp.NarrowU32x4ToU16x8, arg0, arg1); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "narrow", type.toString() + ); + return module.unreachable(); } case BuiltinSymbols.v128_neg: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3239,8 +3457,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_abs: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3262,8 +3480,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_sqrt: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3285,8 +3503,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_convert: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3310,8 +3528,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_trunc_sat: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3335,8 +3553,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_widen_low: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3360,8 +3578,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_widen_high: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3386,8 +3604,8 @@ export function compileCall( } case BuiltinSymbols.v128_shl: // any_shift(a: v128, b: i32) -> v128 case BuiltinSymbols.v128_shr: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 2, reportNode, compiler) ) { @@ -3456,8 +3674,8 @@ export function compileCall( return module.unreachable(); } case BuiltinSymbols.v128_and: { // and(a: v128) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 2, reportNode, compiler) ) { @@ -3469,8 +3687,8 @@ export function compileCall( return module.binary(BinaryOp.AndV128, arg0, arg1); } case BuiltinSymbols.v128_or: { // or(a: v128) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 2, reportNode, compiler) ) { @@ -3482,8 +3700,8 @@ export function compileCall( return module.binary(BinaryOp.OrV128, arg0, arg1); } case BuiltinSymbols.v128_xor: { // xor(a: v128) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 2, reportNode, compiler) ) { @@ -3495,8 +3713,8 @@ export function compileCall( return module.binary(BinaryOp.XorV128, arg0, arg1); } case BuiltinSymbols.v128_not: { // not(a: v128) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3507,8 +3725,8 @@ export function compileCall( return module.unary(UnaryOp.NotV128, arg0); } // case BuiltinSymbols.v128_andnot: { // andnot(a: v128, b: v128) -> v128 - // if (!compiler.options.hasFeature(Feature.SIMD)) break; // if ( + // checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | // checkTypeAbsent(typeArguments, reportNode, prototype) | // checkArgsRequired(operands, 2, reportNode, compiler) // ) { @@ -3520,8 +3738,8 @@ export function compileCall( // return module.binary(BinaryOp.AndnotV128, arg0); // } case BuiltinSymbols.v128_bitselect: { // bitselect(v1: v128, v2: v128, c: v128) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeAbsent(typeArguments, reportNode, prototype) | checkArgsRequired(operands, 3, reportNode, compiler) ) { @@ -3535,8 +3753,8 @@ export function compileCall( } case BuiltinSymbols.v128_any_true: // any_test(a: v128) -> bool case BuiltinSymbols.v128_all_true: { - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 1, reportNode, compiler) ) { @@ -3598,8 +3816,8 @@ export function compileCall( } case BuiltinSymbols.v128_qfma: // qfma(a: v128, b: v128, c: v128) -> v128 case BuiltinSymbols.v128_qfms: { // qfms(a: v128, b: v128, c: v128) -> v128 - if (!compiler.options.hasFeature(Feature.SIMD)) break; if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 3, reportNode, compiler) ) { @@ -3772,250 +3990,246 @@ function tryDeferASM( case BuiltinSymbols.i64_store: return deferASM(BuiltinSymbols.store, compiler, Type.i64, operands, Type.i64, reportNode); case BuiltinSymbols.f32_store: return deferASM(BuiltinSymbols.store, compiler, Type.f32, operands, Type.f32, reportNode); case BuiltinSymbols.f64_store: return deferASM(BuiltinSymbols.store, compiler, Type.f64, operands, Type.f64, reportNode); - } - if (compiler.options.hasFeature(Feature.THREADS)) { - switch (prototype.internalName) { - case BuiltinSymbols.i32_atomic_load8_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_load16_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_load: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_load8_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_load16_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_load32_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_load: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_load8_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_load16_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_load: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_load8_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_load16_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_load32_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_load: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_store8: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_store16: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_store: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_store8: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_store16: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_store32: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_store: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_store8: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_store16: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_store: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_store8: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_store16: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_store32: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_store: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_rmw8_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw16_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw_add: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_rmw8_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw16_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw32_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw_add: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_rmw8_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw16_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw_add: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_rmw8_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw16_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw32_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw_add: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_rmw8_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw16_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw_sub: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_rmw8_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw16_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw32_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw_sub: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_rmw8_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw16_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw_sub: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_rmw8_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw16_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw32_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw_sub: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_rmw8_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw16_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw_and: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_rmw8_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw16_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw32_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw_and: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_rmw8_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw16_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw_and: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_rmw8_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw16_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw32_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw_and: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_rmw8_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw16_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw_or: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_rmw8_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw16_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw32_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw_or: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_rmw8_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw16_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw_or: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_rmw8_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw16_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw32_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw_or: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_rmw8_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw16_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw_xor: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_rmw8_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw16_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw32_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw_xor: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_rmw8_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw16_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw_xor: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_rmw8_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw16_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw32_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw_xor: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_rmw8_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw16_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw_xchg: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_rmw8_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw16_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw32_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw_xchg: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_rmw8_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw16_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw_xchg: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_rmw8_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw16_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw32_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw_xchg: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u8, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u16, operands, Type.i32, reportNode); - case BuiltinSymbols.i32_atomic_rmw_cmpxchg: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u8, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u16, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw32_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u32, operands, Type.i64, reportNode); - case BuiltinSymbols.i64_atomic_rmw_cmpxchg: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i32_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u8, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u16, operands, Type.i32, reportNode); + case BuiltinSymbols.i32_atomic_rmw_cmpxchg: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u8, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u16, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw32_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u32, operands, Type.i64, reportNode); + case BuiltinSymbols.i64_atomic_rmw_cmpxchg: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i32_wait: return deferASM(BuiltinSymbols.atomic_wait, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i64_wait: return deferASM(BuiltinSymbols.atomic_wait, compiler, Type.i64, operands, Type.i32, reportNode); - } - } - if (compiler.options.hasFeature(Feature.SIMD)) { - switch (prototype.internalName) { + case BuiltinSymbols.i32_wait: return deferASM(BuiltinSymbols.atomic_wait, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i64_wait: return deferASM(BuiltinSymbols.atomic_wait, compiler, Type.i64, operands, Type.i32, reportNode); - case BuiltinSymbols.v128_load: return deferASM(BuiltinSymbols.load, compiler, Type.v128, operands, Type.v128, reportNode); - case BuiltinSymbols.v128_store: return deferASM(BuiltinSymbols.store, compiler, Type.v128, operands, Type.v128, reportNode); + case BuiltinSymbols.v128_load: return deferASM(BuiltinSymbols.load, compiler, Type.v128, operands, Type.v128, reportNode); + case BuiltinSymbols.v128_store: return deferASM(BuiltinSymbols.store, compiler, Type.v128, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_extract_lane_s: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i8, operands, Type.i8, reportNode); - case BuiltinSymbols.i8x16_extract_lane_u: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.u8, operands, Type.u8, reportNode); - case BuiltinSymbols.i8x16_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_add_saturate_s: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_add_saturate_u: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_sub_saturate_s: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_sub_saturate_u: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i8, operands, Type.i32, reportNode); - case BuiltinSymbols.i8x16_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i8, operands, Type.i32, reportNode); - case BuiltinSymbols.i8x16_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_narrow_i16x8_s: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i8x16_narrow_i16x8_u: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_extract_lane_s: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i8, operands, Type.i8, reportNode); + case BuiltinSymbols.i8x16_extract_lane_u: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.u8, operands, Type.u8, reportNode); + case BuiltinSymbols.i8x16_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_add_saturate_s: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_add_saturate_u: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_sub_saturate_s: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_sub_saturate_u: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i8, operands, Type.i32, reportNode); + case BuiltinSymbols.i8x16_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i8, operands, Type.i32, reportNode); + case BuiltinSymbols.i8x16_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_narrow_i16x8_s: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i8x16_narrow_i16x8_u: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_extract_lane_s: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i16, operands, Type.i16, reportNode); - case BuiltinSymbols.i16x8_extract_lane_u: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.u16, operands, Type.u16, reportNode); - case BuiltinSymbols.i16x8_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_add_saturate_s: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_add_saturate_u: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_sub_saturate_s: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_sub_saturate_u: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i16, operands, Type.i32, reportNode); - case BuiltinSymbols.i16x8_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i16, operands, Type.i32, reportNode); - case BuiltinSymbols.i16x8_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_narrow_i32x4_s: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_narrow_i32x4_u: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_widen_low_i8x16_s: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_widen_low_i8x16_u: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_widen_high_i8x16_s: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.i8, operands, Type.v128, reportNode); - case BuiltinSymbols.i16x8_widen_high_i8x16_u: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_extract_lane_s: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i16, operands, Type.i16, reportNode); + case BuiltinSymbols.i16x8_extract_lane_u: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.u16, operands, Type.u16, reportNode); + case BuiltinSymbols.i16x8_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_add_saturate_s: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_add_saturate_u: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_sub_saturate_s: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_sub_saturate_u: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i16, operands, Type.i32, reportNode); + case BuiltinSymbols.i16x8_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i16, operands, Type.i32, reportNode); + case BuiltinSymbols.i16x8_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_narrow_i32x4_s: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_narrow_i32x4_u: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_widen_low_i8x16_s: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_widen_low_i8x16_u: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.u8, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_widen_high_i8x16_s: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.i8, operands, Type.v128, reportNode); + case BuiltinSymbols.i16x8_widen_high_i8x16_u: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.u8, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i32x4_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i32x4_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i32, operands, Type.i32, reportNode); - case BuiltinSymbols.i32x4_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_trunc_sat_f32x4_s: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_trunc_sat_f32x4_u: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_widen_low_i16x8_s: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_widen_low_i16x8_u: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_widen_high_i16x8_s: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.i16, operands, Type.v128, reportNode); - case BuiltinSymbols.i32x4_widen_high_i16x8_u: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i32x4_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i32x4_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i32, operands, Type.i32, reportNode); + case BuiltinSymbols.i32x4_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_trunc_sat_f32x4_s: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_trunc_sat_f32x4_u: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_widen_low_i16x8_s: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_widen_low_i16x8_u: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.u16, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_widen_high_i16x8_s: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.i16, operands, Type.v128, reportNode); + case BuiltinSymbols.i32x4_widen_high_i16x8_u: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.u16, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i64, operands, Type.i64, reportNode); - case BuiltinSymbols.i64x2_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i64, operands, Type.i32, reportNode); - case BuiltinSymbols.i64x2_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i64, operands, Type.i32, reportNode); - case BuiltinSymbols.i64x2_trunc_sat_f64x2_s: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.i64x2_trunc_sat_f64x2_u: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.u64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i64, operands, Type.i64, reportNode); + case BuiltinSymbols.i64x2_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i64, operands, Type.i32, reportNode); + case BuiltinSymbols.i64x2_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i64, operands, Type.i32, reportNode); + case BuiltinSymbols.i64x2_trunc_sat_f64x2_s: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.i64x2_trunc_sat_f64x2_u: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.u64, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.f32, operands, Type.f32, reportNode); - case BuiltinSymbols.f32x4_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_div: return deferASM(BuiltinSymbols.v128_div, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_min: return deferASM(BuiltinSymbols.v128_min, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_max: return deferASM(BuiltinSymbols.v128_max, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_abs: return deferASM(BuiltinSymbols.v128_abs, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_sqrt: return deferASM(BuiltinSymbols.v128_sqrt, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_lt: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_le: return deferASM(BuiltinSymbols.v128_le, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_gt: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_ge: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_convert_i32x4_s: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.i32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_convert_i32x4_u: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.u32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_qfma: return deferASM(BuiltinSymbols.v128_qfma, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f32x4_qfms: return deferASM(BuiltinSymbols.v128_qfms, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.f32, operands, Type.f32, reportNode); + case BuiltinSymbols.f32x4_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_div: return deferASM(BuiltinSymbols.v128_div, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_min: return deferASM(BuiltinSymbols.v128_min, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_max: return deferASM(BuiltinSymbols.v128_max, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_abs: return deferASM(BuiltinSymbols.v128_abs, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_sqrt: return deferASM(BuiltinSymbols.v128_sqrt, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_lt: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_le: return deferASM(BuiltinSymbols.v128_le, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_gt: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_ge: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_convert_i32x4_s: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.i32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_convert_i32x4_u: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.u32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_qfma: return deferASM(BuiltinSymbols.v128_qfma, compiler, Type.f32, operands, Type.v128, reportNode); + case BuiltinSymbols.f32x4_qfms: return deferASM(BuiltinSymbols.v128_qfms, compiler, Type.f32, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.f64, operands, Type.f64, reportNode); - case BuiltinSymbols.f64x2_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_div: return deferASM(BuiltinSymbols.v128_div, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_min: return deferASM(BuiltinSymbols.v128_min, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_max: return deferASM(BuiltinSymbols.v128_max, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_abs: return deferASM(BuiltinSymbols.v128_abs, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_sqrt: return deferASM(BuiltinSymbols.v128_sqrt, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_lt: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_le: return deferASM(BuiltinSymbols.v128_le, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_gt: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_ge: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_convert_i64x2_s: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.i64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_convert_i64x2_u: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.u64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_qfma: return deferASM(BuiltinSymbols.v128_qfma, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.f64x2_qfms: return deferASM(BuiltinSymbols.v128_qfms, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.f64, operands, Type.f64, reportNode); + case BuiltinSymbols.f64x2_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_div: return deferASM(BuiltinSymbols.v128_div, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_min: return deferASM(BuiltinSymbols.v128_min, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_max: return deferASM(BuiltinSymbols.v128_max, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_abs: return deferASM(BuiltinSymbols.v128_abs, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_sqrt: return deferASM(BuiltinSymbols.v128_sqrt, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_lt: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_le: return deferASM(BuiltinSymbols.v128_le, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_gt: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_ge: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_convert_i64x2_s: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.i64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_convert_i64x2_u: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.u64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_qfma: return deferASM(BuiltinSymbols.v128_qfma, compiler, Type.f64, operands, Type.v128, reportNode); + case BuiltinSymbols.f64x2_qfms: return deferASM(BuiltinSymbols.v128_qfms, compiler, Type.f64, operands, Type.v128, reportNode); - case BuiltinSymbols.v8x16_shuffle: return deferASM(BuiltinSymbols.v128_shuffle, compiler, Type.i8, operands, Type.v128, reportNode); - } + case BuiltinSymbols.v8x16_shuffle: return deferASM(BuiltinSymbols.v128_shuffle, compiler, Type.i8, operands, Type.v128, reportNode); } /* tslint:enable:max-line-length */ - return 0; + compiler.error( + DiagnosticCode.Not_implemented, + reportNode.range + ); + return compiler.module.unreachable(); } /** A helper for deferring inline-assembler-like calls to built-in functions. */ @@ -4399,6 +4613,22 @@ function evaluateImmediateOffset(expression: Expression, compiler: Compiler): i3 return value; } +/** Checks that the specified feature is enabled. */ +function checkFeatureEnabled( + feature: Feature, + reportNode: Node, + compiler: Compiler +): i32 { + if (!compiler.options.hasFeature(feature)) { + compiler.error( + DiagnosticCode.Feature_0_is_not_enabled, + reportNode.range, featureToString(feature) + ); + return 1; + } + return 0; +} + /** Checks a call with a single required type argument. Returns `1` on error. */ function checkTypeRequired( typeArguments: Type[] | null, diff --git a/src/common.ts b/src/common.ts index dd26e7616f..4c8106a25a 100644 --- a/src/common.ts +++ b/src/common.ts @@ -215,6 +215,6 @@ export namespace CommonSymbols { } // shared -export { Feature } from "../std/assembly/shared/feature"; +export { Feature, featureToString } from "../std/assembly/shared/feature"; export { Target } from "../std/assembly/shared/target"; export { Typeinfo, TypeinfoFlags } from "../std/assembly/shared/typeinfo"; diff --git a/src/compiler.ts b/src/compiler.ts index 57311276a0..a634d88690 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -878,8 +878,8 @@ export class Compiler extends DiagnosticEmitter { // Importing mutable globals is not supported in the MVP } else { this.error( - DiagnosticCode.Operation_not_supported, - global.declaration.range + DiagnosticCode.Feature_0_is_not_enabled, + global.declaration.range, "mutable-globals" ); } return false; @@ -1258,8 +1258,8 @@ export class Compiler extends DiagnosticEmitter { let decoratorNodes = instance.decoratorNodes; let decorator = assert(findDecorator(DecoratorKind.EXTERNAL, decoratorNodes)); this.error( - DiagnosticCode.Operation_not_supported, - decorator.range + DiagnosticCode.Decorator_0_is_not_valid_here, + decorator.range, "external" ); } @@ -1447,7 +1447,7 @@ export class Compiler extends DiagnosticEmitter { ): void { // TODO this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, declaration.range ); } @@ -1765,7 +1765,7 @@ export class Compiler extends DiagnosticEmitter { case NodeKind.TYPEDECLARATION: { // TODO: integrate inner type declaration into flow this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, statement.range ); stmt = module.unreachable(); @@ -1835,7 +1835,7 @@ export class Compiler extends DiagnosticEmitter { var module = this.module; if (statement.label) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, statement.label.range ); return module.unreachable(); @@ -1869,7 +1869,7 @@ export class Compiler extends DiagnosticEmitter { var label = statement.label; if (label) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, label.range ); return module.unreachable(); @@ -2415,7 +2415,7 @@ export class Compiler extends DiagnosticEmitter { // TODO: can't yet support something like: try { return ... } finally { ... } // worthwhile to investigate lowering returns to block results (here)? this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, statement.range ); return this.module.unreachable(); @@ -2859,7 +2859,7 @@ export class Compiler extends DiagnosticEmitter { } default: { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, expression.range ); expr = this.module.unreachable(); @@ -3651,7 +3651,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.ANYREF: { // TODO: ref.eq this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, expression.range ); expr = module.unreachable(); @@ -3748,7 +3748,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.ANYREF: { // TODO: !ref.eq this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, expression.range ); expr = module.unreachable(); @@ -5250,7 +5250,7 @@ export class Compiler extends DiagnosticEmitter { } default: { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, expression.range ); return this.module.unreachable(); @@ -5445,7 +5445,7 @@ export class Compiler extends DiagnosticEmitter { } } this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, valueExpression.range ); return module.unreachable(); @@ -5999,10 +5999,18 @@ export class Compiler extends DiagnosticEmitter { // not supported default: { - this.error( - DiagnosticCode.Operation_not_supported, - expression.range - ); + let type = this.resolver.getTypeOfElement(target); + if (type) { + this.error( + DiagnosticCode.Type_0_has_no_call_signatures, + expression.range, type.toString() + ); + } else { + this.error( + DiagnosticCode.Expression_cannot_be_represented_by_a_type, + expression.range + ); + } return module.unreachable(); } } @@ -6046,7 +6054,7 @@ export class Compiler extends DiagnosticEmitter { } // now compile the builtin, which usually returns a block of code that replaces the call. - var expr = compileBuiltinCall( + return compileBuiltinCall( this, prototype, typeArguments, @@ -6054,14 +6062,6 @@ export class Compiler extends DiagnosticEmitter { contextualType, expression ); - if (!expr) { - this.error( - DiagnosticCode.Operation_not_supported, - expression.range - ); - return this.module.unreachable(); - } - return expr; } /** @@ -6079,7 +6079,7 @@ export class Compiler extends DiagnosticEmitter { var thisType = signature.thisType; if (hasThis != (thisType != null)) { this.error( - DiagnosticCode.Operation_not_supported, // TODO: better message? + DiagnosticCode.The_this_types_of_each_signature_are_incompatible, reportNode.range ); return false; @@ -6089,7 +6089,7 @@ export class Compiler extends DiagnosticEmitter { var hasRest = signature.hasRest; if (hasRest) { this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, reportNode.range ); return false; @@ -7312,7 +7312,7 @@ export class Compiler extends DiagnosticEmitter { } } this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, expression.range ); return this.module.unreachable(); @@ -7390,8 +7390,8 @@ export class Compiler extends DiagnosticEmitter { ); } else { this.error( - DiagnosticCode.Operation_not_supported, - expression.range + DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2, + expression.range, "instanceof", actualType.toString(), expectedType.toString() ); } } @@ -7432,8 +7432,8 @@ export class Compiler extends DiagnosticEmitter { ); } else { this.error( - DiagnosticCode.Operation_not_supported, - expression.range + DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2, + expression.range, "instanceof", actualType.toString(), expectedType.toString() ); } } @@ -7468,8 +7468,8 @@ export class Compiler extends DiagnosticEmitter { } } this.error( - DiagnosticCode.Operation_not_supported, - expression.range + DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly, + expression.range, "T" ); return module.unreachable(); } @@ -7515,7 +7515,7 @@ export class Compiler extends DiagnosticEmitter { // case LiteralKind.REGEXP: } this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, expression.range ); this.currentType = contextualType; @@ -8038,7 +8038,7 @@ export class Compiler extends DiagnosticEmitter { } } this.error( - DiagnosticCode.Operation_not_supported, + DiagnosticCode.Not_implemented, expression.range ); return module.unreachable(); @@ -8190,8 +8190,8 @@ export class Compiler extends DiagnosticEmitter { } } this.error( - DiagnosticCode.Operation_not_supported, - expression.range + DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1, + expression.range, "++", this.currentType.toString() ); if (tempLocal) flow.freeTempLocal(tempLocal); return module.unreachable(); @@ -8279,8 +8279,8 @@ export class Compiler extends DiagnosticEmitter { } } this.error( - DiagnosticCode.Operation_not_supported, - expression.range + DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1, + expression.range, "--", this.currentType.toString() ); if (tempLocal) flow.freeTempLocal(tempLocal); return module.unreachable(); diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index cc89de4046..f930b92df3 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -7,10 +7,10 @@ /** Enum of available diagnostic codes. */ export enum DiagnosticCode { - Operation_not_supported = 100, + Not_implemented = 100, Operation_is_unsafe = 101, User_defined_0 = 102, - Not_implemented = 103, + Feature_0_is_not_enabled = 103, Conversion_from_type_0_to_1_requires_an_explicit_cast = 200, Conversion_from_type_0_to_1_will_require_an_explicit_cast_when_switching_between_32_64_bit = 201, Type_0_cannot_be_changed_to_type_1 = 202, @@ -121,6 +121,7 @@ export enum DiagnosticCode { Duplicate_function_implementation = 2393, Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local = 2395, A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged = 2434, + The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly = 2453, Type_0_has_no_property_1 = 2460, The_0_operator_cannot_be_applied_to_type_1 = 2469, In_const_enum_declarations_member_initializer_must_be_constant_expression = 2474, @@ -135,6 +136,7 @@ export enum DiagnosticCode { A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums = 2651, Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration = 2673, Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration = 2674, + The_this_types_of_each_signature_are_incompatible = 2685, Namespace_0_has_no_exported_member_1 = 2694, Required_type_parameters_may_not_follow_optional_type_parameters = 2706, Duplicate_property_0 = 2718, @@ -149,10 +151,10 @@ export enum DiagnosticCode { /** Translates a diagnostic code to its respective string. */ export function diagnosticCodeToString(code: DiagnosticCode): string { switch (code) { - case 100: return "Operation not supported"; + case 100: return "Not implemented."; case 101: return "Operation is unsafe."; case 102: return "User-defined: {0}"; - case 103: return "Not implemented."; + case 103: return "Feature '{0}' is not enabled."; case 200: return "Conversion from type '{0}' to '{1}' requires an explicit cast."; case 201: return "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit."; case 202: return "Type '{0}' cannot be changed to type '{1}'."; @@ -263,6 +265,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2393: return "Duplicate function implementation."; case 2395: return "Individual declarations in merged declaration '{0}' must be all exported or all local."; case 2434: return "A namespace declaration cannot be located prior to a class or function with which it is merged."; + case 2453: return "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly."; case 2460: return "Type '{0}' has no property '{1}'."; case 2469: return "The '{0}' operator cannot be applied to type '{1}'."; case 2474: return "In 'const' enum declarations member initializer must be constant expression."; @@ -277,6 +280,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2651: return "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums."; case 2673: return "Constructor of class '{0}' is private and only accessible within the class declaration."; case 2674: return "Constructor of class '{0}' is protected and only accessible within the class declaration."; + case 2685: return "The 'this' types of each signature are incompatible."; case 2694: return "Namespace '{0}' has no exported member '{1}'."; case 2706: return "Required type parameters may not follow optional type parameters."; case 2718: return "Duplicate property '{0}'."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 7898eb2aa2..c709b11409 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -1,8 +1,8 @@ { - "Operation not supported": 100, + "Not implemented.": 100, "Operation is unsafe.": 101, "User-defined: {0}": 102, - "Not implemented.": 103, + "Feature '{0}' is not enabled.": 103, "Conversion from type '{0}' to '{1}' requires an explicit cast.": 200, "Conversion from type '{0}' to '{1}' will require an explicit cast when switching between 32/64-bit.": 201, @@ -116,6 +116,7 @@ "Duplicate function implementation.": 2393, "Individual declarations in merged declaration '{0}' must be all exported or all local.": 2395, "A namespace declaration cannot be located prior to a class or function with which it is merged.": 2434, + "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly.": 2453, "Type '{0}' has no property '{1}'.": 2460, "The '{0}' operator cannot be applied to type '{1}'.": 2469, "In 'const' enum declarations member initializer must be constant expression.": 2474, @@ -130,6 +131,7 @@ "A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": 2651, "Constructor of class '{0}' is private and only accessible within the class declaration.": 2673, "Constructor of class '{0}' is protected and only accessible within the class declaration.": 2674, + "The 'this' types of each signature are incompatible.": 2685, "Namespace '{0}' has no exported member '{1}'.": 2694, "Required type parameters may not follow optional type parameters.": 2706, "Duplicate property '{0}'.": 2718, diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 9368bf9484..e28ed8116d 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -14,7 +14,7 @@ import { } from "./diagnosticMessages.generated"; import { - isLineBreak, CharCode + isLineBreak } from "./util"; export { diff --git a/std/assembly/shared/feature.ts b/std/assembly/shared/feature.ts index 47a6bf6a11..038c2a6454 100644 --- a/std/assembly/shared/feature.ts +++ b/std/assembly/shared/feature.ts @@ -23,3 +23,20 @@ export const enum Feature { /** Reference types. */ REFERENCE_TYPES = 1 << 8 // see: https://github.com/WebAssembly/reference-types } + +/** Gets the name of the specified feature one would specify on the command line. */ +export function featureToString(feature: Feature): string { + switch (feature) { + case Feature.SIGN_EXTENSION: return "sign-extension"; + case Feature.MUTABLE_GLOBALS: return "mutable-globals"; + case Feature.NONTRAPPING_F2I: return "nontrapping-f2i"; + case Feature.BULK_MEMORY: return "bulk-memory"; + case Feature.SIMD: return "simd"; + case Feature.THREADS: return "threads"; + case Feature.EXCEPTION_HANDLING: return "exception-handling"; + case Feature.TAIL_CALLS: return "tail-calls"; + case Feature.REFERENCE_TYPES: return "reference-types"; + } + assert(false); + return ""; +} From af38e7f30409aa2d2b36eb84c45c221c6962a92a Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 26 Sep 2019 19:31:51 +0200 Subject: [PATCH 3/4] more --- src/builtins.ts | 227 +++++++++++++++------------- src/diagnosticMessages.generated.ts | 6 +- src/diagnosticMessages.json | 3 +- 3 files changed, 122 insertions(+), 114 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index 831b301783..ac928e20f3 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -561,16 +561,6 @@ export function compileCall( ): ExpressionRef { var module = compiler.module; - // NOTE that some implementations below make use of the select expression where straight-forward. - // whether worth or not should probably be tested once it's known if/how embedders handle it. - // search: createSelect - - // NOTE that consolidation of individual instructions into a single case isn't exactly scientific - // below, but rather done to make this file easier to work with. If there was a general rule it'd - // most likely be "three or more instructions that only differ in their actual opcode". - - var directize = false; - switch (prototype.internalName) { // === Static type evaluation ================================================================= @@ -688,35 +678,31 @@ export function compileCall( compiler.currentType = Type.bool; return module.i32(getExpressionId(expr) == ExpressionId.Const ? 1 : 0); } - case BuiltinSymbols.isManaged: { // isManaged() -> bool + case BuiltinSymbols.isManaged: { // isManaged() -> bool let type = evaluateConstantType(compiler, typeArguments, operands, reportNode); compiler.currentType = Type.bool; if (!type) return module.unreachable(); return module.i32(type.isManaged ? 1 : 0); } - case BuiltinSymbols.isVoid: { // isVoid() -> bool + case BuiltinSymbols.isVoid: { // isVoid() -> bool let type = evaluateConstantType(compiler, typeArguments, operands, reportNode); compiler.currentType = Type.bool; if (!type) return module.unreachable(); return module.i32(type.kind == TypeKind.VOID ? 1 : 0); } - case BuiltinSymbols.lengthof: { // lengthof() -> i32 + case BuiltinSymbols.lengthof: { // lengthof() -> i32 let type = evaluateConstantType(compiler, typeArguments, operands, reportNode); compiler.currentType = Type.i32; if (!type) return module.unreachable(); - - // Report if there is no call signature let signatureReference = type.signatureReference; if (!signatureReference) { compiler.error( DiagnosticCode.Type_0_has_no_call_signatures, - reportNode.range, "1", (typeArguments ? typeArguments.length : 1).toString(10) + reportNode.range, type.toString() ); return module.unreachable(); } - - let parameterNames = signatureReference.parameterNames; - return module.i32(!parameterNames ? 0 : parameterNames.length); + return module.i32(signatureReference.parameterTypes.length); } case BuiltinSymbols.sizeof: { // sizeof() -> usize compiler.currentType = compiler.options.usizeType; @@ -724,26 +710,30 @@ export function compileCall( checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 0, reportNode, compiler) ) return module.unreachable(); - let byteSize = (typeArguments)[0].byteSize; - let expr: ExpressionRef; + let type = typeArguments![0]; + let byteSize = type.byteSize; + if (!byteSize) { + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "sizeof", type.toString() + ); + return module.unreachable(); + } if (compiler.options.isWasm64) { // implicitly wrap if contextual type is a 32-bit integer if (contextualType.is(TypeFlags.INTEGER) && contextualType.size <= 32) { compiler.currentType = Type.u32; - expr = module.i32(byteSize); - } else { - expr = module.i64(byteSize, 0); + return module.i32(byteSize); } + return module.i64(byteSize, 0); } else { // implicitly extend if contextual type is a 64-bit integer if (contextualType.is(TypeFlags.INTEGER) && contextualType.size == 64) { compiler.currentType = Type.u64; - expr = module.i64(byteSize, 0); - } else { - expr = module.i32(byteSize); + return module.i64(byteSize, 0); } + return module.i32(byteSize); } - return expr; } case BuiltinSymbols.alignof: { // alignof() -> usize compiler.currentType = compiler.options.usizeType; @@ -751,28 +741,31 @@ export function compileCall( checkTypeRequired(typeArguments, reportNode, compiler) | checkArgsRequired(operands, 0, reportNode, compiler) ) return module.unreachable(); - let byteSize = (typeArguments)[0].byteSize; - assert(isPowerOf2(byteSize)); + let type = typeArguments![0]; + let byteSize = type.byteSize; + if (!isPowerOf2(byteSize)) { // implies == 0 + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "alignof", type.toString() + ); + return module.unreachable(); + } let alignLog2 = ctz(byteSize); - let expr: ExpressionRef; if (compiler.options.isWasm64) { // implicitly wrap if contextual type is a 32-bit integer if (contextualType.is(TypeFlags.INTEGER) && contextualType.size <= 32) { compiler.currentType = Type.u32; - expr = module.i32(alignLog2); - } else { - expr = module.i64(alignLog2, 0); + return module.i32(alignLog2); } + return module.i64(alignLog2, 0); } else { // implicitly extend if contextual type is a 64-bit integer if (contextualType.is(TypeFlags.INTEGER) && contextualType.size == 64) { compiler.currentType = Type.u64; - expr = module.i64(alignLog2, 0); - } else { - expr = module.i32(alignLog2); + return module.i64(alignLog2, 0); } + return module.i32(alignLog2); } - return expr; } case BuiltinSymbols.offsetof: { // offsetof(fieldName?: string) -> usize compiler.currentType = compiler.options.usizeType; @@ -840,9 +833,11 @@ export function compileCall( } } case BuiltinSymbols.nameof: { - // Check to make sure a parameter or a type was passed to the builtin let resultType = evaluateConstantType(compiler, typeArguments, operands, reportNode); - if (!resultType) return module.unreachable(); + if (!resultType) { + compiler.currentType = compiler.program.stringInstance.type; + return module.unreachable(); + } let value: string; if (resultType.is(TypeFlags.REFERENCE)) { let classReference = resultType.classReference; @@ -974,8 +969,10 @@ export function compileCall( case TypeKind.U16: case TypeKind.I32: case TypeKind.U32: return module.unary(UnaryOp.PopcntI32, arg0); - case TypeKind.USIZE: - case TypeKind.ISIZE: { + 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 @@ -983,8 +980,6 @@ export function compileCall( arg0 ); } - case TypeKind.I64: - case TypeKind.U64: return module.unary(UnaryOp.PopcntI64, arg0); } } compiler.error( @@ -1119,20 +1114,20 @@ export function compileCall( case TypeKind.ISIZE: { let options = compiler.options; let flow = compiler.currentFlow; - let wasm64 = options.isWasm64; + let isWasm64 = options.isWasm64; let tempLocal1 = flow.getTempLocal(options.usizeType); let tempLocalIndex2 = flow.getAndFreeTempLocal(options.usizeType).index; let tempLocalIndex1 = tempLocal1.index; flow.freeTempLocal(tempLocal1); - return module.binary(wasm64 ? BinaryOp.XorI64 : BinaryOp.XorI32, - module.binary(wasm64 ? BinaryOp.AddI64 : BinaryOp.AddI32, + return module.binary(isWasm64 ? BinaryOp.XorI64 : BinaryOp.XorI32, + module.binary(isWasm64 ? BinaryOp.AddI64 : BinaryOp.AddI32, module.local_tee( tempLocalIndex2, - module.binary(wasm64 ? BinaryOp.ShrI64 : BinaryOp.ShrI32, + module.binary(isWasm64 ? BinaryOp.ShrI64 : BinaryOp.ShrI32, module.local_tee(tempLocalIndex1, arg0), - wasm64 ? module.i64(63) : module.i32(31) + isWasm64 ? module.i64(63) : module.i32(31) ) ), module.local_get(tempLocalIndex1, options.nativeSizeType) @@ -1301,8 +1296,7 @@ export function compileCall( ); return module.unreachable(); } - case BuiltinSymbols.ceil: // any_rounding(value: T) -> T - case BuiltinSymbols.floor: { + case BuiltinSymbols.ceil: { // ceil(value: T) -> T if ( checkTypeOptional(typeArguments, reportNode, compiler, true) | checkArgsRequired(operands, 1, reportNode, compiler) @@ -1311,7 +1305,6 @@ export function compileCall( ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); let type = compiler.currentType; - let isCeil = prototype.internalName == BuiltinSymbols.ceil; if (!type.is(TypeFlags.REFERENCE)) { switch (type.kind) { case TypeKind.I8: @@ -1325,13 +1318,45 @@ export function compileCall( case TypeKind.U64: case TypeKind.USIZE: case TypeKind.BOOL: return arg0; // considered rounded - case TypeKind.F32: return module.unary(isCeil ? UnaryOp.CeilF32 : UnaryOp.FloorF32, arg0); - case TypeKind.F64: return module.unary(isCeil ? UnaryOp.CeilF64 : UnaryOp.FloorF64, arg0); + case TypeKind.F32: return module.unary(UnaryOp.CeilF32, arg0); + case TypeKind.F64: return module.unary(UnaryOp.CeilF64, arg0); } } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, isCeil ? "ceil" : "floor", type.toString() + reportNode.typeArgumentsRange, "ceil", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.floor: { // floor(value: T) -> T + if ( + checkTypeOptional(typeArguments, reportNode, compiler, true) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) return module.unreachable(); + let arg0 = typeArguments + ? compiler.compileExpression(operands[0], typeArguments[0], Constraints.CONV_IMPLICIT) + : compiler.compileExpression(operands[0], Type.f64, Constraints.NONE); + let type = compiler.currentType; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: + case TypeKind.I64: + case TypeKind.ISIZE: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: + case TypeKind.BOOL: return arg0; // considered rounded + case TypeKind.F32: return module.unary(UnaryOp.FloorF32, arg0); + case TypeKind.F64: return module.unary(UnaryOp.FloorF64, arg0); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "floor", type.toString() ); return module.unreachable(); } @@ -1477,7 +1502,6 @@ export function compileCall( let type = compiler.currentType; if (!type.is(TypeFlags.REFERENCE)) { switch (type.kind) { - // Nothing to do for integers case TypeKind.I8: case TypeKind.I16: case TypeKind.I32: @@ -1488,15 +1512,14 @@ export function compileCall( case TypeKind.U32: case TypeKind.U64: case TypeKind.USIZE: - case TypeKind.BOOL: return arg0; - // TODO: truncate to contextual type directly? + case TypeKind.BOOL: return arg0; // considered truncated case TypeKind.F32: return module.unary(UnaryOp.TruncF32, arg0); case TypeKind.F64: return module.unary(UnaryOp.TruncF64, arg0); } } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "trunc", type.toString() + reportNode.typeArgumentsRange, "trunc", type.toString() ); return module.unreachable(); } @@ -1515,10 +1538,7 @@ export function compileCall( contextualType.is(TypeFlags.INTEGER) && contextualType.size > type.size ) ? contextualType : type; - let arg0 = compiler.compileExpression(operands[0], - compiler.options.usizeType, - Constraints.CONV_IMPLICIT - ); + let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); let numOperands = operands.length; let immOffset = numOperands >= 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports if (immOffset < 0) { @@ -1569,10 +1589,7 @@ export function compileCall( checkArgsOptional(operands, 2, 4, reportNode, compiler) ) return module.unreachable(); let type = typeArguments![0]; - let arg0 = compiler.compileExpression(operands[0], - compiler.options.usizeType, - Constraints.CONV_IMPLICIT - ); + let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); let arg1 = isAsm ? compiler.compileExpression(operands[1], contextualType, @@ -1658,10 +1675,7 @@ export function compileCall( compiler.currentType = outType; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], - compiler.options.usizeType, - Constraints.CONV_IMPLICIT - ); + let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); let immOffset = operands.length == 2 ? evaluateImmediateOffset(operands[1], compiler) : 0; // reports if (immOffset < 0) { compiler.currentType = outType; @@ -1690,10 +1704,7 @@ export function compileCall( compiler.currentType = Type.void; return module.unreachable(); } - let arg0 = compiler.compileExpression(operands[0], - compiler.options.usizeType, - Constraints.CONV_IMPLICIT - ); + let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); let arg1 = isAsm ? compiler.compileExpression( operands[1], @@ -2228,7 +2239,7 @@ export function compileCall( if (!alreadyUnchecked) flow.unset(FlowFlags.UNCHECKED_CONTEXT); return expr; } - case BuiltinSymbols.call_direct: directize = true; + case BuiltinSymbols.call_direct: case BuiltinSymbols.call_indirect: { // call_indirect(target: Function | u32, ...args: *[]) -> T if ( checkTypeOptional(typeArguments, reportNode, compiler, true) | @@ -2262,7 +2273,7 @@ export function compileCall( let typeRef = module.getFunctionTypeBySignature(nativeReturnType, nativeParamTypes); if (!typeRef) typeRef = module.addFunctionType(typeName, nativeReturnType, nativeParamTypes); compiler.currentType = returnType; - if (directize) { + if (prototype.internalName == BuiltinSymbols.call_direct) { // if the index expression is precomputable to a constant value, emit a direct call if (getExpressionId(arg0 = module.precomputeExpression(arg0)) == ExpressionId.Const) { assert(getExpressionType(arg0) == NativeType.I32); @@ -2677,7 +2688,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "splat", type.toString() + reportNode.typeArgumentsRange, "v128.splat", type.toString() ); return module.unreachable(); } @@ -2734,7 +2745,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "extract_lane", type.toString() + reportNode.typeArgumentsRange, "v128.extract_lane", type.toString() ); return module.unreachable(); } @@ -2795,7 +2806,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "replace_lane", type.toString() + reportNode.typeArgumentsRange, "v128.replace_lane", type.toString() ); return module.unreachable(); } @@ -2900,7 +2911,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "shuffle", type.toString() + reportNode.typeArgumentsRange, "v128.shuffle", type.toString() ); compiler.currentType = Type.v128; return module.unreachable(); @@ -2942,7 +2953,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "add", type.toString() + reportNode.typeArgumentsRange, "v128.add", type.toString() ); return module.unreachable(); } @@ -2983,7 +2994,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "sub", type.toString() + reportNode.typeArgumentsRange, "v128.sub", type.toString() ); return module.unreachable(); } @@ -3020,7 +3031,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "mul", type.toString() + reportNode.typeArgumentsRange, "v128.mul", type.toString() ); return module.unreachable(); } @@ -3044,7 +3055,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "div", type.toString() + reportNode.typeArgumentsRange, "v128.div", type.toString() ); return module.unreachable(); } @@ -3070,7 +3081,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "add_saturate", type.toString() + reportNode.typeArgumentsRange, "v128.add_saturate", type.toString() ); return module.unreachable(); } @@ -3096,7 +3107,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "sub_saturate", type.toString() + reportNode.typeArgumentsRange, "v128.sub_saturate", type.toString() ); return module.unreachable(); } @@ -3120,7 +3131,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "min", type.toString() + reportNode.typeArgumentsRange, "v128.min", type.toString() ); return module.unreachable(); } @@ -3144,7 +3155,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "max", type.toString() + reportNode.typeArgumentsRange, "v128.max", type.toString() ); return module.unreachable(); } @@ -3181,7 +3192,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "eq", type.toString() + reportNode.typeArgumentsRange, "v128.eq", type.toString() ); return module.unreachable(); } @@ -3218,7 +3229,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "ne", type.toString() + reportNode.typeArgumentsRange, "v128.ne", type.toString() ); return module.unreachable(); } @@ -3260,7 +3271,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "lt", type.toString() + reportNode.typeArgumentsRange, "v128.lt", type.toString() ); return module.unreachable(); } @@ -3302,7 +3313,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "le", type.toString() + reportNode.typeArgumentsRange, "v128.le", type.toString() ); return module.unreachable(); } @@ -3344,7 +3355,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "gt", type.toString() + reportNode.typeArgumentsRange, "v128.gt", type.toString() ); return module.unreachable(); } @@ -3386,7 +3397,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "ge", type.toString() + reportNode.typeArgumentsRange, "v128.ge", type.toString() ); return module.unreachable(); } @@ -3412,7 +3423,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, "narrow", type.toString() + reportNode.typeArgumentsRange, "v128.narrow", type.toString() ); return module.unreachable(); } @@ -3452,7 +3463,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "v128.neg", type.toString() + reportNode.typeArgumentsRange, "v128.neg", type.toString() ); return module.unreachable(); } @@ -3475,7 +3486,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "v128.abs", type.toString() + reportNode.typeArgumentsRange, "v128.abs", type.toString() ); return module.unreachable(); } @@ -3498,7 +3509,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "v128.sqrt", type.toString() + reportNode.typeArgumentsRange, "v128.sqrt", type.toString() ); return module.unreachable(); } @@ -3523,7 +3534,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "v128.convert", type.toString() + reportNode.typeArgumentsRange, "v128.convert", type.toString() ); return module.unreachable(); } @@ -3548,7 +3559,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "v128.trunc_sat", type.toString() + reportNode.typeArgumentsRange, "v128.trunc_sat", type.toString() ); return module.unreachable(); } @@ -3573,7 +3584,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "v128.widen_low", type.toString() + reportNode.typeArgumentsRange, "v128.widen_low", type.toString() ); return module.unreachable(); } @@ -3598,7 +3609,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.range, "v128.widen_high", type.toString() + reportNode.typeArgumentsRange, "v128.widen_high", type.toString() ); return module.unreachable(); } @@ -3669,7 +3680,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, isShl ? "shl" : "shr", type.toString() + reportNode.typeArgumentsRange, isShl ? "v128.shl" : "v128.shr", type.toString() ); return module.unreachable(); } @@ -3810,7 +3821,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, isAnyTrue ? "any_true" : "all_true", type.toString() + reportNode.typeArgumentsRange, isAnyTrue ? "v128.any_true" : "v128.all_true", type.toString() ); return module.unreachable(); } @@ -3844,7 +3855,7 @@ export function compileCall( } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, isQfma ? "qfma" : "qfms", type.toString() + reportNode.typeArgumentsRange, isQfma ? "v128.qfma" : "v128.qfms", type.toString() ); return module.unreachable(); } @@ -3866,8 +3877,8 @@ export function compileCall( } } compiler.error( - DiagnosticCode.Type_0_is_not_a_class_or_function_type, - reportNode.typeArgumentsRange, type.toString() + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "idof", type.toString() ); return module.unreachable(); } diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index f930b92df3..abe278a10f 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -25,7 +25,7 @@ export enum DiagnosticCode { Class_0_is_sealed_and_cannot_be_extended = 211, Decorator_0_is_not_valid_here = 212, Duplicate_decorator = 213, - Type_0_is_not_a_class_or_function_type = 214, + Type_0_is_illegal_in_this_context = 214, Optional_parameter_must_have_an_initializer = 215, Constructor_of_class_0_must_not_require_any_arguments = 216, Function_0_cannot_be_inlined_into_itself = 217, @@ -37,7 +37,6 @@ export enum DiagnosticCode { _0_must_be_a_power_of_two = 223, _0_is_not_a_valid_operator = 224, Expression_cannot_be_represented_by_a_type = 225, - Type_0_is_illegal_in_this_context = 226, Unterminated_string_literal = 1002, Identifier_expected = 1003, _0_expected = 1005, @@ -169,7 +168,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 211: return "Class '{0}' is sealed and cannot be extended."; case 212: return "Decorator '{0}' is not valid here."; case 213: return "Duplicate decorator."; - case 214: return "Type '{0}' is not a class or function type."; + case 214: return "Type '{0}' is illegal in this context."; case 215: return "Optional parameter must have an initializer."; case 216: return "Constructor of class '{0}' must not require any arguments."; case 217: return "Function '{0}' cannot be inlined into itself."; @@ -181,7 +180,6 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 223: return "'{0}' must be a power of two."; case 224: return "'{0}' is not a valid operator."; case 225: return "Expression cannot be represented by a type."; - case 226: return "Type '{0}' is illegal in this context."; case 1002: return "Unterminated string literal."; case 1003: return "Identifier expected."; case 1005: return "'{0}' expected."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index c709b11409..8ee257ddb0 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -18,7 +18,7 @@ "Class '{0}' is sealed and cannot be extended.": 211, "Decorator '{0}' is not valid here.": 212, "Duplicate decorator.": 213, - "Type '{0}' is not a class or function type.": 214, + "Type '{0}' is illegal in this context.": 214, "Optional parameter must have an initializer.": 215, "Constructor of class '{0}' must not require any arguments.": 216, "Function '{0}' cannot be inlined into itself.": 217, @@ -30,7 +30,6 @@ "'{0}' must be a power of two.": 223, "'{0}' is not a valid operator.": 224, "Expression cannot be represented by a type.": 225, - "Type '{0}' is illegal in this context.": 226, "Unterminated string literal.": 1002, "Identifier expected.": 1003, From c01a9c63ffd1d25a24a38cf7eea6c0c7f3f74cea Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 26 Sep 2019 22:09:46 +0200 Subject: [PATCH 4/4] more --- src/builtins.ts | 267 ++++++++++++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 112 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index ac928e20f3..d292d53096 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -2302,7 +2302,7 @@ export function compileCall( if (!(typeArgument.is(TypeFlags.REFERENCE) && classInstance !== null)) { compiler.error( DiagnosticCode.This_expression_is_not_constructable, - reportNode.typeArgumentsRange + reportNode.expression.range ); return module.unreachable(); } @@ -3613,8 +3613,7 @@ export function compileCall( ); return module.unreachable(); } - case BuiltinSymbols.v128_shl: // any_shift(a: v128, b: i32) -> v128 - case BuiltinSymbols.v128_shr: { + case BuiltinSymbols.v128_shl: { // shl(a: v128, b: i32) -> v128 if ( checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | @@ -3623,64 +3622,81 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let isShl = prototype.internalName == BuiltinSymbols.v128_shl; let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.i32, Constraints.CONV_IMPLICIT); compiler.currentType = Type.v128; if (!type.is(TypeFlags.REFERENCE)) { - if (isShl) { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: return module.simd_shift(SIMDShiftOp.ShlI8x16, arg0, arg1); - case TypeKind.I16: - case TypeKind.U16: return module.simd_shift(SIMDShiftOp.ShlI16x8, arg0, arg1); - case TypeKind.I32: - case TypeKind.U32: return module.simd_shift(SIMDShiftOp.ShlI32x4, arg0, arg1); - case TypeKind.I64: - case TypeKind.U64: return module.simd_shift(SIMDShiftOp.ShlI64x2, arg0, arg1); - case TypeKind.ISIZE: - case TypeKind.USIZE: { - return module.simd_shift( - compiler.options.isWasm64 - ? SIMDShiftOp.ShlI64x2 - : SIMDShiftOp.ShlI32x4, - arg0, arg1 - ); - } + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.simd_shift(SIMDShiftOp.ShlI8x16, arg0, arg1); + case TypeKind.I16: + case TypeKind.U16: return module.simd_shift(SIMDShiftOp.ShlI16x8, arg0, arg1); + case TypeKind.I32: + case TypeKind.U32: return module.simd_shift(SIMDShiftOp.ShlI32x4, arg0, arg1); + case TypeKind.I64: + case TypeKind.U64: return module.simd_shift(SIMDShiftOp.ShlI64x2, arg0, arg1); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.simd_shift( + compiler.options.isWasm64 + ? SIMDShiftOp.ShlI64x2 + : SIMDShiftOp.ShlI32x4, + arg0, arg1 + ); } - } else { - switch (type.kind) { - case TypeKind.I8: return module.simd_shift(SIMDShiftOp.ShrI8x16, arg0, arg1); - case TypeKind.U8: return module.simd_shift(SIMDShiftOp.ShrU8x16, arg0, arg1); - case TypeKind.I16: return module.simd_shift(SIMDShiftOp.ShrI16x8, arg0, arg1); - case TypeKind.U16: return module.simd_shift(SIMDShiftOp.ShrU16x8, arg0, arg1); - case TypeKind.I32: return module.simd_shift(SIMDShiftOp.ShrI32x4, arg0, arg1); - case TypeKind.U32: return module.simd_shift(SIMDShiftOp.ShrU32x4, arg0, arg1); - case TypeKind.I64: return module.simd_shift(SIMDShiftOp.ShrI64x2, arg0, arg1); - case TypeKind.U64: return module.simd_shift(SIMDShiftOp.ShrU64x2, arg0, arg1); - case TypeKind.ISIZE: { - return module.simd_shift( - compiler.options.isWasm64 - ? SIMDShiftOp.ShrI64x2 - : SIMDShiftOp.ShrI32x4, - arg0, arg1 - ); - } - case TypeKind.USIZE: { - return module.simd_shift( - compiler.options.isWasm64 - ? SIMDShiftOp.ShrU64x2 - : SIMDShiftOp.ShrU32x4, - arg0, arg1 - ); - } + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "v128.shl", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_shr: { // shr(a: v128, b: i32) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 2, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.i32, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.v128; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: return module.simd_shift(SIMDShiftOp.ShrI8x16, arg0, arg1); + case TypeKind.U8: return module.simd_shift(SIMDShiftOp.ShrU8x16, arg0, arg1); + case TypeKind.I16: return module.simd_shift(SIMDShiftOp.ShrI16x8, arg0, arg1); + case TypeKind.U16: return module.simd_shift(SIMDShiftOp.ShrU16x8, arg0, arg1); + case TypeKind.I32: return module.simd_shift(SIMDShiftOp.ShrI32x4, arg0, arg1); + case TypeKind.U32: return module.simd_shift(SIMDShiftOp.ShrU32x4, arg0, arg1); + case TypeKind.I64: return module.simd_shift(SIMDShiftOp.ShrI64x2, arg0, arg1); + case TypeKind.U64: return module.simd_shift(SIMDShiftOp.ShrU64x2, arg0, arg1); + case TypeKind.ISIZE: { + return module.simd_shift( + compiler.options.isWasm64 + ? SIMDShiftOp.ShrI64x2 + : SIMDShiftOp.ShrI32x4, + arg0, arg1 + ); + } + case TypeKind.USIZE: { + return module.simd_shift( + compiler.options.isWasm64 + ? SIMDShiftOp.ShrU64x2 + : SIMDShiftOp.ShrU32x4, + arg0, arg1 + ); } } } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, isShl ? "v128.shl" : "v128.shr", type.toString() + reportNode.typeArgumentsRange, "v128.shr", type.toString() ); return module.unreachable(); } @@ -3762,8 +3778,7 @@ export function compileCall( let arg2 = compiler.compileExpression(operands[2], Type.v128, Constraints.CONV_IMPLICIT); return module.simd_ternary(SIMDTernaryOp.Bitselect, arg0, arg1, arg2); } - case BuiltinSymbols.v128_any_true: // any_test(a: v128) -> bool - case BuiltinSymbols.v128_all_true: { + case BuiltinSymbols.v128_any_true: { // any_true(a: v128) -> bool if ( checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | checkTypeRequired(typeArguments, reportNode, compiler) | @@ -3772,60 +3787,100 @@ export function compileCall( compiler.currentType = Type.bool; return module.unreachable(); } - let isAnyTrue = prototype.internalName == BuiltinSymbols.v128_any_true; let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); compiler.currentType = Type.bool; if (!type.is(TypeFlags.REFERENCE)) { - if (isAnyTrue) { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: return module.unary(UnaryOp.AnyTrueI8x16, arg0); - case TypeKind.I16: - case TypeKind.U16: return module.unary(UnaryOp.AnyTrueI16x8, arg0); - case TypeKind.I32: - case TypeKind.U32: return module.unary(UnaryOp.AnyTrueI32x4, arg0); - case TypeKind.I64: - case TypeKind.U64: return module.unary(UnaryOp.AnyTrueI64x2, arg0); - case TypeKind.ISIZE: - case TypeKind.USIZE: { - return module.unary( - compiler.options.isWasm64 - ? UnaryOp.AnyTrueI64x2 - : UnaryOp.AnyTrueI32x4, - arg0 - ); - } + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.unary(UnaryOp.AnyTrueI8x16, arg0); + case TypeKind.I16: + case TypeKind.U16: return module.unary(UnaryOp.AnyTrueI16x8, arg0); + case TypeKind.I32: + case TypeKind.U32: return module.unary(UnaryOp.AnyTrueI32x4, arg0); + case TypeKind.I64: + case TypeKind.U64: return module.unary(UnaryOp.AnyTrueI64x2, arg0); + case TypeKind.ISIZE: + case TypeKind.USIZE: { + return module.unary( + compiler.options.isWasm64 + ? UnaryOp.AnyTrueI64x2 + : UnaryOp.AnyTrueI32x4, + arg0 + ); } - } else { - switch (type.kind) { - case TypeKind.I8: - case TypeKind.U8: return module.unary(UnaryOp.AllTrueI8x16, arg0); - case TypeKind.I16: - case TypeKind.U16: return module.unary(UnaryOp.AllTrueI16x8, arg0); - case TypeKind.I32: - case TypeKind.U32: return module.unary(UnaryOp.AllTrueI32x4, arg0); - case TypeKind.I64: - 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 - ); - } + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "v128.any_true", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_all_true: { // all_true(a: v128) -> bool + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 1, reportNode, compiler) + ) { + compiler.currentType = Type.bool; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + compiler.currentType = Type.bool; + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.I8: + case TypeKind.U8: return module.unary(UnaryOp.AllTrueI8x16, arg0); + case TypeKind.I16: + case TypeKind.U16: return module.unary(UnaryOp.AllTrueI16x8, arg0); + case TypeKind.I32: + case TypeKind.U32: return module.unary(UnaryOp.AllTrueI32x4, arg0); + case TypeKind.I64: + 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 + ); } } } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, isAnyTrue ? "v128.any_true" : "v128.all_true", type.toString() + reportNode.typeArgumentsRange, "v128.all_true", type.toString() + ); + return module.unreachable(); + } + case BuiltinSymbols.v128_qfma: { // qfma(a: v128, b: v128, c: v128) -> v128 + if ( + checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | + checkTypeRequired(typeArguments, reportNode, compiler) | + checkArgsRequired(operands, 3, reportNode, compiler) + ) { + compiler.currentType = Type.v128; + return module.unreachable(); + } + let type = typeArguments![0]; + let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); + let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); + let arg2 = compiler.compileExpression(operands[2], Type.v128, Constraints.CONV_IMPLICIT); + if (!type.is(TypeFlags.REFERENCE)) { + switch (type.kind) { + case TypeKind.F32: return module.simd_ternary(SIMDTernaryOp.QFMAF32x4, arg0, arg1, arg2); + case TypeKind.F64: return module.simd_ternary(SIMDTernaryOp.QFMAF64x2, arg0, arg1, arg2); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + reportNode.typeArgumentsRange, "v128.qfma", type.toString() ); return module.unreachable(); } - case BuiltinSymbols.v128_qfma: // qfma(a: v128, b: v128, c: v128) -> v128 case BuiltinSymbols.v128_qfms: { // qfms(a: v128, b: v128, c: v128) -> v128 if ( checkFeatureEnabled(Feature.SIMD, reportNode, compiler) | @@ -3835,27 +3890,19 @@ export function compileCall( compiler.currentType = Type.v128; return module.unreachable(); } - let isQfma = prototype.internalName == BuiltinSymbols.v128_qfma; let type = typeArguments![0]; let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT); let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT); let arg2 = compiler.compileExpression(operands[2], Type.v128, Constraints.CONV_IMPLICIT); if (!type.is(TypeFlags.REFERENCE)) { - if (isQfma) { - switch (type.kind) { - case TypeKind.F32: return module.simd_ternary(SIMDTernaryOp.QFMAF32x4, arg0, arg1, arg2); - case TypeKind.F64: return module.simd_ternary(SIMDTernaryOp.QFMAF64x2, arg0, arg1, arg2); - } - } else { - switch (type.kind) { - case TypeKind.F32: return module.simd_ternary(SIMDTernaryOp.QFMSF32x4, arg0, arg1, arg2); - case TypeKind.F64: return module.simd_ternary(SIMDTernaryOp.QFMSF64x2, arg0, arg1, arg2); - } + switch (type.kind) { + case TypeKind.F32: return module.simd_ternary(SIMDTernaryOp.QFMSF32x4, arg0, arg1, arg2); + case TypeKind.F64: return module.simd_ternary(SIMDTernaryOp.QFMSF64x2, arg0, arg1, arg2); } } compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, - reportNode.typeArgumentsRange, isQfma ? "v128.qfma" : "v128.qfms", type.toString() + reportNode.typeArgumentsRange, "v128.qfms", type.toString() ); return module.unreachable(); } @@ -3925,8 +3972,8 @@ export function compileCall( } } compiler.error( - DiagnosticCode.Cannot_find_name_0, - reportNode.expression.range, prototype.internalName + DiagnosticCode.Not_implemented, + reportNode.expression.range ); return module.unreachable(); } @@ -4236,11 +4283,7 @@ function tryDeferASM( case BuiltinSymbols.v8x16_shuffle: return deferASM(BuiltinSymbols.v128_shuffle, compiler, Type.i8, operands, Type.v128, reportNode); } /* tslint:enable:max-line-length */ - compiler.error( - DiagnosticCode.Not_implemented, - reportNode.range - ); - return compiler.module.unreachable(); + return 0; } /** A helper for deferring inline-assembler-like calls to built-in functions. */