diff --git a/src/compiler.ts b/src/compiler.ts index 4966331552..3d7228765c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -193,7 +193,8 @@ import { writeF32, writeF64, uniqueMap, - isPowerOf2 + isPowerOf2, + v128_zero } from "./util"; /** Compiler options. */ @@ -3058,10 +3059,11 @@ export class Compiler extends DiagnosticEmitter { if (initExpr) { let precomp = module.runExpression(initExpr, ExpressionRunnerFlags.PreserveSideeffects); if (precomp) { - initExpr = precomp; - let local = new Local(name, -1, type, flow.parentFunction); + initExpr = precomp; // always use precomputed initExpr + let local: Local | null = null; switch (getExpressionType(initExpr)) { case NativeType.I32: { + local = new Local(name, -1, type, flow.parentFunction); local.setConstantIntegerValue( i64_new( getConstValueI32(initExpr), @@ -3072,6 +3074,7 @@ export class Compiler extends DiagnosticEmitter { break; } case NativeType.I64: { + local = new Local(name, -1, type, flow.parentFunction); local.setConstantIntegerValue( i64_new( getConstValueI64Low(initExpr), @@ -3082,33 +3085,33 @@ export class Compiler extends DiagnosticEmitter { break; } case NativeType.F32: { + local = new Local(name, -1, type, flow.parentFunction); local.setConstantFloatValue(getConstValueF32(initExpr), type); break; } case NativeType.F64: { + local = new Local(name, -1, type, flow.parentFunction); local.setConstantFloatValue(getConstValueF64(initExpr), type); break; } - default: { - assert(false); - return module.unreachable(); - } } - // Create a virtual local that doesn't actually exist in WebAssembly - let scopedLocals = flow.scopedLocals; - if (!scopedLocals) flow.scopedLocals = scopedLocals = new Map(); - else if (scopedLocals.has(name)) { - let existing = assert(scopedLocals.get(name)); - this.errorRelated( - DiagnosticCode.Duplicate_identifier_0, - declaration.name.range, - existing.declaration.name.range, - name - ); - return this.module.unreachable(); + if (local) { + // Add as a virtual local that doesn't actually exist in WebAssembly + let scopedLocals = flow.scopedLocals; + if (!scopedLocals) flow.scopedLocals = scopedLocals = new Map(); + else if (scopedLocals.has(name)) { + let existing = assert(scopedLocals.get(name)); + this.errorRelated( + DiagnosticCode.Duplicate_identifier_0, + declaration.name.range, + existing.declaration.name.range, + name + ); + return this.module.unreachable(); + } + scopedLocals.set(name, local); + isStatic = true; } - scopedLocals.set(name, local); - isStatic = true; } } else { this.error( @@ -11035,8 +11038,6 @@ export class Compiler extends DiagnosticEmitter { // helpers -const v128_zero = new Uint8Array(16); - function mangleImportName( element: Element, declaration: DeclarationStatement diff --git a/src/util/index.ts b/src/util/index.ts index da61a0069f..30d097c078 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -8,3 +8,4 @@ export * from "./collections"; export * from "./math"; export * from "./path"; export * from "./text"; +export * from "./vector"; diff --git a/src/util/vector.ts b/src/util/vector.ts new file mode 100644 index 0000000000..eee9d7ad78 --- /dev/null +++ b/src/util/vector.ts @@ -0,0 +1,7 @@ +/** + * @fileoverview Various vector utility. + * @license Apache-2.0 + */ + +/** v128 zero constant. */ +export const v128_zero = new Uint8Array(16); diff --git a/tests/compiler/features/simd.ts b/tests/compiler/features/simd.ts index c9add23486..c62347b856 100644 --- a/tests/compiler/features/simd.ts +++ b/tests/compiler/features/simd.ts @@ -683,6 +683,11 @@ function test_v64x2(): void { // } } +function test_const(): v128 { + const one = i32x4.splat(1); // should precompute + return one; // should not inline +} + if (ASC_FEATURE_SIMD) { test_v128(); test_i8x16(); @@ -695,4 +700,5 @@ if (ASC_FEATURE_SIMD) { test_v16x8(); test_v32x4(); test_v64x2(); + test_const(); } diff --git a/tests/compiler/features/simd.untouched.wat b/tests/compiler/features/simd.untouched.wat index e308f01d2d..616a7bba44 100644 --- a/tests/compiler/features/simd.untouched.wat +++ b/tests/compiler/features/simd.untouched.wat @@ -3,6 +3,7 @@ (type $i32_=>_none (func (param i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_v128 (func (result v128))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (memory $0 1) (data (i32.const 16) "\1e\00\00\00\01\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00s\00t\00u\00b\00.\00t\00s\00") @@ -2989,6 +2990,12 @@ (func $features/simd/test_v64x2 nop ) + (func $features/simd/test_const (result v128) + (local $0 v128) + v128.const i32x4 0x00000001 0x00000001 0x00000001 0x00000001 + local.set $0 + local.get $0 + ) (func $start:features/simd global.get $~lib/heap/__heap_base i32.const 15 @@ -3013,6 +3020,8 @@ call $features/simd/test_v16x8 call $features/simd/test_v32x4 call $features/simd/test_v64x2 + call $features/simd/test_const + drop ) (func $~start call $start:features/simd