diff --git a/cli/index.js b/cli/index.js index 49ee70c663..1c1e435ca4 100644 --- a/cli/index.js +++ b/cli/index.js @@ -858,7 +858,7 @@ export async function main(argv, options) { if (!opts.noEmit) { if (opts.binaryFile) { // We catched lagacy field for binary output (before 0.20) - return prepareResult(Error("`binaryFile` doesn't support. Please use `outFile` instead.")); + return prepareResult(Error("Usage of the --binaryFile compiler option is no longer supported. Use --outFile instead.")); } let bindings = opts.bindings || []; let hasStdout = false; diff --git a/src/bindings/js.ts b/src/bindings/js.ts index ffeea3f618..510b36e37b 100644 --- a/src/bindings/js.ts +++ b/src/bindings/js.ts @@ -1369,6 +1369,8 @@ function indentText(text: string, indentLevel: i32, sb: string[], butFirst: bool } export function liftRequiresExportRuntime(type: Type): bool { + // TODO: enable v128 in signatures in future + // if (type.isVectorValue) return true; if (!type.isInternalReference) return false; let clazz = type.classReference; if (!clazz) { @@ -1398,6 +1400,8 @@ export function liftRequiresExportRuntime(type: Type): bool { } export function lowerRequiresExportRuntime(type: Type): bool { + // TODO: enable v128 in signatures in future + // if (type.isVectorValue) return true; if (!type.isInternalReference) return false; let clazz = type.classReference; if (!clazz) { diff --git a/src/compiler.ts b/src/compiler.ts index a5a7f2726b..8e0c3dab7b 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -915,6 +915,15 @@ export class Compiler extends DiagnosticEmitter { } } } + if (global.type == Type.v128) { + this.warning( + DiagnosticCode.Exchange_of_0_values_is_not_supported_by_all_embeddings, + global.typeNode + ? assert(global.typeNode).range + : global.identifierNode.range, + "v128" + ); + } return; } break; @@ -1517,6 +1526,25 @@ export class Compiler extends DiagnosticEmitter { instance.set(CommonFlags.ERRORED); } + if (instance.is(CommonFlags.AMBIENT) || instance.is(CommonFlags.EXPORT)) { + // Verify and print warn if signature has v128 type for imported or exported functions + let hasVectorValueOperands = signature.hasVectorValueOperands; + if (hasVectorValueOperands) { + let range: Range; + let fnTypeNode = instance.prototype.functionTypeNode; + if (signature.returnType == Type.v128) { + range = fnTypeNode.returnType.range; + } else { + let firstIndex = signature.getVectorValueOperandIndices()[0]; + range = fnTypeNode.parameters[firstIndex].range; + } + this.warning( + DiagnosticCode.Exchange_of_0_values_is_not_supported_by_all_embeddings, + range, "v128" + ); + } + } + instance.finalize(module, funcRef); this.currentType = previousType; pendingElements.delete(instance); diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 640be631c0..12265ea713 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -11,6 +11,7 @@ "Transform '{0}': {1}": 109, "Start function name '{0}' is invalid or conflicts with another export.": 110, "Element '{0}' not found.": 111, + "Exchange of '{0}' values is not supported by all embeddings": 112, "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, diff --git a/src/types.ts b/src/types.ts index 0b91214bec..72839d13f4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -930,6 +930,38 @@ export class Signature { return indices; } + /** Tests if this signature has at least one v128 operand. */ + get hasVectorValueOperands(): bool { + var thisType = this.thisType; + if (thisType && thisType.isVectorValue) { + return true; + } + var parameterTypes = this.parameterTypes; + for (let i = 0, k = parameterTypes.length; i < k; ++i) { + if (unchecked(parameterTypes[i]).isVectorValue) return true; + } + return false; + } + + /** Gets the indices of all v128 operands. */ + getVectorValueOperandIndices(): i32[] { + var indices = new Array(); + var index = 0; + var thisType = this.thisType; + if (thisType) { + if (thisType.isVectorValue) indices.push(index); + ++index; + } + var parameterTypes = this.parameterTypes; + for (let i = 0, k = parameterTypes.length; i < k; ++i) { + if (unchecked(parameterTypes[i]).isVectorValue) { + indices.push(index); + } + ++index; + } + return indices; + } + /** Converts this signature to a string. */ toString(validWat: bool = false): string { var sb = new Array(); diff --git a/tests/compiler/simd.debug.wat b/tests/compiler/simd.debug.wat index ea7ac48daa..79bbf592bb 100644 --- a/tests/compiler/simd.debug.wat +++ b/tests/compiler/simd.debug.wat @@ -11,6 +11,7 @@ (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $none_=>_v128 (func (result v128))) + (type $v128_=>_v128 (func (param v128) (result v128))) (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_v128 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result v128))) (type $i32_i32_i32_i32_i32_i32_i32_i32_=>_v128 (func (param i32 i32 i32 i32 i32 i32 i32 i32) (result v128))) (type $i32_i32_i32_i32_=>_v128 (func (param i32 i32 i32 i32) (result v128))) @@ -36,7 +37,7 @@ (global $~lib/rt/itcms/fromSpace (mut i32) (i32.const 0)) (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) (global $~lib/native/ASC_LOW_MEMORY_LIMIT i32 (i32.const 0)) - (global $~lib/native/ASC_FEATURE_SIMD i32 (i32.const 1)) + (global $simd/vec (mut v128) (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)) (global $~lib/builtins/u8.MAX_VALUE i32 (i32.const 255)) (global $~lib/builtins/u16.MAX_VALUE i32 (i32.const 65535)) (global $~lib/builtins/i16.MAX_VALUE i32 (i32.const 32767)) @@ -63,6 +64,7 @@ (data (i32.const 560) "\05\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\02\04\00\00\00\00\00\00\02\t\00\00\00\00\00\00") (table $0 1 1 funcref) (elem $0 (i32.const 1)) + (export "reexport" (func $simd/reexport)) (export "test_vars_i8x16_partial" (func $simd/test_vars_i8x16_partial)) (export "test_vars_i8x16_full" (func $simd/test_vars_i8x16_full)) (export "test_vars_i16x8_partial" (func $simd/test_vars_i16x8_partial)) @@ -75,6 +77,7 @@ (export "test_vars_f32x4_full" (func $simd/test_vars_f32x4_full)) (export "test_vars_f64x2_partial" (func $simd/test_vars_f64x2_partial)) (export "test_vars_f64x2_full" (func $simd/test_vars_f64x2_full)) + (export "vec" (global $simd/vec)) (export "memory" (memory $0)) (start $~start) (func $~lib/rt/itcms/Object#set:nextWithColor (param $0 i32) (param $1 i32) @@ -6500,7 +6503,8 @@ unreachable end i32.const 1 - drop + i32x4.splat + global.set $simd/vec i32.const 1 drop i32.const 0 @@ -6525,6 +6529,11 @@ i32.add global.set $~lib/memory/__stack_pointer ) + (func $simd/reexport (param $0 v128) (result v128) + local.get $0 + local.get $0 + i32x4.mul + ) (func $simd/test_vars_i8x16_partial (param $0 i32) (param $1 i32) (param $2 i32) (result v128) v128.const i32x4 0x03000100 0x07000504 0x0b0a0908 0x000e0d0c local.get $0 diff --git a/tests/compiler/simd.release.wat b/tests/compiler/simd.release.wat index cf6fa39352..9ce20cf5a2 100644 --- a/tests/compiler/simd.release.wat +++ b/tests/compiler/simd.release.wat @@ -8,6 +8,7 @@ (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_i32 (func (result i32))) (type $i32_=>_i32 (func (param i32) (result i32))) + (type $v128_=>_v128 (func (param v128) (result v128))) (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_v128 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) (result v128))) (type $i32_i32_i32_i32_i32_i32_i32_i32_=>_v128 (func (param i32 i32 i32 i32 i32 i32 i32 i32) (result v128))) (type $i32_i32_i32_i32_=>_v128 (func (param i32 i32 i32 i32) (result v128))) @@ -28,6 +29,7 @@ (global $~lib/rt/itcms/white (mut i32) (i32.const 0)) (global $~lib/rt/itcms/fromSpace (mut i32) (i32.const 0)) (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) + (global $simd/vec (mut v128) (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)) (global $~lib/memory/__stack_pointer (mut i32) (i32.const 18012)) (memory $0 1) (data (i32.const 1036) ",") @@ -48,6 +50,7 @@ (data (i32.const 1544) "\01\00\00\00\0e\00\00\00s\00i\00m\00d\00.\00t\00s") (data (i32.const 1584) "\05\00\00\00 \00\00\00\00\00\00\00 ") (data (i32.const 1612) "\02\04\00\00\00\00\00\00\02\t") + (export "reexport" (func $simd/reexport)) (export "test_vars_i8x16_partial" (func $simd/test_vars_i8x16_partial)) (export "test_vars_i8x16_full" (func $simd/test_vars_i8x16_full)) (export "test_vars_i16x8_partial" (func $simd/test_vars_i16x8_partial)) @@ -60,6 +63,7 @@ (export "test_vars_f32x4_full" (func $simd/test_vars_f32x4_full)) (export "test_vars_f64x2_partial" (func $simd/test_vars_f64x2_partial)) (export "test_vars_f64x2_full" (func $simd/test_vars_f64x2_full)) + (export "vec" (global $simd/vec)) (export "memory" (memory $0)) (start $~start) (func $~lib/rt/itcms/visitRoots @@ -2009,6 +2013,8 @@ call $~lib/builtins/abort unreachable end + v128.const i32x4 0x00000001 0x00000001 0x00000001 0x00000001 + global.set $simd/vec call $simd/test_v128 global.get $~lib/rt/tlsf/ROOT i32.eqz @@ -2185,6 +2191,11 @@ call $~lib/builtins/abort unreachable ) + (func $simd/reexport (param $0 v128) (result v128) + local.get $0 + local.get $0 + i32x4.mul + ) (func $simd/test_vars_i8x16_partial (param $0 i32) (param $1 i32) (param $2 i32) (result v128) v128.const i32x4 0x03000100 0x07000504 0x0b0a0908 0x000e0d0c local.get $0 diff --git a/tests/compiler/simd.ts b/tests/compiler/simd.ts index 4acb95b520..2a68d5cb8b 100644 --- a/tests/compiler/simd.ts +++ b/tests/compiler/simd.ts @@ -1086,6 +1086,10 @@ function test_const(): v128 { return one; // should not inline } +export function reexport(a: v128): v128 { + return i32x4.mul(a, a); +} + export function test_vars_i8x16_partial(a: i8, b: i8, c: i8): v128 { return i8x16(0, 1, a, 3, 4, 5, b, 7, 8, 9, 10, 11, 12, 13, 14, c); } @@ -1142,20 +1146,21 @@ export function test_vars_f64x2_full(a: f64, b: f64): v128 { return f64x2(a, b); } -if (ASC_FEATURE_SIMD) { - // test builtins - assert(isVector()); - assert(!isVector()); +// test exported var +export let vec: v128 = i32x4.splat(1); - assert(isVector(i32x4.splat(0))); - assert(!isVector(0)); +// test builtins +assert(isVector()); +assert(!isVector()); - test_v128(); - test_i8x16(); - test_i16x8(); - test_i32x4(); - test_i64x2(); - test_f32x4(); - test_f64x2(); - test_const(); -} +assert(isVector(i32x4.splat(0))); +assert(!isVector(0)); + +test_v128(); +test_i8x16(); +test_i16x8(); +test_i32x4(); +test_i64x2(); +test_f32x4(); +test_f64x2(); +test_const();