From 213690e00cb740d0b632fae2ddd7c1ffe5b38612 Mon Sep 17 00:00:00 2001 From: dcode Date: Fri, 3 Apr 2020 18:20:23 +0200 Subject: [PATCH 01/24] Proof-of-concept vtable --- src/compiler.ts | 169 ++++++++--- src/module.ts | 5 +- src/program.ts | 85 ++++-- src/resolver.ts | 1 + std/assembly/arraybuffer.ts | 5 - .../compiler/class-overloading.optimized.wat | 157 ++++++++++- tests/compiler/class-overloading.ts | 26 +- .../compiler/class-overloading.untouched.wat | 264 ++++++++++++++++-- .../resolve-elementaccess.optimized.wat | 2 +- .../resolve-elementaccess.untouched.wat | 2 +- tests/compiler/std/array.untouched.wat | 2 +- tests/compiler/std/arraybuffer.optimized.wat | 2 +- tests/compiler/std/arraybuffer.untouched.wat | 4 +- tests/compiler/std/dataview.untouched.wat | 2 +- tests/compiler/std/map.optimized.wat | 2 +- tests/compiler/std/map.untouched.wat | 2 +- tests/compiler/std/set.optimized.wat | 2 +- tests/compiler/std/set.untouched.wat | 2 +- tests/compiler/std/symbol.optimized.wat | 2 +- tests/compiler/std/symbol.untouched.wat | 2 +- tests/compiler/std/typedarray.optimized.wat | 4 +- tests/compiler/std/typedarray.untouched.wat | 4 +- 22 files changed, 634 insertions(+), 112 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 495f670822..a2d48229df 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -47,8 +47,12 @@ import { getLocalSetValue, getGlobalGetName, isGlobalMutable, - createType, - hasSideEffects + hasSideEffects, + getFunctionBody, + getFunctionParams, + getFunctionResults, + getFunctionVars, + createType } from "./module"; import { @@ -331,7 +335,7 @@ export class Compiler extends DiagnosticEmitter { /** Map of already compiled static string segments. */ stringSegments: Map = new Map(); /** Function table being compiled. First elem is blank. */ - functionTable: string[] = []; + functionTable: Function[] = []; /** Arguments length helper global. */ builtinArgumentsLength: GlobalRef = 0; /** Requires runtime features. */ @@ -493,7 +497,19 @@ export class Compiler extends DiagnosticEmitter { } // set up virtual lookup tables - this.setupVirtualLookupTables(); + var functionTable = this.functionTable; + for (let i = 0, k = functionTable.length; i < k; ++i) { + let instance = functionTable[i]; + if (instance.is(CommonFlags.VIRTUAL)) { + assert(instance.is(CommonFlags.INSTANCE)); + this.makeVirtual(instance); + } + } + var virtualCalls = this.virtualCalls; + for (let _values = Set_values(virtualCalls), i = 0, k = _values.length; i < k; ++i) { + let instance = unchecked(_values[i]); + this.makeVirtual(instance); + } // finalize runtime features module.removeGlobal(BuiltinNames.rtti_base); @@ -551,10 +567,13 @@ export class Compiler extends DiagnosticEmitter { if (options.importMemory) module.addMemoryImport("0", "env", "memory", isSharedMemory); // set up function table (first elem is blank) - var functionTable = this.functionTable; var tableBase = this.options.tableBase; if (!tableBase) tableBase = 1; // leave first elem blank - module.setFunctionTable(tableBase + functionTable.length, Module.UNLIMITED_TABLE, functionTable, module.i32(tableBase)); + var functionTableNames = new Array(functionTable.length); + for (let i = 0, k = functionTable.length; i < k; ++i) { + functionTableNames[i] = functionTable[i].internalName; + } + module.setFunctionTable(tableBase + functionTable.length, Module.UNLIMITED_TABLE, functionTableNames, module.i32(tableBase)); // import and/or export table if requested (default table is named '0' by Binaryen) if (options.importTable) { @@ -585,34 +604,114 @@ export class Compiler extends DiagnosticEmitter { return module; } - private setupVirtualLookupTables(): void { - // TODO: :-) - var program = this.program; - var virtualCalls = this.virtualCalls; + /** Makes a normally compiled function virtual by injecting a vtable. */ + private makeVirtual(instance: Function): void { + // Check if this function has already been processed + var ref = instance.ref; + var body = getFunctionBody(ref); + if (getExpressionId(body) == ExpressionId.Block && getBlockName(body) == "vt") return; - // Virtual instance methods in the function table are potentially called virtually - var functionTable = this.functionTable; - var elementsByName = program.elementsByName; - for (let i = 0, k = functionTable.length; i < k; ++i) { - let instanceName = unchecked(functionTable[i]); - if (elementsByName.has(instanceName)) { // otherwise ~anonymous - let instance = assert(elementsByName.get(instanceName)); - if (instance.is(CommonFlags.INSTANCE | CommonFlags.VIRTUAL)) { - assert(instance.kind == ElementKind.FUNCTION); - virtualCalls.add(instance); + // Wouldn't be here if there wasn't at least one overload + var overloadPrototypes = assert(instance.prototype.overloads); + assert(overloadPrototypes.size); + + var module = this.module; + var usizeType = this.options.usizeType; + var usizeSize = usizeType.byteSize; + var isWasm64 = usizeSize == 8; + var nativeSizeType = usizeType.toNativeType(); + + // Add an additional temporary local holding this's class id + var vars = getFunctionVars(ref); + var tempIndex = 1 + instance.signature.parameterTypes.length + vars.length; + vars.push(NativeType.I32); + + // Check that this's class id is what we expect if we don't call an overload + if (!this.options.noAssert) { + let parent = instance.parent; + let actualParent = parent.kind == ElementKind.PROPERTY + ? parent.parent + : parent; + assert(actualParent.kind == ElementKind.CLASS); + body = module.if( + module.binary(BinaryOp.EqI32, + module.local_get(tempIndex, NativeType.I32), + module.i32((actualParent).id) + ), + body, + module.unreachable() // TODO: abort? + ); + } + + // A method's `overloads` property contains its unbound overload prototypes + // so we first have to find the concrete classes it became bound to, obtain + // their bound prototypes and make sure these are resolved and compiled as + // we are going to call them conditionally based on this's class id. + for (let _values = Set_values(overloadPrototypes), i = 0, k = _values.length; i < k; ++i) { + let unboundOverloadPrototype = _values[i]; + assert(!unboundOverloadPrototype.isBound); + let unboundOverloadParent = unboundOverloadPrototype.parent; + assert(unboundOverloadParent.kind == ElementKind.CLASS_PROTOTYPE); + + let classInstances = (unboundOverloadParent).instances; + if (classInstances) { + for (let _values = Map_values(classInstances), j = 0, l = _values.length; j < l; ++j) { + let classInstance = _values[j]; + let boundPrototype = assert(classInstance.members!.get(unboundOverloadPrototype.name)); + assert(boundPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); + let overloadInstance = this.resolver.resolveFunction(boundPrototype, instance.typeArguments); + if (!overloadInstance || !this.compileFunction(overloadInstance)) continue; + let parameterTypes = overloadInstance.signature.parameterTypes; + let numParameters = parameterTypes.length; + let paramExprs = new Array(1 + numParameters); + paramExprs[0] = module.local_get(0, nativeSizeType); // this + for (let n = 0; n < numParameters; ++n) { + paramExprs[1 + n] = module.local_get(1 + n, parameterTypes[n].toNativeType()); + } + + // TODO: verify signature and use trampoline if overload has additional + // optional parameters. + + // TODO: split this into two functions, one with the actual code and one + // with the vtable since calling the super function must circumvent the + // vtable. Perhaps, if we know we are inserting a vtable, we'd generate + // a stub for the vtable function using the function's original name, + // and generate the code function right away as |virtual? + + body = module.if( + module.binary(BinaryOp.EqI32, + module.local_get(tempIndex, NativeType.I32), + module.i32(classInstance.id) + ), + module.call(overloadInstance.internalName, paramExprs, overloadInstance.signature.returnType.toNativeType()), + body + ); } } } - // Inject a virtual lookup table into each function potentially called virtually - // TODO: for (let instance of virtualCalls.values()) { - for (let _values = Set_values(virtualCalls), i = 0, k = _values.length; i < k; ++i) { - let instance = unchecked(_values[i]); - this.warning( - DiagnosticCode.Function_0_is_possibly_called_virtually_which_is_not_yet_supported, - instance.identifierNode.range, instance.internalName - ); - } + // Finally replace the function and mark it with a vtable block + body = module.block("vt", [ + module.local_set(tempIndex, // BLOCK(this)#id @ this - 8 + module.load(4, false, + module.binary( + isWasm64 + ? BinaryOp.SubI64 + : BinaryOp.SubI32, + module.local_get(0, nativeSizeType), + isWasm64 + ? module.i64(8) + : module.i32(8) + ), + NativeType.I32 + ) + ), + body + ], getExpressionType(body)); + var prevParams = getFunctionParams(ref); + var prevResults = getFunctionResults(ref); + module.removeFunction(instance.internalName); + module.addFunction(instance.internalName, prevParams, prevResults, vars, body); } // === Exports ================================================================================== @@ -1328,16 +1427,12 @@ export class Compiler extends DiagnosticEmitter { this.currentFlow = previousFlow; // create the function - let body = module.flatten(stmts, instance.signature.returnType.toNativeType()); - if (instance.is(CommonFlags.VIRTUAL)) { - body = module.block("vtable", [ body ], getExpressionType(body)); - } funcRef = module.addFunction( instance.internalName, signature.nativeParams, signature.nativeResults, typesToNativeTypes(instance.additionalLocals), - body + module.flatten(stmts, instance.signature.returnType.toNativeType()) ); // imported function @@ -1827,7 +1922,7 @@ export class Compiler extends DiagnosticEmitter { // insert the trampoline if the function has optional parameters instance = this.ensureTrampoline(instance); } - functionTable.push(instance.internalName); + functionTable.push(instance); instance.functionTableIndex = index; return index; } @@ -6886,6 +6981,7 @@ export class Compiler extends DiagnosticEmitter { trampoline = new Function( original.name + "|trampoline", original.prototype, + original.typeArguments, trampolineSignature, original.contextualTypeArguments ); @@ -7703,6 +7799,7 @@ export class Compiler extends DiagnosticEmitter { instance = new Function( prototype.name, prototype, + null, signature, contextualTypeArguments ); @@ -8756,6 +8853,7 @@ export class Compiler extends DiagnosticEmitter { // declaration is important, i.e. to access optional parameter initializers (baseCtor.declaration).clone() ), + null, baseCtor.signature, contextualTypeArguments ); @@ -8771,6 +8869,7 @@ export class Compiler extends DiagnosticEmitter { CommonFlags.INSTANCE | CommonFlags.CONSTRUCTOR ) ), + null, new Signature(this.program, null, classInstance.type, classInstance.type), contextualTypeArguments ); diff --git a/src/module.ts b/src/module.ts index 58c40425b6..3ee80f72da 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1848,14 +1848,13 @@ export function getFunctionResults(func: FunctionRef): NativeType { return binaryen._BinaryenFunctionGetResults(func); } -export function getFunctionVars(func: FunctionRef): NativeType { - // TODO: unify this on Binaryen's side? +export function getFunctionVars(func: FunctionRef): NativeType[] { var count = binaryen._BinaryenFunctionGetNumVars(func); var types = new Array(count); for (let i: Index = 0; i < count; ++i) { types[i] = binaryen._BinaryenFunctionGetVar(func, i); } - return createType(types); + return types; } // globals diff --git a/src/program.ts b/src/program.ts index 6612ae778c..6d7b22ce7e 100644 --- a/src/program.ts +++ b/src/program.ts @@ -664,6 +664,7 @@ export class Program extends DiagnosticEmitter { this.makeNativeFunctionDeclaration(name, flags), decoratorFlags ), + null, signature ); } @@ -1009,6 +1010,13 @@ export class Program extends DiagnosticEmitter { } } + // check for virtual overloads in derived classes + for (let i = 0, k = queuedExtends.length; i < k; ++i) { + let thisPrototype = queuedExtends[i]; + this.markVirtuals(thisPrototype, assert(thisPrototype.basePrototype)); + } + // TODO: interfaces via queuedImplements + // set up global aliases { let globalAliases = options.globalAliases; @@ -1088,6 +1096,51 @@ export class Program extends DiagnosticEmitter { } } + /** Marks virtual members in a base class overloaded in this class. */ + private markVirtuals(thisPrototype: ClassPrototype, basePrototype: ClassPrototype): void { + // TODO: make this work with interfaaces as well + var thisInstanceMembers = thisPrototype.instanceMembers; + if (thisInstanceMembers) { + do { + let baseInstanceMembers = basePrototype.instanceMembers; + if (baseInstanceMembers) { + for (let _values = Map_values(thisInstanceMembers), j = 0, l = _values.length; j < l; ++j) { + let thisMember = _values[j]; + if (!thisMember.is(CommonFlags.CONSTRUCTOR) && baseInstanceMembers.has(thisMember.name)) { + let baseMember = assert(baseInstanceMembers.get(thisMember.name)); + if ( + thisMember.kind == ElementKind.FUNCTION_PROTOTYPE && + baseMember.kind == ElementKind.FUNCTION_PROTOTYPE + ) { + baseMember.set(CommonFlags.VIRTUAL); + let baseMethod = baseMember; + let overloads = baseMethod.overloads; + if (!overloads) baseMethod.overloads = overloads = new Set(); + overloads.add(thisMember); + let baseMethodInstances = baseMethod.instances; + if (baseMethodInstances) { + for (let _values = Map_values(baseMethodInstances), a = 0, b = _values.length; a < b; ++a) { + let baseMethodInstance = _values[a]; + baseMethodInstance.set(CommonFlags.VIRTUAL); + } + } + } else { + this.errorRelated( + DiagnosticCode.Duplicate_identifier_0, + (thisMember).identifierNode.range, + (baseMember).identifierNode.range + ); + } + } + } + } + let nextPrototype = basePrototype.basePrototype; + if (!nextPrototype) break; + basePrototype = nextPrototype; + } while (true); + } + } + /** Requires that a global library element of the specified kind is present and returns it. */ private require(name: string, kind: ElementKind): Element { var element = this.lookupGlobal(name); @@ -2865,6 +2918,8 @@ export class FunctionPrototype extends DeclaredElement { operatorKind: OperatorKind = OperatorKind.INVALID; /** Already resolved instances. */ instances: Map | null = null; + /** Methods overloading this one, if any. These are unbound. */ + overloads: Set | null = null; /** Clones of this prototype that are bounds to specific classes. */ private boundPrototypes: Map | null = null; @@ -2935,6 +2990,7 @@ export class FunctionPrototype extends DeclaredElement { ); bound.flags = this.flags; bound.operatorKind = this.operatorKind; + bound.overloads = this.overloads; // NOTE: this.instances holds instances per bound class / unbound boundPrototypes.set(classInstance, bound); return bound; @@ -2974,6 +3030,8 @@ export class Function extends TypedElement { localsByIndex: Local[] = []; /** List of additional non-parameter locals. */ additionalLocals: Type[] = []; + /** Concrete type arguments. */ + typeArguments: Type[] | null; /** Contextual type arguments. */ contextualTypeArguments: Map | null; /** Default control flow. */ @@ -3000,6 +3058,8 @@ export class Function extends TypedElement { nameInclTypeParameters: string, /** Respective function prototype. */ prototype: FunctionPrototype, + /** Concrete type arguments. */ + typeArguments: Type[] | null, /** Concrete signature. */ signature: Signature, // pre-resolved /** Contextual type arguments inherited from its parent class, if any. */ @@ -3014,6 +3074,7 @@ export class Function extends TypedElement { prototype.declaration ); this.prototype = prototype; + this.typeArguments = typeArguments; this.signature = signature; this.flags = prototype.flags | CommonFlags.RESOLVED; this.decoratorFlags = prototype.decoratorFlags; @@ -3598,30 +3659,6 @@ export class Class extends TypedElement { assert(!this.base); this.base = base; - // Remember extendees and mark overloaded methods virtual - var basePrototype: ClassPrototype = base.prototype; - var thisPrototype = this.prototype; - assert(basePrototype != thisPrototype); - basePrototype.extendees.add(thisPrototype); - var thisInstanceMembers = thisPrototype.instanceMembers; - if (thisInstanceMembers) { - do { - let baseInstanceMembers = basePrototype.instanceMembers; - if (baseInstanceMembers) { - for (let _keys = Map_keys(baseInstanceMembers), i = 0, k = _keys.length; i < k; ++i) { - let memberName = _keys[i]; - let member = assert(baseInstanceMembers.get(memberName)); - if (thisInstanceMembers.has(memberName)) { - member.set(CommonFlags.VIRTUAL); - } - } - } - let nextPrototype = basePrototype.basePrototype; - if (!nextPrototype) break; - basePrototype = nextPrototype; - } while (true); - } - // Inherit contextual type arguments from base class var inheritedTypeArguments = base.contextualTypeArguments; if (inheritedTypeArguments) { diff --git a/src/resolver.ts b/src/resolver.ts index f7868164e5..0219226dca 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -2776,6 +2776,7 @@ export class Resolver extends DiagnosticEmitter { var instance = new Function( nameInclTypeParameters, prototype, + typeArguments, signature, ctxTypes ); diff --git a/std/assembly/arraybuffer.ts b/std/assembly/arraybuffer.ts index 5e948c9bfe..754d986531 100644 --- a/std/assembly/arraybuffer.ts +++ b/std/assembly/arraybuffer.ts @@ -14,11 +14,6 @@ export abstract class ArrayBufferView { return (this.dataStart - changetype(this.buffer)); } - get length(): i32 { - ERROR("missing implementation: subclasses must implement ArrayBufferView#length"); - return unreachable(); - } - protected constructor(length: i32, alignLog2: i32) { if (length > BLOCK_MAXSIZE >>> alignLog2) throw new RangeError(E_INVALIDLENGTH); var buffer = __alloc(length = length << alignLog2, idof()); diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index ba62ff1bdc..8e0ca503a2 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -1,9 +1,156 @@ (module - (type $i32_=>_none (func (param i32))) - (memory $0 0) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (memory $0 1) + (data (i32.const 1024) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s") + (global $class-overloading/itWorks (mut i32) (i32.const 0)) + (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) + (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) + (global $class-overloading/foo (mut i32) (i32.const 0)) (export "memory" (memory $0)) - (export "test" (func $class-overloading/test)) - (func $class-overloading/test (; 0 ;) (param $0 i32) - nop + (start $~start) + (func $~lib/rt/stub/__alloc (; 1 ;) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + global.get $~lib/rt/stub/offset + i32.const 16 + i32.add + local.tee $3 + i32.const 16 + i32.add + local.tee $1 + memory.size + local.tee $4 + i32.const 16 + i32.shl + local.tee $2 + i32.gt_u + if + local.get $4 + local.get $1 + local.get $2 + i32.sub + i32.const 65535 + i32.add + i32.const -65536 + i32.and + i32.const 16 + i32.shr_u + local.tee $2 + local.get $4 + local.get $2 + i32.gt_s + select + memory.grow + i32.const 0 + i32.lt_s + if + local.get $2 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + end + local.get $1 + global.set $~lib/rt/stub/offset + local.get $3 + i32.const 16 + i32.sub + local.tee $1 + i32.const 16 + i32.store + local.get $1 + i32.const 1 + i32.store offset=4 + local.get $1 + local.get $0 + i32.store offset=8 + local.get $1 + i32.const 0 + i32.store offset=12 + local.get $3 + ) + (func $class-overloading/Bar#constructor (; 2 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 4 + call $~lib/rt/stub/__alloc + local.set $0 + end + local.get $0 + i32.eqz + if (result i32) + i32.const 5 + call $~lib/rt/stub/__alloc + else + local.get $0 + end + ) + (func $~start (; 3 ;) + (local $0 i32) + i32.const 1088 + global.set $~lib/rt/stub/startOffset + i32.const 1088 + global.set $~lib/rt/stub/offset + i32.const 3 + call $~lib/rt/stub/__alloc + call $class-overloading/Bar#constructor + drop + i32.const 0 + call $class-overloading/Bar#constructor + global.set $class-overloading/foo + global.get $class-overloading/foo + i32.const 8 + i32.sub + i32.load + local.tee $0 + i32.const 3 + i32.eq + if + i32.const 0 + i32.const 1040 + i32.const 17 + i32.const 5 + call $~lib/builtins/abort + unreachable + else + local.get $0 + i32.const 4 + i32.eq + if + i32.const 1 + global.set $class-overloading/itWorks + else + local.get $0 + i32.const 5 + i32.eq + if + i32.const 0 + i32.const 1040 + i32.const 5 + i32.const 5 + call $~lib/builtins/abort + end + unreachable + end + end + global.get $class-overloading/itWorks + i32.eqz + if + i32.const 0 + i32.const 1040 + i32.const 24 + i32.const 1 + call $~lib/builtins/abort + unreachable + end ) ) diff --git a/tests/compiler/class-overloading.ts b/tests/compiler/class-overloading.ts index bbd64ac5c6..4db7811745 100644 --- a/tests/compiler/class-overloading.ts +++ b/tests/compiler/class-overloading.ts @@ -1,12 +1,24 @@ +var itWorks = false; + class Foo { - baz(): void {} + a(a: T): void { // called + assert(false); + } } + class Bar extends Foo { - baz(): void {} + a(a: T): void { // what becomes called + itWorks = true; + } } -export function test(foo: Foo): void { - foo.baz(); + +class Baz extends Bar { + a(a: T): void { // not virtual + assert(false); + } } -// FIXME: this results in a call to Foo.baz instead of Bar.baz above. -// ultimately, overloaded functions should implicitly become virtual. -test(changetype(0)); + +new Baz(); +var foo: Foo = new Bar(); +foo.a(1); +assert(itWorks); diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index 3044d0fbe1..93dffbc442 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -1,35 +1,267 @@ (module - (type $i32_=>_none (func (param i32))) - (type $none_=>_none (func)) (type $i32_=>_i32 (func (param i32) (result i32))) - (memory $0 0) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_none (func)) + (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))) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (memory $0 1) + (data (i32.const 16) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s\00") (table $0 1 funcref) + (global $class-overloading/itWorks (mut i32) (i32.const 0)) + (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) + (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) + (global $class-overloading/foo (mut i32) (i32.const 0)) + (global $~lib/heap/__heap_base i32 (i32.const 72)) (export "memory" (memory $0)) - (export "test" (func $class-overloading/test)) (start $~start) - (func $~lib/rt/stub/__retain (; 0 ;) (param $0 i32) (result i32) + (func $~lib/rt/stub/maybeGrowMemory (; 1 ;) (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + memory.size + local.set $1 + local.get $1 + i32.const 16 + i32.shl + local.set $2 local.get $0 + local.get $2 + i32.gt_u + if + local.get $0 + local.get $2 + i32.sub + i32.const 65535 + i32.add + i32.const 65535 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.shr_u + local.set $3 + local.get $1 + local.tee $4 + local.get $3 + local.tee $5 + local.get $4 + local.get $5 + i32.gt_s + select + local.set $4 + local.get $4 + memory.grow + i32.const 0 + i32.lt_s + if + local.get $3 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + end + local.get $0 + global.set $~lib/rt/stub/offset ) - (func $class-overloading/Foo#baz (; 1 ;) (param $0 i32) - nop + (func $~lib/rt/stub/__alloc (; 2 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + local.get $0 + i32.const 1073741808 + i32.gt_u + if + unreachable + end + global.get $~lib/rt/stub/offset + i32.const 16 + i32.add + local.set $2 + local.get $0 + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + local.tee $3 + i32.const 16 + local.tee $4 + local.get $3 + local.get $4 + i32.gt_u + select + local.set $5 + local.get $2 + local.get $5 + i32.add + call $~lib/rt/stub/maybeGrowMemory + local.get $2 + i32.const 16 + i32.sub + local.set $6 + local.get $6 + local.get $5 + i32.store + local.get $6 + i32.const 1 + i32.store offset=4 + local.get $6 + local.get $1 + i32.store offset=8 + local.get $6 + local.get $0 + i32.store offset=12 + local.get $2 ) - (func $~lib/rt/stub/__release (; 2 ;) (param $0 i32) - nop + (func $~lib/rt/stub/__retain (; 3 ;) (param $0 i32) (result i32) + local.get $0 ) - (func $class-overloading/test (; 3 ;) (param $0 i32) + (func $class-overloading/Foo#constructor (; 4 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 5 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + ) + (func $class-overloading/Bar#constructor (; 5 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 4 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end local.get $0 - call $~lib/rt/stub/__retain + call $class-overloading/Foo#constructor local.set $0 local.get $0 - call $class-overloading/Foo#baz + ) + (func $class-overloading/Baz#constructor (; 6 ;) (param $0 i32) (result i32) local.get $0 - call $~lib/rt/stub/__release + i32.eqz + if + i32.const 0 + i32.const 3 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + call $class-overloading/Bar#constructor + local.set $0 + local.get $0 + ) + (func $~lib/rt/stub/__release (; 7 ;) (param $0 i32) + nop ) - (func $start:class-overloading (; 4 ;) + (func $start:class-overloading (; 8 ;) + global.get $~lib/heap/__heap_base + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + global.set $~lib/rt/stub/startOffset + global.get $~lib/rt/stub/startOffset + global.set $~lib/rt/stub/offset i32.const 0 - call $class-overloading/test + call $class-overloading/Baz#constructor + call $~lib/rt/stub/__release + i32.const 0 + call $class-overloading/Bar#constructor + global.set $class-overloading/foo + global.get $class-overloading/foo + i32.const 1 + call $class-overloading/Foo#a + global.get $class-overloading/itWorks + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 24 + i32.const 1 + call $~lib/builtins/abort + unreachable + end ) - (func $~start (; 5 ;) + (func $~start (; 9 ;) call $start:class-overloading ) + (func $class-overloading/Bar#a (; 10 ;) (param $0 i32) (param $1 i32) + i32.const 1 + global.set $class-overloading/itWorks + ) + (func $class-overloading/Baz#a (; 11 ;) (param $0 i32) (param $1 i32) + i32.const 0 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 17 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + ) + (func $class-overloading/Foo#a (; 12 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $2 + local.get $2 + i32.const 3 + i32.eq + if + local.get $0 + local.get $1 + call $class-overloading/Baz#a + else + local.get $2 + i32.const 4 + i32.eq + if + local.get $0 + local.get $1 + call $class-overloading/Bar#a + else + local.get $2 + i32.const 5 + i32.eq + if + i32.const 0 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 5 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + else + unreachable + end + end + end + ) ) diff --git a/tests/compiler/resolve-elementaccess.optimized.wat b/tests/compiler/resolve-elementaccess.optimized.wat index 0c6393c88e..e5dea229b5 100644 --- a/tests/compiler/resolve-elementaccess.optimized.wat +++ b/tests/compiler/resolve-elementaccess.optimized.wat @@ -298,7 +298,7 @@ if i32.const 1040 i32.const 1088 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/resolve-elementaccess.untouched.wat b/tests/compiler/resolve-elementaccess.untouched.wat index bae345c1c3..65379d05de 100644 --- a/tests/compiler/resolve-elementaccess.untouched.wat +++ b/tests/compiler/resolve-elementaccess.untouched.wat @@ -387,7 +387,7 @@ if i32.const 32 i32.const 80 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/array.untouched.wat b/tests/compiler/std/array.untouched.wat index 3421557e23..22cda3ee93 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -2034,7 +2034,7 @@ if i32.const 32 i32.const 336 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/arraybuffer.optimized.wat b/tests/compiler/std/arraybuffer.optimized.wat index 461e3be9be..96b9bc0b50 100644 --- a/tests/compiler/std/arraybuffer.optimized.wat +++ b/tests/compiler/std/arraybuffer.optimized.wat @@ -1517,7 +1517,7 @@ if i32.const 1040 i32.const 1088 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/arraybuffer.untouched.wat b/tests/compiler/std/arraybuffer.untouched.wat index 9545b0df7e..a6c738af2d 100644 --- a/tests/compiler/std/arraybuffer.untouched.wat +++ b/tests/compiler/std/arraybuffer.untouched.wat @@ -1680,7 +1680,7 @@ if i32.const 32 i32.const 80 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable @@ -3147,7 +3147,7 @@ if i32.const 32 i32.const 80 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/dataview.untouched.wat b/tests/compiler/std/dataview.untouched.wat index d1d8c93dd1..348044d8be 100644 --- a/tests/compiler/std/dataview.untouched.wat +++ b/tests/compiler/std/dataview.untouched.wat @@ -1704,7 +1704,7 @@ if i32.const 32 i32.const 80 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/map.optimized.wat b/tests/compiler/std/map.optimized.wat index c445e26c40..23a395a568 100644 --- a/tests/compiler/std/map.optimized.wat +++ b/tests/compiler/std/map.optimized.wat @@ -1279,7 +1279,7 @@ if i32.const 1200 i32.const 1248 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/map.untouched.wat b/tests/compiler/std/map.untouched.wat index c166b63fde..d3e40263da 100644 --- a/tests/compiler/std/map.untouched.wat +++ b/tests/compiler/std/map.untouched.wat @@ -1696,7 +1696,7 @@ if i32.const 192 i32.const 240 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/set.optimized.wat b/tests/compiler/std/set.optimized.wat index 2d8da9dc2e..4cba1a3680 100644 --- a/tests/compiler/std/set.optimized.wat +++ b/tests/compiler/std/set.optimized.wat @@ -1276,7 +1276,7 @@ if i32.const 1200 i32.const 1248 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/set.untouched.wat b/tests/compiler/std/set.untouched.wat index cd4f6ccebd..170c738849 100644 --- a/tests/compiler/std/set.untouched.wat +++ b/tests/compiler/std/set.untouched.wat @@ -1691,7 +1691,7 @@ if i32.const 192 i32.const 240 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/symbol.optimized.wat b/tests/compiler/std/symbol.optimized.wat index 1cfc7648e2..f4ee05e314 100644 --- a/tests/compiler/std/symbol.optimized.wat +++ b/tests/compiler/std/symbol.optimized.wat @@ -316,7 +316,7 @@ if i32.const 1120 i32.const 1168 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/symbol.untouched.wat b/tests/compiler/std/symbol.untouched.wat index dc2f17e3d3..950c5c8637 100644 --- a/tests/compiler/std/symbol.untouched.wat +++ b/tests/compiler/std/symbol.untouched.wat @@ -411,7 +411,7 @@ if i32.const 112 i32.const 160 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/typedarray.optimized.wat b/tests/compiler/std/typedarray.optimized.wat index d29c1b9471..a3118dc572 100644 --- a/tests/compiler/std/typedarray.optimized.wat +++ b/tests/compiler/std/typedarray.optimized.wat @@ -1471,7 +1471,7 @@ if i32.const 1040 i32.const 1088 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable @@ -19297,7 +19297,7 @@ if i32.const 1040 i32.const 1088 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/std/typedarray.untouched.wat b/tests/compiler/std/typedarray.untouched.wat index 199db6a10c..54fe156031 100644 --- a/tests/compiler/std/typedarray.untouched.wat +++ b/tests/compiler/std/typedarray.untouched.wat @@ -1887,7 +1887,7 @@ if i32.const 32 i32.const 80 - i32.const 23 + i32.const 18 i32.const 57 call $~lib/builtins/abort unreachable @@ -36982,7 +36982,7 @@ if i32.const 32 i32.const 80 - i32.const 54 + i32.const 49 i32.const 43 call $~lib/builtins/abort unreachable From 97d6fb2d89099e89dfe2551e704e619f11af0b32 Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 4 Apr 2020 19:45:06 +0200 Subject: [PATCH 02/24] split, table for binaryen --- src/compiler.ts | 187 +++++++++++------- src/program.ts | 7 +- .../compiler/class-overloading.optimized.wat | 62 +++--- .../compiler/class-overloading.untouched.wat | 91 +++++---- 4 files changed, 209 insertions(+), 138 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index a2d48229df..429f9a1c5c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -48,10 +48,8 @@ import { getGlobalGetName, isGlobalMutable, hasSideEffects, - getFunctionBody, getFunctionParams, getFunctionResults, - getFunctionVars, createType } from "./module"; @@ -606,42 +604,40 @@ export class Compiler extends DiagnosticEmitter { /** Makes a normally compiled function virtual by injecting a vtable. */ private makeVirtual(instance: Function): void { - // Check if this function has already been processed - var ref = instance.ref; - var body = getFunctionBody(ref); - if (getExpressionId(body) == ExpressionId.Block && getBlockName(body) == "vt") return; + if (instance.virtualRef) return; + + // (block $self + // (block $id1 + // (block $id2 + // temp = thisId + // br_if $virt2 (temp == id2Id) + // br_if $virt1 (temp == id1Id) + // br_if $self (temp == selfId) + // unreachable + // ) + // call(id2) + // return + // ) + // call(id1) + // return + // ) + // call(self) // Wouldn't be here if there wasn't at least one overload var overloadPrototypes = assert(instance.prototype.overloads); - assert(overloadPrototypes.size); var module = this.module; var usizeType = this.options.usizeType; - var usizeSize = usizeType.byteSize; - var isWasm64 = usizeSize == 8; var nativeSizeType = usizeType.toNativeType(); + var isWasm64 = nativeSizeType == NativeType.I64; + var parameterTypes = instance.signature.parameterTypes; + var returnType = instance.signature.returnType; + var tempIndex = 1 + parameterTypes.length; // incl. `this` - // Add an additional temporary local holding this's class id - var vars = getFunctionVars(ref); - var tempIndex = 1 + instance.signature.parameterTypes.length + vars.length; - vars.push(NativeType.I32); - - // Check that this's class id is what we expect if we don't call an overload - if (!this.options.noAssert) { - let parent = instance.parent; - let actualParent = parent.kind == ElementKind.PROPERTY - ? parent.parent - : parent; - assert(actualParent.kind == ElementKind.CLASS); - body = module.if( - module.binary(BinaryOp.EqI32, - module.local_get(tempIndex, NativeType.I32), - module.i32((actualParent).id) - ), - body, - module.unreachable() // TODO: abort? - ); - } + // Determine virtual names and make the block contents + var ids = new Array(); + var names = new Array(); + var blocks = new Array(); // A method's `overloads` property contains its unbound overload prototypes // so we first have to find the concrete classes it became bound to, obtain @@ -652,7 +648,6 @@ export class Compiler extends DiagnosticEmitter { assert(!unboundOverloadPrototype.isBound); let unboundOverloadParent = unboundOverloadPrototype.parent; assert(unboundOverloadParent.kind == ElementKind.CLASS_PROTOTYPE); - let classInstances = (unboundOverloadParent).instances; if (classInstances) { for (let _values = Map_values(classInstances), j = 0, l = _values.length; j < l; ++j) { @@ -661,37 +656,58 @@ export class Compiler extends DiagnosticEmitter { assert(boundPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); let overloadInstance = this.resolver.resolveFunction(boundPrototype, instance.typeArguments); if (!overloadInstance || !this.compileFunction(overloadInstance)) continue; - let parameterTypes = overloadInstance.signature.parameterTypes; - let numParameters = parameterTypes.length; - let paramExprs = new Array(1 + numParameters); - paramExprs[0] = module.local_get(0, nativeSizeType); // this - for (let n = 0; n < numParameters; ++n) { - paramExprs[1 + n] = module.local_get(1 + n, parameterTypes[n].toNativeType()); - } - - // TODO: verify signature and use trampoline if overload has additional - // optional parameters. - - // TODO: split this into two functions, one with the actual code and one - // with the vtable since calling the super function must circumvent the - // vtable. Perhaps, if we know we are inserting a vtable, we'd generate - // a stub for the vtable function using the function's original name, - // and generate the code function right away as |virtual? - - body = module.if( - module.binary(BinaryOp.EqI32, - module.local_get(tempIndex, NativeType.I32), - module.i32(classInstance.id) - ), - module.call(overloadInstance.internalName, paramExprs, overloadInstance.signature.returnType.toNativeType()), - body - ); + let stmts = new Array(); + let overloadType = overloadInstance.type; + let originalType = instance.type; + if (!overloadType.isAssignableTo(originalType)) { + this.error( + DiagnosticCode.Type_0_is_not_assignable_to_type_1, + overloadInstance.identifierNode.range, overloadType.toString(), originalType.toString() + ); + stmts.push( + module.unreachable() + ); + } else { + // TODO: use trampoline if overload has additional optional parameters. + // Probably even better: Inline the trampoline into the varargs function + // in any case and set numArgs here, so we don't end up with four funcs. + let parameterTypes = overloadInstance.signature.parameterTypes; + let numParameters = parameterTypes.length; + let paramExprs = new Array(1 + numParameters); + paramExprs[0] = module.local_get(0, nativeSizeType); // this + for (let n = 0; n < numParameters; ++n) { + paramExprs[1 + n] = module.local_get(1 + n, parameterTypes[n].toNativeType()); + } + let theCall = module.call(overloadInstance.internalName, paramExprs, overloadInstance.signature.returnType.toNativeType()); + if (returnType != Type.void) { + stmts.push(module.return(theCall)); + } else { + stmts.push(theCall); + stmts.push(module.return()); + } + } + let overloadClassId = classInstance.id; + ids.push(overloadClassId); + names.push("id" + classInstance.id.toString()); + blocks.push(stmts); } } } - // Finally replace the function and mark it with a vtable block - body = module.block("vt", [ + // Determine this's class + var parent = instance.parent; + var actualParent = parent.kind == ElementKind.PROPERTY + ? parent.parent + : parent; + assert(actualParent.kind == ElementKind.CLASS); + var thisClass = actualParent; + ids.push(thisClass.id); + names.push("self"); + + // Make the inner-most block, storing this's rtId to a temporary local, + // and wrap it with all the other blocks + var stmts = new Array(); + stmts.push( module.local_set(tempIndex, // BLOCK(this)#id @ this - 8 module.load(4, false, module.binary( @@ -705,13 +721,48 @@ export class Compiler extends DiagnosticEmitter { ), NativeType.I32 ) - ), - body - ], getExpressionType(body)); - var prevParams = getFunctionParams(ref); - var prevResults = getFunctionResults(ref); - module.removeFunction(instance.internalName); - module.addFunction(instance.internalName, prevParams, prevResults, vars, body); + ) + ); + for (let i = 0, k = names.length; i < k; ++i) { + stmts.push( + module.br(names[i], + module.binary(BinaryOp.EqI32, + module.local_get(tempIndex, NativeType.I32), + module.i32(ids[i]) + ) + ) + ); + } + stmts.push(module.unreachable()); // trap if no id matches + stmts[0] = module.block(names[0], stmts); + stmts.length = 1; + for (let i = 0, k = blocks.length; i < k; ++i) { + let block = blocks[i]; + for (let j = 0, l = block.length; j < l; ++j) { + stmts.push(block[j]); + } + stmts[0] = module.block(names[1 + i], stmts); + stmts.length = 1; + } + + // Last case (self) is calling the original function + var numParameters = parameterTypes.length; + var paramExprs = new Array(numParameters); + paramExprs[0] = module.local_get(0, nativeSizeType); // this + for (let i = 0, k = parameterTypes.length; i < k; ++i) { + paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); + } + stmts.push( + module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()) + ); + + // Make the virtual wrapper + var originalRef = instance.ref; + instance.virtualRef = module.addFunction( + instance.internalName + "|virtual", + getFunctionParams(originalRef), getFunctionResults(originalRef), [ NativeType.I32 ], + module.flatten(stmts, returnType.toNativeType()) + ); } // === Exports ================================================================================== @@ -7515,10 +7566,14 @@ export class Compiler extends DiagnosticEmitter { } } + // Call the virtual stub with the vtable if the function has overloads + var calledName = instance.internalName; + if (instance.is(CommonFlags.VIRTUAL)) calledName += "|virtual"; + // If the return value is of a reference type it has not yet been released but is in flight // which is equivalent to a skipped autorelease. Hence, insert either a release if it is // dropped anyway, preserve the skipped autorelease if explicitly requested or autorelease now. - var expr = module.call(instance.internalName, operands, returnType.toNativeType()); + var expr = module.call(calledName, operands, returnType.toNativeType()); this.currentType = returnType; if (returnType.isManaged) { if (immediatelyDropped) { diff --git a/src/program.ts b/src/program.ts index 6d7b22ce7e..ecbfa5ab01 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1106,7 +1106,10 @@ export class Program extends DiagnosticEmitter { if (baseInstanceMembers) { for (let _values = Map_values(thisInstanceMembers), j = 0, l = _values.length; j < l; ++j) { let thisMember = _values[j]; - if (!thisMember.is(CommonFlags.CONSTRUCTOR) && baseInstanceMembers.has(thisMember.name)) { + if ( + !thisMember.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.PRIVATE) && + baseInstanceMembers.has(thisMember.name) + ) { let baseMember = assert(baseInstanceMembers.get(thisMember.name)); if ( thisMember.kind == ElementKind.FUNCTION_PROTOTYPE && @@ -3040,6 +3043,8 @@ export class Function extends TypedElement { debugLocations: Range[] = []; /** Function reference, if compiled. */ ref: FunctionRef = 0; + /** Function reference of the virtual stub, if compiled. */ + virtualRef: FunctionRef = 0; /** Function table index, if any. */ functionTableIndex: i32 = -1; /** Trampoline function for calling with omitted arguments. */ diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index 8e0ca503a2..d1ecdc7148 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -107,40 +107,44 @@ i32.const 0 call $class-overloading/Bar#constructor global.set $class-overloading/foo - global.get $class-overloading/foo - i32.const 8 - i32.sub - i32.load - local.tee $0 - i32.const 3 - i32.eq - if + block $__inlined_func$class-overloading/Foo#a|virtual + block $self + block $id3 + global.get $class-overloading/foo + i32.const 8 + i32.sub + i32.load + local.tee $0 + i32.const 4 + i32.ne + if + local.get $0 + i32.const 3 + i32.eq + br_if $id3 + local.get $0 + i32.const 5 + i32.eq + br_if $self + unreachable + end + i32.const 1 + global.set $class-overloading/itWorks + br $__inlined_func$class-overloading/Foo#a|virtual + end + i32.const 0 + i32.const 1040 + i32.const 17 + i32.const 5 + call $~lib/builtins/abort + unreachable + end i32.const 0 i32.const 1040 - i32.const 17 + i32.const 5 i32.const 5 call $~lib/builtins/abort unreachable - else - local.get $0 - i32.const 4 - i32.eq - if - i32.const 1 - global.set $class-overloading/itWorks - else - local.get $0 - i32.const 5 - i32.eq - if - i32.const 0 - i32.const 1040 - i32.const 5 - i32.const 5 - call $~lib/builtins/abort - end - unreachable - end end global.get $class-overloading/itWorks i32.eqz diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index 93dffbc442..8d54dcb4cc 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -1,6 +1,6 @@ (module - (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) @@ -171,7 +171,19 @@ (func $~lib/rt/stub/__release (; 7 ;) (param $0 i32) nop ) - (func $start:class-overloading (; 8 ;) + (func $class-overloading/Foo#a (; 8 ;) (param $0 i32) (param $1 i32) + i32.const 0 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 5 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + ) + (func $start:class-overloading (; 9 ;) global.get $~lib/heap/__heap_base i32.const 15 i32.add @@ -190,7 +202,7 @@ global.set $class-overloading/foo global.get $class-overloading/foo i32.const 1 - call $class-overloading/Foo#a + call $class-overloading/Foo#a|virtual global.get $class-overloading/itWorks i32.eqz if @@ -202,14 +214,14 @@ unreachable end ) - (func $~start (; 9 ;) + (func $~start (; 10 ;) call $start:class-overloading ) - (func $class-overloading/Bar#a (; 10 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/Bar#a (; 11 ;) (param $0 i32) (param $1 i32) i32.const 1 global.set $class-overloading/itWorks ) - (func $class-overloading/Baz#a (; 11 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/Baz#a (; 12 ;) (param $0 i32) (param $1 i32) i32.const 0 i32.eqz if @@ -221,47 +233,42 @@ unreachable end ) - (func $class-overloading/Foo#a (; 12 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/Foo#a|virtual (; 13 ;) (param $0 i32) (param $1 i32) (local $2 i32) - local.get $0 - i32.const 8 - i32.sub - i32.load - local.set $2 - local.get $2 - i32.const 3 - i32.eq - if - local.get $0 - local.get $1 - call $class-overloading/Baz#a - else - local.get $2 - i32.const 4 - i32.eq - if + block $self + block $id3 + block $id4 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $2 + local.get $2 + i32.const 4 + i32.eq + br_if $id4 + local.get $2 + i32.const 3 + i32.eq + br_if $id3 + local.get $2 + i32.const 5 + i32.eq + br_if $self + unreachable + end local.get $0 local.get $1 call $class-overloading/Bar#a - else - local.get $2 - i32.const 5 - i32.eq - if - i32.const 0 - i32.eqz - if - i32.const 0 - i32.const 32 - i32.const 5 - i32.const 5 - call $~lib/builtins/abort - unreachable - end - else - unreachable - end + return end + local.get $0 + local.get $1 + call $class-overloading/Baz#a + return end + local.get $0 + local.get $1 + call $class-overloading/Foo#a ) ) From c6659d242e664ddefd799c54a8af7938b402920d Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 4 Apr 2020 19:48:23 +0200 Subject: [PATCH 03/24] fix --- src/compiler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.ts b/src/compiler.ts index 429f9a1c5c..aa9dcfb4bc 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -747,7 +747,7 @@ export class Compiler extends DiagnosticEmitter { // Last case (self) is calling the original function var numParameters = parameterTypes.length; - var paramExprs = new Array(numParameters); + var paramExprs = new Array(numParameters); paramExprs[0] = module.local_get(0, nativeSizeType); // this for (let i = 0, k = parameterTypes.length; i < k; ++i) { paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); From b4ffa4505e06d08f2894fe4fa33c0128eb7ddaf1 Mon Sep 17 00:00:00 2001 From: dcode Date: Sun, 5 Apr 2020 21:13:25 +0200 Subject: [PATCH 04/24] relooper, edge cases --- src/ast.ts | 10 + src/compiler.ts | 260 ++++++++---------- src/diagnosticMessages.generated.ts | 2 + src/diagnosticMessages.json | 1 + src/program.ts | 21 ++ src/types.ts | 1 + tests/binaryen/reloop.js | 71 +++++ tests/bootstrap/index.ts | 2 +- .../compiler/class-overloading.optimized.wat | 58 ++-- tests/compiler/class-overloading.ts | 10 +- .../compiler/class-overloading.untouched.wat | 95 +++---- 11 files changed, 298 insertions(+), 233 deletions(-) create mode 100644 tests/binaryen/reloop.js diff --git a/src/ast.ts b/src/ast.ts index 155b1603fc..7322247cba 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -1165,6 +1165,16 @@ export abstract class Node { } return false; } + + /** Checks if this is a call calling a method on super. */ + get isCallOnSuper(): bool { + if (this.kind != NodeKind.CALL) return false; + var expression = changetype(this).expression; + if (expression.kind != NodeKind.PROPERTYACCESS) return false; + var target = (expression).expression; + if (target.kind == NodeKind.SUPER) return true; + return false; + } } // types diff --git a/src/compiler.ts b/src/compiler.ts index aa9dcfb4bc..da640264e8 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -50,7 +50,8 @@ import { hasSideEffects, getFunctionParams, getFunctionResults, - createType + createType, + Relooper } from "./module"; import { @@ -602,42 +603,40 @@ export class Compiler extends DiagnosticEmitter { return module; } - /** Makes a normally compiled function virtual by injecting a vtable. */ + /** Makes a normally compiled function callable virtually. */ private makeVirtual(instance: Function): void { if (instance.virtualRef) return; - // (block $self - // (block $id1 - // (block $id2 - // temp = thisId - // br_if $virt2 (temp == id2Id) - // br_if $virt1 (temp == id1Id) - // br_if $self (temp == selfId) - // unreachable - // ) - // call(id2) - // return - // ) - // call(id1) - // return - // ) - // call(self) - // Wouldn't be here if there wasn't at least one overload var overloadPrototypes = assert(instance.prototype.overloads); var module = this.module; var usizeType = this.options.usizeType; var nativeSizeType = usizeType.toNativeType(); - var isWasm64 = nativeSizeType == NativeType.I64; var parameterTypes = instance.signature.parameterTypes; - var returnType = instance.signature.returnType; + var numParameters = parameterTypes.length; var tempIndex = 1 + parameterTypes.length; // incl. `this` - // Determine virtual names and make the block contents - var ids = new Array(); - var names = new Array(); - var blocks = new Array(); + // Use a relooper to map this's class id to the matching overload. Note + // that we do not emit a switch here since ids may be distant, and we + // instead rely on the optimizer to figure this out based on opt levels. + var relooper = Relooper.create(this.module); + var entry = relooper.addBlock( + module.local_set(tempIndex, + module.load(4, false, + module.binary( + nativeSizeType == NativeType.I64 + ? BinaryOp.SubI64 + : BinaryOp.SubI32, + module.local_get(0, nativeSizeType), + nativeSizeType == NativeType.I64 + ? module.i64(8) // rtId offset = -8 + : module.i32(8) + ), + NativeType.I32 + ) + ) + ); // A method's `overloads` property contains its unbound overload prototypes // so we first have to find the concrete classes it became bound to, obtain @@ -656,7 +655,6 @@ export class Compiler extends DiagnosticEmitter { assert(boundPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); let overloadInstance = this.resolver.resolveFunction(boundPrototype, instance.typeArguments); if (!overloadInstance || !this.compileFunction(overloadInstance)) continue; - let stmts = new Array(); let overloadType = overloadInstance.type; let originalType = instance.type; if (!overloadType.isAssignableTo(originalType)) { @@ -664,104 +662,83 @@ export class Compiler extends DiagnosticEmitter { DiagnosticCode.Type_0_is_not_assignable_to_type_1, overloadInstance.identifierNode.range, overloadType.toString(), originalType.toString() ); - stmts.push( - module.unreachable() + continue; + } + // TODO: additional optional parameters are not permitted by `isAssignableTo` yet + let overloadSignature = overloadInstance.signature; + let overloadParameterTypes = overloadSignature.parameterTypes; + let overloadNumParameters = overloadParameterTypes.length; + let paramExprs = new Array(1 + overloadNumParameters); + paramExprs[0] = module.local_get(0, nativeSizeType); // this + for (let n = 0; n < numParameters; ++n) { + paramExprs[1 + n] = module.local_get(1 + n, parameterTypes[n].toNativeType()); + } + let needsTrampoline = false; + for (let n = numParameters; n < overloadNumParameters; ++n) { + // TODO: inline constant initializers and skip trampoline + paramExprs[1 + n] = this.makeZero(overloadParameterTypes[n]); + needsTrampoline = true; + } + let calledName = needsTrampoline + ? this.ensureTrampoline(overloadInstance).internalName + : overloadInstance.internalName; + let theCall = module.call(calledName, paramExprs, overloadSignature.returnType.toNativeType()); + let stmts = new Array(); + if (needsTrampoline) { + this.ensureBuiltinArgumentsLength(); + stmts.push(module.global_set(BuiltinNames.argumentsLength, module.i32(numParameters))); + } + stmts.push(theCall); + let block = relooper.addBlock(module.flatten(stmts, NativeType.None)); + relooper.addBranch(entry, block, + module.binary(BinaryOp.EqI32, + module.local_get(tempIndex, NativeType.I32), + module.i32(classInstance.id) + ) + ); + // Do the same for each extendee inheriting this overload, i.e. each + // extendee before there's another actual overload. + let extendees = classInstance.getAllExtendees(instance.prototype.name); + for (let _values = Set_values(extendees), a = 0, b = _values.length; a < b; ++a) { + let extendee = _values[a]; + relooper.addBranch(entry, block, + module.binary(BinaryOp.EqI32, + module.local_get(tempIndex, NativeType.I32), + module.i32(extendee.id) + ) ); - } else { - // TODO: use trampoline if overload has additional optional parameters. - // Probably even better: Inline the trampoline into the varargs function - // in any case and set numArgs here, so we don't end up with four funcs. - let parameterTypes = overloadInstance.signature.parameterTypes; - let numParameters = parameterTypes.length; - let paramExprs = new Array(1 + numParameters); - paramExprs[0] = module.local_get(0, nativeSizeType); // this - for (let n = 0; n < numParameters; ++n) { - paramExprs[1 + n] = module.local_get(1 + n, parameterTypes[n].toNativeType()); - } - let theCall = module.call(overloadInstance.internalName, paramExprs, overloadInstance.signature.returnType.toNativeType()); - if (returnType != Type.void) { - stmts.push(module.return(theCall)); - } else { - stmts.push(theCall); - stmts.push(module.return()); - } } - let overloadClassId = classInstance.id; - ids.push(overloadClassId); - names.push("id" + classInstance.id.toString()); - blocks.push(stmts); } } } - // Determine this's class - var parent = instance.parent; - var actualParent = parent.kind == ElementKind.PROPERTY - ? parent.parent - : parent; - assert(actualParent.kind == ElementKind.CLASS); - var thisClass = actualParent; - ids.push(thisClass.id); - names.push("self"); - - // Make the inner-most block, storing this's rtId to a temporary local, - // and wrap it with all the other blocks - var stmts = new Array(); - stmts.push( - module.local_set(tempIndex, // BLOCK(this)#id @ this - 8 - module.load(4, false, - module.binary( - isWasm64 - ? BinaryOp.SubI64 - : BinaryOp.SubI32, - module.local_get(0, nativeSizeType), - isWasm64 - ? module.i64(8) - : module.i32(8) - ), - NativeType.I32 - ) - ) - ); - for (let i = 0, k = names.length; i < k; ++i) { - stmts.push( - module.br(names[i], - module.binary(BinaryOp.EqI32, - module.local_get(tempIndex, NativeType.I32), - module.i32(ids[i]) - ) + // Call the original function if no other id matches and the method is not + // abstract or part of an interface. Note that doing so will not catch an + // invalid id, but can reduce code size significantly since we also don't + // have to add branches for extendees inheriting the original function. + if (instance.prototype.bodyNode) { + let paramExprs = new Array(numParameters); + paramExprs[0] = module.local_get(0, nativeSizeType); // this + for (let i = 0, k = parameterTypes.length; i < k; ++i) { + paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); + } + relooper.addBranch(entry, + relooper.addBlock( + module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()) ) ); - } - stmts.push(module.unreachable()); // trap if no id matches - stmts[0] = module.block(names[0], stmts); - stmts.length = 1; - for (let i = 0, k = blocks.length; i < k; ++i) { - let block = blocks[i]; - for (let j = 0, l = block.length; j < l; ++j) { - stmts.push(block[j]); - } - stmts[0] = module.block(names[1 + i], stmts); - stmts.length = 1; - } - // Last case (self) is calling the original function - var numParameters = parameterTypes.length; - var paramExprs = new Array(numParameters); - paramExprs[0] = module.local_get(0, nativeSizeType); // this - for (let i = 0, k = parameterTypes.length; i < k; ++i) { - paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); + // Otherwise trap + } else { + relooper.addBranch(entry, relooper.addBlock(module.unreachable())); } - stmts.push( - module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()) - ); // Make the virtual wrapper var originalRef = instance.ref; instance.virtualRef = module.addFunction( instance.internalName + "|virtual", getFunctionParams(originalRef), getFunctionResults(originalRef), [ NativeType.I32 ], - module.flatten(stmts, returnType.toNativeType()) + relooper.renderAndDispose(entry, tempIndex) ); } @@ -1508,7 +1485,6 @@ export class Compiler extends DiagnosticEmitter { null, module.unreachable() ); - this.virtualCalls.add(instance); } else { this.error( DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, @@ -6878,9 +6854,8 @@ export class Compiler extends DiagnosticEmitter { thisArg: ExpressionRef = 0, immediatelyDropped: bool = false ): ExpressionRef { - if (instance.is(CommonFlags.VIRTUAL)) { - this.virtualCalls.add(instance); - } + assert(!instance.is(CommonFlags.VIRTUAL)); + var module = this.module; var numArguments = operands ? operands.length : 0; var signature = instance.signature; @@ -7441,37 +7416,41 @@ export class Compiler extends DiagnosticEmitter { /** Skip the usual autorelease and manage this at the callsite instead. */ skipAutorelease: bool = false ): ExpressionRef { - if (instance.is(CommonFlags.VIRTUAL)) { - this.virtualCalls.add(instance); - } if (instance.hasDecorator(DecoratorFlags.INLINE)) { - assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense - let inlineStack = this.inlineStack; - if (inlineStack.includes(instance)) { - this.warning( - DiagnosticCode.Function_0_cannot_be_inlined_into_itself, - reportNode.range, instance.internalName - ); - } else { - inlineStack.push(instance); - let expr: ExpressionRef; - if (instance.is(CommonFlags.INSTANCE)) { - let theOperands = assert(operands); - assert(theOperands.length); - expr = this.makeCallInline(instance, theOperands.slice(1), theOperands[0], immediatelyDropped); + if (!instance.is(CommonFlags.VIRTUAL)) { + assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense + let inlineStack = this.inlineStack; + if (inlineStack.includes(instance)) { + this.warning( + DiagnosticCode.Function_0_cannot_be_inlined_into_itself, + reportNode.range, instance.internalName + ); } else { - expr = this.makeCallInline(instance, operands, 0, immediatelyDropped); - } - let returnType = this.currentType; - if (returnType.isManaged) { - if (!skipAutorelease) { - expr = this.makeAutorelease(expr, returnType); + inlineStack.push(instance); + let expr: ExpressionRef; + if (instance.is(CommonFlags.INSTANCE)) { + let theOperands = assert(operands); + assert(theOperands.length); + expr = this.makeCallInline(instance, theOperands.slice(1), theOperands[0], immediatelyDropped); } else { - this.skippedAutoreleases.add(expr); + expr = this.makeCallInline(instance, operands, 0, immediatelyDropped); + } + let returnType = this.currentType; + if (returnType.isManaged) { + if (!skipAutorelease) { + expr = this.makeAutorelease(expr, returnType); + } else { + this.skippedAutoreleases.add(expr); + } } + inlineStack.pop(); + return expr; } - inlineStack.pop(); - return expr; + } else { + this.warning( + DiagnosticCode.Function_0_is_virtual_and_will_not_be_inlined, + reportNode.range, instance.internalName + ); } } var numOperands = operands ? operands.length : 0; @@ -7568,7 +7547,10 @@ export class Compiler extends DiagnosticEmitter { // Call the virtual stub with the vtable if the function has overloads var calledName = instance.internalName; - if (instance.is(CommonFlags.VIRTUAL)) calledName += "|virtual"; + if (instance.is(CommonFlags.VIRTUAL) && !reportNode.isCallOnSuper) { + calledName += "|virtual"; + this.virtualCalls.add(instance); + } // If the return value is of a reference type it has not yet been released but is in flight // which is equivalent to a skipped autorelease. Hence, insert either a release if it is diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 45988f1d65..4ae6cb7139 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -40,6 +40,7 @@ export enum DiagnosticCode { _0_is_not_a_valid_operator = 224, Expression_cannot_be_represented_by_a_type = 225, Expression_resolves_to_unusual_type_0 = 226, + Function_0_is_virtual_and_will_not_be_inlined = 227, Type_0_is_cyclic_Module_will_include_deferred_garbage_collection = 900, Importing_the_table_disables_some_indirect_call_optimizations = 901, Exporting_the_table_disables_some_indirect_call_optimizations = 902, @@ -194,6 +195,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 224: return "'{0}' is not a valid operator."; case 225: return "Expression cannot be represented by a type."; case 226: return "Expression resolves to unusual type '{0}'."; + case 227: return "Function '{0}' is virtual and will not be inlined."; case 900: return "Type '{0}' is cyclic. Module will include deferred garbage collection."; case 901: return "Importing the table disables some indirect call optimizations."; case 902: return "Exporting the table disables some indirect call optimizations."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 94ef96a447..dfc8722c4e 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -33,6 +33,7 @@ "'{0}' is not a valid operator.": 224, "Expression cannot be represented by a type.": 225, "Expression resolves to unusual type '{0}'.": 226, + "Function '{0}' is virtual and will not be inlined.": 227, "Type '{0}' is cyclic. Module will include deferred garbage collection.": 900, "Importing the table disables some indirect call optimizations.": 901, diff --git a/src/program.ts b/src/program.ts index ecbfa5ab01..2eab03ae8b 100644 --- a/src/program.ts +++ b/src/program.ts @@ -3582,6 +3582,8 @@ export class Class extends TypedElement { rttiFlags: u32 = 0; /** Wrapped type, if a wrapper for a basic type. */ wrappedType: Type | null = null; + /** Classes directly extending this class. */ + extendees: Set = new Set(); /** Gets the unique runtime id of this class. */ get id(): u32 { @@ -3663,6 +3665,7 @@ export class Class extends TypedElement { setBase(base: Class): void { assert(!this.base); this.base = base; + base.extendees.add(this); // Inherit contextual type arguments from base class var inheritedTypeArguments = base.contextualTypeArguments; @@ -3924,6 +3927,24 @@ export class Class extends TypedElement { } return false; } + + /** Gets all extendees of this class (that do not have the specified instance member). */ + getAllExtendees(exceptIfMember: string | null = null, out: Set = new Set()): Set { + for (let _values = Set_values(this.extendees), i = 0, k = _values.length; i < k; ++i) { + let extendee = _values[i]; + if (!exceptIfMember) { + out.add(extendee); + extendee.getAllExtendees(null, out); + } else { + let instanceMembers = extendee.prototype.instanceMembers; + if (!instanceMembers || !instanceMembers.has(exceptIfMember)) { + out.add(extendee); + extendee.getAllExtendees(exceptIfMember, out); + } + } + } + return out; + } } /** A yet unresolved interface. */ diff --git a/src/types.ts b/src/types.ts index 113bf04b9e..a0b0f862fb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -615,6 +615,7 @@ export class Signature { /** Tests if a value of this function type is assignable to a target of the specified function type. */ isAssignableTo(target: Signature): bool { + // TODO: allow additional optional parameters return this.equals(target); } diff --git a/tests/binaryen/reloop.js b/tests/binaryen/reloop.js new file mode 100644 index 0000000000..c133002653 --- /dev/null +++ b/tests/binaryen/reloop.js @@ -0,0 +1,71 @@ +var binaryen = require("binaryen"); +binaryen.setOptimizeLevel(3); +binaryen.setShrinkLevel(0); + +function usingBranches() { + var module = new binaryen.Module(); + var rl = new binaryen.Relooper(module); + var entry = rl.addBlock(module.nop()); + + for (let i = 0; i < 10; ++i) { + rl.addBranch(entry, + rl.addBlock( + module.return( + module.call("other", [ module.i32.const(i) ], binaryen.none, binaryen.i32) + ) + ), + module.i32.eq( + module.local.get(0, binaryen.i32), + module.i32.const(i) + ) + ); + } + rl.addBranch(entry, + rl.addBlock( + module.unreachable() + ) + ); + + module.addFunction("test", binaryen.i32, binaryen.i32, [ binaryen.i32 ], rl.renderAndDispose(entry, 1)); + module.addFunctionImport("other", "env", "other", binaryen.i32, binaryen.i32); + module.addFunctionExport("test", "test"); + + console.log("=== unoptimized ==="); + console.log(module.emitText()); + module.optimize(); + console.log("=== optimized ==="); + console.log(module.emitText()); +} +usingBranches(); + +function usingSwitch() { + var module = new binaryen.Module(); + var rl = new binaryen.Relooper(module); + var entry = rl.addBlockWithSwitch(module.nop(), module.local.get(0, binaryen.i32)); + + for (let i = 0; i < 10; ++i) { + rl.addBranchForSwitch(entry, + rl.addBlock( + module.return( + module.call("other", [ module.i32.const(i) ], binaryen.none, binaryen.i32) + ) + ), + [ i ] + ); + } + rl.addBranchForSwitch(entry, + rl.addBlock( + module.unreachable() + ), + [] + ); + + module.addFunction("test", binaryen.i32, binaryen.i32, [ binaryen.i32 ], rl.renderAndDispose(entry, 1)); + module.addFunctionImport("other", "env", "other", binaryen.none, binaryen.i32); + module.addFunctionExport("test", "test"); + + console.log(module.emitText()); + module.optimize(); + console.log(module.emitText()); +} +// usingSwitch(); diff --git a/tests/bootstrap/index.ts b/tests/bootstrap/index.ts index bafb9ff1b7..2e44d700b5 100644 --- a/tests/bootstrap/index.ts +++ b/tests/bootstrap/index.ts @@ -21,7 +21,7 @@ async function test(build: string): Promise { console.log("nextFile: " + asc.__getString(nextFilePtr)); nextFilePtr = asc.nextFile(programPtr); } - // assemblyscript.compile(programPtr); + // asc.compile(programPtr); // ^ abort: missing ArrayBuffer at src/program.ts:1015:18 console.log("So far, so good."); } diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index d1ecdc7148..c347d55fd6 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -8,6 +8,7 @@ (global $class-overloading/itWorks (mut i32) (i32.const 0)) (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) + (global $class-overloading/baz (mut i32) (i32.const 0)) (global $class-overloading/foo (mut i32) (i32.const 0)) (export "memory" (memory $0)) (start $~start) @@ -103,55 +104,44 @@ i32.const 3 call $~lib/rt/stub/__alloc call $class-overloading/Bar#constructor - drop + global.set $class-overloading/baz + i32.const 1 + global.set $class-overloading/itWorks i32.const 0 call $class-overloading/Bar#constructor global.set $class-overloading/foo - block $__inlined_func$class-overloading/Foo#a|virtual - block $self - block $id3 - global.get $class-overloading/foo - i32.const 8 - i32.sub - i32.load - local.tee $0 - i32.const 4 - i32.ne - if - local.get $0 - i32.const 3 - i32.eq - br_if $id3 - local.get $0 - i32.const 5 - i32.eq - br_if $self - unreachable - end - i32.const 1 - global.set $class-overloading/itWorks - br $__inlined_func$class-overloading/Foo#a|virtual - end + global.get $class-overloading/foo + i32.const 8 + i32.sub + i32.load + local.tee $0 + i32.const 4 + i32.eq + if + i32.const 1 + global.set $class-overloading/itWorks + else + local.get $0 + i32.const 3 + i32.eq + if + i32.const 1 + global.set $class-overloading/itWorks + else i32.const 0 i32.const 1040 - i32.const 17 + i32.const 5 i32.const 5 call $~lib/builtins/abort unreachable end - i32.const 0 - i32.const 1040 - i32.const 5 - i32.const 5 - call $~lib/builtins/abort - unreachable end global.get $class-overloading/itWorks i32.eqz if i32.const 0 i32.const 1040 - i32.const 24 + i32.const 26 i32.const 1 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/class-overloading.ts b/tests/compiler/class-overloading.ts index 4db7811745..f92f9d0425 100644 --- a/tests/compiler/class-overloading.ts +++ b/tests/compiler/class-overloading.ts @@ -1,24 +1,26 @@ var itWorks = false; class Foo { - a(a: T): void { // called + a(a: T): void { // virtual, called assert(false); } } class Bar extends Foo { - a(a: T): void { // what becomes called + a(a: T): void { // virtual, what becomes called itWorks = true; } } class Baz extends Bar { a(a: T): void { // not virtual - assert(false); + super.a(a); // calls non-virtual Bar#a } } -new Baz(); +var baz: Baz = new Baz(); +baz.a(1); + var foo: Foo = new Bar(); foo.a(1); assert(itWorks); diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index 8d54dcb4cc..f77967447f 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -12,6 +12,7 @@ (global $class-overloading/itWorks (mut i32) (i32.const 0)) (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) + (global $class-overloading/baz (mut i32) (i32.const 0)) (global $class-overloading/foo (mut i32) (i32.const 0)) (global $~lib/heap/__heap_base i32 (i32.const 72)) (export "memory" (memory $0)) @@ -168,10 +169,16 @@ local.set $0 local.get $0 ) - (func $~lib/rt/stub/__release (; 7 ;) (param $0 i32) - nop + (func $class-overloading/Bar#a (; 7 ;) (param $0 i32) (param $1 i32) + i32.const 1 + global.set $class-overloading/itWorks + ) + (func $class-overloading/Baz#a (; 8 ;) (param $0 i32) (param $1 i32) + local.get $0 + local.get $1 + call $class-overloading/Bar#a ) - (func $class-overloading/Foo#a (; 8 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/Foo#a (; 9 ;) (param $0 i32) (param $1 i32) i32.const 0 i32.eqz if @@ -183,7 +190,7 @@ unreachable end ) - (func $start:class-overloading (; 9 ;) + (func $start:class-overloading (; 10 ;) global.get $~lib/heap/__heap_base i32.const 15 i32.add @@ -196,7 +203,10 @@ global.set $~lib/rt/stub/offset i32.const 0 call $class-overloading/Baz#constructor - call $~lib/rt/stub/__release + global.set $class-overloading/baz + global.get $class-overloading/baz + i32.const 1 + call $class-overloading/Baz#a i32.const 0 call $class-overloading/Bar#constructor global.set $class-overloading/foo @@ -208,67 +218,42 @@ if i32.const 0 i32.const 32 - i32.const 24 + i32.const 26 i32.const 1 call $~lib/builtins/abort unreachable end ) - (func $~start (; 10 ;) + (func $~start (; 11 ;) call $start:class-overloading ) - (func $class-overloading/Bar#a (; 11 ;) (param $0 i32) (param $1 i32) - i32.const 1 - global.set $class-overloading/itWorks - ) - (func $class-overloading/Baz#a (; 12 ;) (param $0 i32) (param $1 i32) - i32.const 0 - i32.eqz - if - i32.const 0 - i32.const 32 - i32.const 17 - i32.const 5 - call $~lib/builtins/abort - unreachable - end - ) - (func $class-overloading/Foo#a|virtual (; 13 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/Foo#a|virtual (; 12 ;) (param $0 i32) (param $1 i32) (local $2 i32) - block $self - block $id3 - block $id4 - local.get $0 - i32.const 8 - i32.sub - i32.load - local.set $2 - local.get $2 - i32.const 4 - i32.eq - br_if $id4 - local.get $2 - i32.const 3 - i32.eq - br_if $id3 - local.get $2 - i32.const 5 - i32.eq - br_if $self - unreachable - end + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $2 + local.get $2 + i32.const 4 + i32.eq + if + local.get $0 + local.get $1 + call $class-overloading/Bar#a + else + local.get $2 + i32.const 3 + i32.eq + if + local.get $0 + local.get $1 + call $class-overloading/Baz#a + else local.get $0 local.get $1 - call $class-overloading/Bar#a - return + call $class-overloading/Foo#a end - local.get $0 - local.get $1 - call $class-overloading/Baz#a - return end - local.get $0 - local.get $1 - call $class-overloading/Foo#a ) ) From f89c24e4cea689b307e4c70aa1e2ecc2fba7286d Mon Sep 17 00:00:00 2001 From: dcode Date: Sun, 5 Apr 2020 22:23:50 +0200 Subject: [PATCH 05/24] fix --- src/compiler.ts | 40 ++++++++++++++++++++++++---------------- src/program.ts | 12 ++++-------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index da640264e8..8feeed4b67 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -682,32 +682,38 @@ export class Compiler extends DiagnosticEmitter { let calledName = needsTrampoline ? this.ensureTrampoline(overloadInstance).internalName : overloadInstance.internalName; - let theCall = module.call(calledName, paramExprs, overloadSignature.returnType.toNativeType()); + let nativeReturnType = overloadSignature.returnType.toNativeType(); let stmts = new Array(); if (needsTrampoline) { this.ensureBuiltinArgumentsLength(); stmts.push(module.global_set(BuiltinNames.argumentsLength, module.i32(numParameters))); } - stmts.push(theCall); - let block = relooper.addBlock(module.flatten(stmts, NativeType.None)); - relooper.addBranch(entry, block, - module.binary(BinaryOp.EqI32, - module.local_get(tempIndex, NativeType.I32), - module.i32(classInstance.id) - ) + stmts.push( + module.call(calledName, paramExprs, nativeReturnType) + ); + // Include each extendee inheriting this overload, i.e. each extendee + // before there's another actual overload. + let cond = module.binary(BinaryOp.EqI32, + module.local_get(tempIndex, NativeType.I32), + module.i32(classInstance.id) ); - // Do the same for each extendee inheriting this overload, i.e. each - // extendee before there's another actual overload. let extendees = classInstance.getAllExtendees(instance.prototype.name); for (let _values = Set_values(extendees), a = 0, b = _values.length; a < b; ++a) { let extendee = _values[a]; - relooper.addBranch(entry, block, + cond = module.binary(BinaryOp.OrI32, + cond, module.binary(BinaryOp.EqI32, module.local_get(tempIndex, NativeType.I32), module.i32(extendee.id) ) ); } + relooper.addBranch(entry, + relooper.addBlock( + module.flatten(stmts, nativeReturnType) + ), + cond + ); } } } @@ -722,15 +728,17 @@ export class Compiler extends DiagnosticEmitter { for (let i = 0, k = parameterTypes.length; i < k; ++i) { paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); } - relooper.addBranch(entry, - relooper.addBlock( - module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()) - ) + let block = relooper.addBlock( + module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()) ); + relooper.addBranch(entry, block); // Otherwise trap } else { - relooper.addBranch(entry, relooper.addBlock(module.unreachable())); + let block = relooper.addBlock( + module.unreachable() + ); + relooper.addBranch(entry, block); } // Make the virtual wrapper diff --git a/src/program.ts b/src/program.ts index 2eab03ae8b..e057f91d3e 100644 --- a/src/program.ts +++ b/src/program.ts @@ -3932,16 +3932,12 @@ export class Class extends TypedElement { getAllExtendees(exceptIfMember: string | null = null, out: Set = new Set()): Set { for (let _values = Set_values(this.extendees), i = 0, k = _values.length; i < k; ++i) { let extendee = _values[i]; - if (!exceptIfMember) { - out.add(extendee); - extendee.getAllExtendees(null, out); - } else { + if (exceptIfMember) { let instanceMembers = extendee.prototype.instanceMembers; - if (!instanceMembers || !instanceMembers.has(exceptIfMember)) { - out.add(extendee); - extendee.getAllExtendees(exceptIfMember, out); - } + if (instanceMembers !== null && instanceMembers.has(exceptIfMember)) continue; } + out.add(extendee); + extendee.getAllExtendees(exceptIfMember, out); } return out; } From 6fcd1570368a70d9698c1948a52a4705194a4e2f Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 6 Apr 2020 16:32:04 +0200 Subject: [PATCH 06/24] extend bootstrap --- std/portable/index.d.ts | 3 ++ std/portable/index.js | 5 +++ tests/bootstrap/index.ts | 68 +++++++++++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/std/portable/index.d.ts b/std/portable/index.d.ts index df78e5ac25..938fb4a728 100644 --- a/std/portable/index.d.ts +++ b/std/portable/index.d.ts @@ -300,3 +300,6 @@ declare interface StringConstructor { /** Annotates a class as being unmanaged with limited capabilities. */ declare function unmanaged(constructor: Function): void; + +/** Environmental tracing function. */ +declare function trace(msg: string, n?: i32, a0?: f64, a1?: f64, a2?: f64, a3?: f64, a4?: f64): void; diff --git a/std/portable/index.js b/std/portable/index.js index 481b48a09d..95e528eae3 100644 --- a/std/portable/index.js +++ b/std/portable/index.js @@ -299,3 +299,8 @@ Object.defineProperties(globalScope["JSMath"], { }); globalScope["unmanaged"] = function() {}; + +globalScope["trace"] = function(message, n) { + if (n) message += Array.prototype.slice.call(arguments, 2, 2 + n); + console.error("trace: " + message); +}; diff --git a/tests/bootstrap/index.ts b/tests/bootstrap/index.ts index 2e44d700b5..5730582031 100644 --- a/tests/bootstrap/index.ts +++ b/tests/bootstrap/index.ts @@ -1,28 +1,82 @@ import * as fs from "fs"; +import * as path from "path"; import * as binaryen from "binaryen"; import * as util from "util"; import * as loader from "../../lib/loader"; +import * as find from "../../cli/util/find"; import AssemblyScript from "../../out/assemblyscript"; +// Load stdlib +const libDir = path.join(__dirname, "..", "..", "std", "assembly"); +const libraryFiles = {}; +find.files(libDir, find.TS_EXCEPT_DTS).forEach((file: string) => { + libraryFiles[file.replace(/\.ts$/, "")] = fs.readFileSync(path.join(libDir, file), "utf8" ); +}); + async function test(build: string): Promise { await binaryen.ready; + const { exports: asc } = await loader.instantiate( fs.promises.readFile(`${ __dirname }/../../out/assemblyscript.${ build }.wasm`), { binaryen } ); console.log(util.inspect(asc, true)); + + const cachedStrings = new Map(); + function allocString(text: string): number { + if (cachedStrings.has(text)) return cachedStrings.get(text); + var ptr = asc.__retain(asc.__allocString(text)); + cachedStrings.set(text, ptr); + return ptr; + } + const optionsPtr = asc.newOptions(); const programPtr = asc.newProgram(optionsPtr); - const textPtr = asc.__allocString("export function add(a: i32, b: i32): i32 { return a + b; }\n"); - const pathPtr = asc.__allocString("index.ts"); - asc.parse(programPtr, textPtr, pathPtr, true); + + console.log("\nParsing standard library ..."); + Object.keys(libraryFiles).forEach((libPath: string) => { + if (libPath.indexOf("/") >= 0) return; + const textPtr = allocString(libraryFiles[libPath]); + const pathPtr = allocString("~lib/" + libPath + ".ts"); + console.log(" " + asc.__getString(pathPtr)); + asc.parse(programPtr, textPtr, pathPtr, false); + }); + + console.log("\nParsing backlog ..."); var nextFilePtr = asc.nextFile(programPtr); while (nextFilePtr) { - console.log("nextFile: " + asc.__getString(nextFilePtr)); + const nextFile = asc.__getString(nextFilePtr); + if (!nextFile.startsWith("~lib/")) throw Error("unexpected file: " + nextFile); + const text = libraryFiles[nextFile.substring(5)]; + if (text == null) throw Error("missing file: " + nextFile); + const textPtr = allocString(libraryFiles[nextFile.substring(5)]); + const pathPtr = allocString(nextFile + ".ts"); + console.log(" " + asc.__getString(pathPtr)); + asc.parse(programPtr, textPtr, pathPtr, false); + asc.__release(nextFilePtr); nextFilePtr = asc.nextFile(programPtr); } - // asc.compile(programPtr); - // ^ abort: missing ArrayBuffer at src/program.ts:1015:18 - console.log("So far, so good."); + + console.log("\nParsing entry file ..."); + { + const textPtr = allocString("export function add(a: i32, b: i32): i32 { return a + b; }\n"); + const pathPtr = allocString("index.ts"); + console.log(" " + asc.__getString(pathPtr)); + asc.parse(programPtr, textPtr, pathPtr, true); + } + + try { + console.log("\nInitializing program ..."); + asc.initializeProgram(programPtr, optionsPtr); + console.log("\nCompiling program ..."); + const modulePtr = asc.compile(programPtr); + console.log(binaryen.wrapModule(modulePtr).emitText()); + } catch (e) { + console.log("\nTODO: " + e.message); + } + + cachedStrings.forEach(asc.__release); + + console.log("\nSo far, so good."); } test("untouched"); From 016ff3ea93aed621bcfd13e1462d29a49c7425e2 Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 6 Apr 2020 18:17:24 +0200 Subject: [PATCH 07/24] more --- package.json | 4 ++-- tests/bootstrap/index.ts | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3d343ffdda..77e661698e 100644 --- a/package.json +++ b/package.json @@ -65,8 +65,8 @@ "prepublishOnly": "node scripts/prepublish", "postpublish": "node scripts/postpublish", "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized", - "asbuild:untouched": "node bin/asc src/glue/wasm/index.ts src/index.ts -t out/assemblyscript.untouched.wat -b out/assemblyscript.untouched.wasm -d out/assemblyscript.d.ts --validate --debug --measure", - "asbuild:optimized": "node bin/asc src/glue/wasm/index.ts src/index.ts -t out/assemblyscript.optimized.wat -b out/assemblyscript.optimized.wasm -O3 --validate --measure", + "asbuild:untouched": "node bin/asc src/glue/wasm/index.ts src/index.ts -t out/assemblyscript.untouched.wat -b out/assemblyscript.untouched.wasm -d out/assemblyscript.d.ts --validate --debug --measure --runtime stub", + "asbuild:optimized": "node bin/asc src/glue/wasm/index.ts src/index.ts -t out/assemblyscript.optimized.wat -b out/assemblyscript.optimized.wasm -O3 --validate --measure --runtime stub", "astest": "ts-node tests/bootstrap" }, "releaseFiles": [ diff --git a/tests/bootstrap/index.ts b/tests/bootstrap/index.ts index 5730582031..562b3a0d79 100644 --- a/tests/bootstrap/index.ts +++ b/tests/bootstrap/index.ts @@ -42,6 +42,14 @@ async function test(build: string): Promise { asc.parse(programPtr, textPtr, pathPtr, false); }); + console.log("\nParsing runtime ..."); + { + const textPtr = allocString(libraryFiles["rt/index-stub"]); + const pathPtr = allocString("~lib/rt/index-stub"); + console.log(" " + asc.__getString(pathPtr)); + asc.parse(programPtr, textPtr, pathPtr, true); + } + console.log("\nParsing backlog ..."); var nextFilePtr = asc.nextFile(programPtr); while (nextFilePtr) { @@ -72,7 +80,7 @@ async function test(build: string): Promise { const modulePtr = asc.compile(programPtr); console.log(binaryen.wrapModule(modulePtr).emitText()); } catch (e) { - console.log("\nTODO: " + e.message); + console.log("\nTODO: " + e.stack); } cachedStrings.forEach(asc.__release); From 9aeee59eea09891913a591d6df9079402ab13482 Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 6 Apr 2020 18:29:38 +0200 Subject: [PATCH 08/24] show full stack trace --- tests/bootstrap/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/bootstrap/index.ts b/tests/bootstrap/index.ts index 562b3a0d79..e799e2477b 100644 --- a/tests/bootstrap/index.ts +++ b/tests/bootstrap/index.ts @@ -6,6 +6,8 @@ import * as loader from "../../lib/loader"; import * as find from "../../cli/util/find"; import AssemblyScript from "../../out/assemblyscript"; +Error.stackTraceLimit = Infinity; + // Load stdlib const libDir = path.join(__dirname, "..", "..", "std", "assembly"); const libraryFiles = {}; From 27bf5e7b24b6fcf81cce0b0095563d398467f469 Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 6 Apr 2020 18:51:21 +0200 Subject: [PATCH 09/24] wow... --- src/builtins.ts | 8 +++++--- tests/bootstrap/index.ts | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index 8800a8c4c9..8771f36471 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -1397,7 +1397,8 @@ function builtin_max(ctx: BuiltinContext): ExpressionRef { module.binary(op, module.local_get(temp1.index, nativeType), module.local_get(temp2.index, nativeType) - ) + ), + nativeType ); flow.freeTempLocal(temp2); flow.freeTempLocal(temp1); @@ -1476,7 +1477,8 @@ function builtin_min(ctx: BuiltinContext): ExpressionRef { module.binary(op, module.local_get(temp1.index, nativeType), module.local_get(temp2.index, nativeType) - ) + ), + nativeType ); flow.freeTempLocal(temp2); flow.freeTempLocal(temp1); @@ -2453,7 +2455,7 @@ function builtin_select(ctx: BuiltinContext): ExpressionRef { compiler.currentType // ^ ); compiler.currentType = type; - return module.select(arg0, arg1, arg2); + return module.select(arg0, arg1, arg2, type.toNativeType()); } builtins.set(BuiltinNames.select, builtin_select); diff --git a/tests/bootstrap/index.ts b/tests/bootstrap/index.ts index e799e2477b..e3020f423c 100644 --- a/tests/bootstrap/index.ts +++ b/tests/bootstrap/index.ts @@ -80,7 +80,9 @@ async function test(build: string): Promise { asc.initializeProgram(programPtr, optionsPtr); console.log("\nCompiling program ..."); const modulePtr = asc.compile(programPtr); - console.log(binaryen.wrapModule(modulePtr).emitText()); + const moduleRef = new Uint32Array(asc.memory.buffer, modulePtr)[0]; + console.log(binaryen.wrapModule(moduleRef).emitText()); + // Wow! } catch (e) { console.log("\nTODO: " + e.stack); } From 661866d60cf1420edcb8dc3fa8df22ea3e7701e3 Mon Sep 17 00:00:00 2001 From: dcode Date: Tue, 7 Apr 2020 23:11:30 +0200 Subject: [PATCH 10/24] fix varargs confusion --- src/builtins.ts | 8 +- src/compiler.ts | 77 +- tests/compiler/call-optional.untouched.wat | 20 +- .../function-expression.untouched.wat | 20 +- tests/compiler/function-types.untouched.wat | 28 +- tests/compiler/infer-generic.optimized.wat | 9 +- tests/compiler/infer-generic.untouched.wat | 4 +- tests/compiler/inlining.untouched.wat | 2 +- .../resolve-function-expression.untouched.wat | 6 +- tests/compiler/resolve-ternary.untouched.wat | 6 +- tests/compiler/retain-release.untouched.wat | 2 +- tests/compiler/retain-return.untouched.wat | 4 +- tests/compiler/rt/flags.optimized.wat | 116 +- tests/compiler/rt/flags.untouched.wat | 346 ++-- tests/compiler/std/array.optimized.wat | 233 +-- tests/compiler/std/array.untouched.wat | 172 +- tests/compiler/std/arraybuffer.optimized.wat | 4 +- tests/compiler/std/arraybuffer.untouched.wat | 4 +- tests/compiler/std/dataview.optimized.wat | 7 +- tests/compiler/std/dataview.untouched.wat | 4 +- tests/compiler/std/string.untouched.wat | 6 +- tests/compiler/std/typedarray.optimized.wat | 1539 +++++++++-------- tests/compiler/std/typedarray.untouched.wat | 598 +++---- 23 files changed, 1658 insertions(+), 1557 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index ac784483af..671ba4221c 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -1397,8 +1397,7 @@ function builtin_max(ctx: BuiltinContext): ExpressionRef { module.binary(op, module.local_get(temp1.index, nativeType), module.local_get(temp2.index, nativeType) - ), - nativeType + ) ); flow.freeTempLocal(temp2); flow.freeTempLocal(temp1); @@ -1477,8 +1476,7 @@ function builtin_min(ctx: BuiltinContext): ExpressionRef { module.binary(op, module.local_get(temp1.index, nativeType), module.local_get(temp2.index, nativeType) - ), - nativeType + ) ); flow.freeTempLocal(temp2); flow.freeTempLocal(temp1); @@ -2455,7 +2453,7 @@ function builtin_select(ctx: BuiltinContext): ExpressionRef { compiler.currentType // ^ ); compiler.currentType = type; - return module.select(arg0, arg1, arg2, type.toNativeType()); + return module.select(arg0, arg1, arg2); } builtins.set(BuiltinNames.select, builtin_select); diff --git a/src/compiler.ts b/src/compiler.ts index 8bdf740be4..71542407e7 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -51,7 +51,9 @@ import { getFunctionParams, getFunctionResults, createType, - Relooper + Relooper, + getSideEffects, + SideEffects } from "./module"; import { @@ -688,6 +690,7 @@ export class Compiler extends DiagnosticEmitter { let stmts = new Array(); if (needsTrampoline) { this.ensureBuiltinArgumentsLength(); + // Safe to prepend since paramExprs are local.get's stmts.push(module.global_set(BuiltinNames.argumentsLength, module.i32(numParameters))); } stmts.push( @@ -7492,11 +7495,13 @@ export class Compiler extends DiagnosticEmitter { ); } } + var module = this.module; var numOperands = operands ? operands.length : 0; var numArguments = numOperands; var minArguments = instance.signature.requiredParameters; var minOperands = minArguments; - var maxArguments = instance.signature.parameterTypes.length; + var parameterTypes = instance.signature.parameterTypes; + var maxArguments = parameterTypes.length; var maxOperands = maxArguments; if (instance.is(CommonFlags.INSTANCE)) { ++minOperands; @@ -7505,10 +7510,8 @@ export class Compiler extends DiagnosticEmitter { } assert(numOperands >= minOperands); - var module = this.module; if (!this.compileFunction(instance)) return module.unreachable(); var returnType = instance.signature.returnType; - var isCallImport = instance.is(CommonFlags.MODULE_IMPORT); // fill up omitted arguments with their initializers, if constant, otherwise with zeroes. if (numOperands < maxOperands) { @@ -7516,7 +7519,6 @@ export class Compiler extends DiagnosticEmitter { operands = new Array(maxOperands); operands.length = 0; } - let parameterTypes = instance.signature.parameterTypes; let parameterNodes = instance.prototype.functionTypeNode.parameters; assert(parameterNodes.length == parameterTypes.length); let allOptionalsAreConstant = true; @@ -7557,12 +7559,21 @@ export class Compiler extends DiagnosticEmitter { allOptionalsAreConstant = false; } if (!allOptionalsAreConstant) { - if (!isCallImport) { + if (!instance.is(CommonFlags.MODULE_IMPORT)) { let original = instance; instance = this.ensureTrampoline(instance); if (!this.compileFunction(instance)) return module.unreachable(); instance.flow.flags = original.flow.flags; let nativeReturnType = returnType.toNativeType(); + // We know the last operand is optional and omitted, so inject setting + // ~argumentsLength into that operand, which is always safe. + let lastOperand = operands[maxOperands - 1]; + assert(!(getSideEffects(lastOperand) & SideEffects.WritesGlobal)); + let lastOperandType = parameterTypes[maxArguments - 1]; + operands[maxOperands - 1] = module.block(null, [ + module.global_set(BuiltinNames.argumentsLength, module.i32(numArguments)), + lastOperand + ], lastOperandType.toNativeType()); let expr = module.call(instance.internalName, operands, nativeReturnType); this.currentType = returnType; if (returnType.isManaged) { @@ -7576,10 +7587,7 @@ export class Compiler extends DiagnosticEmitter { } } this.ensureBuiltinArgumentsLength(); - return module.block(null, [ - module.global_set(BuiltinNames.argumentsLength, module.i32(numArguments)), - expr - ], this.currentType.toNativeType()); + return expr; } } } @@ -7651,11 +7659,14 @@ export class Compiler extends DiagnosticEmitter { operands: ExpressionRef[] | null = null, immediatelyDropped: bool = false ): ExpressionRef { + var module = this.module; var numOperands = operands ? operands.length : 0; var numArguments = numOperands; var minArguments = signature.requiredParameters; var minOperands = minArguments; - var maxArguments = signature.parameterTypes.length; + var parameterTypes = signature.parameterTypes; + var returnType = signature.returnType; + var maxArguments = parameterTypes.length; var maxOperands = maxArguments; if (signature.thisType) { ++minOperands; @@ -7664,8 +7675,6 @@ export class Compiler extends DiagnosticEmitter { } assert(numOperands >= minOperands); - var module = this.module; - // fill up omitted arguments with zeroes if (numOperands < maxOperands) { if (!operands) { @@ -7678,21 +7687,35 @@ export class Compiler extends DiagnosticEmitter { } } - var returnType = signature.returnType; + if (this.options.isWasm64) { + indexArg = module.unary(UnaryOp.WrapI64, indexArg); + } + + // We might be calling a trampoline here, even if all operands have been + // provided, so we must set ~argumentsLength in any case. Inject setting it + // into the index argument, which becomes executed last after any operands. this.ensureBuiltinArgumentsLength(); - var expr = module.block(null, [ - module.global_set(BuiltinNames.argumentsLength, // might be calling a trampoline - module.i32(numArguments) - ), - module.call_indirect( - this.options.isWasm64 - ? module.unary(UnaryOp.WrapI64, indexArg) - : indexArg, - operands, - signature.nativeParams, - signature.nativeResults - ) - ], returnType.toNativeType()); + if (getSideEffects(indexArg) & SideEffects.WritesGlobal) { + let flow = this.currentFlow; + let temp = flow.getTempLocal(Type.i32, findUsedLocals(indexArg)); + indexArg = module.block(null, [ + module.local_set(temp.index, indexArg), + module.global_set(BuiltinNames.argumentsLength, module.i32(numArguments)), + module.local_get(temp.index, NativeType.I32) + ], NativeType.I32); + flow.freeTempLocal(temp); + } else { // simplify + indexArg = module.block(null, [ + module.global_set(BuiltinNames.argumentsLength, module.i32(numArguments)), + indexArg + ], NativeType.I32); + } + var expr = module.call_indirect( + indexArg, + operands, + signature.nativeParams, + signature.nativeResults + ); this.currentType = returnType; if (returnType.isManaged) { if (immediatelyDropped) { diff --git a/tests/compiler/call-optional.untouched.wat b/tests/compiler/call-optional.untouched.wat index e7492de6f0..1d93559128 100644 --- a/tests/compiler/call-optional.untouched.wat +++ b/tests/compiler/call-optional.untouched.wat @@ -48,10 +48,10 @@ global.set $~argumentsLength ) (func $start:call-optional (; 4 ;) - i32.const 1 - global.set $~argumentsLength i32.const 3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $call-optional/opt|trampoline i32.const 0 @@ -65,10 +65,10 @@ call $~lib/builtins/abort unreachable end - i32.const 2 - global.set $~argumentsLength i32.const 3 i32.const 4 + i32.const 2 + global.set $~argumentsLength i32.const 0 call $call-optional/opt|trampoline i32.const 5 @@ -97,11 +97,11 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength i32.const 3 i32.const 0 i32.const 0 + i32.const 1 + global.set $~argumentsLength global.get $call-optional/optIndirect call_indirect (type $i32_i32_i32_=>_i32) i32.const 0 @@ -115,11 +115,11 @@ call $~lib/builtins/abort unreachable end - i32.const 2 - global.set $~argumentsLength i32.const 3 i32.const 4 i32.const 0 + i32.const 2 + global.set $~argumentsLength global.get $call-optional/optIndirect call_indirect (type $i32_i32_i32_=>_i32) i32.const 5 @@ -134,10 +134,10 @@ unreachable end i32.const 3 - global.set $~argumentsLength - i32.const 3 i32.const 4 i32.const 5 + i32.const 3 + global.set $~argumentsLength global.get $call-optional/optIndirect call_indirect (type $i32_i32_i32_=>_i32) i32.const 12 diff --git a/tests/compiler/function-expression.untouched.wat b/tests/compiler/function-expression.untouched.wat index 9d36d390c4..5b4a30692c 100644 --- a/tests/compiler/function-expression.untouched.wat +++ b/tests/compiler/function-expression.untouched.wat @@ -40,10 +40,10 @@ i32.add ) (func $function-expression/testOmitted (; 7 ;) (param $0 i32) (result i32) - i32.const 2 - global.set $~argumentsLength i32.const 1 i32.const 2 + i32.const 2 + global.set $~argumentsLength local.get $0 call_indirect (type $i32_i32_=>_i32) ) @@ -89,8 +89,8 @@ ) (func $start:function-expression (; 18 ;) i32.const 1 - global.set $~argumentsLength i32.const 1 + global.set $~argumentsLength global.get $function-expression/f1 call_indirect (type $i32_=>_i32) i32.const 1 @@ -104,9 +104,9 @@ call $~lib/builtins/abort unreachable end + i32.const 2 i32.const 1 global.set $~argumentsLength - i32.const 2 global.get $function-expression/f2 call_indirect (type $i32_=>_i32) i32.const 2 @@ -178,10 +178,10 @@ call $~lib/builtins/abort unreachable end - i32.const 2 - global.set $~argumentsLength i32.const 1 i32.const 2 + i32.const 2 + global.set $~argumentsLength call $function-expression/testOmittedReturn1 call_indirect (type $i32_i32_=>_i32) i32.const 3 @@ -195,10 +195,10 @@ call $~lib/builtins/abort unreachable end - i32.const 2 - global.set $~argumentsLength i32.const 1 i32.const 2 + i32.const 2 + global.set $~argumentsLength call $function-expression/testOmittedReturn2 call_indirect (type $i32_i32_=>_i32) i32.const 1 @@ -212,10 +212,10 @@ call $~lib/builtins/abort unreachable end - i32.const 2 - global.set $~argumentsLength i32.const 1 i32.const 2 + i32.const 2 + global.set $~argumentsLength call $function-expression/testOmittedReturn3 call_indirect (type $i32_i32_=>_i32) i32.const 42 diff --git a/tests/compiler/function-types.untouched.wat b/tests/compiler/function-types.untouched.wat index 94ea28d030..6a0a94e806 100644 --- a/tests/compiler/function-types.untouched.wat +++ b/tests/compiler/function-types.untouched.wat @@ -47,18 +47,18 @@ i32.const 3 ) (func $function-types/doAddWithFn (; 8 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $1 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) ) (func $function-types/doAdd (; 9 ;) (param $0 i32) (param $1 i32) (result i32) - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $1 + i32.const 2 + global.set $~argumentsLength call $function-types/makeAdder call_indirect (type $i32_i32_=>_i32) ) @@ -68,10 +68,10 @@ i32.add ) (func $function-types/makeAndAdd (; 11 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $1 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) ) @@ -97,10 +97,10 @@ (func $start:function-types (; 13 ;) call $function-types/makeAdder global.set $function-types/i32Adder - i32.const 2 - global.set $~argumentsLength i32.const 1 i32.const 2 + i32.const 2 + global.set $~argumentsLength global.get $function-types/i32Adder call_indirect (type $i32_i32_=>_i32) i32.const 3 @@ -116,10 +116,10 @@ end call $function-types/makeAdder global.set $function-types/i64Adder - i32.const 2 - global.set $~argumentsLength i64.const 10 i64.const 20 + i32.const 2 + global.set $~argumentsLength global.get $function-types/i64Adder call_indirect (type $i64_i64_=>_i64) i64.const 30 @@ -133,10 +133,10 @@ call $~lib/builtins/abort unreachable end - i32.const 2 - global.set $~argumentsLength f64.const 1.5 f64.const 2.5 + i32.const 2 + global.set $~argumentsLength call $function-types/makeAdder call_indirect (type $f64_f64_=>_f64) f64.const 4 @@ -194,10 +194,10 @@ call $~lib/builtins/abort unreachable end - i32.const 2 - global.set $~argumentsLength i32.const 1 i32.const 2 + i32.const 2 + global.set $~argumentsLength i32.const 0 call $function-types/makeAndAdd|trampoline i32.const 3 diff --git a/tests/compiler/infer-generic.optimized.wat b/tests/compiler/infer-generic.optimized.wat index ccb423410a..1b7df3990e 100644 --- a/tests/compiler/infer-generic.optimized.wat +++ b/tests/compiler/infer-generic.optimized.wat @@ -39,6 +39,7 @@ (local $1 i32) (local $2 i32) (local $3 i32) + (local $4 f32) i32.const 1132 i32.load local.set $2 @@ -54,9 +55,6 @@ select i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $1 i32.const 1124 i32.load local.get $0 @@ -64,6 +62,11 @@ i32.shl i32.add f32.load + local.set $4 + i32.const 4 + global.set $~argumentsLength + local.get $1 + local.get $4 local.get $0 i32.const 1120 call $start:infer-generic~anonymous|0 diff --git a/tests/compiler/infer-generic.untouched.wat b/tests/compiler/infer-generic.untouched.wat index 382a89c960..86e5529737 100644 --- a/tests/compiler/infer-generic.untouched.wat +++ b/tests/compiler/infer-generic.untouched.wat @@ -84,8 +84,6 @@ local.set $6 local.get $6 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $0 i32.load offset=4 @@ -96,6 +94,8 @@ f32.load local.get $4 local.get $0 + i32.const 4 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_f32_i32_i32_=>_i32) local.set $3 diff --git a/tests/compiler/inlining.untouched.wat b/tests/compiler/inlining.untouched.wat index 2c6eb457ca..f047b10f9a 100644 --- a/tests/compiler/inlining.untouched.wat +++ b/tests/compiler/inlining.untouched.wat @@ -218,9 +218,9 @@ end i32.const 0 local.set $2 + i32.const 2 i32.const 1 global.set $~argumentsLength - i32.const 2 i32.const 1 call_indirect (type $i32_=>_i32) i32.const 2 diff --git a/tests/compiler/resolve-function-expression.untouched.wat b/tests/compiler/resolve-function-expression.untouched.wat index 6c5e9e274f..6992c5636f 100644 --- a/tests/compiler/resolve-function-expression.untouched.wat +++ b/tests/compiler/resolve-function-expression.untouched.wat @@ -617,9 +617,9 @@ ) (func $start:resolve-function-expression (; 17 ;) (local $0 i32) + i32.const 2 i32.const 1 global.set $~argumentsLength - i32.const 2 i32.const 1 call_indirect (type $i32_=>_i32) i32.const 42 @@ -634,8 +634,8 @@ unreachable end i32.const 1 - global.set $~argumentsLength i32.const 1 + global.set $~argumentsLength i32.const 2 call_indirect (type $i32_=>_i32) i32.const 42 @@ -659,9 +659,9 @@ global.set $~lib/rt/stub/startOffset global.get $~lib/rt/stub/startOffset global.set $~lib/rt/stub/offset + i32.const 0 i32.const 1 global.set $~argumentsLength - i32.const 0 i32.const 3 call_indirect (type $i32_=>_i32) call $~lib/number/I32#toString diff --git a/tests/compiler/resolve-ternary.untouched.wat b/tests/compiler/resolve-ternary.untouched.wat index 62e4265933..47a391ebea 100644 --- a/tests/compiler/resolve-ternary.untouched.wat +++ b/tests/compiler/resolve-ternary.untouched.wat @@ -4751,8 +4751,8 @@ unreachable end i32.const 1 - global.set $~argumentsLength i32.const 1 + global.set $~argumentsLength global.get $resolve-ternary/b if (result i32) i32.const 1 @@ -4772,8 +4772,8 @@ unreachable end i32.const 1 - global.set $~argumentsLength i32.const 1 + global.set $~argumentsLength global.get $resolve-ternary/b if (result i32) i32.const 3 @@ -4793,8 +4793,8 @@ unreachable end i32.const 1 - global.set $~argumentsLength i32.const 1 + global.set $~argumentsLength global.get $resolve-ternary/b if (result i32) i32.const 2 diff --git a/tests/compiler/retain-release.untouched.wat b/tests/compiler/retain-release.untouched.wat index 4ad2336ea3..ab2110a4cc 100644 --- a/tests/compiler/retain-release.untouched.wat +++ b/tests/compiler/retain-release.untouched.wat @@ -778,9 +778,9 @@ global.set $~argumentsLength ) (func $retain-release/provideRefIndirect (; 43 ;) (param $0 i32) + global.get $retain-release/REF i32.const 1 global.set $~argumentsLength - global.get $retain-release/REF local.get $0 call_indirect (type $i32_=>_none) ) diff --git a/tests/compiler/retain-return.untouched.wat b/tests/compiler/retain-return.untouched.wat index 6d336f6e1d..3e39e21b1d 100644 --- a/tests/compiler/retain-return.untouched.wat +++ b/tests/compiler/retain-return.untouched.wat @@ -1556,15 +1556,15 @@ global.get $retain-return/returnNewFnExpr call_indirect (type $none_=>_i32) call $~lib/rt/pure/__release + global.get $retain-return/ref i32.const 1 global.set $~argumentsLength - global.get $retain-return/ref global.get $retain-return/returnLocalFnExpr call_indirect (type $i32_=>_i32) call $~lib/rt/pure/__release + global.get $retain-return/ref i32.const 1 global.set $~argumentsLength - global.get $retain-return/ref global.get $retain-return/returnLocalFnExpr call_indirect (type $i32_=>_i32) call $~lib/rt/pure/__release diff --git a/tests/compiler/rt/flags.optimized.wat b/tests/compiler/rt/flags.optimized.wat index 8b58b02b27..fe13a28e74 100644 --- a/tests/compiler/rt/flags.optimized.wat +++ b/tests/compiler/rt/flags.optimized.wat @@ -7,11 +7,11 @@ (data (i32.const 1024) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e") (data (i32.const 1088) "\14\00\00\00\01\00\00\00\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s") (data (i32.const 1136) "\16\00\00\00\01\00\00\00\01\00\00\00\16\00\00\00r\00t\00/\00f\00l\00a\00g\00s\00.\00t\00s") - (data (i32.const 1184) "D\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\001\04\00\00\02\00\00\001\00\00\00\02\00\00\001\00\00\00\02\00\00\00Q\04\00\00\02\00\00\00Q\00\00\00\02\00\00\00\91\04\00\00\02\00\00\00\91\00\00\00\02\00\00\00\11\05\00\00\02\00\00\00\11\01\00\00\02\00\00\00\91\0c\00\00\02\00\00\00\11\0d\00\00\02\00\00\002\04\00\00\00\00\00\002\00\00\00\00\00\00\00R\04\00\00\00\00\00\00R\00\00\00\00\00\00\00\92\04\00\00\00\00\00\00\92\00\00\00\00\00\00\00\12\05\00\00\00\00\00\00\12\01\00\00\00\00\00\00\92\0c\00\00\00\00\00\00\12\0d\00\00\00\00\00\00\12\02\00\00\00\00\00\00\10\00\00\00\00\00\00\00\92 \00\00\00\00\00\00\920\00\00\00\00\00\004\04\00\00\00\00\00\004\00\00\00\00\00\00\00T\04\00\00\00\00\00\00T\00\00\00\00\00\00\00\94\04\00\00\00\00\00\00\94\00\00\00\00\00\00\00\14\05\00\00\00\00\00\00\14\01\00\00\00\00\00\00\94\0c\00\00\00\00\00\00\14\0d\00\00\00\00\00\00\14\02\00\00\00\00\00\00\94 \00\00\00\00\00\00\940\00\00\00\00\00\008\04\04\00\00\00\00\00X\04\n\00\00\00\00\00\98\04\t\00\00\00\00\00\18\85\08\00\00\00\00\00\18B\08\00\00\00\00\008\04A\00\00\00\00\008\04a\00\00\00\00\00\98`\08\00\00\00\00\00\98p\08\00\00\00\00\00\980a\00\00\00\00\00\98\04\19\00\00\00\00\00\10") - (data (i32.const 1644) "\82 \00\00\00\00\00\00\10") - (data (i32.const 1668) "\84 \00\00\00\00\00\00\10") - (data (i32.const 1692) "\88\04A") - (data (i32.const 1708) "\88 \t\00\00\00\00\00\10\00\00\00\00\00\00\00\10") + (data (i32.const 1184) "D\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00a\08\00\00\02\00\00\00a\00\00\00\02\00\00\00a\00\00\00\02\00\00\00\a1\08\00\00\02\00\00\00\a1\00\00\00\02\00\00\00!\t\00\00\02\00\00\00!\01\00\00\02\00\00\00!\n\00\00\02\00\00\00!\02\00\00\02\00\00\00!\19\00\00\02\00\00\00!\1a\00\00\02\00\00\00b\08\00\00\00\00\00\00b\00\00\00\00\00\00\00\a2\08\00\00\00\00\00\00\a2\00\00\00\00\00\00\00\"\t\00\00\00\00\00\00\"\01\00\00\00\00\00\00\"\n\00\00\00\00\00\00\"\02\00\00\00\00\00\00\"\19\00\00\00\00\00\00\"\1a\00\00\00\00\00\00\"\04\00\00\00\00\00\00 \00\00\00\00\00\00\00\"A\00\00\00\00\00\00\"a\00\00\00\00\00\00h\08\00\00\00\00\00\00h\00\00\00\00\00\00\00\a8\08\00\00\00\00\00\00\a8\00\00\00\00\00\00\00(\t\00\00\00\00\00\00(\01\00\00\00\00\00\00(\n\00\00\00\00\00\00(\02\00\00\00\00\00\00(\19\00\00\00\00\00\00(\1a\00\00\00\00\00\00(\04\00\00\00\00\00\00(A\00\00\00\00\00\00(a\00\00\00\00\00\00p\08\08\00\00\00\00\00\b0\08\14\00\00\00\00\000\t\12\00\00\00\00\000\n\11\00\00\00\00\000\84\10\00\00\00\00\00p\08\82\00\00\00\00\00p\08\c2\00\00\00\00\000\c1\10\00\00\00\00\000\e1\10\00\00\00\00\000a\c2\00\00\00\00\000\t2\00\00\00\00\00 ") + (data (i32.const 1644) "\02A\00\00\00\00\00\00 ") + (data (i32.const 1668) "\08A\00\00\00\00\00\00 ") + (data (i32.const 1692) "\10\t\82") + (data (i32.const 1708) "\10A\12\00\00\00\00\00 \00\00\00\00\00\00\00 ") (export "memory" (memory $0)) (start $~start) (func $~lib/rt/__typeinfo (; 1 ;) (param $0 i32) (result i32) @@ -38,247 +38,247 @@ block $folding-inner0 i32.const 3 call $~lib/rt/__typeinfo - i32.const 1073 + i32.const 2145 i32.ne br_if $folding-inner0 i32.const 4 call $~lib/rt/__typeinfo - i32.const 49 + i32.const 97 i32.ne br_if $folding-inner0 i32.const 5 call $~lib/rt/__typeinfo - i32.const 49 + i32.const 97 i32.ne br_if $folding-inner0 i32.const 6 call $~lib/rt/__typeinfo - i32.const 1105 + i32.const 2209 i32.ne br_if $folding-inner0 i32.const 7 call $~lib/rt/__typeinfo - i32.const 81 + i32.const 161 i32.ne br_if $folding-inner0 i32.const 8 call $~lib/rt/__typeinfo - i32.const 1169 + i32.const 2337 i32.ne br_if $folding-inner0 i32.const 9 call $~lib/rt/__typeinfo - i32.const 145 + i32.const 289 i32.ne br_if $folding-inner0 i32.const 10 call $~lib/rt/__typeinfo - i32.const 1297 + i32.const 2593 i32.ne br_if $folding-inner0 i32.const 11 call $~lib/rt/__typeinfo - i32.const 273 + i32.const 545 i32.ne br_if $folding-inner0 i32.const 12 call $~lib/rt/__typeinfo - i32.const 3217 + i32.const 6433 i32.ne br_if $folding-inner0 i32.const 13 call $~lib/rt/__typeinfo - i32.const 3345 + i32.const 6689 i32.ne br_if $folding-inner0 i32.const 14 call $~lib/rt/__typeinfo - i32.const 1074 + i32.const 2146 i32.ne br_if $folding-inner0 i32.const 15 call $~lib/rt/__typeinfo - i32.const 50 + i32.const 98 i32.ne br_if $folding-inner0 i32.const 16 call $~lib/rt/__typeinfo - i32.const 1106 + i32.const 2210 i32.ne br_if $folding-inner0 i32.const 17 call $~lib/rt/__typeinfo - i32.const 82 + i32.const 162 i32.ne br_if $folding-inner0 i32.const 18 call $~lib/rt/__typeinfo - i32.const 1170 + i32.const 2338 i32.ne br_if $folding-inner0 i32.const 19 call $~lib/rt/__typeinfo - i32.const 146 + i32.const 290 i32.ne br_if $folding-inner0 i32.const 20 call $~lib/rt/__typeinfo - i32.const 1298 + i32.const 2594 i32.ne br_if $folding-inner0 i32.const 21 call $~lib/rt/__typeinfo - i32.const 274 + i32.const 546 i32.ne br_if $folding-inner0 i32.const 22 call $~lib/rt/__typeinfo - i32.const 3218 + i32.const 6434 i32.ne br_if $folding-inner0 i32.const 23 call $~lib/rt/__typeinfo - i32.const 3346 + i32.const 6690 i32.ne br_if $folding-inner0 i32.const 24 call $~lib/rt/__typeinfo - i32.const 530 + i32.const 1058 i32.ne br_if $folding-inner0 i32.const 26 call $~lib/rt/__typeinfo - i32.const 8338 + i32.const 16674 i32.ne br_if $folding-inner0 i32.const 27 call $~lib/rt/__typeinfo - i32.const 12434 + i32.const 24866 i32.ne br_if $folding-inner0 i32.const 28 call $~lib/rt/__typeinfo - i32.const 1076 + i32.const 2152 i32.ne br_if $folding-inner0 i32.const 29 call $~lib/rt/__typeinfo - i32.const 52 + i32.const 104 i32.ne br_if $folding-inner0 i32.const 30 call $~lib/rt/__typeinfo - i32.const 1108 + i32.const 2216 i32.ne br_if $folding-inner0 i32.const 31 call $~lib/rt/__typeinfo - i32.const 84 + i32.const 168 i32.ne br_if $folding-inner0 i32.const 32 call $~lib/rt/__typeinfo - i32.const 1172 + i32.const 2344 i32.ne br_if $folding-inner0 i32.const 33 call $~lib/rt/__typeinfo - i32.const 148 + i32.const 296 i32.ne br_if $folding-inner0 i32.const 34 call $~lib/rt/__typeinfo - i32.const 1300 + i32.const 2600 i32.ne br_if $folding-inner0 i32.const 35 call $~lib/rt/__typeinfo - i32.const 276 + i32.const 552 i32.ne br_if $folding-inner0 i32.const 36 call $~lib/rt/__typeinfo - i32.const 3220 + i32.const 6440 i32.ne br_if $folding-inner0 i32.const 37 call $~lib/rt/__typeinfo - i32.const 3348 + i32.const 6696 i32.ne br_if $folding-inner0 i32.const 38 call $~lib/rt/__typeinfo - i32.const 532 + i32.const 1064 i32.ne br_if $folding-inner0 i32.const 39 call $~lib/rt/__typeinfo - i32.const 8340 + i32.const 16680 i32.ne br_if $folding-inner0 i32.const 40 call $~lib/rt/__typeinfo - i32.const 12436 + i32.const 24872 i32.ne br_if $folding-inner0 i32.const 41 call $~lib/rt/__typeinfo - i32.const 263224 + i32.const 526448 i32.ne br_if $folding-inner0 i32.const 42 call $~lib/rt/__typeinfo - i32.const 656472 + i32.const 1312944 i32.ne br_if $folding-inner0 i32.const 43 call $~lib/rt/__typeinfo - i32.const 591000 + i32.const 1182000 i32.ne br_if $folding-inner0 i32.const 44 call $~lib/rt/__typeinfo - i32.const 558360 + i32.const 1116720 i32.ne br_if $folding-inner0 i32.const 45 call $~lib/rt/__typeinfo - i32.const 541208 + i32.const 1082416 i32.ne br_if $folding-inner0 i32.const 46 call $~lib/rt/__typeinfo - i32.const 4260920 + i32.const 8521840 i32.ne br_if $folding-inner0 i32.const 47 call $~lib/rt/__typeinfo - i32.const 6358072 + i32.const 12716144 i32.ne br_if $folding-inner0 i32.const 48 call $~lib/rt/__typeinfo - i32.const 549016 + i32.const 1098032 i32.ne br_if $folding-inner0 i32.const 49 call $~lib/rt/__typeinfo - i32.const 553112 + i32.const 1106224 i32.ne br_if $folding-inner0 i32.const 50 call $~lib/rt/__typeinfo - i32.const 6369432 + i32.const 12738864 i32.ne br_if $folding-inner0 i32.const 51 call $~lib/rt/__typeinfo - i32.const 1639576 + i32.const 3279152 i32.ne br_if $folding-inner0 i32.const 52 call $~lib/rt/__typeinfo - i32.const 16 + i32.const 32 i32.ne br_if $folding-inner0 i32.const 53 @@ -292,7 +292,7 @@ br_if $folding-inner0 i32.const 58 call $~lib/rt/__typeinfo - i32.const 16 + i32.const 32 i32.ne br_if $folding-inner0 i32.const 59 @@ -300,7 +300,7 @@ br_if $folding-inner0 i32.const 61 call $~lib/rt/__typeinfo - i32.const 16 + i32.const 32 i32.ne br_if $folding-inner0 i32.const 62 @@ -311,12 +311,12 @@ br_if $folding-inner0 i32.const 66 call $~lib/rt/__typeinfo - i32.const 16 + i32.const 32 i32.ne br_if $folding-inner0 i32.const 67 call $~lib/rt/__typeinfo - i32.const 16 + i32.const 32 i32.ne br_if $folding-inner0 return diff --git a/tests/compiler/rt/flags.untouched.wat b/tests/compiler/rt/flags.untouched.wat index 323ad5abd3..af4e1a6b5b 100644 --- a/tests/compiler/rt/flags.untouched.wat +++ b/tests/compiler/rt/flags.untouched.wat @@ -8,10 +8,10 @@ (data (i32.const 16) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00") (data (i32.const 80) "\14\00\00\00\01\00\00\00\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s\00") (data (i32.const 128) "\16\00\00\00\01\00\00\00\01\00\00\00\16\00\00\00r\00t\00/\00f\00l\00a\00g\00s\00.\00t\00s\00") - (data (i32.const 176) "D\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\001\04\00\00\02\00\00\001\00\00\00\02\00\00\001\00\00\00\02\00\00\00Q\04\00\00\02\00\00\00Q\00\00\00\02\00\00\00\91\04\00\00\02\00\00\00\91\00\00\00\02\00\00\00\11\05\00\00\02\00\00\00\11\01\00\00\02\00\00\00\91\0c\00\00\02\00\00\00\11\0d\00\00\02\00\00\002\04\00\00\00\00\00\002\00\00\00\00\00\00\00R\04\00\00\00\00\00\00R\00\00\00\00\00\00\00\92\04\00\00\00\00\00\00\92\00\00\00\00\00\00\00\12\05\00\00\00\00\00\00\12\01\00\00\00\00\00\00\92\0c\00\00\00\00\00\00\12\0d\00\00\00\00\00\00\12\02\00\00\00\00\00\00\10\00\00\00\00\00\00\00\92 \00\00\00\00\00\00\920\00\00\00\00\00\004\04\00\00\00\00\00\004\00\00\00\00\00\00\00T\04\00\00\00\00\00\00T\00\00\00\00\00\00\00\94\04\00\00\00\00\00\00\94\00\00\00\00\00\00\00\14\05\00\00\00\00\00\00\14\01\00\00\00\00\00\00\94\0c\00\00\00\00\00\00\14\0d\00\00\00\00\00\00\14\02\00\00\00\00\00\00\94 \00\00\00\00\00\00\940\00\00\00\00\00\008\04\04\00\00\00\00\00X\04\n\00\00\00\00\00\98\04\t\00\00\00\00\00\18\85\08\00\00\00\00\00\18B\08\00\00\00\00\008\04A\00\00\00\00\008\04a\00\00\00\00\00\98`\08\00\00\00\00\00\98p\08\00\00\00\00\00\980a\00\00\00\00\00\98\04\19\00\00\00\00\00\10\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\00\00\00\00\00\00\00\00\00\00\00\00\00\00\82 \00\00\00\00\00\00\10\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\84 \00\00\00\00\00\00\10\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\88\04A\00\00\00\00\00\00\00\00\00\00\00\00\00\88 \t\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00") + (data (i32.const 176) "D\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00a\08\00\00\02\00\00\00a\00\00\00\02\00\00\00a\00\00\00\02\00\00\00\a1\08\00\00\02\00\00\00\a1\00\00\00\02\00\00\00!\t\00\00\02\00\00\00!\01\00\00\02\00\00\00!\n\00\00\02\00\00\00!\02\00\00\02\00\00\00!\19\00\00\02\00\00\00!\1a\00\00\02\00\00\00b\08\00\00\00\00\00\00b\00\00\00\00\00\00\00\a2\08\00\00\00\00\00\00\a2\00\00\00\00\00\00\00\"\t\00\00\00\00\00\00\"\01\00\00\00\00\00\00\"\n\00\00\00\00\00\00\"\02\00\00\00\00\00\00\"\19\00\00\00\00\00\00\"\1a\00\00\00\00\00\00\"\04\00\00\00\00\00\00 \00\00\00\00\00\00\00\"A\00\00\00\00\00\00\"a\00\00\00\00\00\00h\08\00\00\00\00\00\00h\00\00\00\00\00\00\00\a8\08\00\00\00\00\00\00\a8\00\00\00\00\00\00\00(\t\00\00\00\00\00\00(\01\00\00\00\00\00\00(\n\00\00\00\00\00\00(\02\00\00\00\00\00\00(\19\00\00\00\00\00\00(\1a\00\00\00\00\00\00(\04\00\00\00\00\00\00(A\00\00\00\00\00\00(a\00\00\00\00\00\00p\08\08\00\00\00\00\00\b0\08\14\00\00\00\00\000\t\12\00\00\00\00\000\n\11\00\00\00\00\000\84\10\00\00\00\00\00p\08\82\00\00\00\00\00p\08\c2\00\00\00\00\000\c1\10\00\00\00\00\000\e1\10\00\00\00\00\000a\c2\00\00\00\00\000\t2\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\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\02A\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\08A\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\10\t\82\00\00\00\00\00\00\00\00\00\00\00\00\00\10A\12\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00") (table $0 1 funcref) - (global $rt/flags/VALUE_ALIGN_REF i32 (i32.const 128)) - (global $rt/flags/KEY_ALIGN_REF i32 (i32.const 65536)) + (global $rt/flags/VALUE_ALIGN_REF i32 (i32.const 256)) + (global $rt/flags/KEY_ALIGN_REF i32 (i32.const 131072)) (global $~lib/rt/__rtti_base i32 (i32.const 176)) (export "memory" (memory $0)) (start $~start) @@ -927,426 +927,426 @@ ) (func $start:rt/flags (; 61 ;) i32.const 1 - i32.const 16 - i32.or i32.const 32 i32.or - i32.const 1024 + i32.const 64 + i32.or + i32.const 2048 i32.or call $rt/flags/test<~lib/typedarray/Int8Array> i32.const 1 - i32.const 16 - i32.or i32.const 32 i32.or + i32.const 64 + i32.or call $rt/flags/test<~lib/typedarray/Uint8Array> i32.const 1 - i32.const 16 - i32.or i32.const 32 i32.or + i32.const 64 + i32.or call $rt/flags/test<~lib/typedarray/Uint8ClampedArray> i32.const 1 - i32.const 16 + i32.const 32 i32.or - i32.const 64 + i32.const 128 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/typedarray/Int16Array> i32.const 1 - i32.const 16 + i32.const 32 i32.or - i32.const 64 + i32.const 128 i32.or call $rt/flags/test<~lib/typedarray/Uint16Array> i32.const 1 - i32.const 16 + i32.const 32 i32.or - i32.const 128 + i32.const 256 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/typedarray/Int32Array> i32.const 1 - i32.const 16 + i32.const 32 i32.or - i32.const 128 + i32.const 256 i32.or call $rt/flags/test<~lib/typedarray/Uint32Array> i32.const 1 - i32.const 16 + i32.const 32 i32.or - i32.const 256 + i32.const 512 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/typedarray/Int64Array> i32.const 1 - i32.const 16 + i32.const 32 i32.or - i32.const 256 + i32.const 512 i32.or call $rt/flags/test<~lib/typedarray/Uint64Array> i32.const 1 - i32.const 16 - i32.or - i32.const 128 + i32.const 32 i32.or - i32.const 1024 + i32.const 256 i32.or i32.const 2048 i32.or + i32.const 4096 + i32.or call $rt/flags/test<~lib/typedarray/Float32Array> i32.const 1 - i32.const 16 - i32.or - i32.const 256 + i32.const 32 i32.or - i32.const 1024 + i32.const 512 i32.or i32.const 2048 i32.or + i32.const 4096 + i32.or call $rt/flags/test<~lib/typedarray/Float64Array> i32.const 2 - i32.const 16 - i32.or i32.const 32 i32.or - i32.const 1024 + i32.const 64 + i32.or + i32.const 2048 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 - i32.or i32.const 32 i32.or + i32.const 64 + i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or - i32.const 64 + i32.const 128 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or - i32.const 64 + i32.const 128 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or - i32.const 128 + i32.const 256 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or - i32.const 128 + i32.const 256 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or - i32.const 256 + i32.const 512 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or - i32.const 256 + i32.const 512 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 - i32.or - i32.const 128 + i32.const 32 i32.or - i32.const 1024 + i32.const 256 i32.or i32.const 2048 i32.or + i32.const 4096 + i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 - i32.or - i32.const 256 + i32.const 32 i32.or - i32.const 1024 + i32.const 512 i32.or i32.const 2048 i32.or + i32.const 4096 + i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or - i32.const 512 + i32.const 1024 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or global.get $rt/flags/VALUE_ALIGN_REF i32.or - i32.const 8192 + i32.const 16384 i32.or call $rt/flags/test<~lib/array/Array> i32.const 2 - i32.const 16 + i32.const 32 i32.or global.get $rt/flags/VALUE_ALIGN_REF i32.or - i32.const 4096 - i32.or i32.const 8192 i32.or - call $rt/flags/test<~lib/array/Array> - i32.const 4 - i32.const 16 + i32.const 16384 i32.or + call $rt/flags/test<~lib/array/Array> + i32.const 8 i32.const 32 i32.or - i32.const 1024 + i32.const 64 i32.or - call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 2048 i32.or + call $rt/flags/test<~lib/set/Set> + i32.const 8 i32.const 32 i32.or + i32.const 64 + i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or - i32.const 64 + i32.const 128 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or - i32.const 64 + i32.const 128 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or - i32.const 128 + i32.const 256 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or - i32.const 128 + i32.const 256 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or - i32.const 256 + i32.const 512 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or - i32.const 256 + i32.const 512 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 - i32.or - i32.const 128 + i32.const 8 + i32.const 32 i32.or - i32.const 1024 + i32.const 256 i32.or i32.const 2048 i32.or - call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 4096 i32.or - i32.const 256 + call $rt/flags/test<~lib/set/Set> + i32.const 8 + i32.const 32 i32.or - i32.const 1024 + i32.const 512 i32.or i32.const 2048 i32.or + i32.const 4096 + i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or - i32.const 512 + i32.const 1024 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or global.get $rt/flags/VALUE_ALIGN_REF i32.or - i32.const 8192 + i32.const 16384 i32.or call $rt/flags/test<~lib/set/Set> - i32.const 4 - i32.const 16 + i32.const 8 + i32.const 32 i32.or global.get $rt/flags/VALUE_ALIGN_REF i32.or - i32.const 4096 - i32.or i32.const 8192 i32.or + i32.const 16384 + i32.or call $rt/flags/test<~lib/set/Set> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 262144 + i32.const 524288 i32.or - i32.const 32 + i32.const 64 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 131072 + i32.const 262144 i32.or - i32.const 524288 + i32.const 1048576 i32.or - i32.const 64 + i32.const 128 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 65536 + i32.const 131072 i32.or - i32.const 524288 + i32.const 1048576 i32.or - i32.const 128 + i32.const 256 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 32768 + i32.const 65536 i32.or - i32.const 524288 + i32.const 1048576 i32.or - i32.const 256 + i32.const 512 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 16384 + i32.const 32768 i32.or - i32.const 524288 + i32.const 1048576 i32.or - i32.const 512 + i32.const 1024 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or global.get $rt/flags/KEY_ALIGN_REF i32.or - i32.const 4194304 + i32.const 8388608 i32.or - i32.const 32 + i32.const 64 i32.or - i32.const 1024 + i32.const 2048 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or global.get $rt/flags/KEY_ALIGN_REF i32.or - i32.const 2097152 - i32.or i32.const 4194304 i32.or - i32.const 32 + i32.const 8388608 i32.or - i32.const 1024 + i32.const 64 + i32.or + i32.const 2048 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 16384 + i32.const 32768 i32.or - i32.const 524288 + i32.const 1048576 i32.or - i32.const 8192 + i32.const 16384 i32.or global.get $rt/flags/VALUE_ALIGN_REF i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 16384 - i32.or - i32.const 524288 + i32.const 32768 i32.or - i32.const 4096 + i32.const 1048576 i32.or i32.const 8192 i32.or + i32.const 16384 + i32.or global.get $rt/flags/VALUE_ALIGN_REF i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 - i32.or - i32.const 2097152 + i32.const 32 i32.or i32.const 4194304 i32.or - global.get $rt/flags/KEY_ALIGN_REF + i32.const 8388608 i32.or - i32.const 4096 + global.get $rt/flags/KEY_ALIGN_REF i32.or i32.const 8192 i32.or + i32.const 16384 + i32.or global.get $rt/flags/VALUE_ALIGN_REF i32.or call $rt/flags/test<~lib/map/Map> - i32.const 8 i32.const 16 + i32.const 32 i32.or - i32.const 65536 - i32.or - i32.const 524288 + i32.const 131072 i32.or i32.const 1048576 i32.or - i32.const 128 + i32.const 2097152 i32.or - i32.const 1024 + i32.const 256 + i32.or + i32.const 2048 i32.or call $rt/flags/test<~lib/map/Map> - i32.const 16 + i32.const 32 call $rt/flags/test i32.const 0 call $rt/flags/test @@ -1354,19 +1354,19 @@ call $rt/flags/test i32.const 0 call $rt/flags/test - i32.const 16 + i32.const 32 call $rt/flags/test i32.const 0 call $rt/flags/test - i32.const 16 + i32.const 32 call $rt/flags/test i32.const 0 call $rt/flags/test i32.const 0 call $rt/flags/test - i32.const 16 + i32.const 32 call $rt/flags/test - i32.const 16 + i32.const 32 call $rt/flags/test ) (func $~start (; 62 ;) diff --git a/tests/compiler/std/array.optimized.wat b/tests/compiler/std/array.optimized.wat index 53f5b53b95..16902811dd 100644 --- a/tests/compiler/std/array.optimized.wat +++ b/tests/compiler/std/array.optimized.wat @@ -2960,21 +2960,19 @@ (local $4 i32) local.get $0 i32.load offset=12 - local.set $3 + local.set $4 loop $for-loop|0 local.get $2 - local.get $3 + local.get $4 local.get $0 i32.load offset=12 - local.tee $4 - local.get $3 + local.tee $3 local.get $4 + local.get $3 i32.lt_s select i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -2982,6 +2980,8 @@ i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -3036,21 +3036,19 @@ (local $4 i32) local.get $0 i32.load offset=12 - local.set $3 + local.set $4 loop $for-loop|0 local.get $2 - local.get $3 + local.get $4 local.get $0 i32.load offset=12 - local.tee $4 - local.get $3 + local.tee $3 local.get $4 + local.get $3 i32.lt_s select i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -3058,6 +3056,8 @@ i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -3113,21 +3113,19 @@ (local $4 i32) local.get $0 i32.load offset=12 - local.set $3 + local.set $4 loop $for-loop|0 local.get $2 - local.get $3 + local.get $4 local.get $0 i32.load offset=12 - local.tee $4 - local.get $3 + local.tee $3 local.get $4 + local.get $3 i32.lt_s select i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -3135,6 +3133,8 @@ i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -3190,21 +3190,19 @@ (local $4 i32) local.get $0 i32.load offset=12 - local.set $3 + local.set $4 loop $for-loop|0 local.get $2 - local.get $3 + local.get $4 local.get $0 i32.load offset=12 - local.tee $4 - local.get $3 + local.tee $3 local.get $4 + local.get $3 i32.lt_s select i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -3212,6 +3210,8 @@ i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -3400,8 +3400,6 @@ select i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $2 i32.const 2 i32.shl @@ -3410,15 +3408,17 @@ i32.load offset=4 i32.add i32.load - local.get $2 - local.get $0 - local.get $1 - call_indirect (type $i32_i32_i32_=>_i32) local.set $7 + i32.const 3 + global.set $~argumentsLength local.get $3 local.get $6 i32.add local.get $7 + local.get $2 + local.get $0 + local.get $1 + call_indirect (type $i32_i32_i32_=>_i32) i32.store local.get $2 i32.const 1 @@ -3551,22 +3551,19 @@ (local $5 i32) local.get $0 i32.load offset=12 - local.set $4 + local.set $5 loop $for-loop|0 local.get $3 - local.get $4 + local.get $5 local.get $0 i32.load offset=12 - local.tee $5 - local.get $4 + local.tee $4 local.get $5 + local.get $4 i32.lt_s select i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $2 local.get $0 i32.load offset=4 local.get $3 @@ -3574,6 +3571,11 @@ i32.shl i32.add i32.load + local.set $4 + i32.const 4 + global.set $~argumentsLength + local.get $2 + local.get $4 local.get $3 local.get $0 local.get $1 @@ -3622,6 +3624,7 @@ ) (func $~lib/array/Array#reduceRight (; 90 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (local $3 i32) + (local $4 i32) local.get $0 i32.load offset=12 i32.const 1 @@ -3632,9 +3635,6 @@ i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $2 local.get $0 i32.load offset=4 local.get $3 @@ -3642,6 +3642,11 @@ i32.shl i32.add i32.load + local.set $4 + i32.const 4 + global.set $~argumentsLength + local.get $2 + local.get $4 local.get $3 local.get $0 local.get $1 @@ -5191,6 +5196,8 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) + (local $6 i32) block $__inlined_func$std/array/isSorted (result i32) i32.const 1 local.set $2 @@ -5206,17 +5213,21 @@ local.get $4 i32.lt_s if - i32.const 2 - global.set $~argumentsLength - i32.const 0 local.get $0 local.get $2 i32.const 1 i32.sub call $~lib/array/Array#__get + local.set $5 local.get $0 local.get $2 call $~lib/array/Array#__get + local.set $6 + i32.const 2 + global.set $~argumentsLength + i32.const 0 + local.get $5 + local.get $6 local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -5456,7 +5467,7 @@ local.get $1 call $~lib/array/Array<~lib/array/Array>#sort local.tee $5 - local.tee $0 + local.tee $4 i32.load offset=12 local.set $6 loop $for-loop|0 @@ -5464,33 +5475,35 @@ local.get $6 i32.lt_s if - i32.const 2 - global.set $~argumentsLength - local.get $0 + local.get $4 local.get $2 i32.const 1 i32.sub call $~lib/array/Array#__get - local.tee $3 - local.get $0 + local.set $0 + local.get $4 local.get $2 call $~lib/array/Array#__get - local.tee $4 + local.set $3 + i32.const 2 + global.set $~argumentsLength + local.get $0 + local.get $3 local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 i32.gt_s if - local.get $3 + local.get $0 call $~lib/rt/pure/__release - local.get $4 + local.get $3 call $~lib/rt/pure/__release i32.const 0 br $__inlined_func$std/array/isSorted<~lib/array/Array> end - local.get $3 + local.get $0 call $~lib/rt/pure/__release - local.get $4 + local.get $3 call $~lib/rt/pure/__release local.get $2 i32.const 1 @@ -5760,16 +5773,16 @@ unreachable end i32.const 55 - local.set $2 + local.set $3 end block $__inlined_func$std/array/isSorted<~lib/string/String | null> (result i32) i32.const 1 local.set $1 local.get $0 - local.get $2 + local.get $3 call $~lib/array/Array<~lib/array/Array>#sort local.tee $5 - local.tee $0 + local.tee $4 i32.load offset=12 local.set $6 loop $for-loop|0 @@ -5777,33 +5790,35 @@ local.get $6 i32.lt_s if - i32.const 2 - global.set $~argumentsLength - local.get $0 + local.get $4 local.get $1 i32.const 1 i32.sub call $~lib/array/Array#__get - local.tee $3 - local.get $0 + local.set $0 + local.get $4 local.get $1 call $~lib/array/Array#__get - local.tee $4 + local.set $2 + i32.const 2 + global.set $~argumentsLength + local.get $0 local.get $2 + local.get $3 call_indirect (type $i32_i32_=>_i32) i32.const 0 i32.gt_s if - local.get $3 + local.get $0 call $~lib/rt/pure/__release - local.get $4 + local.get $2 call $~lib/rt/pure/__release i32.const 0 br $__inlined_func$std/array/isSorted<~lib/string/String | null> end - local.get $3 + local.get $0 call $~lib/rt/pure/__release - local.get $4 + local.get $2 call $~lib/rt/pure/__release local.get $1 i32.const 1 @@ -9869,11 +9884,11 @@ (local $34 i32) (local $35 i32) (local $36 f64) - (local $37 i32) + (local $37 f32) (local $38 i32) (local $39 i32) (local $40 i32) - (local $41 f32) + (local $41 i32) (local $42 i32) (local $43 i32) (local $44 i32) @@ -11116,7 +11131,7 @@ i32.const 2880 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $40 + local.tee $41 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -11141,14 +11156,14 @@ i32.const -3 i32.const -2 call $~lib/array/Array#copyWithin - local.tee $39 + local.tee $40 i32.const 5 i32.const 2 i32.const 3 i32.const 2976 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $38 + local.tee $39 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -11174,7 +11189,7 @@ i32.const -3 i32.const -1 call $~lib/array/Array#copyWithin - local.tee $37 + local.tee $38 i32.const 5 i32.const 2 i32.const 3 @@ -11262,14 +11277,14 @@ call $~lib/rt/pure/__release local.get $47 call $~lib/rt/pure/__release + local.get $41 + call $~lib/rt/pure/__release local.get $40 call $~lib/rt/pure/__release local.get $39 call $~lib/rt/pure/__release local.get $38 call $~lib/rt/pure/__release - local.get $37 - call $~lib/rt/pure/__release local.get $35 call $~lib/rt/pure/__release local.get $1 @@ -12226,14 +12241,14 @@ i32.shl i32.add f32.load - local.tee $41 + local.tee $37 f32.const nan:0x400000 f32.eq if (result i32) i32.const 1 else - local.get $41 - local.get $41 + local.get $37 + local.get $37 f32.ne end br_if $__inlined_func$~lib/array/Array#includes @@ -12595,14 +12610,14 @@ i32.const 0 i32.const 1 call $~lib/array/Array#splice - local.tee $40 + local.tee $41 i32.const 1 i32.const 2 i32.const 3 i32.const 3840 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $39 + local.tee $40 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -12621,7 +12636,7 @@ i32.const 3872 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $38 + local.tee $39 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -12645,7 +12660,7 @@ i32.const -1 i32.const 2147483647 call $~lib/array/Array#splice - local.tee $37 + local.tee $38 i32.const 1 i32.const 2 i32.const 3 @@ -13382,14 +13397,14 @@ call $~lib/rt/pure/__release local.get $47 call $~lib/rt/pure/__release + local.get $41 + call $~lib/rt/pure/__release local.get $40 call $~lib/rt/pure/__release local.get $39 call $~lib/rt/pure/__release local.get $38 call $~lib/rt/pure/__release - local.get $37 - call $~lib/rt/pure/__release local.get $35 call $~lib/rt/pure/__release local.get $34 @@ -13982,8 +13997,6 @@ select i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $58 i32.const 2 i32.shl @@ -13992,12 +14005,14 @@ i32.load offset=4 i32.add i32.load - f32.convert_i32_s - local.set $41 + local.set $52 + i32.const 3 + global.set $~argumentsLength local.get $53 local.get $54 i32.add - local.get $41 + local.get $52 + f32.convert_i32_s f32.store local.get $58 i32.const 1 @@ -14591,15 +14606,15 @@ local.get $58 local.get $1 call $~lib/array/Array#__get - local.tee $41 - local.get $41 + local.tee $37 + local.get $37 f32.ne if (result i32) local.get $56 local.get $1 call $~lib/array/Array#__get - local.tee $41 - local.get $41 + local.tee $37 + local.get $37 f32.ne else i32.const 0 @@ -14744,7 +14759,7 @@ i32.const 5584 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $40 + local.tee $41 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -14776,7 +14791,7 @@ i32.const 5680 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $39 + local.tee $40 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -14851,7 +14866,7 @@ i32.const 5872 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $38 + local.tee $39 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -14873,7 +14888,7 @@ i32.const 5904 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $37 + local.tee $38 i32.const 0 call $std/array/isArraysEqual i32.eqz @@ -14978,11 +14993,11 @@ call $~lib/rt/pure/__release local.get $53 call $~lib/rt/pure/__release - local.get $40 + local.get $41 call $~lib/rt/pure/__release local.get $52 call $~lib/rt/pure/__release - local.get $39 + local.get $40 call $~lib/rt/pure/__release local.get $43 call $~lib/rt/pure/__release @@ -15004,9 +15019,9 @@ call $~lib/rt/pure/__release local.get $47 call $~lib/rt/pure/__release - local.get $38 + local.get $39 call $~lib/rt/pure/__release - local.get $37 + local.get $38 call $~lib/rt/pure/__release i32.const 64 call $std/array/createRandomOrderedArray @@ -15495,7 +15510,7 @@ i32.load offset=12 call $~lib/util/string/joinIntegerArray local.tee $1 - local.set $40 + local.set $41 local.get $1 i32.const 8528 call $~lib/string/String.__eq @@ -15520,7 +15535,7 @@ i32.load offset=12 call $~lib/util/string/joinIntegerArray local.tee $1 - local.set $39 + local.set $40 local.get $1 i32.const 8624 call $~lib/string/String.__eq @@ -15545,7 +15560,7 @@ i32.load offset=12 call $~lib/util/string/joinIntegerArray local.tee $1 - local.set $38 + local.set $39 local.get $1 i32.const 8736 call $~lib/string/String.__eq @@ -15564,7 +15579,7 @@ i32.const 8848 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $37 + local.tee $38 i32.const 6304 call $~lib/array/Array<~lib/string/String | null>#join local.tee $1 @@ -15755,17 +15770,17 @@ call $~lib/rt/pure/__release local.get $50 call $~lib/rt/pure/__release - local.get $40 + local.get $41 call $~lib/rt/pure/__release local.get $49 call $~lib/rt/pure/__release - local.get $39 + local.get $40 call $~lib/rt/pure/__release local.get $48 call $~lib/rt/pure/__release - local.get $38 + local.get $39 call $~lib/rt/pure/__release - local.get $37 + local.get $38 call $~lib/rt/pure/__release local.get $35 call $~lib/rt/pure/__release diff --git a/tests/compiler/std/array.untouched.wat b/tests/compiler/std/array.untouched.wat index 22cda3ee93..9b5e7cea75 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -5575,8 +5575,6 @@ local.set $4 local.get $4 if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -5586,6 +5584,8 @@ i32.load local.get $2 local.get $0 + i32.const 3 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if @@ -5711,8 +5711,6 @@ local.set $4 local.get $4 if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -5722,6 +5720,8 @@ i32.load local.get $2 local.get $0 + i32.const 3 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_=>_i32) i32.eqz @@ -5835,8 +5835,6 @@ local.set $4 local.get $4 if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -5846,6 +5844,8 @@ i32.load local.get $2 local.get $0 + i32.const 3 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if @@ -5956,8 +5956,6 @@ local.set $4 local.get $4 if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $2 @@ -5967,6 +5965,8 @@ i32.load local.get $2 local.get $0 + i32.const 3 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_=>_none) local.get $2 @@ -6180,8 +6180,6 @@ local.set $6 local.get $6 if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $5 @@ -6191,6 +6189,8 @@ i32.load local.get $5 local.get $0 + i32.const 3 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_=>_f32) local.set $8 @@ -6299,8 +6299,6 @@ local.set $6 local.get $6 if - i32.const 3 - global.set $~argumentsLength local.get $0 i32.load offset=4 local.get $5 @@ -6310,6 +6308,8 @@ i32.load local.get $5 local.get $0 + i32.const 3 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_=>_i32) local.set $7 @@ -6416,11 +6416,11 @@ i32.add i32.load local.set $6 - i32.const 3 - global.set $~argumentsLength local.get $6 local.get $3 local.get $0 + i32.const 3 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if @@ -6537,8 +6537,6 @@ local.set $6 local.get $6 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $0 i32.load offset=4 @@ -6549,6 +6547,8 @@ i32.load local.get $4 local.get $0 + i32.const 4 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6620,8 +6620,6 @@ local.set $6 local.get $6 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $0 i32.load offset=4 @@ -6632,6 +6630,8 @@ i32.load local.get $4 local.get $0 + i32.const 4 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6739,8 +6739,6 @@ local.set $5 local.get $5 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $0 i32.load offset=4 @@ -6751,6 +6749,8 @@ i32.load local.get $4 local.get $0 + i32.const 4 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6812,8 +6812,6 @@ local.set $5 local.get $5 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $0 i32.load offset=4 @@ -6824,6 +6822,8 @@ i32.load local.get $4 local.get $0 + i32.const 4 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -7059,10 +7059,10 @@ i32.add f32.load local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_f32_=>_i32) i32.const 0 @@ -7201,10 +7201,10 @@ i32.add f32.load local.set $10 - i32.const 2 - global.set $~argumentsLength local.get $9 local.get $10 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_f32_=>_i32) i32.const 0 @@ -7332,10 +7332,10 @@ i32.add f32.load local.set $9 - i32.const 2 - global.set $~argumentsLength local.get $10 local.get $9 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_f32_=>_i32) i32.const 0 @@ -7433,10 +7433,10 @@ local.get $3 f32.load local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $f32_f32_=>_i32) i32.const 0 @@ -7678,10 +7678,10 @@ i32.add f64.load local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -7814,10 +7814,10 @@ i32.add f64.load local.set $10 - i32.const 2 - global.set $~argumentsLength local.get $9 local.get $10 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -7945,10 +7945,10 @@ i32.add f64.load local.set $9 - i32.const 2 - global.set $~argumentsLength local.get $10 local.get $9 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -8046,10 +8046,10 @@ local.get $3 f64.load local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -8324,10 +8324,10 @@ i32.add i32.load local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -8460,10 +8460,10 @@ i32.add i32.load local.set $10 - i32.const 2 - global.set $~argumentsLength local.get $9 local.get $10 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -8591,10 +8591,10 @@ i32.add i32.load local.set $11 - i32.const 2 - global.set $~argumentsLength local.get $10 local.get $11 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -8690,10 +8690,10 @@ local.get $3 i32.load local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -8800,10 +8800,10 @@ i32.add i32.load local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -8936,10 +8936,10 @@ i32.add i32.load local.set $10 - i32.const 2 - global.set $~argumentsLength local.get $9 local.get $10 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -9067,10 +9067,10 @@ i32.add i32.load local.set $11 - i32.const 2 - global.set $~argumentsLength local.get $10 local.get $11 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -9166,10 +9166,10 @@ local.get $3 i32.load local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -9382,8 +9382,6 @@ local.set $4 local.get $4 if - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $2 i32.const 1 @@ -9392,6 +9390,8 @@ local.get $0 local.get $2 call $~lib/array/Array#__get + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -9736,10 +9736,10 @@ i32.load call $~lib/rt/pure/__retain local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -9821,10 +9821,10 @@ i32.load call $~lib/rt/pure/__retain local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -9928,8 +9928,6 @@ local.set $4 local.get $4 if - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $2 i32.const 1 @@ -9940,6 +9938,8 @@ local.get $2 call $~lib/array/Array<~lib/array/Array>#__get local.tee $6 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -10267,10 +10267,10 @@ i32.load call $~lib/rt/pure/__retain local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -10352,10 +10352,10 @@ i32.load call $~lib/rt/pure/__retain local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -10459,8 +10459,6 @@ local.set $4 local.get $4 if - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $2 i32.const 1 @@ -10471,6 +10469,8 @@ local.get $2 call $~lib/array/Array>#__get local.tee $6 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -10574,10 +10574,10 @@ i32.load call $~lib/rt/pure/__retain local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -10659,10 +10659,10 @@ i32.load call $~lib/rt/pure/__retain local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -10754,8 +10754,6 @@ local.set $4 local.get $4 if - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $2 i32.const 1 @@ -10766,6 +10764,8 @@ local.get $2 call $~lib/array/Array<~lib/string/String | null>#__get local.tee $6 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -11688,10 +11688,10 @@ i32.load call $~lib/rt/pure/__retain local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -11773,10 +11773,10 @@ i32.load call $~lib/rt/pure/__retain local.set $5 - i32.const 2 - global.set $~argumentsLength local.get $4 local.get $5 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -11880,8 +11880,6 @@ local.set $4 local.get $4 if - i32.const 2 - global.set $~argumentsLength local.get $0 local.get $2 i32.const 1 @@ -11892,6 +11890,8 @@ local.get $2 call $~lib/array/Array<~lib/string/String>#__get local.tee $6 + i32.const 2 + global.set $~argumentsLength local.get $1 call_indirect (type $i32_i32_=>_i32) i32.const 0 @@ -22757,9 +22757,9 @@ call $~lib/rt/__allocArray call $~lib/rt/pure/__retain local.set $50 + local.get $50 i32.const 0 global.set $~argumentsLength - local.get $50 i32.const 0 call $~lib/array/Array#sort|trampoline call $~lib/rt/pure/__release @@ -22789,9 +22789,9 @@ call $~lib/rt/__allocArray call $~lib/rt/pure/__retain local.set $49 + local.get $49 i32.const 0 global.set $~argumentsLength - local.get $49 i32.const 0 call $~lib/array/Array#sort|trampoline call $~lib/rt/pure/__release @@ -22821,9 +22821,9 @@ call $~lib/rt/__allocArray call $~lib/rt/pure/__retain local.set $47 + local.get $47 i32.const 0 global.set $~argumentsLength - local.get $47 i32.const 0 call $~lib/array/Array#sort|trampoline call $~lib/rt/pure/__release @@ -22853,9 +22853,9 @@ call $~lib/rt/__allocArray call $~lib/rt/pure/__retain local.set $41 + local.get $41 i32.const 0 global.set $~argumentsLength - local.get $41 i32.const 0 call $~lib/array/Array#sort|trampoline call $~lib/rt/pure/__release @@ -23141,9 +23141,9 @@ call $~lib/rt/__allocArray call $~lib/rt/pure/__retain local.set $34 + local.get $31 i32.const 1 global.set $~argumentsLength - local.get $31 i32.const 0 call $std/array/assertSorted<~lib/string/String | null>|trampoline local.get $31 @@ -23162,9 +23162,9 @@ i32.const 400 call $std/array/createRandomStringArray local.set $29 + local.get $29 i32.const 1 global.set $~argumentsLength - local.get $29 i32.const 0 call $std/array/assertSorted<~lib/string/String>|trampoline local.get $31 diff --git a/tests/compiler/std/arraybuffer.optimized.wat b/tests/compiler/std/arraybuffer.optimized.wat index 96b9bc0b50..70f87974a3 100644 --- a/tests/compiler/std/arraybuffer.optimized.wat +++ b/tests/compiler/std/arraybuffer.optimized.wat @@ -1905,10 +1905,10 @@ i32.const 2 call $~lib/arraybuffer/ArrayBufferView#constructor local.set $3 - i32.const 1 - global.set $~argumentsLength local.get $4 i32.load + i32.const 1 + global.set $~argumentsLength call $~lib/dataview/DataView#constructor|trampoline local.set $2 local.get $5 diff --git a/tests/compiler/std/arraybuffer.untouched.wat b/tests/compiler/std/arraybuffer.untouched.wat index a6c738af2d..5a6d1538fc 100644 --- a/tests/compiler/std/arraybuffer.untouched.wat +++ b/tests/compiler/std/arraybuffer.untouched.wat @@ -3777,12 +3777,12 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength i32.const 0 local.get $2 i32.load i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/dataview/DataView#constructor|trampoline local.tee $5 diff --git a/tests/compiler/std/dataview.optimized.wat b/tests/compiler/std/dataview.optimized.wat index 9969b73849..c35b5fd080 100644 --- a/tests/compiler/std/dataview.optimized.wat +++ b/tests/compiler/std/dataview.optimized.wat @@ -3385,11 +3385,12 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $1 i32.load - local.tee $2 + local.set $2 + i32.const 1 + global.set $~argumentsLength + local.get $2 i32.const 0 local.get $2 i32.const 16 diff --git a/tests/compiler/std/dataview.untouched.wat b/tests/compiler/std/dataview.untouched.wat index 348044d8be..4347a8ba82 100644 --- a/tests/compiler/std/dataview.untouched.wat +++ b/tests/compiler/std/dataview.untouched.wat @@ -4368,12 +4368,12 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength i32.const 0 local.get $0 i32.load i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/dataview/DataView#constructor|trampoline local.set $2 diff --git a/tests/compiler/std/string.untouched.wat b/tests/compiler/std/string.untouched.wat index ec92358ef2..31c3cfbd0f 100644 --- a/tests/compiler/std/string.untouched.wat +++ b/tests/compiler/std/string.untouched.wat @@ -10885,10 +10885,10 @@ call $~lib/builtins/abort unreachable end + i32.const 0 i32.const 1 global.set $~argumentsLength i32.const 0 - i32.const 0 call $~lib/string/String.fromCharCode|trampoline local.tee $0 i32.const 288 @@ -10902,9 +10902,9 @@ call $~lib/builtins/abort unreachable end + i32.const 54 i32.const 1 global.set $~argumentsLength - i32.const 54 i32.const 0 call $~lib/string/String.fromCharCode|trampoline local.tee $1 @@ -10919,9 +10919,9 @@ call $~lib/builtins/abort unreachable end + i32.const 65590 i32.const 1 global.set $~argumentsLength - i32.const 65590 i32.const 0 call $~lib/string/String.fromCharCode|trampoline local.tee $2 diff --git a/tests/compiler/std/typedarray.optimized.wat b/tests/compiler/std/typedarray.optimized.wat index a3118dc572..249c0a334e 100644 --- a/tests/compiler/std/typedarray.optimized.wat +++ b/tests/compiler/std/typedarray.optimized.wat @@ -3655,6 +3655,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $4 @@ -3666,13 +3667,15 @@ local.get $5 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $3 local.get $2 local.get $4 i32.add i32.load8_u + local.set $6 + i32.const 4 + global.set $~argumentsLength + local.get $3 + local.get $6 local.get $2 local.get $0 local.get $1 @@ -3740,6 +3743,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $4 @@ -3753,15 +3757,17 @@ local.get $5 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $3 local.get $4 local.get $2 i32.const 2 i32.shl i32.add i32.load + local.set $6 + i32.const 4 + global.set $~argumentsLength + local.get $3 + local.get $6 local.get $2 local.get $0 local.get $1 @@ -3834,6 +3840,7 @@ (local $3 i64) (local $4 i32) (local $5 i32) + (local $6 i64) local.get $0 i32.load offset=4 local.set $4 @@ -3847,15 +3854,17 @@ local.get $5 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $3 local.get $4 local.get $2 i32.const 3 i32.shl i32.add i64.load + local.set $6 + i32.const 4 + global.set $~argumentsLength + local.get $3 + local.get $6 local.get $2 local.get $0 local.get $1 @@ -3932,6 +3941,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $4 @@ -3945,13 +3955,15 @@ i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $3 local.get $2 local.get $4 i32.add i32.load8_u + local.set $5 + i32.const 4 + global.set $~argumentsLength + local.get $3 + local.get $5 local.get $2 local.get $0 local.get $1 @@ -3970,6 +3982,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $4 @@ -3985,15 +3998,17 @@ i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $3 local.get $4 local.get $2 i32.const 2 i32.shl i32.add i32.load + local.set $5 + i32.const 4 + global.set $~argumentsLength + local.get $3 + local.get $5 local.get $2 local.get $0 local.get $1 @@ -4012,6 +4027,7 @@ (local $2 i32) (local $3 i64) (local $4 i32) + (local $5 i64) local.get $0 i32.load offset=4 local.set $4 @@ -4027,15 +4043,17 @@ i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $3 local.get $4 local.get $2 i32.const 3 i32.shl i32.add i64.load + local.set $5 + i32.const 4 + global.set $~argumentsLength + local.get $3 + local.get $5 local.get $2 local.get $0 local.get $1 @@ -6305,6 +6323,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6317,19 +6336,19 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Int8Array,i8>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $2 local.get $3 i32.add i32.load8_s + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Int8Array,i8>|inlined.0 end local.get $2 @@ -6340,7 +6359,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Int8Array,i8>~anonymous|1 (; 122 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6353,6 +6372,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6365,19 +6385,19 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Uint8Array,u8>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $2 local.get $3 i32.add i32.load8_u + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Uint8Array,u8>|inlined.0 end local.get $2 @@ -6388,7 +6408,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Int16Array,i16>~anonymous|0 (; 124 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6402,6 +6422,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6416,21 +6437,21 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Int16Array,i16>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 1 i32.shl i32.add i32.load16_s + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Int16Array,i16>|inlined.0 end local.get $2 @@ -6441,7 +6462,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Int16Array,i16>~anonymous|1 (; 126 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6454,6 +6475,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6468,21 +6490,21 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Uint16Array,u16>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 1 i32.shl i32.add i32.load16_u + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Uint16Array,u16>|inlined.0 end local.get $2 @@ -6493,7 +6515,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Int32Array,i32>~anonymous|0 (; 128 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6505,6 +6527,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6519,21 +6542,21 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Int32Array,i32>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 2 i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $i32_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Int32Array,i32>|inlined.0 end local.get $2 @@ -6544,7 +6567,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Int32Array,i32>~anonymous|1 (; 130 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6559,7 +6582,8 @@ (local $2 i32) (local $3 i32) (local $4 i32) - (local $5 i32) + (local $5 i64) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6574,21 +6598,21 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Int64Array,i64>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 3 i32.shl i32.add i64.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $i64_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Int64Array,i64>|inlined.0 end local.get $2 @@ -6599,7 +6623,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Int64Array,i64>~anonymous|1 (; 133 ;) (param $0 i64) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6614,7 +6638,8 @@ (local $2 i32) (local $3 i32) (local $4 i32) - (local $5 i32) + (local $5 f32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6629,21 +6654,21 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Float32Array,f32>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 2 i32.shl i32.add f32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $f32_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Float32Array,f32>|inlined.0 end local.get $2 @@ -6654,7 +6679,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Float32Array,f32>~anonymous|1 (; 136 ;) (param $0 f32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6670,7 +6695,8 @@ (local $2 i32) (local $3 i32) (local $4 i32) - (local $5 i32) + (local $5 f64) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6685,21 +6711,21 @@ i32.lt_s if block $~lib/typedarray/SOME<~lib/typedarray/Float64Array,f64>|inlined.0 - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 3 i32.shl i32.add f64.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 call_indirect (type $f64_i32_i32_=>_i32) if i32.const 1 - local.set $5 + local.set $6 br $~lib/typedarray/SOME<~lib/typedarray/Float64Array,f64>|inlined.0 end local.get $2 @@ -6710,7 +6736,7 @@ end end end - local.get $5 + local.get $6 ) (func $std/typedarray/testArraySome<~lib/typedarray/Float64Array,f64>~anonymous|1 (; 139 ;) (param $0 f64) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -6721,6 +6747,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6733,12 +6760,12 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $2 local.get $3 i32.add i32.load8_s + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -6767,6 +6794,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6779,12 +6807,12 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $2 local.get $3 i32.add i32.load8_u + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -6806,6 +6834,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6820,14 +6849,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 1 i32.shl i32.add i32.load16_s + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -6856,6 +6885,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6870,14 +6900,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 1 i32.shl i32.add i32.load16_u + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -6899,6 +6929,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $3 @@ -6913,14 +6944,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 2 i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -6947,6 +6978,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i64) local.get $0 i32.load offset=4 local.set $3 @@ -6961,14 +6993,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 3 i32.shl i32.add i64.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -6995,6 +7027,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 f32) local.get $0 i32.load offset=4 local.set $3 @@ -7009,14 +7042,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 2 i32.shl i32.add f32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7043,6 +7076,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 f64) local.get $0 i32.load offset=4 local.set $3 @@ -7057,14 +7091,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 3 i32.shl i32.add f64.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7102,6 +7136,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7114,12 +7149,12 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $2 local.get $3 i32.add i32.load8_s + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7134,9 +7169,9 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $std/typedarray/testArrayEvery<~lib/typedarray/Uint8Array,u8>~anonymous|0 (; 156 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -7149,6 +7184,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7161,12 +7197,12 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $2 local.get $3 i32.add i32.load8_u + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7181,9 +7217,9 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $std/typedarray/testArrayEvery<~lib/typedarray/Int16Array,i16>~anonymous|0 (; 158 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -7200,6 +7236,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7214,14 +7251,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 1 i32.shl i32.add i32.load16_s + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7236,15 +7273,16 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $~lib/typedarray/Uint16Array#every (; 160 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7259,14 +7297,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 1 i32.shl i32.add i32.load16_u + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7281,9 +7319,9 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $std/typedarray/testArrayEvery<~lib/typedarray/Int32Array,i32>~anonymous|0 (; 161 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -7296,6 +7334,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7310,14 +7349,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 2 i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7332,9 +7371,9 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $std/typedarray/testArrayEvery<~lib/typedarray/Int64Array,i64>~anonymous|0 (; 163 ;) (param $0 i64) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -7346,7 +7385,8 @@ (local $2 i32) (local $3 i32) (local $4 i32) - (local $5 i32) + (local $5 i64) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7361,14 +7401,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 3 i32.shl i32.add i64.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7383,9 +7423,9 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $std/typedarray/testArrayEvery<~lib/typedarray/Uint64Array,u64>~anonymous|0 (; 165 ;) (param $0 i64) (param $1 i32) (param $2 i32) (result i32) local.get $0 @@ -7550,7 +7590,8 @@ (local $2 i32) (local $3 i32) (local $4 i32) - (local $5 i32) + (local $5 f32) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7565,14 +7606,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 2 i32.shl i32.add f32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7587,9 +7628,9 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $~lib/math/NativeMath.mod (; 169 ;) (param $0 f64) (result f64) (local $1 i64) @@ -7755,7 +7796,8 @@ (local $2 i32) (local $3 i32) (local $4 i32) - (local $5 i32) + (local $5 f64) + (local $6 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7770,14 +7812,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 3 i32.shl i32.add f64.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7792,9 +7834,9 @@ end end i32.const 1 - local.set $5 + local.set $6 end - local.get $5 + local.get $6 ) (func $std/typedarray/testArrayForEach<~lib/typedarray/Int8Array,i8>~anonymous|0 (; 172 ;) (param $0 i32) (param $1 i32) (param $2 i32) local.get $0 @@ -7845,6 +7887,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7856,12 +7899,12 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $2 local.get $3 i32.add i32.load8_u + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -7964,6 +8007,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i32) local.get $0 i32.load offset=4 local.set $3 @@ -7977,14 +8021,14 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 2 i32.shl i32.add i32.load + i32.const 3 + global.set $~argumentsLength local.get $2 local.get $0 local.get $1 @@ -8043,6 +8087,7 @@ (local $2 i32) (local $3 i32) (local $4 i32) + (local $5 i64) local.get $0 i32.load offset=4 local.set $3 @@ -8056,15 +8101,15 @@ local.get $4 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $3 local.get $2 i32.const 3 i32.shl i32.add i64.load - local.get $2 + i32.const 3 + global.set $~argumentsLength + local.get $2 local.get $0 local.get $1 call_indirect (type $i64_i32_i32_=>_none) @@ -25853,20 +25898,21 @@ (local $13 i32) (local $14 i32) (local $15 i32) - (local $16 f64) + (local $16 f32) (local $17 i32) (local $18 i32) (local $19 i32) (local $20 i64) - (local $21 f32) - (local $22 f64) - (local $23 i32) + (local $21 f64) + (local $22 f32) + (local $23 f64) (local $24 i32) (local $25 i32) (local $26 i32) (local $27 i32) (local $28 i32) (local $29 i32) + (local $30 i32) i32.const 0 call $std/typedarray/testInstantiate i32.const 5 @@ -26104,58 +26150,58 @@ block $~lib/typedarray/SORT<~lib/typedarray/Float64Array,f64>|inlined.0 local.get $0 call $~lib/rt/pure/__retain - local.tee $28 + local.tee $29 i32.load offset=8 i32.const 3 i32.shr_u - local.tee $29 + local.tee $30 i32.const 1 i32.le_s br_if $~lib/typedarray/SORT<~lib/typedarray/Float64Array,f64>|inlined.0 - local.get $28 + local.get $29 i32.load offset=4 local.set $1 - local.get $29 + local.get $30 i32.const 2 i32.eq if local.get $1 f64.load offset=8 - local.set $22 + local.set $23 local.get $1 f64.load - local.set $16 + local.set $21 i32.const 2 global.set $~argumentsLength - local.get $22 - local.get $16 + local.get $23 + local.get $21 call $~lib/util/sort/COMPARATOR~anonymous|0 i32.const 0 i32.lt_s if local.get $1 - local.get $16 + local.get $21 f64.store offset=8 local.get $1 - local.get $22 + local.get $23 f64.store end br $~lib/typedarray/SORT<~lib/typedarray/Float64Array,f64>|inlined.0 end - local.get $29 + local.get $30 i32.const 256 i32.lt_s if local.get $1 - local.get $29 + local.get $30 call $~lib/util/sort/insertionSort else local.get $1 - local.get $29 + local.get $30 call $~lib/util/sort/weakHeapSort end end - local.get $28 + local.get $29 call $~lib/rt/pure/__release local.get $0 i32.const 0 @@ -26288,7 +26334,7 @@ i32.const 1504 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $29 + local.tee $30 call $std/typedarray/isInt8ArrayEqual i32.eqz if @@ -26312,7 +26358,7 @@ i32.const 1584 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $28 + local.tee $29 call $std/typedarray/isInt8ArrayEqual i32.eqz if @@ -26336,7 +26382,7 @@ i32.const 1616 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $27 + local.tee $28 call $std/typedarray/isInt8ArrayEqual i32.eqz if @@ -26360,7 +26406,7 @@ i32.const 1648 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $25 + local.tee $27 call $std/typedarray/isInt8ArrayEqual i32.eqz if @@ -26448,7 +26494,7 @@ i32.const 1712 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $24 + local.tee $25 call $std/typedarray/isInt8ArrayEqual i32.eqz if @@ -26466,7 +26512,7 @@ i32.const 1744 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $23 + local.tee $24 call $std/typedarray/isInt8ArrayEqual i32.eqz if @@ -26479,21 +26525,21 @@ end local.get $1 call $~lib/rt/pure/__release + local.get $30 + call $~lib/rt/pure/__release local.get $29 call $~lib/rt/pure/__release local.get $28 call $~lib/rt/pure/__release local.get $27 call $~lib/rt/pure/__release - local.get $25 - call $~lib/rt/pure/__release local.get $26 call $~lib/rt/pure/__release local.get $0 call $~lib/rt/pure/__release - local.get $24 + local.get $25 call $~lib/rt/pure/__release - local.get $23 + local.get $24 call $~lib/rt/pure/__release i32.const 5 call $~lib/typedarray/Int32Array#constructor @@ -26530,7 +26576,7 @@ i32.const 1776 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $29 + local.tee $30 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -26554,7 +26600,7 @@ i32.const 1824 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $28 + local.tee $29 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -26578,7 +26624,7 @@ i32.const 1872 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $27 + local.tee $28 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -26602,7 +26648,7 @@ i32.const 1920 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $25 + local.tee $27 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -26692,7 +26738,7 @@ i32.const 2016 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $24 + local.tee $25 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -26710,7 +26756,7 @@ i32.const 2048 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $23 + local.tee $24 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -26723,21 +26769,21 @@ end local.get $1 call $~lib/rt/pure/__release + local.get $30 + call $~lib/rt/pure/__release local.get $29 call $~lib/rt/pure/__release local.get $28 call $~lib/rt/pure/__release local.get $27 call $~lib/rt/pure/__release - local.get $25 - call $~lib/rt/pure/__release local.get $26 call $~lib/rt/pure/__release local.get $0 call $~lib/rt/pure/__release - local.get $24 + local.get $25 call $~lib/rt/pure/__release - local.get $23 + local.get $24 call $~lib/rt/pure/__release i32.const 6 call $~lib/typedarray/Int8Array#constructor @@ -26822,7 +26868,7 @@ i32.const 1 i32.const 5 call $~lib/typedarray/Int8Array#subarray - local.tee $29 + local.tee $30 i32.const 0 call $~lib/typedarray/Int8Array#__get i32.const 3 @@ -26835,7 +26881,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.load offset=8 i32.const 4 i32.ne @@ -26847,7 +26893,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 call $~lib/arraybuffer/ArrayBufferView#get:byteOffset i32.const 2 i32.ne @@ -26859,7 +26905,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.load offset=8 i32.const 4 i32.ne @@ -26871,11 +26917,11 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 1 i32.const 4 call $~lib/typedarray/Int8Array#subarray - local.tee $28 + local.tee $29 i32.const 0 call $~lib/typedarray/Int8Array#__get i32.const 4 @@ -26888,7 +26934,7 @@ call $~lib/builtins/abort unreachable end - local.get $28 + local.get $29 i32.load offset=8 i32.const 3 i32.ne @@ -26900,7 +26946,7 @@ call $~lib/builtins/abort unreachable end - local.get $28 + local.get $29 call $~lib/arraybuffer/ArrayBufferView#get:byteOffset i32.const 3 i32.ne @@ -26912,7 +26958,7 @@ call $~lib/builtins/abort unreachable end - local.get $28 + local.get $29 i32.load offset=8 i32.const 3 i32.ne @@ -26928,9 +26974,9 @@ call $~lib/rt/pure/__release local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release - local.get $28 + local.get $29 call $~lib/rt/pure/__release i32.const 5 call $~lib/typedarray/Int32Array#constructor @@ -26958,7 +27004,7 @@ i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice - local.set $29 + local.set $30 local.get $1 i32.const 0 i32.const 3 @@ -26982,7 +27028,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice @@ -26994,14 +27040,14 @@ i32.const 3 i32.const 2147483647 call $~lib/typedarray/Int32Array#copyWithin - local.tee $25 + local.tee $26 i32.const 5 i32.const 2 i32.const 15 i32.const 2144 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $26 + local.tee $25 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -27012,13 +27058,14 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice + local.set $29 local.get $0 call $~lib/rt/pure/__release - local.tee $0 + local.get $29 i32.const 1 i32.const 2 i32.const 2147483647 @@ -27030,7 +27077,7 @@ i32.const 2192 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $23 + local.tee $19 call $std/typedarray/isInt32ArrayEqual i32.eqz if @@ -27041,18 +27088,18 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice - local.get $0 + local.get $29 call $~lib/rt/pure/__release local.tee $0 i32.const 2 i32.const 2 i32.const 2147483647 call $~lib/typedarray/Int32Array#copyWithin - local.tee $19 + local.tee $29 i32.const 5 i32.const 2 i32.const 15 @@ -27070,7 +27117,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice @@ -27099,7 +27146,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice @@ -27128,7 +27175,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice @@ -27157,7 +27204,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice @@ -27186,7 +27233,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice @@ -27215,7 +27262,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice @@ -27244,14 +27291,13 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice - local.set $1 local.get $0 call $~lib/rt/pure/__release - local.get $1 + local.tee $0 i32.const -4 i32.const -3 i32.const -1 @@ -27274,19 +27320,19 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice - local.set $0 - local.get $1 - call $~lib/rt/pure/__release + local.set $1 local.get $0 + call $~lib/rt/pure/__release + local.get $1 i32.const -4 i32.const -3 i32.const 2147483647 call $~lib/typedarray/Int32Array#copyWithin - local.tee $1 + local.tee $0 i32.const 5 i32.const 2 i32.const 15 @@ -27304,24 +27350,24 @@ call $~lib/builtins/abort unreachable end - local.get $0 + local.get $1 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $28 call $~lib/rt/pure/__release local.get $27 call $~lib/rt/pure/__release - local.get $25 - call $~lib/rt/pure/__release local.get $26 call $~lib/rt/pure/__release - local.get $24 + local.get $25 call $~lib/rt/pure/__release - local.get $23 + local.get $24 call $~lib/rt/pure/__release local.get $19 call $~lib/rt/pure/__release + local.get $29 + call $~lib/rt/pure/__release local.get $18 call $~lib/rt/pure/__release local.get $17 @@ -27352,7 +27398,7 @@ call $~lib/rt/pure/__release local.get $3 call $~lib/rt/pure/__release - local.get $1 + local.get $0 call $~lib/rt/pure/__release local.get $2 call $~lib/rt/pure/__release @@ -27382,7 +27428,7 @@ i32.const 1 i32.const 4 call $~lib/typedarray/Int32Array#subarray - local.tee $29 + local.tee $30 i32.load offset=8 i32.const 2 i32.shr_u @@ -27396,7 +27442,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 call $~lib/arraybuffer/ArrayBufferView#get:byteOffset i32.const 4 i32.ne @@ -27408,7 +27454,7 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.load offset=8 i32.const 12 i32.ne @@ -27486,11 +27532,11 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 i32.const 1 i32.const 2 call $~lib/typedarray/Int32Array#slice - local.tee $28 + local.tee $29 i32.const 0 call $~lib/typedarray/Int32Array#__get i32.const 3 @@ -27503,7 +27549,7 @@ call $~lib/builtins/abort unreachable end - local.get $28 + local.get $29 i32.load offset=8 i32.const 2 i32.shr_u @@ -27517,7 +27563,7 @@ call $~lib/builtins/abort unreachable end - local.get $28 + local.get $29 call $~lib/arraybuffer/ArrayBufferView#get:byteOffset if i32.const 0 @@ -27527,7 +27573,7 @@ call $~lib/builtins/abort unreachable end - local.get $28 + local.get $29 i32.load offset=8 i32.const 4 i32.ne @@ -27544,7 +27590,7 @@ i32.const 0 i32.const 2147483647 call $~lib/typedarray/Int32Array#slice - local.tee $27 + local.tee $28 i32.eq if i32.const 0 @@ -27554,7 +27600,7 @@ call $~lib/builtins/abort unreachable end - local.get $27 + local.get $28 i32.load offset=8 i32.const 2 i32.shr_u @@ -27571,7 +27617,7 @@ call $~lib/builtins/abort unreachable end - local.get $27 + local.get $28 call $~lib/arraybuffer/ArrayBufferView#get:byteOffset local.get $1 call $~lib/arraybuffer/ArrayBufferView#get:byteOffset @@ -27584,7 +27630,7 @@ call $~lib/builtins/abort unreachable end - local.get $27 + local.get $28 i32.load offset=8 local.get $1 i32.load offset=8 @@ -27599,25 +27645,25 @@ end local.get $1 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $0 call $~lib/rt/pure/__release - local.get $28 + local.get $29 call $~lib/rt/pure/__release - local.get $27 + local.get $28 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Int8Array#constructor - local.tee $29 + local.tee $30 i32.const 0 i32.const 1 call $~lib/typedarray/Int8Array#__set - local.get $29 + local.get $30 i32.const 1 i32.const 2 call $~lib/typedarray/Int8Array#__set - local.get $29 + local.get $30 i32.const 2 i32.const 3 call $~lib/typedarray/Int8Array#__set @@ -27625,24 +27671,26 @@ local.set $0 i32.const 0 local.set $1 - local.get $29 + local.get $30 i32.load offset=4 - local.set $28 - local.get $29 + local.set $29 + local.get $30 i32.load offset=8 - local.set $27 + local.set $28 loop $for-loop|0 local.get $0 - local.get $27 + local.get $28 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $1 local.get $0 - local.get $28 + local.get $29 i32.add i32.load8_s + local.set $27 + i32.const 4 + global.set $~argumentsLength + local.get $1 + local.get $27 i32.add local.set $1 local.get $0 @@ -27675,7 +27723,7 @@ i32.const 6 i32.ne br_if $folding-inner0 - local.get $29 + local.get $30 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Uint8Array#constructor @@ -27727,15 +27775,15 @@ call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Int16Array#constructor - local.tee $29 + local.tee $30 i32.const 0 i32.const 1 call $~lib/typedarray/Int16Array#__set - local.get $29 + local.get $30 i32.const 1 i32.const 2 call $~lib/typedarray/Int16Array#__set - local.get $29 + local.get $30 i32.const 2 i32.const 3 call $~lib/typedarray/Int16Array#__set @@ -27743,28 +27791,30 @@ local.set $0 i32.const 0 local.set $1 - local.get $29 + local.get $30 i32.load offset=4 - local.set $28 - local.get $29 + local.set $29 + local.get $30 i32.load offset=8 i32.const 1 i32.shr_u - local.set $27 + local.set $28 loop $for-loop|00 local.get $0 - local.get $27 + local.get $28 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $1 - local.get $28 + local.get $29 local.get $0 i32.const 1 i32.shl i32.add i32.load16_s + local.set $27 + i32.const 4 + global.set $~argumentsLength + local.get $1 + local.get $27 i32.add local.set $1 local.get $0 @@ -27780,19 +27830,19 @@ i32.const 6 i32.ne br_if $folding-inner0 - local.get $29 + local.get $30 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Uint16Array#constructor - local.tee $29 + local.tee $30 i32.const 0 i32.const 1 call $~lib/typedarray/Uint16Array#__set - local.get $29 + local.get $30 i32.const 1 i32.const 2 call $~lib/typedarray/Uint16Array#__set - local.get $29 + local.get $30 i32.const 2 i32.const 3 call $~lib/typedarray/Uint16Array#__set @@ -27800,28 +27850,30 @@ local.set $0 i32.const 0 local.set $1 - local.get $29 + local.get $30 i32.load offset=4 - local.set $28 - local.get $29 + local.set $29 + local.get $30 i32.load offset=8 i32.const 1 i32.shr_u - local.set $27 + local.set $28 loop $for-loop|01 local.get $0 - local.get $27 + local.get $28 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $1 - local.get $28 + local.get $29 local.get $0 i32.const 1 i32.shl i32.add i32.load16_u + local.set $27 + i32.const 4 + global.set $~argumentsLength + local.get $1 + local.get $27 i32.add local.set $1 local.get $0 @@ -27837,7 +27889,7 @@ i32.const 6 i32.ne br_if $folding-inner0 - local.get $29 + local.get $30 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Int32Array#constructor @@ -27929,132 +27981,136 @@ call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Float32Array#constructor - local.tee $0 + local.tee $1 i32.const 0 f32.const 1 call $~lib/typedarray/Float32Array#__set - local.get $0 + local.get $1 i32.const 1 f32.const 2 call $~lib/typedarray/Float32Array#__set - local.get $0 + local.get $1 i32.const 2 f32.const 3 call $~lib/typedarray/Float32Array#__set i32.const 0 - local.set $1 - local.get $0 + local.set $0 + local.get $1 i32.load offset=4 - local.set $29 - local.get $0 + local.set $30 + local.get $1 i32.load offset=8 i32.const 2 i32.shr_u - local.set $28 + local.set $29 loop $for-loop|02 - local.get $1 - local.get $28 + local.get $0 + local.get $29 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $21 - local.get $29 - local.get $1 + local.get $30 + local.get $0 i32.const 2 i32.shl i32.add f32.load + local.set $16 + i32.const 4 + global.set $~argumentsLength + local.get $22 + local.get $16 f32.add - local.set $21 - local.get $1 + local.set $22 + local.get $0 i32.const 1 i32.add - local.set $1 + local.set $0 br $for-loop|02 end end - local.get $21 + local.get $22 f32.const 6 f32.ne br_if $folding-inner0 - local.get $0 + local.get $1 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Float64Array#constructor - local.tee $0 + local.tee $1 i32.const 0 f64.const 1 call $~lib/typedarray/Float64Array#__set - local.get $0 + local.get $1 i32.const 1 f64.const 2 call $~lib/typedarray/Float64Array#__set - local.get $0 + local.get $1 i32.const 2 f64.const 3 call $~lib/typedarray/Float64Array#__set i32.const 0 - local.set $1 + local.set $0 f64.const 0 - local.set $22 - local.get $0 + local.set $23 + local.get $1 i32.load offset=4 - local.set $29 - local.get $0 + local.set $30 + local.get $1 i32.load offset=8 i32.const 3 i32.shr_u - local.set $28 + local.set $29 loop $for-loop|03 - local.get $1 - local.get $28 + local.get $0 + local.get $29 i32.lt_s if - i32.const 4 - global.set $~argumentsLength - local.get $22 - local.get $29 - local.get $1 + local.get $30 + local.get $0 i32.const 3 i32.shl i32.add f64.load - f64.add - local.set $22 - local.get $1 + local.set $21 + i32.const 4 + global.set $~argumentsLength + local.get $23 + local.get $21 + f64.add + local.set $23 + local.get $0 i32.const 1 i32.add - local.set $1 + local.set $0 br $for-loop|03 end end - local.get $22 + local.get $23 f64.const 6 f64.ne br_if $folding-inner0 - local.get $0 + local.get $1 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Int8Array#constructor - local.tee $29 + local.tee $30 i32.const 0 i32.const 1 call $~lib/typedarray/Int8Array#__set - local.get $29 + local.get $30 i32.const 1 i32.const 2 call $~lib/typedarray/Int8Array#__set - local.get $29 + local.get $30 i32.const 2 i32.const 3 call $~lib/typedarray/Int8Array#__set i32.const 0 local.set $0 - local.get $29 + local.get $30 i32.load offset=4 - local.set $28 - local.get $29 + local.set $29 + local.get $30 i32.load offset=8 i32.const 1 i32.sub @@ -28064,14 +28120,16 @@ i32.const 0 i32.ge_s if + local.get $1 + local.get $29 + i32.add + i32.load8_s + local.set $28 i32.const 4 global.set $~argumentsLength local.get $0 - local.get $1 local.get $28 i32.add - i32.load8_s - i32.add local.set $0 local.get $1 i32.const 1 @@ -28086,7 +28144,7 @@ i32.const 6 i32.ne br_if $folding-inner1 - local.get $29 + local.get $30 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Uint8Array#constructor @@ -28138,24 +28196,24 @@ call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Int16Array#constructor - local.tee $29 + local.tee $30 i32.const 0 i32.const 1 call $~lib/typedarray/Int16Array#__set - local.get $29 + local.get $30 i32.const 1 i32.const 2 call $~lib/typedarray/Int16Array#__set - local.get $29 + local.get $30 i32.const 2 i32.const 3 call $~lib/typedarray/Int16Array#__set i32.const 0 local.set $0 - local.get $29 + local.get $30 i32.load offset=4 - local.set $28 - local.get $29 + local.set $29 + local.get $30 i32.load offset=8 i32.const 1 i32.shr_u @@ -28167,15 +28225,17 @@ i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $0 - local.get $28 + local.get $29 local.get $1 i32.const 1 i32.shl i32.add i32.load16_s + local.set $28 + i32.const 4 + global.set $~argumentsLength + local.get $0 + local.get $28 i32.add local.set $0 local.get $1 @@ -28191,28 +28251,28 @@ i32.const 6 i32.ne br_if $folding-inner1 - local.get $29 + local.get $30 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Uint16Array#constructor - local.tee $29 + local.tee $30 i32.const 0 i32.const 1 call $~lib/typedarray/Uint16Array#__set - local.get $29 + local.get $30 i32.const 1 i32.const 2 call $~lib/typedarray/Uint16Array#__set - local.get $29 + local.get $30 i32.const 2 i32.const 3 call $~lib/typedarray/Uint16Array#__set i32.const 0 local.set $0 - local.get $29 + local.get $30 i32.load offset=4 - local.set $28 - local.get $29 + local.set $29 + local.get $30 i32.load offset=8 i32.const 1 i32.shr_u @@ -28224,15 +28284,17 @@ i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $0 - local.get $28 + local.get $29 local.get $1 i32.const 1 i32.shl i32.add i32.load16_u + local.set $28 + i32.const 4 + global.set $~argumentsLength + local.get $0 + local.get $28 i32.add local.set $0 local.get $1 @@ -28248,7 +28310,7 @@ i32.const 6 i32.ne br_if $folding-inner1 - local.get $29 + local.get $30 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Int32Array#constructor @@ -28340,113 +28402,117 @@ call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Float32Array#constructor - local.tee $1 + local.tee $0 i32.const 0 f32.const 1 call $~lib/typedarray/Float32Array#__set - local.get $1 + local.get $0 i32.const 1 f32.const 2 call $~lib/typedarray/Float32Array#__set - local.get $1 + local.get $0 i32.const 2 f32.const 3 call $~lib/typedarray/Float32Array#__set f32.const 0 - local.set $21 - local.get $1 + local.set $22 + local.get $0 i32.load offset=4 - local.set $29 - local.get $1 + local.set $30 + local.get $0 i32.load offset=8 i32.const 2 i32.shr_u i32.const 1 i32.sub - local.set $0 + local.set $1 loop $for-loop|07 - local.get $0 + local.get $1 i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $21 - local.get $29 - local.get $0 + local.get $30 + local.get $1 i32.const 2 i32.shl i32.add f32.load + local.set $16 + i32.const 4 + global.set $~argumentsLength + local.get $22 + local.get $16 f32.add - local.set $21 - local.get $0 + local.set $22 + local.get $1 i32.const 1 i32.sub - local.set $0 + local.set $1 br $for-loop|07 end end - local.get $21 + local.get $22 f32.const 6 f32.ne br_if $folding-inner1 - local.get $1 + local.get $0 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Float64Array#constructor - local.tee $1 + local.tee $0 i32.const 0 f64.const 1 call $~lib/typedarray/Float64Array#__set - local.get $1 + local.get $0 i32.const 1 f64.const 2 call $~lib/typedarray/Float64Array#__set - local.get $1 + local.get $0 i32.const 2 f64.const 3 call $~lib/typedarray/Float64Array#__set f64.const 0 - local.set $22 - local.get $1 + local.set $23 + local.get $0 i32.load offset=4 - local.set $29 - local.get $1 + local.set $30 + local.get $0 i32.load offset=8 i32.const 3 i32.shr_u i32.const 1 i32.sub - local.set $0 + local.set $1 loop $for-loop|08 - local.get $0 + local.get $1 i32.const 0 i32.ge_s if - i32.const 4 - global.set $~argumentsLength - local.get $22 - local.get $29 - local.get $0 + local.get $30 + local.get $1 i32.const 3 i32.shl i32.add f64.load + local.set $21 + i32.const 4 + global.set $~argumentsLength + local.get $23 + local.get $21 f64.add - local.set $22 - local.get $0 + local.set $23 + local.get $1 i32.const 1 i32.sub - local.set $0 + local.set $1 br $for-loop|08 end end - local.get $22 + local.get $23 f64.const 6 f64.ne br_if $folding-inner1 - local.get $1 + local.get $0 call $~lib/rt/pure/__release i32.const 3 call $~lib/typedarray/Int8Array#constructor @@ -28466,34 +28532,35 @@ local.set $1 local.get $0 i32.load offset=8 - local.set $28 + local.set $29 local.get $0 i32.load offset=4 - local.set $25 + local.set $26 i32.const 12 i32.const 3 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $28 + local.set $30 + local.get $29 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $27 + local.set $28 loop $for-loop|09 local.get $1 - local.get $28 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $1 - local.get $27 + local.get $26 i32.add + i32.load8_s + local.set $27 + i32.const 3 + global.set $~argumentsLength local.get $1 - local.get $25 + local.get $28 i32.add - i32.load8_s - local.tee $26 - local.get $26 + local.get $27 + local.get $27 i32.mul i32.store8 local.get $1 @@ -28503,17 +28570,17 @@ br $for-loop|09 end end - local.get $29 - local.get $27 + local.get $30 + local.get $28 call $~lib/rt/pure/__retain i32.store - local.get $29 - local.get $27 + local.get $30 + local.get $28 i32.store offset=4 + local.get $30 local.get $29 - local.get $28 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -28555,34 +28622,35 @@ local.set $1 local.get $0 i32.load offset=8 - local.set $28 + local.set $29 local.get $0 i32.load offset=4 - local.set $25 + local.set $26 i32.const 12 i32.const 4 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $28 + local.set $30 + local.get $29 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $27 + local.set $28 loop $for-loop|010 local.get $1 - local.get $28 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $1 - local.get $27 + local.get $26 i32.add + i32.load8_u + local.set $27 + i32.const 3 + global.set $~argumentsLength local.get $1 - local.get $25 + local.get $28 i32.add - i32.load8_u - local.tee $26 - local.get $26 + local.get $27 + local.get $27 i32.mul i32.store8 local.get $1 @@ -28592,17 +28660,17 @@ br $for-loop|010 end end - local.get $29 - local.get $27 + local.get $30 + local.get $28 call $~lib/rt/pure/__retain i32.store - local.get $29 - local.get $27 + local.get $30 + local.get $28 i32.store offset=4 + local.get $30 local.get $29 - local.get $28 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -28644,34 +28712,35 @@ local.set $1 local.get $0 i32.load offset=8 - local.set $28 + local.set $29 local.get $0 i32.load offset=4 - local.set $25 + local.set $26 i32.const 12 i32.const 5 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $28 + local.set $30 + local.get $29 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $27 + local.set $28 loop $for-loop|011 local.get $1 - local.get $28 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $1 - local.get $27 + local.get $26 i32.add + i32.load8_u + local.set $27 + i32.const 3 + global.set $~argumentsLength local.get $1 - local.get $25 + local.get $28 i32.add - i32.load8_u - local.tee $26 - local.get $26 + local.get $27 + local.get $27 i32.mul i32.store8 local.get $1 @@ -28681,17 +28750,17 @@ br $for-loop|011 end end - local.get $29 - local.get $27 + local.get $30 + local.get $28 call $~lib/rt/pure/__retain i32.store - local.get $29 - local.get $27 + local.get $30 + local.get $28 i32.store offset=4 + local.get $30 local.get $29 - local.get $28 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -28735,43 +28804,42 @@ i32.load offset=8 i32.const 1 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $26 i32.const 12 i32.const 6 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 1 i32.shl - local.tee $26 + local.tee $25 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|012 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $26 local.get $1 i32.const 1 i32.shl local.tee $24 i32.add i32.load16_s - local.tee $23 - local.get $23 - i32.mul - local.set $23 + local.set $27 + i32.const 3 + global.set $~argumentsLength local.get $24 - local.get $28 + local.get $29 i32.add - local.get $23 + local.get $27 + local.get $27 + i32.mul i32.store16 local.get $1 i32.const 1 @@ -28780,17 +28848,17 @@ br $for-loop|012 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 - local.get $26 + local.get $30 + local.get $25 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -28834,43 +28902,42 @@ i32.load offset=8 i32.const 1 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $26 i32.const 12 i32.const 7 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 1 i32.shl - local.tee $26 + local.tee $25 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|013 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $26 local.get $1 i32.const 1 i32.shl local.tee $24 i32.add i32.load16_u - local.tee $23 - local.get $23 - i32.mul - local.set $23 + local.set $27 + i32.const 3 + global.set $~argumentsLength local.get $24 - local.get $28 + local.get $29 i32.add - local.get $23 + local.get $27 + local.get $27 + i32.mul i32.store16 local.get $1 i32.const 1 @@ -28879,17 +28946,17 @@ br $for-loop|013 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 - local.get $26 + local.get $30 + local.get $25 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -28933,43 +29000,42 @@ i32.load offset=8 i32.const 2 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $26 i32.const 12 i32.const 8 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 2 i32.shl - local.tee $26 + local.tee $25 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|014 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $26 local.get $1 i32.const 2 i32.shl local.tee $24 i32.add i32.load - local.tee $23 - local.get $23 - i32.mul - local.set $23 + local.set $27 + i32.const 3 + global.set $~argumentsLength local.get $24 - local.get $28 + local.get $29 i32.add - local.get $23 + local.get $27 + local.get $27 + i32.mul i32.store local.get $1 i32.const 1 @@ -28978,17 +29044,17 @@ br $for-loop|014 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 - local.get $26 + local.get $30 + local.get $25 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -29032,43 +29098,42 @@ i32.load offset=8 i32.const 2 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $26 i32.const 12 i32.const 9 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 2 i32.shl - local.tee $26 + local.tee $25 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|015 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $26 local.get $1 i32.const 2 i32.shl local.tee $24 i32.add i32.load - local.tee $23 - local.get $23 - i32.mul - local.set $23 + local.set $27 + i32.const 3 + global.set $~argumentsLength local.get $24 - local.get $28 + local.get $29 i32.add - local.get $23 + local.get $27 + local.get $27 + i32.mul i32.store local.get $1 i32.const 1 @@ -29077,17 +29142,17 @@ br $for-loop|015 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 - local.get $26 + local.get $30 + local.get $25 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -29131,43 +29196,42 @@ i32.load offset=8 i32.const 3 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $27 i32.const 12 i32.const 10 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 3 i32.shl local.tee $26 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|016 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $27 local.get $1 i32.const 3 i32.shl - local.tee $24 + local.tee $25 i32.add i64.load - local.tee $20 - local.get $20 - i64.mul local.set $20 - local.get $24 - local.get $28 + i32.const 3 + global.set $~argumentsLength + local.get $25 + local.get $29 i32.add local.get $20 + local.get $20 + i64.mul i64.store local.get $1 i32.const 1 @@ -29176,17 +29240,17 @@ br $for-loop|016 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 + local.get $30 local.get $26 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -29230,43 +29294,42 @@ i32.load offset=8 i32.const 3 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $27 i32.const 12 i32.const 11 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 3 i32.shl local.tee $26 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|017 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $27 local.get $1 i32.const 3 i32.shl - local.tee $24 + local.tee $25 i32.add i64.load - local.tee $20 - local.get $20 - i64.mul local.set $20 - local.get $24 - local.get $28 + i32.const 3 + global.set $~argumentsLength + local.get $25 + local.get $29 i32.add local.get $20 + local.get $20 + i64.mul i64.store local.get $1 i32.const 1 @@ -29275,17 +29338,17 @@ br $for-loop|017 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 + local.get $30 local.get $26 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -29329,43 +29392,42 @@ i32.load offset=8 i32.const 2 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $27 i32.const 12 i32.const 12 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 2 i32.shl local.tee $26 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|018 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $27 local.get $1 i32.const 2 i32.shl - local.tee $24 + local.tee $25 i32.add f32.load - local.tee $21 - local.get $21 - f32.mul - local.set $21 - local.get $24 - local.get $28 + local.set $22 + i32.const 3 + global.set $~argumentsLength + local.get $25 + local.get $29 i32.add - local.get $21 + local.get $22 + local.get $22 + f32.mul f32.store local.get $1 i32.const 1 @@ -29374,17 +29436,17 @@ br $for-loop|018 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 + local.get $30 local.get $26 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -29428,43 +29490,42 @@ i32.load offset=8 i32.const 3 i32.shr_u - local.set $27 + local.set $28 local.get $0 i32.load offset=4 - local.set $25 + local.set $27 i32.const 12 i32.const 13 call $~lib/rt/tlsf/__alloc - local.set $29 - local.get $27 + local.set $30 + local.get $28 i32.const 3 i32.shl local.tee $26 i32.const 0 call $~lib/rt/tlsf/__alloc - local.set $28 + local.set $29 loop $for-loop|019 local.get $1 - local.get $27 + local.get $28 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $25 + local.get $27 local.get $1 i32.const 3 i32.shl - local.tee $24 + local.tee $25 i32.add f64.load - local.tee $22 - local.get $22 - f64.mul - local.set $22 - local.get $24 - local.get $28 + local.set $23 + i32.const 3 + global.set $~argumentsLength + local.get $25 + local.get $29 i32.add - local.get $22 + local.get $23 + local.get $23 + f64.mul f64.store local.get $1 i32.const 1 @@ -29473,17 +29534,17 @@ br $for-loop|019 end end + local.get $30 local.get $29 - local.get $28 call $~lib/rt/pure/__retain i32.store + local.get $30 local.get $29 - local.get $28 i32.store offset=4 - local.get $29 + local.get $30 local.get $26 i32.store offset=8 - local.get $29 + local.get $30 call $~lib/rt/pure/__retain local.tee $1 i32.const 0 @@ -30416,21 +30477,21 @@ local.set $1 local.get $0 i32.load offset=4 - local.set $29 + local.set $30 local.get $0 i32.load offset=8 - local.set $28 + local.set $29 loop $for-loop|020 local.get $1 - local.get $28 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength local.get $1 - local.get $29 + local.get $30 i32.add i32.load8_s + i32.const 3 + global.set $~argumentsLength local.get $1 local.get $0 call $std/typedarray/testArrayForEach<~lib/typedarray/Int8Array,i8>~anonymous|0 @@ -30565,25 +30626,25 @@ local.set $1 local.get $0 i32.load offset=4 - local.set $29 + local.set $30 local.get $0 i32.load offset=8 i32.const 1 i32.shr_u - local.set $28 + local.set $29 loop $for-loop|021 local.get $1 - local.get $28 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $29 + local.get $30 local.get $1 i32.const 1 i32.shl i32.add i32.load16_s + i32.const 3 + global.set $~argumentsLength local.get $1 local.get $0 call $std/typedarray/testArrayForEach<~lib/typedarray/Int16Array,i16>~anonymous|0 @@ -30634,25 +30695,25 @@ local.set $1 local.get $0 i32.load offset=4 - local.set $29 + local.set $30 local.get $0 i32.load offset=8 i32.const 1 i32.shr_u - local.set $28 + local.set $29 loop $for-loop|022 local.get $1 - local.get $28 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $29 + local.get $30 local.get $1 i32.const 1 i32.shl i32.add i32.load16_u + i32.const 3 + global.set $~argumentsLength local.get $1 local.get $0 call $std/typedarray/testArrayForEach<~lib/typedarray/Int16Array,i16>~anonymous|0 @@ -30811,23 +30872,23 @@ global.set $std/typedarray/forEachCallCount i32.const 3 call $~lib/typedarray/Float32Array#constructor - local.tee $0 + local.tee $1 global.set $std/typedarray/forEachSelf - local.get $0 + local.get $1 i32.const 0 i32.const 2704 i32.const 0 call $~lib/array/Array#__get f32.convert_i32_s call $~lib/typedarray/Float32Array#__set - local.get $0 + local.get $1 i32.const 1 i32.const 2704 i32.const 1 call $~lib/array/Array#__get f32.convert_i32_s call $~lib/typedarray/Float32Array#__set - local.get $0 + local.get $1 i32.const 2 i32.const 2704 i32.const 2 @@ -30835,35 +30896,35 @@ f32.convert_i32_s call $~lib/typedarray/Float32Array#__set i32.const 0 - local.set $1 - local.get $0 + local.set $0 + local.get $1 i32.load offset=4 - local.set $29 - local.get $0 + local.set $30 + local.get $1 i32.load offset=8 i32.const 2 i32.shr_u - local.set $28 + local.set $29 loop $for-loop|023 - local.get $1 - local.get $28 + local.get $0 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $29 - local.get $1 + local.get $30 + local.get $0 i32.const 2 i32.shl i32.add f32.load - local.get $1 + i32.const 3 + global.set $~argumentsLength local.get $0 - call $std/typedarray/testArrayForEach<~lib/typedarray/Float32Array,f32>~anonymous|0 local.get $1 + call $std/typedarray/testArrayForEach<~lib/typedarray/Float32Array,f32>~anonymous|0 + local.get $0 i32.const 1 i32.add - local.set $1 + local.set $0 br $for-loop|023 end end @@ -30871,29 +30932,29 @@ i32.const 3 i32.ne br_if $folding-inner11 - local.get $0 + local.get $1 call $~lib/rt/pure/__release i32.const 0 global.set $std/typedarray/forEachCallCount i32.const 3 call $~lib/typedarray/Float64Array#constructor - local.tee $0 + local.tee $1 global.set $std/typedarray/forEachSelf - local.get $0 + local.get $1 i32.const 0 i32.const 2704 i32.const 0 call $~lib/array/Array#__get f64.convert_i32_s call $~lib/typedarray/Float64Array#__set - local.get $0 + local.get $1 i32.const 1 i32.const 2704 i32.const 1 call $~lib/array/Array#__get f64.convert_i32_s call $~lib/typedarray/Float64Array#__set - local.get $0 + local.get $1 i32.const 2 i32.const 2704 i32.const 2 @@ -30901,35 +30962,35 @@ f64.convert_i32_s call $~lib/typedarray/Float64Array#__set i32.const 0 - local.set $1 - local.get $0 + local.set $0 + local.get $1 i32.load offset=4 - local.set $29 - local.get $0 + local.set $30 + local.get $1 i32.load offset=8 i32.const 3 i32.shr_u - local.set $28 + local.set $29 loop $for-loop|024 - local.get $1 - local.get $28 + local.get $0 + local.get $29 i32.lt_s if - i32.const 3 - global.set $~argumentsLength - local.get $29 - local.get $1 + local.get $30 + local.get $0 i32.const 3 i32.shl i32.add f64.load - local.get $1 + i32.const 3 + global.set $~argumentsLength local.get $0 - call $std/typedarray/testArrayForEach<~lib/typedarray/Float64Array,f64>~anonymous|0 local.get $1 + call $std/typedarray/testArrayForEach<~lib/typedarray/Float64Array,f64>~anonymous|0 + local.get $0 i32.const 1 i32.add - local.set $1 + local.set $0 br $for-loop|024 end end @@ -30937,7 +30998,7 @@ i32.const 3 i32.ne br_if $folding-inner11 - local.get $0 + local.get $1 call $~lib/rt/pure/__release call $std/typedarray/testArrayReverse<~lib/typedarray/Int8Array,i8> call $std/typedarray/testArrayReverse<~lib/typedarray/Uint8Array,u8> @@ -30963,11 +31024,11 @@ call $std/typedarray/testArrayIndexOfAndLastIndexOf<~lib/typedarray/Float64Array,f64> i32.const 1 call $~lib/typedarray/Float64Array#constructor - local.tee $29 + local.tee $30 i32.const 0 f64.const nan:0x8000000000000 call $~lib/typedarray/Float64Array#__set - local.get $29 + local.get $30 f64.const nan:0x8000000000000 i32.const 0 call $~lib/typedarray/Float64Array#indexOf @@ -30982,61 +31043,61 @@ unreachable end i32.const 0 - local.set $1 - i32.const 0 local.set $0 + i32.const 0 + local.set $1 block $~lib/typedarray/INCLUDES<~lib/typedarray/Float64Array,f64>|inlined.0 - local.get $29 + local.get $30 i32.load offset=8 i32.const 3 i32.shr_u - local.tee $28 + local.tee $29 if (result i32) i32.const 0 - local.get $28 + local.get $29 i32.ge_s else i32.const 1 end br_if $~lib/typedarray/INCLUDES<~lib/typedarray/Float64Array,f64>|inlined.0 - local.get $29 + local.get $30 i32.load offset=4 - local.set $25 + local.set $27 loop $while-continue|0 - local.get $1 - local.get $28 + local.get $0 + local.get $29 i32.lt_s if - local.get $25 - local.get $1 + local.get $27 + local.get $0 i32.const 3 i32.shl i32.add f64.load - local.tee $22 + local.tee $23 f64.const nan:0x8000000000000 f64.eq if (result i32) i32.const 1 else - local.get $22 - local.get $22 + local.get $23 + local.get $23 f64.ne end if i32.const 1 - local.set $0 + local.set $1 br $~lib/typedarray/INCLUDES<~lib/typedarray/Float64Array,f64>|inlined.0 end - local.get $1 + local.get $0 i32.const 1 i32.add - local.set $1 + local.set $0 br $while-continue|0 end end end - local.get $0 + local.get $1 i32.const 0 i32.ne i32.const 1 @@ -31051,11 +31112,11 @@ end i32.const 1 call $~lib/typedarray/Float32Array#constructor - local.tee $0 + local.tee $29 i32.const 0 f32.const nan:0x400000 call $~lib/typedarray/Float32Array#__set - local.get $0 + local.get $29 f32.const nan:0x400000 i32.const 0 call $~lib/typedarray/Float32Array#indexOf @@ -31070,61 +31131,61 @@ unreachable end i32.const 0 - local.set $28 - i32.const 0 local.set $1 + i32.const 0 + local.set $0 block $~lib/typedarray/INCLUDES<~lib/typedarray/Float32Array,f32>|inlined.0 - local.get $0 + local.get $29 i32.load offset=8 i32.const 2 i32.shr_u - local.tee $27 + local.tee $28 if (result i32) i32.const 0 - local.get $27 + local.get $28 i32.ge_s else i32.const 1 end br_if $~lib/typedarray/INCLUDES<~lib/typedarray/Float32Array,f32>|inlined.0 - local.get $0 + local.get $29 i32.load offset=4 local.set $26 loop $while-continue|025 + local.get $1 local.get $28 - local.get $27 i32.lt_s if local.get $26 - local.get $28 + local.get $1 i32.const 2 i32.shl i32.add f32.load - local.tee $21 + local.tee $22 f32.const nan:0x400000 f32.eq if (result i32) i32.const 1 else - local.get $21 - local.get $21 + local.get $22 + local.get $22 f32.ne end if i32.const 1 - local.set $1 + local.set $0 br $~lib/typedarray/INCLUDES<~lib/typedarray/Float32Array,f32>|inlined.0 end - local.get $28 + local.get $1 i32.const 1 i32.add - local.set $28 + local.set $1 br $while-continue|025 end end end - local.get $1 + local.get $0 i32.const 0 i32.ne i32.const 1 @@ -31137,9 +31198,9 @@ call $~lib/builtins/abort unreachable end - local.get $29 + local.get $30 call $~lib/rt/pure/__release - local.get $0 + local.get $29 call $~lib/rt/pure/__release i32.const 5 call $~lib/typedarray/Int8Array#constructor @@ -31172,14 +31233,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Int8Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31214,14 +31275,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Uint8Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31256,14 +31317,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Uint8Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31298,14 +31359,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Int16Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31340,14 +31401,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Uint16Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31382,14 +31443,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Int32Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31424,14 +31485,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Uint32Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31466,14 +31527,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Int64Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31508,14 +31569,14 @@ br_if $folding-inner12 local.get $1 call $~lib/typedarray/Uint64Array#join - local.tee $29 + local.tee $30 i32.const 3008 call $~lib/string/String.__eq i32.eqz br_if $folding-inner13 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31550,14 +31611,14 @@ br_if $folding-inner14 local.get $1 call $~lib/typedarray/Float32Array#join - local.tee $29 + local.tee $30 i32.const 4176 call $~lib/string/String.__eq i32.eqz br_if $folding-inner15 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31592,14 +31653,14 @@ br_if $folding-inner14 local.get $1 call $~lib/typedarray/Float64Array#join - local.tee $29 + local.tee $30 i32.const 4176 call $~lib/string/String.__eq i32.eqz br_if $folding-inner15 local.get $0 call $~lib/rt/pure/__release - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release @@ -31611,7 +31672,7 @@ local.get $1 i32.const 0 call $~lib/typedarray/Uint8Array.wrap|trampoline - local.tee $29 + local.tee $30 i32.load offset=8 if i32.const 0 @@ -31632,7 +31693,7 @@ i32.const 2 call $~lib/typedarray/Uint8Array.wrap|trampoline local.set $1 - local.get $29 + local.get $30 call $~lib/rt/pure/__release local.get $1 i32.load offset=8 @@ -31675,49 +31736,49 @@ local.set $0 i32.const 3 call $~lib/typedarray/Float32Array#constructor - local.tee $29 + local.tee $30 i32.const 0 f32.const 400 call $~lib/typedarray/Float32Array#__set - local.get $29 + local.get $30 i32.const 1 f32.const nan:0x400000 call $~lib/typedarray/Float32Array#__set - local.get $29 + local.get $30 i32.const 2 f32.const inf call $~lib/typedarray/Float32Array#__set i32.const 4 call $~lib/typedarray/Int64Array#constructor - local.tee $28 + local.tee $29 i32.const 0 i64.const -10 call $~lib/typedarray/Int64Array#__set - local.get $28 + local.get $29 i32.const 1 i64.const 100 call $~lib/typedarray/Int64Array#__set - local.get $28 + local.get $29 i32.const 2 i64.const 10 call $~lib/typedarray/Int64Array#__set - local.get $28 + local.get $29 i32.const 3 i64.const 300 call $~lib/typedarray/Int64Array#__set i32.const 2 call $~lib/typedarray/Int32Array#constructor - local.tee $27 + local.tee $28 i32.const 0 i32.const 300 call $~lib/typedarray/Int32Array#__set - local.get $27 + local.get $28 i32.const 1 i32.const -1 call $~lib/typedarray/Int32Array#__set i32.const 0 local.set $1 - local.get $29 + local.get $30 i32.load offset=8 i32.const 2 i32.shr_u @@ -31732,37 +31793,37 @@ i32.const 1 i32.add local.set $26 - local.get $29 + local.get $30 i32.load offset=4 - local.set $24 - local.get $29 + local.set $25 + local.get $30 i32.load offset=8 i32.const 2 i32.shr_u - local.set $23 + local.set $24 loop $for-loop|026 local.get $1 - local.get $23 + local.get $24 i32.lt_s if local.get $1 local.get $26 i32.add - local.get $24 + local.get $25 local.get $1 i32.const 2 i32.shl i32.add f32.load - local.tee $21 - local.get $21 + local.tee $22 + local.get $22 f32.sub f32.const 0 f32.eq if (result i32) f32.const 0 f32.const 255 - local.get $21 + local.get $22 f32.min f32.max i32.trunc_f32_u @@ -31778,12 +31839,12 @@ end end local.get $0 - local.get $28 + local.get $29 i32.const 4 call $~lib/typedarray/Uint8ClampedArray#set<~lib/typedarray/Int64Array> i32.const 0 local.set $1 - local.get $27 + local.get $28 i32.load offset=8 i32.const 2 i32.shr_u @@ -31798,36 +31859,36 @@ i32.const 8 i32.add local.set $26 - local.get $27 + local.get $28 i32.load offset=4 - local.set $24 - local.get $27 + local.set $25 + local.get $28 i32.load offset=8 i32.const 2 i32.shr_u - local.set $23 + local.set $24 loop $for-loop|027 local.get $1 - local.get $23 + local.get $24 i32.lt_s if local.get $1 local.get $26 i32.add - local.get $24 + local.get $25 local.get $1 i32.const 2 i32.shl i32.add i32.load - local.tee $25 + local.tee $27 i32.const 31 i32.shr_s i32.const -1 i32.xor - local.get $25 + local.get $27 i32.const 255 - local.get $25 + local.get $27 i32.sub i32.const 31 i32.shr_s @@ -31848,7 +31909,7 @@ i32.const 8352 call $~lib/rt/__allocArray call $~lib/rt/pure/__retain - local.tee $24 + local.tee $25 call $std/typedarray/valuesEqual<~lib/typedarray/Uint8ClampedArray> i32.const 4 call $~lib/typedarray/Uint32Array#constructor @@ -31870,19 +31931,19 @@ call $~lib/typedarray/Uint32Array#__set i32.const 4 call $~lib/typedarray/Int16Array#constructor - local.tee $25 + local.tee $27 i32.const 0 i32.const -10 call $~lib/typedarray/Int16Array#__set - local.get $25 + local.get $27 i32.const 1 i32.const 100 call $~lib/typedarray/Int16Array#__set - local.get $25 + local.get $27 i32.const 2 i32.const 10 call $~lib/typedarray/Int16Array#__set - local.get $25 + local.get $27 i32.const 3 i32.const 300 call $~lib/typedarray/Int16Array#__set @@ -31898,7 +31959,7 @@ br_if $folding-inner16 local.get $0 i32.load offset=4 - local.set $23 + local.set $24 local.get $1 i32.load offset=4 local.set $19 @@ -31912,7 +31973,7 @@ local.get $18 i32.lt_s if - local.get $23 + local.get $24 local.get $26 i32.add i32.const 255 @@ -31936,7 +31997,7 @@ end end local.get $0 - local.get $25 + local.get $27 i32.const 5 call $~lib/typedarray/Uint8ClampedArray#set<~lib/typedarray/Int16Array> local.get $0 @@ -31950,17 +32011,17 @@ call $std/typedarray/valuesEqual<~lib/typedarray/Uint8ClampedArray> local.get $0 call $~lib/rt/pure/__release + local.get $30 + call $~lib/rt/pure/__release local.get $29 call $~lib/rt/pure/__release local.get $28 call $~lib/rt/pure/__release - local.get $27 - call $~lib/rt/pure/__release - local.get $24 + local.get $25 call $~lib/rt/pure/__release local.get $1 call $~lib/rt/pure/__release - local.get $25 + local.get $27 call $~lib/rt/pure/__release local.get $26 call $~lib/rt/pure/__release diff --git a/tests/compiler/std/typedarray.untouched.wat b/tests/compiler/std/typedarray.untouched.wat index 54fe156031..4118c89339 100644 --- a/tests/compiler/std/typedarray.untouched.wat +++ b/tests/compiler/std/typedarray.untouched.wat @@ -3051,10 +3051,10 @@ i32.add f64.load local.set $8 - i32.const 2 - global.set $~argumentsLength local.get $5 local.get $8 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -3255,10 +3255,10 @@ i32.add f64.load local.set $10 - i32.const 2 - global.set $~argumentsLength local.get $9 local.get $10 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -3386,10 +3386,10 @@ i32.add f64.load local.set $9 - i32.const 2 - global.set $~argumentsLength local.get $10 local.get $9 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -3494,10 +3494,10 @@ local.get $5 f64.load local.set $7 - i32.const 2 - global.set $~argumentsLength local.get $6 local.get $7 + i32.const 2 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_f64_=>_i32) i32.const 0 @@ -5779,8 +5779,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -5790,6 +5788,8 @@ i32.load8_s local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -5917,8 +5917,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -5928,6 +5926,8 @@ i32.load8_u local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6033,8 +6033,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6044,6 +6042,8 @@ i32.load8_u local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6173,8 +6173,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6184,6 +6182,8 @@ i32.load16_s local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6315,8 +6315,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6326,6 +6324,8 @@ i32.load16_u local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6431,8 +6431,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6442,6 +6440,8 @@ i32.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6569,8 +6569,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6580,6 +6578,8 @@ i32.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -6708,8 +6708,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6719,6 +6717,8 @@ i64.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i64_i64_i32_i32_=>_i64) local.set $3 @@ -6847,8 +6847,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6858,6 +6856,8 @@ i64.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i64_i64_i32_i32_=>_i64) local.set $3 @@ -6986,8 +6986,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -6997,6 +6995,8 @@ f32.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $f32_f32_i32_i32_=>_f32) local.set $3 @@ -7101,8 +7101,6 @@ local.set $9 local.get $9 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7112,6 +7110,8 @@ f64.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $f64_f64_i32_i32_=>_f64) local.set $3 @@ -7214,8 +7214,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7225,6 +7223,8 @@ i32.load8_s local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -7331,8 +7331,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7342,6 +7340,8 @@ i32.load8_u local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -7446,8 +7446,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7457,6 +7455,8 @@ i32.load8_u local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -7561,8 +7561,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7572,6 +7570,8 @@ i32.load16_s local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -7678,8 +7678,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7689,6 +7687,8 @@ i32.load16_u local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -7793,8 +7793,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7804,6 +7802,8 @@ i32.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -7906,8 +7906,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -7917,6 +7915,8 @@ i32.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i32_i32_i32_i32_=>_i32) local.set $3 @@ -8020,8 +8020,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -8031,6 +8029,8 @@ i64.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i64_i64_i32_i32_=>_i64) local.set $3 @@ -8134,8 +8134,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -8145,6 +8143,8 @@ i64.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $i64_i64_i32_i32_=>_i64) local.set $3 @@ -8248,8 +8248,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -8259,6 +8257,8 @@ f32.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $f32_f32_i32_i32_=>_f32) local.set $3 @@ -8362,8 +8362,6 @@ local.set $8 local.get $8 if - i32.const 4 - global.set $~argumentsLength local.get $3 local.get $6 local.get $7 @@ -8373,6 +8371,8 @@ f64.load local.get $7 local.get $5 + i32.const 4 + global.set $~argumentsLength local.get $4 call_indirect (type $f64_f64_i32_i32_=>_f64) local.set $3 @@ -8493,8 +8493,6 @@ i32.const 0 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 0 @@ -8503,6 +8501,8 @@ i32.load8_s local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) i32.store8 @@ -8665,8 +8665,6 @@ i32.const 0 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 0 @@ -8675,6 +8673,8 @@ i32.load8_u local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) i32.store8 @@ -8856,8 +8856,6 @@ i32.const 0 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 0 @@ -8866,6 +8864,8 @@ i32.load8_u local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) i32.store8 @@ -9028,8 +9028,6 @@ i32.const 1 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 1 @@ -9038,6 +9036,8 @@ i32.load16_s local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) i32.store16 @@ -9223,8 +9223,6 @@ i32.const 1 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 1 @@ -9233,6 +9231,8 @@ i32.load16_u local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) i32.store16 @@ -9418,8 +9418,6 @@ i32.const 2 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 2 @@ -9428,6 +9426,8 @@ i32.load local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) i32.store @@ -9590,8 +9590,6 @@ i32.const 2 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 2 @@ -9600,6 +9598,8 @@ i32.load local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) i32.store @@ -9785,8 +9785,6 @@ i32.const 3 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 3 @@ -9795,6 +9793,8 @@ i64.load local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i64) i64.store @@ -9980,8 +9980,6 @@ i32.const 3 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 3 @@ -9990,6 +9988,8 @@ i64.load local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i64) i64.store @@ -10175,8 +10175,6 @@ i32.const 2 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 2 @@ -10185,6 +10183,8 @@ f32.load local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_i32_i32_=>_f32) f32.store @@ -10370,8 +10370,6 @@ i32.const 3 i32.shl i32.add - i32.const 3 - global.set $~argumentsLength local.get $5 local.get $9 i32.const 3 @@ -10380,6 +10378,8 @@ f64.load local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_i32_i32_=>_f64) f64.store @@ -10678,11 +10678,11 @@ i32.add i32.load8_s local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -10906,11 +10906,11 @@ i32.add i32.load8_u local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -11134,11 +11134,11 @@ i32.add i32.load8_u local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -11364,11 +11364,11 @@ i32.add i32.load16_s local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -11592,11 +11592,11 @@ i32.add i32.load16_u local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -11818,11 +11818,11 @@ i32.add i32.load local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -12044,11 +12044,11 @@ i32.add i32.load local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -12270,11 +12270,11 @@ i32.add i64.load local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -12496,11 +12496,11 @@ i32.add i64.load local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -12722,11 +12722,11 @@ i32.add f32.load local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_i32_i32_=>_i32) if @@ -12948,11 +12948,11 @@ i32.add f64.load local.set $11 - i32.const 3 - global.set $~argumentsLength local.get $11 local.get $9 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_i32_i32_=>_i32) if @@ -13156,8 +13156,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -13166,6 +13164,8 @@ i32.load8_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -13310,8 +13310,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -13320,6 +13318,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -13462,8 +13462,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -13472,6 +13470,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -13616,8 +13616,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -13626,6 +13624,8 @@ i32.load16_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -13770,8 +13770,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -13780,6 +13778,8 @@ i32.load16_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -13920,8 +13920,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -13930,6 +13928,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -14068,8 +14068,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -14078,6 +14076,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -14216,8 +14216,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -14226,6 +14224,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -14364,8 +14364,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -14374,6 +14372,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -14512,8 +14512,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -14522,6 +14520,8 @@ f32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_i32_i32_=>_i32) if @@ -14660,8 +14660,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -14670,6 +14668,8 @@ f64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_i32_i32_=>_i32) if @@ -14812,8 +14812,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -14822,6 +14820,8 @@ i32.load8_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -14967,8 +14967,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -14977,6 +14975,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -15120,8 +15120,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -15130,6 +15128,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -15275,8 +15275,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -15285,6 +15283,8 @@ i32.load16_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -15430,8 +15430,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -15440,6 +15438,8 @@ i32.load16_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -15581,8 +15581,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -15591,6 +15589,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -15730,8 +15730,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -15740,6 +15738,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -15879,8 +15879,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -15889,6 +15887,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -16028,8 +16028,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -16038,6 +16036,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -16177,8 +16177,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -16187,6 +16185,8 @@ f32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_i32_i32_=>_i32) if @@ -16326,8 +16326,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -16336,6 +16334,8 @@ f64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_i32_i32_=>_i32) if @@ -16482,8 +16482,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -16492,6 +16490,8 @@ i32.load8_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -16641,8 +16641,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -16651,6 +16649,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -16798,8 +16798,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -16808,6 +16806,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -16957,8 +16957,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -16967,6 +16965,8 @@ i32.load16_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -17116,8 +17116,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -17126,6 +17124,8 @@ i32.load16_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -17271,8 +17271,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -17281,6 +17279,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -17424,8 +17424,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -17434,6 +17432,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_i32) if @@ -17577,8 +17577,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -17587,6 +17585,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -17730,8 +17730,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -17740,6 +17738,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_i32) if @@ -18131,8 +18131,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -18141,6 +18139,8 @@ f32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_i32_i32_=>_i32) if @@ -18538,8 +18538,6 @@ local.get $7 if block $for-continue|0 - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -18548,6 +18546,8 @@ f64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_i32_i32_=>_i32) if @@ -18733,8 +18733,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -18743,6 +18741,8 @@ i32.load8_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_none) local.get $5 @@ -18901,8 +18901,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -18911,6 +18909,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_none) local.get $5 @@ -19063,8 +19063,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 0 @@ -19073,6 +19071,8 @@ i32.load8_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_none) local.get $5 @@ -19229,8 +19229,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -19239,6 +19237,8 @@ i32.load16_s local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_none) local.get $5 @@ -19397,8 +19397,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 1 @@ -19407,6 +19405,8 @@ i32.load16_u local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_none) local.get $5 @@ -19555,8 +19555,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -19565,6 +19563,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_none) local.get $5 @@ -19707,8 +19707,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -19717,6 +19715,8 @@ i32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i32_i32_i32_=>_none) local.get $5 @@ -19860,8 +19860,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -19870,6 +19868,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_none) local.get $5 @@ -20016,8 +20016,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -20026,6 +20024,8 @@ i64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $i64_i32_i32_=>_none) local.get $5 @@ -20172,8 +20172,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 2 @@ -20182,6 +20180,8 @@ f32.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f32_i32_i32_=>_none) local.get $5 @@ -20328,8 +20328,6 @@ local.set $7 local.get $7 if - i32.const 3 - global.set $~argumentsLength local.get $4 local.get $5 i32.const 3 @@ -20338,6 +20336,8 @@ f64.load local.get $5 local.get $3 + i32.const 3 + global.set $~argumentsLength local.get $2 call_indirect (type $f64_i32_i32_=>_none) local.get $5 @@ -24318,10 +24318,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int8Array#lastIndexOf|trampoline i32.const 0 @@ -24335,10 +24335,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int8Array#lastIndexOf|trampoline i32.const -1 @@ -24352,10 +24352,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int8Array#lastIndexOf|trampoline i32.const -1 @@ -24369,10 +24369,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int8Array#lastIndexOf|trampoline i32.const 3 @@ -25001,10 +25001,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline i32.const 0 @@ -25018,10 +25018,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline i32.const -1 @@ -25035,10 +25035,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline i32.const -1 @@ -25052,10 +25052,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline i32.const 3 @@ -25684,10 +25684,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline i32.const 0 @@ -25701,10 +25701,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline i32.const -1 @@ -25718,10 +25718,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline i32.const -1 @@ -25735,10 +25735,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline i32.const 3 @@ -26373,10 +26373,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int16Array#lastIndexOf|trampoline i32.const 0 @@ -26390,10 +26390,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int16Array#lastIndexOf|trampoline i32.const -1 @@ -26407,10 +26407,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int16Array#lastIndexOf|trampoline i32.const -1 @@ -26424,10 +26424,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int16Array#lastIndexOf|trampoline i32.const 3 @@ -27056,10 +27056,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline i32.const 0 @@ -27073,10 +27073,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline i32.const -1 @@ -27090,10 +27090,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline i32.const -1 @@ -27107,10 +27107,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline i32.const 3 @@ -27733,10 +27733,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int32Array#lastIndexOf|trampoline i32.const 0 @@ -27750,10 +27750,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int32Array#lastIndexOf|trampoline i32.const -1 @@ -27767,10 +27767,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int32Array#lastIndexOf|trampoline i32.const -1 @@ -27784,10 +27784,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int32Array#lastIndexOf|trampoline i32.const 3 @@ -28410,10 +28410,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline i32.const 0 @@ -28427,10 +28427,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline i32.const -1 @@ -28444,10 +28444,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline i32.const -1 @@ -28461,10 +28461,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline i32.const 3 @@ -29088,10 +29088,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int64Array#lastIndexOf|trampoline i32.const 0 @@ -29105,10 +29105,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int64Array#lastIndexOf|trampoline i32.const -1 @@ -29122,10 +29122,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int64Array#lastIndexOf|trampoline i32.const -1 @@ -29139,10 +29139,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int64Array#lastIndexOf|trampoline i32.const 3 @@ -29766,10 +29766,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline i32.const 0 @@ -29783,10 +29783,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline i32.const -1 @@ -29800,10 +29800,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline i32.const -1 @@ -29817,10 +29817,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 i64.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline i32.const 3 @@ -30444,10 +30444,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float32Array#lastIndexOf|trampoline i32.const 0 @@ -30461,10 +30461,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f32.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float32Array#lastIndexOf|trampoline i32.const -1 @@ -30478,10 +30478,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f32.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float32Array#lastIndexOf|trampoline i32.const -1 @@ -30495,10 +30495,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f32.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float32Array#lastIndexOf|trampoline i32.const 3 @@ -31122,10 +31122,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f64.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float64Array#lastIndexOf|trampoline i32.const 0 @@ -31139,10 +31139,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f64.const 11 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float64Array#lastIndexOf|trampoline i32.const -1 @@ -31156,10 +31156,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f64.const -1 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float64Array#lastIndexOf|trampoline i32.const -1 @@ -31173,10 +31173,10 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - global.set $~argumentsLength local.get $3 f64.const 3 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float64Array#lastIndexOf|trampoline i32.const 3 @@ -37435,10 +37435,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int8Array.wrap|trampoline local.set $5 @@ -37547,10 +37547,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8Array.wrap|trampoline local.set $5 @@ -37803,10 +37803,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8ClampedArray.wrap|trampoline local.set $5 @@ -38061,10 +38061,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int16Array.wrap|trampoline local.set $5 @@ -38317,10 +38317,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint16Array.wrap|trampoline local.set $5 @@ -38571,10 +38571,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int32Array.wrap|trampoline local.set $5 @@ -38825,10 +38825,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint32Array.wrap|trampoline local.set $5 @@ -39080,10 +39080,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Int64Array.wrap|trampoline local.set $5 @@ -39335,10 +39335,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint64Array.wrap|trampoline local.set $5 @@ -39590,10 +39590,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float32Array.wrap|trampoline local.set $5 @@ -39845,10 +39845,10 @@ local.set $6 i32.const 0 local.set $7 - i32.const 1 - global.set $~argumentsLength local.get $6 i32.const 0 + i32.const 1 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Float64Array.wrap|trampoline local.set $5 @@ -50851,9 +50851,9 @@ call $~lib/builtins/abort unreachable end + local.get $0 i32.const 0 global.set $~argumentsLength - local.get $0 i32.const 0 call $~lib/typedarray/Float64Array#sort|trampoline call $~lib/rt/pure/__release @@ -52598,10 +52598,10 @@ i32.const 0 call $~lib/arraybuffer/ArrayBuffer#constructor local.set $21 - i32.const 2 - global.set $~argumentsLength local.get $21 i32.const 0 + i32.const 2 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8Array.wrap|trampoline local.set $22 @@ -52626,10 +52626,10 @@ call $~lib/rt/pure/__release local.get $25 local.set $21 - i32.const 2 - global.set $~argumentsLength local.get $21 i32.const 2 + i32.const 2 + global.set $~argumentsLength i32.const 0 call $~lib/typedarray/Uint8Array.wrap|trampoline local.set $3 From 2ae59f418623f3570408c1c07f3cf9a65e59d2d5 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 8 Apr 2020 15:02:40 +0200 Subject: [PATCH 11/24] add a reusable SwitchBuilder --- src/compiler.ts | 91 ++-- src/module.ts | 90 ++++ .../compiler/class-overloading.optimized.wat | 330 ++++++++++-- tests/compiler/class-overloading.ts | 64 ++- .../compiler/class-overloading.untouched.wat | 508 ++++++++++++++++-- 5 files changed, 917 insertions(+), 166 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 71542407e7..4508e93dc3 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -51,9 +51,9 @@ import { getFunctionParams, getFunctionResults, createType, - Relooper, getSideEffects, - SideEffects + SideEffects, + SwitchBuilder } from "./module"; import { @@ -618,27 +618,23 @@ export class Compiler extends DiagnosticEmitter { var usizeType = this.options.usizeType; var nativeSizeType = usizeType.toNativeType(); var parameterTypes = instance.signature.parameterTypes; + var returnType = instance.signature.returnType; var numParameters = parameterTypes.length; var tempIndex = 1 + parameterTypes.length; // incl. `this` - // Use a relooper to map this's class id to the matching overload. Note - // that we do not emit a switch here since ids may be distant, and we - // instead rely on the optimizer to figure this out based on opt levels. - var relooper = Relooper.create(this.module); - var entry = relooper.addBlock( - module.local_set(tempIndex, - module.load(4, false, - module.binary( - nativeSizeType == NativeType.I64 - ? BinaryOp.SubI64 - : BinaryOp.SubI32, - module.local_get(0, nativeSizeType), - nativeSizeType == NativeType.I64 - ? module.i64(8) // rtId offset = -8 - : module.i32(8) - ), - NativeType.I32 - ) + // Switch over this's rtId and map it to the respective overload + var builder = new SwitchBuilder(this.module, + module.load(4, false, + module.binary( + nativeSizeType == NativeType.I64 + ? BinaryOp.SubI64 + : BinaryOp.SubI32, + module.local_get(0, nativeSizeType), + nativeSizeType == NativeType.I64 + ? module.i64(8) // rtId offset = -8 + : module.i32(8) + ), + NativeType.I32 ) ); @@ -693,32 +689,27 @@ export class Compiler extends DiagnosticEmitter { // Safe to prepend since paramExprs are local.get's stmts.push(module.global_set(BuiltinNames.argumentsLength, module.i32(numParameters))); } - stmts.push( - module.call(calledName, paramExprs, nativeReturnType) - ); - // Include each extendee inheriting this overload, i.e. each extendee - // before there's another actual overload. - let cond = module.binary(BinaryOp.EqI32, - module.local_get(tempIndex, NativeType.I32), - module.i32(classInstance.id) - ); + if (returnType == Type.void) { + stmts.push( + module.call(calledName, paramExprs, nativeReturnType) + ); + stmts.push( + module.return() + ); + } else { + stmts.push( + module.return( + module.call(calledName, paramExprs, nativeReturnType) + ) + ); + } + builder.addCase(classInstance.id, stmts); + // Also alias each extendee inheriting this exact overload let extendees = classInstance.getAllExtendees(instance.prototype.name); for (let _values = Set_values(extendees), a = 0, b = _values.length; a < b; ++a) { let extendee = _values[a]; - cond = module.binary(BinaryOp.OrI32, - cond, - module.binary(BinaryOp.EqI32, - module.local_get(tempIndex, NativeType.I32), - module.i32(extendee.id) - ) - ); + builder.addCase(extendee.id, stmts); } - relooper.addBranch(entry, - relooper.addBlock( - module.flatten(stmts, nativeReturnType) - ), - cond - ); } } } @@ -727,23 +718,18 @@ export class Compiler extends DiagnosticEmitter { // abstract or part of an interface. Note that doing so will not catch an // invalid id, but can reduce code size significantly since we also don't // have to add branches for extendees inheriting the original function. + var body: ExpressionRef; if (instance.prototype.bodyNode) { let paramExprs = new Array(numParameters); paramExprs[0] = module.local_get(0, nativeSizeType); // this for (let i = 0, k = parameterTypes.length; i < k; ++i) { paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); } - let block = relooper.addBlock( - module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()) - ); - relooper.addBranch(entry, block); + body = module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()); // Otherwise trap } else { - let block = relooper.addBlock( - module.unreachable() - ); - relooper.addBranch(entry, block); + body = module.unreachable(); } // Make the virtual wrapper @@ -751,7 +737,10 @@ export class Compiler extends DiagnosticEmitter { instance.virtualRef = module.addFunction( instance.internalName + "|virtual", getFunctionParams(originalRef), getFunctionResults(originalRef), [ NativeType.I32 ], - relooper.renderAndDispose(entry, tempIndex) + module.block(null, [ + builder.render(tempIndex), + body + ], returnType.toNativeType()) ); } diff --git a/src/module.ts b/src/module.ts index 3ee80f72da..68bb00c6a5 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1940,6 +1940,96 @@ export class Relooper { } } +/** Builds a switch using a sequence of `br_if`s. */ +export class SwitchBuilder { + // This is useful because Binaryen understands sequences of `br_if`s and + // knows how to make a `br_table` from such a sequence if switched over + // values are considered dense enough, respectively a size-efficient sequence + // of `if`s if not, depending on optimization levels. + + private module: Module; + private condition: ExpressionRef; + private values: i32[] = new Array(); + private indexes: i32[] = new Array(); + private cases: ExpressionRef[][] = new Array(); + private defaultIndex: i32 = -1; + + /** Creates a new builder using the specified i32 condition. */ + constructor(module: Module, condition: ExpressionRef) { + this.module = module; + this.condition = condition; + } + + /** Links a case to the specified branch. */ + addCase(value: i32, code: ExpressionRef[]): void { + var cases = this.cases; + var index = cases.indexOf(code); + if (index < 0) { + index = cases.length; + cases.push(code); + } + this.values.push(value); + this.indexes.push(index); + } + + /** Links the default branch. */ + addDefault(code: ExpressionRef[]): void { + assert(this.defaultIndex == -1); + var cases = this.cases; + this.defaultIndex = cases.length; + cases.push(code); + } + + /** Renders the switch to a block. */ + render(localIndex: i32, labelPostfix: string = ""): ExpressionRef { + var module = this.module; + var cases = this.cases; + var numCases = cases.length; + if (!numCases) { + return module.drop(this.condition); + } + var values = this.values; + var numValues = values.length; + var indexes = this.indexes; + var entry = new Array(1 + numValues + 1); + var labels = new Array(numCases); + for (let i = 0; i < numCases; ++i) { + labels[i] = "case" + i.toString() + labelPostfix; + } + entry[0] = module.local_set(localIndex, this.condition); + for (let i = 0; i < numValues; ++i) { + let index = indexes[i]; + entry[1 + i] = module.br(labels[index], + module.binary(BinaryOp.EqI32, + module.local_get(localIndex, NativeType.I32), + module.i32(values[i]) + ) + ); + } + var defaultIndex = this.defaultIndex; + var defaultLabel = "default" + labelPostfix; + entry[1 + numValues] = module.br( + ~defaultIndex + ? labels[defaultIndex] + : defaultLabel + ); + var current = module.block(labels[0], entry); + for (let i = 1; i < numCases; ++i) { + let block = cases[i - 1]; + block.unshift(current); + current = module.block(labels[i], block); + } + var lastCase = cases[numCases - 1]; + lastCase.unshift(current); + return module.block( + ~defaultIndex + ? null + : defaultLabel, + lastCase + ); + } +} + export enum SideEffects { None = 0 /* _BinaryenSideEffectNone */, Branches = 1 /* _BinaryenSideEffectBranches */, diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index c347d55fd6..b6d2e093da 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -1,15 +1,23 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) + (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 $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (memory $0 1) - (data (i32.const 1024) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s") - (global $class-overloading/itWorks (mut i32) (i32.const 0)) + (data (i32.const 1028) "\01\00\00\00\01") + (data (i32.const 1040) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00A") + (data (i32.const 1072) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00B") + (data (i32.const 1104) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s") + (data (i32.const 1168) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00C") + (data (i32.const 1200) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00F") + (global $class-overloading/which (mut i32) (i32.const 1040)) (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) - (global $class-overloading/baz (mut i32) (i32.const 0)) - (global $class-overloading/foo (mut i32) (i32.const 0)) + (global $class-overloading/a (mut i32) (i32.const 0)) + (global $class-overloading/c (mut i32) (i32.const 0)) (export "memory" (memory $0)) (start $~start) (func $~lib/rt/stub/__alloc (; 1 ;) (param $0 i32) (result i32) @@ -78,7 +86,7 @@ i32.store offset=12 local.get $3 ) - (func $class-overloading/Bar#constructor (; 2 ;) (param $0 i32) (result i32) + (func $class-overloading/B#constructor (; 2 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -89,62 +97,300 @@ local.get $0 i32.eqz if (result i32) - i32.const 5 + i32.const 3 call $~lib/rt/stub/__alloc else local.get $0 end ) - (func $~start (; 3 ;) - (local $0 i32) - i32.const 1088 - global.set $~lib/rt/stub/startOffset - i32.const 1088 - global.set $~lib/rt/stub/offset - i32.const 3 - call $~lib/rt/stub/__alloc - call $class-overloading/Bar#constructor - global.set $class-overloading/baz + (func $~lib/string/String#get:length (; 3 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 16 + i32.sub + i32.load offset=12 i32.const 1 - global.set $class-overloading/itWorks + i32.shr_u + ) + (func $~lib/util/string/compareImpl (; 4 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + local.get $0 + i32.const 7 + i32.and + local.get $1 + i32.const 7 + i32.and + i32.or + i32.eqz i32.const 0 - call $class-overloading/Bar#constructor - global.set $class-overloading/foo - global.get $class-overloading/foo - i32.const 8 - i32.sub - i32.load - local.tee $0 + local.get $2 i32.const 4 - i32.eq + i32.ge_u + select if + loop $do-continue|0 + local.get $0 + i64.load + local.get $1 + i64.load + i64.eq + if + local.get $0 + i32.const 8 + i32.add + local.set $0 + local.get $1 + i32.const 8 + i32.add + local.set $1 + local.get $2 + i32.const 4 + i32.sub + local.tee $2 + i32.const 4 + i32.ge_u + br_if $do-continue|0 + end + end + end + loop $while-continue|1 + local.get $2 + local.tee $3 i32.const 1 - global.set $class-overloading/itWorks - else - local.get $0 - i32.const 3 - i32.eq + i32.sub + local.set $2 + local.get $3 if - i32.const 1 - global.set $class-overloading/itWorks - else - i32.const 0 - i32.const 1040 - i32.const 5 - i32.const 5 - call $~lib/builtins/abort - unreachable + local.get $1 + i32.load16_u + local.tee $3 + local.get $0 + i32.load16_u + local.tee $4 + i32.ne + if + local.get $4 + local.get $3 + i32.sub + return + end + local.get $0 + i32.const 2 + i32.add + local.set $0 + local.get $1 + i32.const 2 + i32.add + local.set $1 + br $while-continue|1 end end - global.get $class-overloading/itWorks + i32.const 0 + ) + (func $~lib/string/String.__eq (; 5 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + local.get $0 + local.get $1 + i32.eq + if + i32.const 1 + return + end + block $folding-inner0 + local.get $1 + i32.eqz + i32.const 1 + local.get $0 + select + br_if $folding-inner0 + local.get $0 + call $~lib/string/String#get:length + local.tee $2 + local.get $1 + call $~lib/string/String#get:length + i32.ne + br_if $folding-inner0 + local.get $0 + local.get $1 + local.get $2 + call $~lib/util/string/compareImpl + i32.eqz + return + end + i32.const 0 + ) + (func $class-overloading/C#a (; 6 ;) + i32.const 1088 + global.set $class-overloading/which + i32.const 1088 + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 23 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + i32.const 1184 + global.set $class-overloading/which + ) + (func $class-overloading/D#constructor (; 7 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 6 + call $~lib/rt/stub/__alloc + local.set $0 + end + local.get $0 + call $class-overloading/B#constructor + ) + (func $class-overloading/E#constructor (; 8 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 7 + call $~lib/rt/stub/__alloc + local.set $0 + end + local.get $0 + call $class-overloading/D#constructor + ) + (func $start:class-overloading (; 9 ;) + i32.const 1232 + global.set $~lib/rt/stub/startOffset + i32.const 1232 + global.set $~lib/rt/stub/offset + i32.const 0 + call $class-overloading/B#constructor + global.set $class-overloading/a + global.get $class-overloading/a + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 18 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 5 + call $~lib/rt/stub/__alloc + call $class-overloading/B#constructor + global.set $class-overloading/c + call $class-overloading/C#a + global.get $class-overloading/which + i32.const 1184 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 31 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 0 + call $class-overloading/D#constructor + global.set $class-overloading/a + global.get $class-overloading/a + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq i32.eqz if i32.const 0 - i32.const 1040 - i32.const 26 + i32.const 1120 + i32.const 40 i32.const 1 call $~lib/builtins/abort unreachable end + i32.const 0 + call $class-overloading/E#constructor + global.set $class-overloading/a + global.get $class-overloading/a + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 49 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 8 + call $~lib/rt/stub/__alloc + call $class-overloading/E#constructor + global.set $class-overloading/a + global.get $class-overloading/a + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 1216 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 60 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + ) + (func $~start (; 10 ;) + call $start:class-overloading + ) + (func $class-overloading/A#a|virtual (; 11 ;) (param $0 i32) + block $default + block $case2 + block $case1 + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.tee $0 + i32.const 4 + i32.eq + local.get $0 + i32.const 6 + i32.eq + i32.or + br_if $case0 + block $tablify|0 + local.get $0 + i32.const 5 + i32.sub + br_table $case1 $tablify|0 $case0 $case2 $tablify|0 + end + br $default + end + i32.const 1088 + global.set $class-overloading/which + return + end + call $class-overloading/C#a + return + end + i32.const 1216 + global.set $class-overloading/which + return + end + i32.const 1056 + global.set $class-overloading/which ) ) diff --git a/tests/compiler/class-overloading.ts b/tests/compiler/class-overloading.ts index f92f9d0425..0bc20ed137 100644 --- a/tests/compiler/class-overloading.ts +++ b/tests/compiler/class-overloading.ts @@ -1,26 +1,60 @@ -var itWorks = false; +var which: string = ""; -class Foo { - a(a: T): void { // virtual, called - assert(false); +class A { + a(a: T): void { // virtual + which = "A"; } } -class Bar extends Foo { - a(a: T): void { // virtual, what becomes called - itWorks = true; +class B extends A { + a(a: T): void { // virtual + overload + which = "B"; } } -class Baz extends Bar { - a(a: T): void { // not virtual - super.a(a); // calls non-virtual Bar#a +// Should call the overload +var a: A = new B(); +a.a(1); +assert(which == "B"); + +class C extends B { + a(a: T): void { // overload + super.a(a); + assert(which == "B"); + which = "C"; } } -var baz: Baz = new Baz(); -baz.a(1); +// Should call non-virtual super +var c = new C(); +c.a(1); +assert(which == "C"); + +class D extends B { + // inherits B's +} + +// Should call inherited overload +a = new D(); +a.a(1); +assert(which == "B"); + +class E extends D { + // inherits B's +} + +// Should still call inherited overload +a = new E(); +a.a(1); +assert(which == "B"); + +class F extends E { + a(a: T): void { // overload + which = "F"; + } +} -var foo: Foo = new Bar(); -foo.a(1); -assert(itWorks); +// Should no longer call inherited overload +a = new F(); +a.a(1); +assert(which == "F"); diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index f77967447f..8a7b4fdce4 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -1,20 +1,27 @@ (module - (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) (type $none_=>_none (func)) (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 $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (memory $0 1) - (data (i32.const 16) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s\00") + (data (i32.const 16) "\00\00\00\00\01\00\00\00\01\00\00\00\00\00\00\00") + (data (i32.const 32) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00A\00") + (data (i32.const 64) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00B\00") + (data (i32.const 96) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s\00") + (data (i32.const 160) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00C\00") + (data (i32.const 192) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00F\00") (table $0 1 funcref) - (global $class-overloading/itWorks (mut i32) (i32.const 0)) + (global $class-overloading/which (mut i32) (i32.const 32)) (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) - (global $class-overloading/baz (mut i32) (i32.const 0)) - (global $class-overloading/foo (mut i32) (i32.const 0)) - (global $~lib/heap/__heap_base i32 (i32.const 72)) + (global $class-overloading/a (mut i32) (i32.const 0)) + (global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0)) + (global $class-overloading/c (mut i32) (i32.const 0)) + (global $~lib/heap/__heap_base i32 (i32.const 212)) (export "memory" (memory $0)) (start $~start) (func $~lib/rt/stub/maybeGrowMemory (; 1 ;) (param $0 i32) @@ -127,19 +134,19 @@ (func $~lib/rt/stub/__retain (; 3 ;) (param $0 i32) (result i32) local.get $0 ) - (func $class-overloading/Foo#constructor (; 4 ;) (param $0 i32) (result i32) + (func $class-overloading/A#constructor (; 4 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if i32.const 0 - i32.const 5 + i32.const 3 call $~lib/rt/stub/__alloc call $~lib/rt/stub/__retain local.set $0 end local.get $0 ) - (func $class-overloading/Bar#constructor (; 5 ;) (param $0 i32) (result i32) + (func $class-overloading/B#constructor (; 5 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -150,47 +157,320 @@ local.set $0 end local.get $0 - call $class-overloading/Foo#constructor + call $class-overloading/A#constructor + local.set $0 + local.get $0 + ) + (func $~lib/rt/stub/__release (; 6 ;) (param $0 i32) + nop + ) + (func $class-overloading/A#a (; 7 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 48 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $~lib/string/String#get:length (; 8 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 16 + i32.sub + i32.load offset=12 + i32.const 1 + i32.shr_u + ) + (func $~lib/util/string/compareImpl (; 9 ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + local.get $0 + call $~lib/rt/stub/__retain local.set $0 + local.get $2 + call $~lib/rt/stub/__retain + local.set $2 local.get $0 + local.get $1 + i32.const 1 + i32.shl + i32.add + local.set $5 + local.get $2 + local.get $3 + i32.const 1 + i32.shl + i32.add + local.set $6 + local.get $4 + i32.const 4 + i32.ge_u + if (result i32) + local.get $5 + i32.const 7 + i32.and + local.get $6 + i32.const 7 + i32.and + i32.or + i32.eqz + else + i32.const 0 + end + if + block $do-break|0 + loop $do-continue|0 + local.get $5 + i64.load + local.get $6 + i64.load + i64.ne + if + br $do-break|0 + end + local.get $5 + i32.const 8 + i32.add + local.set $5 + local.get $6 + i32.const 8 + i32.add + local.set $6 + local.get $4 + i32.const 4 + i32.sub + local.set $4 + local.get $4 + i32.const 4 + i32.ge_u + local.set $7 + local.get $7 + br_if $do-continue|0 + end + end + end + loop $while-continue|1 + local.get $4 + local.tee $7 + i32.const 1 + i32.sub + local.set $4 + local.get $7 + local.set $7 + local.get $7 + if + local.get $5 + i32.load16_u + local.set $8 + local.get $6 + i32.load16_u + local.set $9 + local.get $8 + local.get $9 + i32.ne + if + local.get $8 + local.get $9 + i32.sub + local.set $10 + local.get $0 + call $~lib/rt/stub/__release + local.get $2 + call $~lib/rt/stub/__release + local.get $10 + return + end + local.get $5 + i32.const 2 + i32.add + local.set $5 + local.get $6 + i32.const 2 + i32.add + local.set $6 + br $while-continue|1 + end + end + i32.const 0 + local.set $7 + local.get $0 + call $~lib/rt/stub/__release + local.get $2 + call $~lib/rt/stub/__release + local.get $7 + ) + (func $~lib/string/String.__eq (; 10 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + local.get $0 + call $~lib/rt/stub/__retain + local.set $0 + local.get $1 + call $~lib/rt/stub/__retain + local.set $1 + local.get $0 + local.get $1 + i32.eq + if + i32.const 1 + local.set $2 + local.get $0 + call $~lib/rt/stub/__release + local.get $1 + call $~lib/rt/stub/__release + local.get $2 + return + end + local.get $0 + i32.const 0 + i32.eq + if (result i32) + i32.const 1 + else + local.get $1 + i32.const 0 + i32.eq + end + if + i32.const 0 + local.set $2 + local.get $0 + call $~lib/rt/stub/__release + local.get $1 + call $~lib/rt/stub/__release + local.get $2 + return + end + local.get $0 + call $~lib/string/String#get:length + local.set $3 + local.get $3 + local.get $1 + call $~lib/string/String#get:length + i32.ne + if + i32.const 0 + local.set $2 + local.get $0 + call $~lib/rt/stub/__release + local.get $1 + call $~lib/rt/stub/__release + local.get $2 + return + end + local.get $0 + i32.const 0 + local.get $1 + i32.const 0 + local.get $3 + call $~lib/util/string/compareImpl + i32.eqz + local.set $2 + local.get $0 + call $~lib/rt/stub/__release + local.get $1 + call $~lib/rt/stub/__release + local.get $2 ) - (func $class-overloading/Baz#constructor (; 6 ;) (param $0 i32) (result i32) + (func $class-overloading/C#constructor (; 11 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if i32.const 0 - i32.const 3 + i32.const 5 call $~lib/rt/stub/__alloc call $~lib/rt/stub/__retain local.set $0 end local.get $0 - call $class-overloading/Bar#constructor + call $class-overloading/B#constructor local.set $0 local.get $0 ) - (func $class-overloading/Bar#a (; 7 ;) (param $0 i32) (param $1 i32) - i32.const 1 - global.set $class-overloading/itWorks + (func $class-overloading/B#a (; 12 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 80 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which ) - (func $class-overloading/Baz#a (; 8 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/C#a (; 13 ;) (param $0 i32) (param $1 i32) + (local $2 i32) local.get $0 local.get $1 - call $class-overloading/Bar#a - ) - (func $class-overloading/Foo#a (; 9 ;) (param $0 i32) (param $1 i32) - i32.const 0 + call $class-overloading/B#a + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq i32.eqz if i32.const 0 - i32.const 32 - i32.const 5 + i32.const 112 + i32.const 23 i32.const 5 call $~lib/builtins/abort unreachable end + i32.const 176 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/D#constructor (; 14 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 6 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + call $class-overloading/B#constructor + local.set $0 + local.get $0 ) - (func $start:class-overloading (; 10 ;) + (func $class-overloading/E#constructor (; 15 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 7 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + call $class-overloading/D#constructor + local.set $0 + local.get $0 + ) + (func $class-overloading/F#constructor (; 16 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 8 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + call $class-overloading/E#constructor + local.set $0 + local.get $0 + ) + (func $start:class-overloading (; 17 ;) + (local $0 i32) global.get $~lib/heap/__heap_base i32.const 15 i32.add @@ -202,58 +482,170 @@ global.get $~lib/rt/stub/startOffset global.set $~lib/rt/stub/offset i32.const 0 - call $class-overloading/Baz#constructor - global.set $class-overloading/baz - global.get $class-overloading/baz + call $class-overloading/B#constructor + global.set $class-overloading/a + global.get $class-overloading/a i32.const 1 - call $class-overloading/Baz#a + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 18 + i32.const 1 + call $~lib/builtins/abort + unreachable + end i32.const 0 - call $class-overloading/Bar#constructor - global.set $class-overloading/foo - global.get $class-overloading/foo + call $class-overloading/C#constructor + global.set $class-overloading/c + global.get $class-overloading/c i32.const 1 - call $class-overloading/Foo#a|virtual - global.get $class-overloading/itWorks + call $class-overloading/C#a + global.get $class-overloading/which + i32.const 176 + call $~lib/string/String.__eq i32.eqz if i32.const 0 - i32.const 32 - i32.const 26 + i32.const 112 + i32.const 31 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 0 + call $class-overloading/D#constructor + local.set $0 + global.get $class-overloading/a + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/a + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 40 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 0 + call $class-overloading/E#constructor + local.set $0 + global.get $class-overloading/a + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/a + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 49 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 0 + call $class-overloading/F#constructor + local.set $0 + global.get $class-overloading/a + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/a + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#a|virtual + global.get $class-overloading/which + i32.const 208 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 60 i32.const 1 call $~lib/builtins/abort unreachable end ) - (func $~start (; 11 ;) + (func $~start (; 18 ;) call $start:class-overloading ) - (func $class-overloading/Foo#a|virtual (; 12 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/F#a (; 19 ;) (param $0 i32) (param $1 i32) (local $2 i32) - local.get $0 - i32.const 8 - i32.sub - i32.load + i32.const 208 local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release local.get $2 - i32.const 4 - i32.eq - if - local.get $0 - local.get $1 - call $class-overloading/Bar#a - else - local.get $2 - i32.const 3 - i32.eq - if - local.get $0 - local.get $1 - call $class-overloading/Baz#a - else + global.set $class-overloading/which + ) + (func $class-overloading/A#a|virtual (; 20 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + block $default + block $case2 + block $case1 + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $2 + local.get $2 + i32.const 4 + i32.eq + br_if $case0 + local.get $2 + i32.const 6 + i32.eq + br_if $case0 + local.get $2 + i32.const 7 + i32.eq + br_if $case0 + local.get $2 + i32.const 5 + i32.eq + br_if $case1 + local.get $2 + i32.const 8 + i32.eq + br_if $case2 + br $default + end + local.get $0 + local.get $1 + call $class-overloading/B#a + return + end local.get $0 local.get $1 - call $class-overloading/Foo#a + call $class-overloading/C#a + return end + local.get $0 + local.get $1 + call $class-overloading/F#a + return end + local.get $0 + local.get $1 + call $class-overloading/A#a ) ) From 103ce20aeafb9b843f7696e8b0695cb56fdbe491 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 8 Apr 2020 20:03:13 +0200 Subject: [PATCH 12/24] link interfaces --- src/diagnosticMessages.generated.ts | 2 ++ src/diagnosticMessages.json | 1 + src/program.ts | 40 ++++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 4ae6cb7139..8ae5487e62 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -130,6 +130,7 @@ export enum DiagnosticCode { Multiple_constructor_implementations_are_not_allowed = 2392, Duplicate_function_implementation = 2393, Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local = 2395, + A_class_can_only_implement_an_interface = 2422, 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, @@ -285,6 +286,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2392: return "Multiple constructor implementations are not allowed."; case 2393: return "Duplicate function implementation."; case 2395: return "Individual declarations in merged declaration '{0}' must be all exported or all local."; + case 2422: return "A class can only implement an interface."; 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}'."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index dfc8722c4e..3329ac81c6 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -126,6 +126,7 @@ "Multiple constructor implementations are not allowed.": 2392, "Duplicate function implementation.": 2393, "Individual declarations in merged declaration '{0}' must be all exported or all local.": 2395, + "A class can only implement an interface.": 2422, "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, diff --git a/src/program.ts b/src/program.ts index 715e8ea191..066d3fd01d 100644 --- a/src/program.ts +++ b/src/program.ts @@ -981,7 +981,7 @@ export class Program extends DiagnosticEmitter { this.f32ArrayPrototype = this.require(CommonNames.Float32Array, ElementKind.CLASS_PROTOTYPE); this.f64ArrayPrototype = this.require(CommonNames.Float64Array, ElementKind.CLASS_PROTOTYPE); - // resolve base prototypes of derived classes + // resolve base prototypes of extended classes var resolver = this.resolver; for (let i = 0, k = queuedExtends.length; i < k; ++i) { let thisPrototype = queuedExtends[i]; @@ -1014,12 +1014,42 @@ export class Program extends DiagnosticEmitter { } } - // check for virtual overloads in derived classes + // resolve interface prototypes of implemented interfaces + for (let i = 0, k = queuedImplements.length; i < k; ++i) { + let thisPrototype = queuedImplements[i]; + let implementsNodes = assert(thisPrototype.implementsNodes); // must be present if in queuedImplements + for (let j = 0, l = implementsNodes.length; j < l; ++j) { + let implementsNode = implementsNodes[j]; + let interfaceElement = resolver.resolveTypeName(implementsNode.name, thisPrototype.parent); + if (!interfaceElement) continue; + if (interfaceElement.kind == ElementKind.INTERFACE_PROTOTYPE) { + let interfacePrototype = interfaceElement; + let interfacePrototypes = thisPrototype.interfacePrototypes; + if (!interfacePrototypes) thisPrototype.interfacePrototypes = interfacePrototypes = new Array(); + interfacePrototypes.push(interfacePrototype); + } else { + this.error( + DiagnosticCode.A_class_can_only_implement_an_interface, + implementsNode.range + ); + } + } + } + + // check for virtual overloads in extended classes and implemented interfaces for (let i = 0, k = queuedExtends.length; i < k; ++i) { let thisPrototype = queuedExtends[i]; this.markVirtuals(thisPrototype, assert(thisPrototype.basePrototype)); } - // TODO: interfaces via queuedImplements + for (let i = 0, k = queuedImplements.length; i < k; ++i) { + let thisPrototype = queuedImplements[i]; + let interfacePrototypes = thisPrototype.interfacePrototypes; + if (interfacePrototypes) { + for (let j = 0, l = interfacePrototypes.length; j < l; ++j) { + this.markVirtuals(thisPrototype, interfacePrototypes[j]); + } + } + } // set up global aliases { @@ -3433,7 +3463,9 @@ export class ClassPrototype extends DeclaredElement { /** Instance member prototypes. */ instanceMembers: Map | null = null; /** Base class prototype, if applicable. */ - basePrototype: ClassPrototype | null = null; // set in Program#initialize + basePrototype: ClassPrototype | null = null; + /** Interface prototypes, if applicable. */ + interfacePrototypes: InterfacePrototype[] | null = null; /** Constructor prototype. */ constructorPrototype: FunctionPrototype | null = null; /** Operator overload prototypes. */ From 62703dc972c4f6dcbdfef19fc42ac848b5b53364 Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 9 Apr 2020 00:28:00 +0200 Subject: [PATCH 13/24] handle interfaces --- src/compiler.ts | 4 +- src/diagnosticMessages.generated.ts | 2 + src/diagnosticMessages.json | 1 + src/parser.ts | 5 + src/program.ts | 205 +++++++++++++----- src/resolver.ts | 70 +++++- .../compiler/class-overloading.optimized.wat | 35 ++- tests/compiler/class-overloading.ts | 14 ++ .../compiler/class-overloading.untouched.wat | 76 ++++++- 9 files changed, 344 insertions(+), 68 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 4508e93dc3..37ad618b78 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1482,8 +1482,8 @@ export class Compiler extends DiagnosticEmitter { ); funcRef = module.getFunction(instance.internalName); - // abstract function - } else if (instance.is(CommonFlags.ABSTRACT)) { + // abstract or interface function + } else if (instance.is(CommonFlags.ABSTRACT) || instance.parent.kind == ElementKind.INTERFACE) { funcRef = module.addFunction( instance.internalName, signature.nativeParams, diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 8ae5487e62..95536348bc 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -108,6 +108,7 @@ export enum DiagnosticCode { Duplicate_identifier_0 = 2300, Cannot_find_name_0 = 2304, Module_0_has_no_exported_member_1 = 2305, + An_interface_can_only_extend_an_interface = 2312, Generic_type_0_requires_1_type_argument_s = 2314, Type_0_is_not_generic = 2315, Type_0_is_not_assignable_to_type_1 = 2322, @@ -264,6 +265,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2300: return "Duplicate identifier '{0}'."; case 2304: return "Cannot find name '{0}'."; case 2305: return "Module '{0}' has no exported member '{1}'."; + case 2312: return "An interface can only extend an interface."; case 2314: return "Generic type '{0}' requires {1} type argument(s)."; case 2315: return "Type '{0}' is not generic."; case 2322: return "Type '{0}' is not assignable to type '{1}'."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 3329ac81c6..41a46fbf87 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -104,6 +104,7 @@ "Duplicate identifier '{0}'.": 2300, "Cannot find name '{0}'.": 2304, "Module '{0}' has no exported member '{1}'.": 2305, + "An interface can only extend an interface.": 2312, "Generic type '{0}' requires {1} type argument(s).": 2314, "Type '{0}' is not generic.": 2315, "Type '{0}' is not assignable to type '{1}'.": 2322, diff --git a/src/parser.ts b/src/parser.ts index 0c0ac7d9c0..c2dc46bc2b 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -2126,6 +2126,11 @@ export class Parser extends DiagnosticEmitter { DiagnosticCode.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, tn.range(), name.text ); // recoverable + } else if (isInterface) { + this.error( + DiagnosticCode._0_expected, + tn.range(), ";" + ); // recoverable } body = this.parseBlockStatement(tn, false); if (!body) return null; diff --git a/src/program.ts b/src/program.ts index 066d3fd01d..d0fd480a80 100644 --- a/src/program.ts +++ b/src/program.ts @@ -110,7 +110,8 @@ import { TypeDeclaration, VariableDeclaration, VariableLikeDeclarationStatement, - VariableStatement + VariableStatement, + ParameterKind } from "./ast"; import { @@ -816,7 +817,7 @@ export class Program extends DiagnosticEmitter { break; } case NodeKind.INTERFACEDECLARATION: { - this.initializeInterface(statement, file); + this.initializeInterface(statement, file, queuedExtends); break; } case NodeKind.NAMESPACEDECLARATION: { @@ -981,40 +982,51 @@ export class Program extends DiagnosticEmitter { this.f32ArrayPrototype = this.require(CommonNames.Float32Array, ElementKind.CLASS_PROTOTYPE); this.f64ArrayPrototype = this.require(CommonNames.Float64Array, ElementKind.CLASS_PROTOTYPE); - // resolve base prototypes of extended classes + // resolve prototypes of extended classes or interfaces var resolver = this.resolver; for (let i = 0, k = queuedExtends.length; i < k; ++i) { let thisPrototype = queuedExtends[i]; let extendsNode = assert(thisPrototype.extendsNode); // must be present if in queuedExtends - let baseElement = resolver.resolveTypeName(extendsNode.name, thisPrototype.parent); // reports + let baseElement = resolver.resolveTypeName(extendsNode.name, thisPrototype.parent); if (!baseElement) continue; - if (baseElement.kind == ElementKind.CLASS_PROTOTYPE) { - let basePrototype = baseElement; - if (basePrototype.hasDecorator(DecoratorFlags.SEALED)) { + if (thisPrototype.kind == ElementKind.CLASS_PROTOTYPE) { + if (baseElement.kind == ElementKind.CLASS_PROTOTYPE) { + let basePrototype = baseElement; + if (basePrototype.hasDecorator(DecoratorFlags.SEALED)) { + this.error( + DiagnosticCode.Class_0_is_sealed_and_cannot_be_extended, + extendsNode.range, basePrototype.identifierNode.text + ); + } + if ( + basePrototype.hasDecorator(DecoratorFlags.UNMANAGED) != + thisPrototype.hasDecorator(DecoratorFlags.UNMANAGED) + ) { + this.error( + DiagnosticCode.Unmanaged_classes_cannot_extend_managed_classes_and_vice_versa, + Range.join(thisPrototype.identifierNode.range, extendsNode.range) + ); + } + thisPrototype.basePrototype = basePrototype; + } else { this.error( - DiagnosticCode.Class_0_is_sealed_and_cannot_be_extended, - extendsNode.range, basePrototype.identifierNode.text + DiagnosticCode.A_class_may_only_extend_another_class, + extendsNode.range ); } - if ( - basePrototype.hasDecorator(DecoratorFlags.UNMANAGED) != - thisPrototype.hasDecorator(DecoratorFlags.UNMANAGED) - ) { + } else if (thisPrototype.kind == ElementKind.INTERFACE_PROTOTYPE) { + if (baseElement.kind == ElementKind.INTERFACE_PROTOTYPE) { + thisPrototype.basePrototype = baseElement; + } else { this.error( - DiagnosticCode.Unmanaged_classes_cannot_extend_managed_classes_and_vice_versa, - Range.join(thisPrototype.identifierNode.range, extendsNode.range) + DiagnosticCode.An_interface_can_only_extend_an_interface, + extendsNode.range ); } - thisPrototype.basePrototype = basePrototype; - } else { - this.error( - DiagnosticCode.A_class_may_only_extend_another_class, - extendsNode.range - ); } } - // resolve interface prototypes of implemented interfaces + // resolve prototypes of implemented interfaces for (let i = 0, k = queuedImplements.length; i < k; ++i) { let thisPrototype = queuedImplements[i]; let implementsNodes = assert(thisPrototype.implementsNodes); // must be present if in queuedImplements @@ -1039,12 +1051,21 @@ export class Program extends DiagnosticEmitter { // check for virtual overloads in extended classes and implemented interfaces for (let i = 0, k = queuedExtends.length; i < k; ++i) { let thisPrototype = queuedExtends[i]; - this.markVirtuals(thisPrototype, assert(thisPrototype.basePrototype)); + let basePrototype = thisPrototype.basePrototype; + if (basePrototype) { + this.markVirtuals(thisPrototype, basePrototype); + } } for (let i = 0, k = queuedImplements.length; i < k; ++i) { let thisPrototype = queuedImplements[i]; + let basePrototype = thisPrototype.basePrototype; let interfacePrototypes = thisPrototype.interfacePrototypes; + if (basePrototype) { + assert(!interfacePrototypes); + this.markVirtuals(thisPrototype, basePrototype); + } if (interfacePrototypes) { + assert(!basePrototype); for (let j = 0, l = interfacePrototypes.length; j < l; ++j) { this.markVirtuals(thisPrototype, interfacePrototypes[j]); } @@ -1488,12 +1509,13 @@ export class Program extends DiagnosticEmitter { ); if (!parent.add(name, element)) return null; + // remember classes that implement interfaces var implementsTypes = declaration.implementsTypes; if (implementsTypes) { let numImplementsTypes = implementsTypes.length; - // cannot implement interfaces when unmanaged - if (element.hasDecorator(DecoratorFlags.UNMANAGED)) { - if (numImplementsTypes) { + if (numImplementsTypes) { + // cannot implement interfaces when unmanaged + if (element.hasDecorator(DecoratorFlags.UNMANAGED)) { this.error( DiagnosticCode.Unmanaged_classes_cannot_implement_interfaces, Range.join( @@ -1501,18 +1523,12 @@ export class Program extends DiagnosticEmitter { implementsTypes[numImplementsTypes - 1].range ) ); + } else { + queuedImplements.push(element); } - } else if (numImplementsTypes) { - // remember classes that implement interfaces - for (let i = 0; i < numImplementsTypes; ++i) { - this.warning( - DiagnosticCode.Not_implemented, - implementsTypes[i].range - ); - } - queuedImplements.push(element); } } + // remember classes that extend another class if (declaration.extendsType) queuedExtends.push(element); @@ -1911,7 +1927,7 @@ export class Program extends DiagnosticEmitter { break; } case NodeKind.INTERFACEDECLARATION: { - element = this.initializeInterface(declaration, parent); + element = this.initializeInterface(declaration, parent, queuedExtends); break; } case NodeKind.NAMESPACEDECLARATION: { @@ -2048,7 +2064,9 @@ export class Program extends DiagnosticEmitter { /** The declaration to initialize. */ declaration: InterfaceDeclaration, /** Parent element, usually a file or namespace. */ - parent: Element + parent: Element, + /** So far queued `extends` clauses. */ + queuedExtends: ClassPrototype[], ): InterfacePrototype | null { var name = declaration.name.text; var element = new InterfacePrototype( @@ -2060,12 +2078,16 @@ export class Program extends DiagnosticEmitter { ) ); if (!parent.add(name, element)) return null; + + // remember interfaces that extend another interface + if (declaration.extendsType) queuedExtends.push(element); + var memberDeclarations = declaration.members; for (let i = 0, k = memberDeclarations.length; i < k; ++i) { let memberDeclaration = memberDeclarations[i]; switch (memberDeclaration.kind) { case NodeKind.FIELDDECLARATION: { - this.initializeField(memberDeclaration, element); + this.initializeFieldAsProperty(memberDeclaration, element); break; } case NodeKind.METHODDECLARATION: { @@ -2083,6 +2105,63 @@ export class Program extends DiagnosticEmitter { return element; } + /** Initializes a field of an interface, as a property. */ + private initializeFieldAsProperty( + /** Field declaration. */ + declaration: FieldDeclaration, + /** Parent interface. */ + parent: InterfacePrototype + ): void { + var typeNode = declaration.type; + if (!typeNode) typeNode = Node.createOmittedType(declaration.name.range.atEnd); + this.initializeProperty( + Node.createMethodDeclaration( + declaration.name, + null, + Node.createFunctionType( + [], + typeNode, + null, + false, + declaration.range + ), + null, + declaration.decorators, + declaration.flags | CommonFlags.GET, + declaration.range + ), + parent + ); + if (!declaration.is(CommonFlags.READONLY)) { + this.initializeProperty( + Node.createMethodDeclaration( + declaration.name, + null, + Node.createFunctionType( + [ + Node.createParameter( + declaration.name, + typeNode, + null, + ParameterKind.DEFAULT, + declaration.name.range + ) + ], + Node.createOmittedType(declaration.name.range.atEnd), + null, + false, + declaration.range + ), + null, + declaration.decorators, + declaration.flags | CommonFlags.SET, + declaration.range + ), + parent + ); + } + } + /** Initializes a namespace. */ private initializeNamespace( /** The declaration to initialize. */ @@ -2120,7 +2199,7 @@ export class Program extends DiagnosticEmitter { break; } case NodeKind.INTERFACEDECLARATION: { - this.initializeInterface(member, original); + this.initializeInterface(member, original, queuedExtends); break; } case NodeKind.NAMESPACEDECLARATION: { @@ -3601,6 +3680,8 @@ export class Class extends TypedElement { typeArguments: Type[] | null; /** Base class, if applicable. */ base: Class | null = null; + /** Implemented interfaces, if applicable. */ + interfaces: Set | null = null; /** Contextual type arguments for fields and methods. */ contextualTypeArguments: Map | null = null; /** Current member memory offset. */ @@ -3620,7 +3701,9 @@ export class Class extends TypedElement { /** Wrapped type, if a wrapper for a basic type. */ wrappedType: Type | null = null; /** Classes directly extending this class. */ - extendees: Set = new Set(); + extendees: Set | null = null; + /** Classes implementing this interface. */ + implementers: Set | null = null; /** Gets the unique runtime id of this class. */ get id(): u32 { @@ -3702,7 +3785,9 @@ export class Class extends TypedElement { setBase(base: Class): void { assert(!this.base); this.base = base; - base.extendees.add(this); + var extendees = base.extendees; + if (!extendees) base.extendees = extendees = new Set(); + extendees.add(this); // Inherit contextual type arguments from base class var inheritedTypeArguments = base.contextualTypeArguments; @@ -3722,11 +3807,25 @@ export class Class extends TypedElement { } } + /** Adds an interface. */ + addInterface(iface: Interface): void { + var interfaces = this.interfaces; + if (!interfaces) this.interfaces = interfaces = new Set(); + interfaces.add(iface); + var implementers = iface.implementers; + if (!implementers) iface.implementers = implementers = new Set(); + implementers.add(this); + } + /** Tests if a value of this class type is assignable to a target of the specified class type. */ isAssignableTo(target: Class): bool { var current: Class | null = this; do { if (current == target) return true; + if (target.kind == ElementKind.INTERFACE) { + let interfaces = current.interfaces; + if (interfaces !== null && interfaces.has(target)) return true; + } current = current.base; } while (current); return false; @@ -3971,21 +4070,24 @@ export class Class extends TypedElement { /** Gets all extendees of this class (that do not have the specified instance member). */ getAllExtendees(exceptIfMember: string | null = null, out: Set = new Set()): Set { - for (let _values = Set_values(this.extendees), i = 0, k = _values.length; i < k; ++i) { - let extendee = _values[i]; - if (exceptIfMember) { - let instanceMembers = extendee.prototype.instanceMembers; - if (instanceMembers !== null && instanceMembers.has(exceptIfMember)) continue; + var extendees = this.extendees; + if (extendees) { + for (let _values = Set_values(extendees), i = 0, k = _values.length; i < k; ++i) { + let extendee = _values[i]; + if (exceptIfMember) { + let instanceMembers = extendee.prototype.instanceMembers; + if (instanceMembers !== null && instanceMembers.has(exceptIfMember)) continue; + } + out.add(extendee); + extendee.getAllExtendees(exceptIfMember, out); } - out.add(extendee); - extendee.getAllExtendees(exceptIfMember, out); } return out; } } /** A yet unresolved interface. */ -export class InterfacePrototype extends ClassPrototype { // FIXME +export class InterfacePrototype extends ClassPrototype { /** Constructs a new interface prototype. */ constructor( @@ -4009,9 +4111,12 @@ export class Interface extends Class { // FIXME /** Constructs a new interface. */ constructor( + /** Name incl. type parameters, i.e. `Foo`. */ nameInclTypeParameters: string, + /** The respective class prototype. */ prototype: InterfacePrototype, - typeArguments: Type[] = [] + /** Concrete type arguments, if any. */ + typeArguments: Type[] | null = null, ) { super( nameInclTypeParameters, diff --git a/src/resolver.ts b/src/resolver.ts index 0219226dca..4c1d8c19eb 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -23,6 +23,7 @@ import { Element, Class, ClassPrototype, + Interface, Function, FunctionPrototype, VariableLikeElement, @@ -35,7 +36,8 @@ import { TypedElement, FunctionTarget, IndexSignature, - isTypedElement + isTypedElement, + InterfacePrototype } from "./program"; import { @@ -243,8 +245,11 @@ export class Resolver extends DiagnosticEmitter { return Type.i32; } - // Handle classes - if (element.kind == ElementKind.CLASS_PROTOTYPE) { + // Handle classes and interfaces + if ( + element.kind == ElementKind.CLASS_PROTOTYPE || + element.kind == ElementKind.INTERFACE_PROTOTYPE + ) { let instance = this.resolveClassInclTypeArguments( element, typeArgumentNodes, @@ -1408,7 +1413,9 @@ export class Resolver extends DiagnosticEmitter { // Look up the member within switch (target.kind) { case ElementKind.CLASS_PROTOTYPE: - case ElementKind.CLASS: { + case ElementKind.INTERFACE_PROTOTYPE: + case ElementKind.CLASS: + case ElementKind.INTERFACE: { do { let members = target.members; if (members !== null && members.has(propertyName)) { @@ -1417,7 +1424,10 @@ export class Resolver extends DiagnosticEmitter { return assert(members.get(propertyName)); // instance FIELD, static GLOBAL, FUNCTION_PROTOTYPE... } // traverse inherited static members on the base prototype if target is a class prototype - if (target.kind == ElementKind.CLASS_PROTOTYPE) { + if ( + target.kind == ElementKind.CLASS_PROTOTYPE || + target.kind == ElementKind.INTERFACE_PROTOTYPE + ) { let classPrototype = target; let basePrototype = classPrototype.basePrototype; if (basePrototype) { @@ -1426,7 +1436,10 @@ export class Resolver extends DiagnosticEmitter { break; } // traverse inherited instance members on the base class if target is a class instance - } else if (target.kind == ElementKind.CLASS) { + } else if ( + target.kind == ElementKind.CLASS || + target.kind == ElementKind.INTERFACE + ) { let classInstance = target; let baseInstance = classInstance.base; if (baseInstance) { @@ -2646,7 +2659,7 @@ export class Resolver extends DiagnosticEmitter { // Instance method prototypes are pre-bound to their concrete class as their parent if (prototype.is(CommonFlags.INSTANCE)) { - assert(actualParent.kind == ElementKind.CLASS); + assert(actualParent.kind == ElementKind.CLASS || actualParent.kind == ElementKind.INTERFACE); classInstance = actualParent; // check if this exact concrete class and function combination is known already @@ -2881,7 +2894,11 @@ export class Resolver extends DiagnosticEmitter { // Otherwise create var nameInclTypeParamters = prototype.name; if (instanceKey.length) nameInclTypeParamters += "<" + instanceKey + ">"; - instance = new Class(nameInclTypeParamters, prototype, typeArguments); + if (prototype.kind == ElementKind.INTERFACE_PROTOTYPE) { + instance = new Interface(nameInclTypeParamters, prototype, typeArguments); + } else { + instance = new Class(nameInclTypeParamters, prototype, typeArguments); + } prototype.setResolvedInstance(instanceKey, instance); var pendingClasses = this.resolveClassPending; pendingClasses.push(instance); @@ -2936,6 +2953,43 @@ export class Resolver extends DiagnosticEmitter { if (pendingClasses.includes(base)) return instance; } + // Resolve interfaces if applicable + var interfacePrototypes = prototype.interfacePrototypes; + if (interfacePrototypes) { + let anyPending = false; + for (let i = 0, k = interfacePrototypes.length; i < k; ++i) { + let interfacePrototype = interfacePrototypes[i]; + let current: ClassPrototype | null = interfacePrototype; + do { + if (current == prototype) { + this.error( + DiagnosticCode._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, + prototype.identifierNode.range, + prototype.internalName + ); + return null; + } + current = current.basePrototype; + } while (current); + let implementsNode = assert(prototype.implementsNodes![i]); + let iface = this.resolveClassInclTypeArguments( + interfacePrototype, + implementsNode.typeArguments, + prototype.parent, + makeMap(ctxTypes), + implementsNode, + reportMode + ); + if (!iface) return null; + assert(iface.kind == ElementKind.INTERFACE); + instance.addInterface(iface); + if (pendingClasses.includes(iface)) anyPending = true; + } + + // Like above, if any implemented interface is still pending, yield + if (anyPending) return instance; + } + // We only get here if the base class has been fully resolved already. this.finishResolveClass(instance, reportMode); return instance; diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index b6d2e093da..5196fdb076 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -13,11 +13,13 @@ (data (i32.const 1104) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s") (data (i32.const 1168) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00C") (data (i32.const 1200) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00F") + (data (i32.const 1232) "\04\00\00\00\01\00\00\00\01\00\00\00\04\00\00\00I\00B") (global $class-overloading/which (mut i32) (i32.const 1040)) (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) (global $class-overloading/a (mut i32) (i32.const 0)) (global $class-overloading/c (mut i32) (i32.const 0)) + (global $class-overloading/ia (mut i32) (i32.const 0)) (export "memory" (memory $0)) (start $~start) (func $~lib/rt/stub/__alloc (; 1 ;) (param $0 i32) (result i32) @@ -260,9 +262,9 @@ call $class-overloading/D#constructor ) (func $start:class-overloading (; 9 ;) - i32.const 1232 + i32.const 1264 global.set $~lib/rt/stub/startOffset - i32.const 1232 + i32.const 1264 global.set $~lib/rt/stub/offset i32.const 0 call $class-overloading/B#constructor @@ -350,6 +352,35 @@ call $~lib/builtins/abort unreachable end + i32.const 10 + call $~lib/rt/stub/__alloc + global.set $class-overloading/ia + block $__inlined_func$class-overloading/IA#foo|virtual + global.get $class-overloading/ia + i32.const 8 + i32.sub + i32.load + i32.const 10 + i32.eq + if + i32.const 1248 + global.set $class-overloading/which + br $__inlined_func$class-overloading/IA#foo|virtual + end + unreachable + end + global.get $class-overloading/which + i32.const 1248 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 74 + i32.const 1 + call $~lib/builtins/abort + unreachable + end ) (func $~start (; 10 ;) call $start:class-overloading diff --git a/tests/compiler/class-overloading.ts b/tests/compiler/class-overloading.ts index 0bc20ed137..245bc949cb 100644 --- a/tests/compiler/class-overloading.ts +++ b/tests/compiler/class-overloading.ts @@ -58,3 +58,17 @@ class F extends E { a = new F(); a.a(1); assert(which == "F"); + +interface IA { + foo(): void; +} + +class IB implements IA { + foo(): void { + which = "IB"; + } +} + +var ia: IA = new IB(); +ia.foo(); +assert(which == "IB"); diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index 8a7b4fdce4..77008f464a 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -1,8 +1,8 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) (type $none_=>_none (func)) - (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) @@ -14,6 +14,7 @@ (data (i32.const 96) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00.\00t\00s\00") (data (i32.const 160) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00C\00") (data (i32.const 192) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00F\00") + (data (i32.const 224) "\04\00\00\00\01\00\00\00\01\00\00\00\04\00\00\00I\00B\00") (table $0 1 funcref) (global $class-overloading/which (mut i32) (i32.const 32)) (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) @@ -21,7 +22,8 @@ (global $class-overloading/a (mut i32) (i32.const 0)) (global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0)) (global $class-overloading/c (mut i32) (i32.const 0)) - (global $~lib/heap/__heap_base i32 (i32.const 212)) + (global $class-overloading/ia (mut i32) (i32.const 0)) + (global $~lib/heap/__heap_base i32 (i32.const 244)) (export "memory" (memory $0)) (start $~start) (func $~lib/rt/stub/maybeGrowMemory (; 1 ;) (param $0 i32) @@ -469,7 +471,22 @@ local.set $0 local.get $0 ) - (func $start:class-overloading (; 17 ;) + (func $class-overloading/IB#constructor (; 17 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 10 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + ) + (func $class-overloading/IA#foo (; 18 ;) (param $0 i32) + unreachable + ) + (func $start:class-overloading (; 19 ;) (local $0 i32) global.get $~lib/heap/__heap_base i32.const 15 @@ -583,11 +600,28 @@ call $~lib/builtins/abort unreachable end + i32.const 0 + call $class-overloading/IB#constructor + global.set $class-overloading/ia + global.get $class-overloading/ia + call $class-overloading/IA#foo|virtual + global.get $class-overloading/which + i32.const 240 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 74 + i32.const 1 + call $~lib/builtins/abort + unreachable + end ) - (func $~start (; 18 ;) + (func $~start (; 20 ;) call $start:class-overloading ) - (func $class-overloading/F#a (; 19 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/F#a (; 21 ;) (param $0 i32) (param $1 i32) (local $2 i32) i32.const 208 local.set $2 @@ -596,7 +630,7 @@ local.get $2 global.set $class-overloading/which ) - (func $class-overloading/A#a|virtual (; 20 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/A#a|virtual (; 22 ;) (param $0 i32) (param $1 i32) (local $2 i32) block $default block $case2 @@ -648,4 +682,34 @@ local.get $1 call $class-overloading/A#a ) + (func $class-overloading/IB#foo (; 23 ;) (param $0 i32) + (local $1 i32) + i32.const 240 + local.set $1 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $1 + global.set $class-overloading/which + ) + (func $class-overloading/IA#foo|virtual (; 24 ;) (param $0 i32) + (local $1 i32) + block $default + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $1 + local.get $1 + i32.const 10 + i32.eq + br_if $case0 + br $default + end + local.get $0 + call $class-overloading/IB#foo + return + end + unreachable + ) ) From c4f48debd86d9dbbaf34cab43ccdbfd988c1284d Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 9 Apr 2020 00:49:33 +0200 Subject: [PATCH 14/24] guard object literals for now --- src/compiler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler.ts b/src/compiler.ts index 37ad618b78..31787abe08 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -8788,7 +8788,8 @@ export class Compiler extends DiagnosticEmitter { // contextual type must be a class var classReference = contextualType.classReference; - if (!classReference || classReference.is(CommonFlags.ABSTRACT)) { + if (!classReference || classReference.is(CommonFlags.ABSTRACT) || classReference.kind == ElementKind.INTERFACE) { + // TODO: interfaces don't have own storage. hidden class maybe? this.error( DiagnosticCode.Type_0_is_not_assignable_to_type_1, expression.range, "", contextualType.toString() From 0b81d241e55523e5379e2bdaaa7cac3d2aa3d41c Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 13 Apr 2020 02:32:13 +0200 Subject: [PATCH 15/24] progress --- src/compiler.ts | 56 +- src/diagnosticMessages.generated.ts | 10 + src/diagnosticMessages.json | 5 + src/program.ts | 108 ++- src/resolver.ts | 140 +++- tests/compiler/class-overloading.json | 3 +- .../compiler/class-overloading.optimized.wat | 330 +++++++++- tests/compiler/class-overloading.ts | 88 +++ .../compiler/class-overloading.untouched.wat | 619 +++++++++++++++++- 9 files changed, 1279 insertions(+), 80 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 31787abe08..64341f5755 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -646,14 +646,34 @@ export class Compiler extends DiagnosticEmitter { let unboundOverloadPrototype = _values[i]; assert(!unboundOverloadPrototype.isBound); let unboundOverloadParent = unboundOverloadPrototype.parent; - assert(unboundOverloadParent.kind == ElementKind.CLASS_PROTOTYPE); - let classInstances = (unboundOverloadParent).instances; + let isProperty = unboundOverloadParent.kind == ElementKind.PROPERTY_PROTOTYPE; + let classInstances: Map | null; + if (isProperty) { + let propertyParent = (unboundOverloadParent).parent; + assert(propertyParent.kind == ElementKind.CLASS_PROTOTYPE); + classInstances = (propertyParent).instances; + } else { + assert(unboundOverloadParent.kind == ElementKind.CLASS_PROTOTYPE); + classInstances = (unboundOverloadParent).instances; + } if (classInstances) { for (let _values = Map_values(classInstances), j = 0, l = _values.length; j < l; ++j) { let classInstance = _values[j]; - let boundPrototype = assert(classInstance.members!.get(unboundOverloadPrototype.name)); - assert(boundPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); - let overloadInstance = this.resolver.resolveFunction(boundPrototype, instance.typeArguments); + let overloadInstance: Function | null; + if (isProperty) { + let boundProperty = assert(classInstance.members!.get(unboundOverloadParent.name)); + assert(boundProperty.kind == ElementKind.PROPERTY); + if (instance.is(CommonFlags.GET)) { + overloadInstance = (boundProperty).getterInstance; + } else { + assert(instance.is(CommonFlags.SET)); + overloadInstance = (boundProperty).setterInstance; + } + } else { + let boundPrototype = assert(classInstance.members!.get(unboundOverloadPrototype.name)); + assert(boundPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); + overloadInstance = this.resolver.resolveFunction(boundPrototype, instance.typeArguments); + } if (!overloadInstance || !this.compileFunction(overloadInstance)) continue; let overloadType = overloadInstance.type; let originalType = instance.type; @@ -1453,10 +1473,15 @@ export class Compiler extends DiagnosticEmitter { } } - this.compileFunctionBody(instance, stmts); - if (!flow.is(FlowFlags.TERMINATES)) { - this.performAutoreleases(flow, stmts); - this.finishAutoreleases(flow, stmts); + let body: ExpressionRef; + if (this.compileFunctionBody(instance, stmts)) { + if (!flow.is(FlowFlags.TERMINATES)) { + this.performAutoreleases(flow, stmts); + this.finishAutoreleases(flow, stmts); + } + body = module.flatten(stmts, instance.signature.returnType.toNativeType()); + } else { + body = module.unreachable(); } this.currentFlow = previousFlow; @@ -1509,8 +1534,8 @@ export class Compiler extends DiagnosticEmitter { /** Function to compile. */ instance: Function, /** Target array of statements also being returned. Creates a new array if omitted. */ - stmts: ExpressionRef[] | null = null - ): ExpressionRef[] { + stmts: ExpressionRef[] + ): bool { var module = this.module; var bodyNode = assert(instance.prototype.bodyNode); var returnType = instance.signature.returnType; @@ -1607,9 +1632,10 @@ export class Compiler extends DiagnosticEmitter { DiagnosticCode.A_function_whose_declared_type_is_not_void_must_return_a_value, instance.prototype.functionTypeNode.returnType.range ); + return false; // not recoverable } - return stmts; + return true; } // === Classes ================================================================================== @@ -6133,9 +6159,9 @@ export class Compiler extends DiagnosticEmitter { } case ElementKind.PROPERTY: { // instance property let propertyInstance = target; - assert(propertyInstance.parent.kind == ElementKind.CLASS); - let classInstance = propertyInstance.parent; - assert(classInstance.kind == ElementKind.CLASS); + let propertyInstanceParent = propertyInstance.parent; + assert(propertyInstanceParent.kind == ElementKind.CLASS || propertyInstanceParent.kind == ElementKind.INTERFACE); + let classInstance = propertyInstanceParent; let setterInstance = propertyInstance.setterInstance; if (!setterInstance) { this.error( diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 95536348bc..cd78c52749 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -41,6 +41,7 @@ export enum DiagnosticCode { Expression_cannot_be_represented_by_a_type = 225, Expression_resolves_to_unusual_type_0 = 226, Function_0_is_virtual_and_will_not_be_inlined = 227, + Property_0_only_has_a_setter_and_is_missing_a_getter = 228, Type_0_is_cyclic_Module_will_include_deferred_garbage_collection = 900, Importing_the_table_disables_some_indirect_call_optimizations = 901, Exporting_the_table_disables_some_indirect_call_optimizations = 902, @@ -125,11 +126,14 @@ export enum DiagnosticCode { Operator_0_cannot_be_applied_to_types_1_and_2 = 2365, A_super_call_must_be_the_first_statement_in_the_constructor = 2376, Constructors_for_derived_classes_must_contain_a_super_call = 2377, + Getter_and_setter_accessors_do_not_agree_in_visibility = 2379, _get_and_set_accessor_must_have_the_same_type = 2380, + Overload_signatures_must_all_be_public_private_or_protected = 2385, Constructor_implementation_is_missing = 2390, Function_implementation_is_missing_or_not_immediately_following_the_declaration = 2391, Multiple_constructor_implementations_are_not_allowed = 2392, Duplicate_function_implementation = 2393, + This_overload_signature_is_not_compatible_with_its_implementation_signature = 2394, Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local = 2395, A_class_can_only_implement_an_interface = 2422, A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged = 2434, @@ -139,6 +143,7 @@ export enum DiagnosticCode { In_const_enum_declarations_member_initializer_must_be_constant_expression = 2474, Export_declaration_conflicts_with_exported_declaration_of_0 = 2484, _0_is_referenced_directly_or_indirectly_in_its_own_base_expression = 2506, + Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_2 = 2515, Object_is_possibly_null = 2531, Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property = 2540, The_target_of_an_assignment_must_be_a_variable_or_a_property_access = 2541, @@ -198,6 +203,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 225: return "Expression cannot be represented by a type."; case 226: return "Expression resolves to unusual type '{0}'."; case 227: return "Function '{0}' is virtual and will not be inlined."; + case 228: return "Property '{0}' only has a setter and is missing a getter."; case 900: return "Type '{0}' is cyclic. Module will include deferred garbage collection."; case 901: return "Importing the table disables some indirect call optimizations."; case 902: return "Exporting the table disables some indirect call optimizations."; @@ -282,11 +288,14 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2365: return "Operator '{0}' cannot be applied to types '{1}' and '{2}'."; case 2376: return "A 'super' call must be the first statement in the constructor."; case 2377: return "Constructors for derived classes must contain a 'super' call."; + case 2379: return "Getter and setter accessors do not agree in visibility."; case 2380: return "'get' and 'set' accessor must have the same type."; + case 2385: return "Overload signatures must all be public, private or protected."; case 2390: return "Constructor implementation is missing."; case 2391: return "Function implementation is missing or not immediately following the declaration."; case 2392: return "Multiple constructor implementations are not allowed."; case 2393: return "Duplicate function implementation."; + case 2394: return "This overload signature is not compatible with its implementation signature."; case 2395: return "Individual declarations in merged declaration '{0}' must be all exported or all local."; case 2422: return "A class can only implement an interface."; case 2434: return "A namespace declaration cannot be located prior to a class or function with which it is merged."; @@ -296,6 +305,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2474: return "In 'const' enum declarations member initializer must be constant expression."; case 2484: return "Export declaration conflicts with exported declaration of '{0}'."; case 2506: return "'{0}' is referenced directly or indirectly in its own base expression."; + case 2515: return "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from '{2}'."; case 2531: return "Object is possibly 'null'."; case 2540: return "Cannot assign to '{0}' because it is a constant or a read-only property."; case 2541: return "The target of an assignment must be a variable or a property access."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 41a46fbf87..13d590e687 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -34,6 +34,7 @@ "Expression cannot be represented by a type.": 225, "Expression resolves to unusual type '{0}'.": 226, "Function '{0}' is virtual and will not be inlined.": 227, + "Property '{0}' only has a setter and is missing a getter.": 228, "Type '{0}' is cyclic. Module will include deferred garbage collection.": 900, "Importing the table disables some indirect call optimizations.": 901, @@ -121,11 +122,14 @@ "Operator '{0}' cannot be applied to types '{1}' and '{2}'.": 2365, "A 'super' call must be the first statement in the constructor.": 2376, "Constructors for derived classes must contain a 'super' call.": 2377, + "Getter and setter accessors do not agree in visibility.": 2379, "'get' and 'set' accessor must have the same type.": 2380, + "Overload signatures must all be public, private or protected.": 2385, "Constructor implementation is missing.": 2390, "Function implementation is missing or not immediately following the declaration.": 2391, "Multiple constructor implementations are not allowed.": 2392, "Duplicate function implementation.": 2393, + "This overload signature is not compatible with its implementation signature.": 2394, "Individual declarations in merged declaration '{0}' must be all exported or all local.": 2395, "A class can only implement an interface.": 2422, "A namespace declaration cannot be located prior to a class or function with which it is merged.": 2434, @@ -135,6 +139,7 @@ "In 'const' enum declarations member initializer must be constant expression.": 2474, "Export declaration conflicts with exported declaration of '{0}'.": 2484, "'{0}' is referenced directly or indirectly in its own base expression.": 2506, + "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from '{2}'.": 2515, "Object is possibly 'null'.": 2531, "Cannot assign to '{0}' because it is a constant or a read-only property.": 2540, "The target of an assignment must be a variable or a property access.": 2541, diff --git a/src/program.ts b/src/program.ts index d0fd480a80..40fb8b26e5 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1171,8 +1171,15 @@ export class Program extends DiagnosticEmitter { thisMember.kind == ElementKind.FUNCTION_PROTOTYPE && baseMember.kind == ElementKind.FUNCTION_PROTOTYPE ) { - baseMember.set(CommonFlags.VIRTUAL); + let thisMethod = thisMember; let baseMethod = baseMember; + if (!thisMethod.visibilityEquals(baseMethod)) { + this.errorRelated( + DiagnosticCode.Overload_signatures_must_all_be_public_private_or_protected, + thisMethod.identifierNode.range, baseMethod.identifierNode.range + ); + } + baseMember.set(CommonFlags.VIRTUAL); let overloads = baseMethod.overloads; if (!overloads) baseMethod.overloads = overloads = new Set(); overloads.add(thisMember); @@ -1183,11 +1190,58 @@ export class Program extends DiagnosticEmitter { baseMethodInstance.set(CommonFlags.VIRTUAL); } } + } else if ( + thisMember.kind == ElementKind.PROPERTY_PROTOTYPE && + baseMember.kind == ElementKind.PROPERTY_PROTOTYPE + ) { + let thisProperty = thisMember; + let baseProperty = baseMember; + if (!thisProperty.visibilityEquals(baseProperty)) { + this.errorRelated( + DiagnosticCode.Overload_signatures_must_all_be_public_private_or_protected, + thisProperty.identifierNode.range, baseProperty.identifierNode.range + ); + } + baseProperty.set(CommonFlags.VIRTUAL); + let baseGetter = baseProperty.getterPrototype; + if (baseGetter) { + baseGetter.set(CommonFlags.VIRTUAL); + let thisGetter = thisProperty.getterPrototype; + if (thisGetter) { + let overloads = baseGetter.overloads; + if (!overloads) baseGetter.overloads = overloads = new Set(); + overloads.add(thisGetter); + } + let baseGetterInstances = baseGetter.instances; + if (baseGetterInstances) { + for (let _values = Map_values(baseGetterInstances), a = 0, b = _values.length; a < b; ++a) { + let baseGetterInstance = _values[a]; + baseGetterInstance.set(CommonFlags.VIRTUAL); + } + } + } + let baseSetter = baseProperty.setterPrototype; + if (baseSetter !== null && thisProperty.setterPrototype !== null) { + baseSetter.set(CommonFlags.VIRTUAL); + let thisSetter = thisProperty.setterPrototype; + if (thisSetter) { + let overloads = baseSetter.overloads; + if (!overloads) baseSetter.overloads = overloads = new Set(); + overloads.add(thisSetter); + } + let baseSetterInstances = baseSetter.instances; + if (baseSetterInstances) { + for (let _values = Map_values(baseSetterInstances), a = 0, b = _values.length; a < b; ++a) { + let baseSetterInstance = _values[a]; + baseSetterInstance.set(CommonFlags.VIRTUAL); + } + } + } } else { this.errorRelated( DiagnosticCode.Duplicate_identifier_0, - (thisMember).identifierNode.range, - (baseMember).identifierNode.range + thisMember.identifierNode.range, + baseMember.identifierNode.range ); } } @@ -2509,6 +2563,23 @@ export abstract class Element { return true; } + /** Checks if this element is public, explicitly or implicitly. */ + get isPublic(): bool { + return !this.isAny(CommonFlags.PRIVATE | CommonFlags.PROTECTED); + } + + /** Checks if this element is implicitly public, i.e. not explicitly declared to be. */ + get isImplicitlyPublic(): bool { + return this.isPublic && !this.is(CommonFlags.PUBLIC); + } + + /** Checks if the visibility of this element equals the specified. */ + visibilityEquals(other: Element): bool { + if (this.isPublic == other.isPublic) return true; + const vis = CommonFlags.PRIVATE | CommonFlags.PROTECTED; + return (this.flags & vis) == (other.flags & vis); + } + /** Returns a string representation of this element. */ toString(): string { return this.internalName + ", kind=" + this.kind.toString(); @@ -2563,10 +2634,31 @@ export abstract class DeclaredElement extends Element { return this.declaration.name; } + /** Gets the signature node, if applicable, otherwise the identifier node. */ + get signatureOrIdentifierNode(): Node { + var declaration = this.declaration; + if (declaration.kind == NodeKind.FUNCTIONDECLARATION || declaration.kind == NodeKind.METHODDECLARATION) { + return (declaration).signature; + } + return declaration.name; + } + /** Gets the assiciated decorator nodes. */ get decoratorNodes(): DecoratorNode[] | null { return this.declaration.decorators; } + + /** Checks if this element is a compatible override of the specified. */ + isCompatibleOverride(base: DeclaredElement): bool { + var self: DeclaredElement = this; // TS + if (self.kind != base.kind) return false; + switch (self.kind) { + case ElementKind.FUNCTION: { + return (self).signature.equals((base).signature); + } + } + return false; + } } // Kinds of all typed elements @@ -3483,11 +3575,13 @@ export class Property extends VariableLikeElement { ElementKind.PROPERTY, prototype.name, parent, - prototype.program.makeNativeVariableDeclaration( - prototype.name, + Node.createVariableDeclaration( + prototype.identifierNode, + null, null, null, prototype.is(CommonFlags.INSTANCE) ? CommonFlags.INSTANCE - : CommonFlags.NONE + : CommonFlags.NONE, + prototype.identifierNode.range ) ); this.prototype = prototype; @@ -3540,7 +3634,7 @@ export class IndexSignature extends TypedElement { export class ClassPrototype extends DeclaredElement { /** Instance member prototypes. */ - instanceMembers: Map | null = null; + instanceMembers: Map | null = null; /** Base class prototype, if applicable. */ basePrototype: ClassPrototype | null = null; /** Interface prototypes, if applicable. */ diff --git a/src/resolver.ts b/src/resolver.ts index 4c1d8c19eb..6855de3699 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -37,7 +37,8 @@ import { FunctionTarget, IndexSignature, isTypedElement, - InterfacePrototype + InterfacePrototype, + DeclaredElement } from "./program"; import { @@ -3005,19 +3006,64 @@ export class Resolver extends DiagnosticEmitter { var instanceMembers = instance.members; if (!instanceMembers) instance.members = instanceMembers = new Map(); + var pending = this.resolveClassPending; + var unimplemented = new Map(); + + // Alias interface members + var interfaces = instance.interfaces; + if (interfaces) { + for (let _values = Set_values(interfaces), i = 0, k = _values.length; i < k; ++i) { + let iface = _values[i]; + assert(!pending.includes(iface)); + let ifaceMembers = iface.members; + if (ifaceMembers) { + for (let _keys = Map_keys(ifaceMembers), i = 0, k = _keys.length; i < k; ++i) { + let memberName = unchecked(_keys[i]); + let member = assert(ifaceMembers.get(memberName)); + if (instanceMembers.has(memberName)) { + let existing = assert(instanceMembers.get(memberName)); + if (!member.isCompatibleOverride(existing)) { + this.errorRelated( + DiagnosticCode.This_overload_signature_is_not_compatible_with_its_implementation_signature, + member.signatureOrIdentifierNode.range, existing.signatureOrIdentifierNode.range + ); + continue; + } + } + instanceMembers.set(memberName, member); + unimplemented.set(memberName, member); + } + } + } + } + // Alias base members - var pendingClasses = this.resolveClassPending; var memoryOffset: u32 = 0; var base = instance.base; if (base) { - assert(!pendingClasses.includes(base)); + assert(!pending.includes(base)); let baseMembers = base.members; if (baseMembers) { // TODO: for (let [baseMemberName, baseMember] of baseMembers) { for (let _keys = Map_keys(baseMembers), i = 0, k = _keys.length; i < k; ++i) { - let baseMemberName = unchecked(_keys[i]); - let baseMember = assert(baseMembers.get(baseMemberName)); - instanceMembers.set(baseMemberName, baseMember); + let memberName = unchecked(_keys[i]); + let member = assert(baseMembers.get(memberName)); + if (instanceMembers.has(memberName)) { + let existing = assert(instanceMembers.get(memberName)); + if (!member.isCompatibleOverride(existing)) { + this.errorRelated( + DiagnosticCode.This_overload_signature_is_not_compatible_with_its_implementation_signature, + member.signatureOrIdentifierNode.range, existing.signatureOrIdentifierNode.range + ); + continue; + } + } + instanceMembers.set(memberName, member); + if (member.is(CommonFlags.ABSTRACT)) { + unimplemented.set(memberName, member); + } else { + unimplemented.delete(memberName); + } } } memoryOffset = base.nextMemoryOffset; @@ -3026,10 +3072,12 @@ export class Resolver extends DiagnosticEmitter { // Resolve instance members var prototype = instance.prototype; var instanceMemberPrototypes = prototype.instanceMembers; + var properties = new Array(); if (instanceMemberPrototypes) { // TODO: for (let member of instanceMemberPrototypes.values()) { for (let _values = Map_values(instanceMemberPrototypes), i = 0, k = _values.length; i < k; ++i) { let member = unchecked(_values[i]); + let memberName = member.name; switch (member.kind) { case ElementKind.FIELD_PROTOTYPE: { @@ -3071,7 +3119,7 @@ export class Resolver extends DiagnosticEmitter { if (memoryOffset & mask) memoryOffset = (memoryOffset | mask) + 1; fieldInstance.memoryOffset = memoryOffset; memoryOffset += fieldType.byteSize; - instance.add(member.name, fieldInstance); // reports + instance.add(memberName, fieldInstance); // reports break; } case ElementKind.FUNCTION_PROTOTYPE: { @@ -3082,6 +3130,7 @@ export class Resolver extends DiagnosticEmitter { case ElementKind.PROPERTY_PROTOTYPE: { let propertyPrototype = member; let propertyInstance = new Property(propertyPrototype, instance); + properties.push(propertyInstance); let getterPrototype = propertyPrototype.getterPrototype; if (getterPrototype) { let getterInstance = this.resolveFunction( @@ -3116,24 +3165,63 @@ export class Resolver extends DiagnosticEmitter { } default: assert(false); } + if (!member.is(CommonFlags.ABSTRACT)) { + unimplemented.delete(memberName); + } } } - // Finalize memory offset - instance.nextMemoryOffset = memoryOffset; - - // Link _own_ constructor if present - { - let ctorPrototype = instance.lookupInSelf(CommonNames.constructor); - if (ctorPrototype !== null && ctorPrototype.parent === instance) { - assert(ctorPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); - let ctorInstance = this.resolveFunction( - ctorPrototype, - null, - assert(instance.contextualTypeArguments), - reportMode + // Check that property getters and setters match + for (let i = 0, k = properties.length; i < k; ++i) { + let property = properties[i]; + let propertyGetter = property.getterInstance; + if (!propertyGetter) { + this.error( + DiagnosticCode.Property_0_only_has_a_setter_and_is_missing_a_getter, + property.identifierNode.range, property.name ); - if (ctorInstance) instance.constructorInstance = ctorInstance; + } else { + let propertySetter = property.setterInstance; + if (propertySetter !== null && !propertyGetter.visibilityEquals(propertySetter)) { + this.errorRelated( + DiagnosticCode.Getter_and_setter_accessors_do_not_agree_in_visibility, + propertyGetter.identifierNode.range, propertySetter.identifierNode.range + ); + } + } + } + + if (instance.kind != ElementKind.INTERFACE) { + + // Check that all required members are implemented + if (!instance.is(CommonFlags.ABSTRACT) && unimplemented.size > 0) { + for (let _keys = Map_keys(unimplemented), i = 0, k = _keys.length; i < k; ++i) { + let memberName = _keys[i]; + let member = assert(unimplemented.get(memberName)); + this.errorRelated( + DiagnosticCode.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_2, + instance.identifierNode.range, member.identifierNode.range, + instance.internalName, memberName, member.parent.internalName + ); + } + } + + // Finalize memory offset + instance.nextMemoryOffset = memoryOffset; + + // Link _own_ constructor if present + { + let ctorPrototype = instance.lookupInSelf(CommonNames.constructor); + if (ctorPrototype !== null && ctorPrototype.parent === instance) { + assert(ctorPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); + let ctorInstance = this.resolveFunction( + ctorPrototype, + null, + assert(instance.contextualTypeArguments), + reportMode + ); + if (ctorInstance) instance.constructorInstance = ctorInstance; + } } } @@ -3205,18 +3293,18 @@ export class Resolver extends DiagnosticEmitter { } // Remove this class from pending - var pendingIndex = pendingClasses.indexOf(instance); + var pendingIndex = pending.indexOf(instance); assert(~pendingIndex); // must be pending - pendingClasses.splice(pendingIndex, 1); + pending.splice(pendingIndex, 1); // Finish derived classes that we postponed in `resolveClass` due to the // base class still being pending, again triggering `finishResolveClass` // of any classes derived from those classes, ultimately leading to all // pending classes being resolved. var derivedPendingClasses = new Array(); - for (let i = 0, k = pendingClasses.length; i < k; ++i) { - let pending = pendingClasses[i]; - if (instance == pending.base) derivedPendingClasses.push(pending); + for (let i = 0, k = pending.length; i < k; ++i) { + let other = pending[i]; + if (instance == other.base) derivedPendingClasses.push(other); } for (let i = 0, k = derivedPendingClasses.length; i < k; ++i) { this.finishResolveClass(derivedPendingClasses[i], reportMode); diff --git a/tests/compiler/class-overloading.json b/tests/compiler/class-overloading.json index b1da366ff4..bf222c4d2d 100644 --- a/tests/compiler/class-overloading.json +++ b/tests/compiler/class-overloading.json @@ -1,5 +1,6 @@ { "asc_flags": [ - "--runtime none" + "--runtime none", + "--explicitStart" ] } \ No newline at end of file diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index 5196fdb076..6586006699 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -20,8 +20,9 @@ (global $class-overloading/a (mut i32) (i32.const 0)) (global $class-overloading/c (mut i32) (i32.const 0)) (global $class-overloading/ia (mut i32) (i32.const 0)) + (global $~started (mut i32) (i32.const 0)) + (export "_start" (func $~start)) (export "memory" (memory $0)) - (start $~start) (func $~lib/rt/stub/__alloc (; 1 ;) (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -231,7 +232,7 @@ if i32.const 0 i32.const 1120 - i32.const 23 + i32.const 52 i32.const 5 call $~lib/builtins/abort unreachable @@ -278,7 +279,55 @@ if i32.const 0 i32.const 1120 - i32.const 18 + i32.const 38 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 41 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 44 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 47 i32.const 1 call $~lib/builtins/abort unreachable @@ -287,6 +336,8 @@ call $~lib/rt/stub/__alloc call $class-overloading/B#constructor global.set $class-overloading/c + i32.const 1040 + global.set $class-overloading/which call $class-overloading/C#a global.get $class-overloading/which i32.const 1184 @@ -295,7 +346,53 @@ if i32.const 0 i32.const 1120 - i32.const 31 + i32.const 71 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + i32.const 1184 + global.set $class-overloading/which + i32.const 1184 + i32.const 1184 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 74 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + i32.const 1184 + global.set $class-overloading/which + i32.const 1184 + i32.const 1184 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 77 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1184 + global.set $class-overloading/which + i32.const 1184 + i32.const 1184 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 79 i32.const 1 call $~lib/builtins/abort unreachable @@ -303,6 +400,8 @@ i32.const 0 call $class-overloading/D#constructor global.set $class-overloading/a + i32.const 1040 + global.set $class-overloading/which global.get $class-overloading/a call $class-overloading/A#a|virtual global.get $class-overloading/which @@ -312,7 +411,53 @@ if i32.const 0 i32.const 1120 - i32.const 40 + i32.const 89 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 92 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 95 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 97 i32.const 1 call $~lib/builtins/abort unreachable @@ -320,6 +465,8 @@ i32.const 0 call $class-overloading/E#constructor global.set $class-overloading/a + i32.const 1040 + global.set $class-overloading/which global.get $class-overloading/a call $class-overloading/A#a|virtual global.get $class-overloading/which @@ -329,7 +476,53 @@ if i32.const 0 i32.const 1120 - i32.const 49 + i32.const 107 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 110 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 113 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + global.get $class-overloading/which + i32.const 1088 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 115 i32.const 1 call $~lib/builtins/abort unreachable @@ -338,6 +531,8 @@ call $~lib/rt/stub/__alloc call $class-overloading/E#constructor global.set $class-overloading/a + i32.const 1040 + global.set $class-overloading/which global.get $class-overloading/a call $class-overloading/A#a|virtual global.get $class-overloading/which @@ -347,7 +542,23 @@ if i32.const 0 i32.const 1120 - i32.const 60 + i32.const 137 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 1216 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 140 i32.const 1 call $~lib/builtins/abort unreachable @@ -355,6 +566,8 @@ i32.const 10 call $~lib/rt/stub/__alloc global.set $class-overloading/ia + i32.const 1040 + global.set $class-overloading/which block $__inlined_func$class-overloading/IA#foo|virtual global.get $class-overloading/ia i32.const 8 @@ -376,13 +589,20 @@ if i32.const 0 i32.const 1120 - i32.const 74 + i32.const 162 i32.const 1 call $~lib/builtins/abort unreachable end ) (func $~start (; 10 ;) + global.get $~started + if + return + else + i32.const 1 + global.set $~started + end call $start:class-overloading ) (func $class-overloading/A#a|virtual (; 11 ;) (param $0 i32) @@ -424,4 +644,98 @@ i32.const 1056 global.set $class-overloading/which ) + (func $class-overloading/A#b|virtual (; 12 ;) (param $0 i32) + block $default + block $case2 + block $case1 + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.tee $0 + i32.const 4 + i32.eq + local.get $0 + i32.const 6 + i32.eq + i32.or + br_if $case0 + block $tablify|0 + local.get $0 + i32.const 5 + i32.sub + br_table $case1 $tablify|0 $case0 $case2 $tablify|0 + end + br $default + end + i32.const 1088 + global.set $class-overloading/which + return + end + i32.const 1184 + global.set $class-overloading/which + return + end + i32.const 1216 + global.set $class-overloading/which + return + end + i32.const 1056 + global.set $class-overloading/which + ) + (func $class-overloading/A#get:c|virtual (; 13 ;) (param $0 i32) + block $default + block $case2 + block $case1 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.tee $0 + i32.const 4 + i32.eq + local.get $0 + i32.const 5 + i32.eq + i32.or + local.get $0 + i32.const 6 + i32.eq + local.get $0 + i32.const 7 + i32.eq + i32.or + i32.or + local.get $0 + i32.const 8 + i32.eq + i32.or + i32.eqz + if + local.get $0 + i32.const 5 + i32.eq + br_if $case1 + local.get $0 + i32.const 8 + i32.eq + br_if $case2 + br $default + end + i32.const 1088 + global.set $class-overloading/which + return + end + i32.const 1184 + global.set $class-overloading/which + return + end + i32.const 1216 + global.set $class-overloading/which + return + end + i32.const 1056 + global.set $class-overloading/which + ) ) diff --git a/tests/compiler/class-overloading.ts b/tests/compiler/class-overloading.ts index 245bc949cb..6bd4ccbc24 100644 --- a/tests/compiler/class-overloading.ts +++ b/tests/compiler/class-overloading.ts @@ -4,18 +4,47 @@ class A { a(a: T): void { // virtual which = "A"; } + b(b: i32): void { // virtual + which = "A"; + } + get c(): i32 { // virtual + which = "A"; + return 0; + } + set c(c: i32) { // virtual + which = "A"; + } } class B extends A { a(a: T): void { // virtual + overload which = "B"; } + b(b: i32): void { // virtual + overload + which = "B"; + } + get c(): i32 { // virtual + overload + which = "B"; + return 0; + } + set c(c: i32) { // virtual + overload + which = "B"; + } } // Should call the overload var a: A = new B(); a.a(1); assert(which == "B"); +which = ""; +a.b(1); +assert(which == "B"); +which = ""; +a.c; +assert(which == "B"); +which = ""; +a.c = 1; +assert(which == "B"); class C extends B { a(a: T): void { // overload @@ -23,12 +52,31 @@ class C extends B { assert(which == "B"); which = "C"; } + b(b: i32): void { // overload + which = "C"; + } + get c(): i32 { // overload + which = "C"; + return 0; + } + set c(c: i32) { // overload + which = "C"; + } } // Should call non-virtual super var c = new C(); +which = ""; c.a(1); assert(which == "C"); +which = ""; +c.b(1); +assert(which == "C"); +which = ""; +c.c; +assert(which == "C"); +c.c = 1; +assert(which == "C"); class D extends B { // inherits B's @@ -36,8 +84,17 @@ class D extends B { // Should call inherited overload a = new D(); +which = ""; a.a(1); assert(which == "B"); +which = ""; +a.b(1); +assert(which == "B"); +which = ""; +a.c; +assert(which == "B"); +a.c = 1; +assert(which == "B"); class E extends D { // inherits B's @@ -45,19 +102,49 @@ class E extends D { // Should still call inherited overload a = new E(); +which = ""; a.a(1); assert(which == "B"); +which = ""; +a.b(1); +assert(which == "B"); +which = ""; +a.c; +assert(which == "B"); +a.c = 1; +assert(which == "B"); class F extends E { a(a: T): void { // overload which = "F"; } + b(b: i32): void { // overload + which = "F"; + } + get c(): i32 { // overload + which = "F"; + return 0; + } + set c(c: i32) { // overload + which = "F"; + } } // Should no longer call inherited overload a = new F(); +which = ""; a.a(1); assert(which == "F"); +which = ""; +a.b(1); +assert(which == "F"); + +// FIXME +// which = ""; +// a.c; +// assert(which == "F"); +// a.c = 1; +// assert(which == "F"); interface IA { foo(): void; @@ -70,5 +157,6 @@ class IB implements IA { } var ia: IA = new IB(); +which = ""; ia.foo(); assert(which == "IB"); diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index 77008f464a..1368021944 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -1,7 +1,7 @@ (module + (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_=>_none (func (param i32))) - (type $i32_i32_=>_none (func (param i32 i32))) (type $none_=>_none (func)) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) @@ -23,9 +23,10 @@ (global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0)) (global $class-overloading/c (mut i32) (i32.const 0)) (global $class-overloading/ia (mut i32) (i32.const 0)) + (global $~started (mut i32) (i32.const 0)) (global $~lib/heap/__heap_base i32 (i32.const 244)) + (export "_start" (func $~start)) (export "memory" (memory $0)) - (start $~start) (func $~lib/rt/stub/maybeGrowMemory (; 1 ;) (param $0 i32) (local $1 i32) (local $2 i32) @@ -378,7 +379,35 @@ call $~lib/rt/stub/__release local.get $2 ) - (func $class-overloading/C#constructor (; 11 ;) (param $0 i32) (result i32) + (func $class-overloading/A#b (; 11 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 48 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/A#get:c (; 12 ;) (param $0 i32) (result i32) + (local $1 i32) + i32.const 48 + local.set $1 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $1 + global.set $class-overloading/which + i32.const 0 + ) + (func $class-overloading/A#set:c (; 13 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 48 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/C#constructor (; 14 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -393,7 +422,7 @@ local.set $0 local.get $0 ) - (func $class-overloading/B#a (; 12 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/B#a (; 15 ;) (param $0 i32) (param $1 i32) (local $2 i32) i32.const 80 local.set $2 @@ -402,7 +431,7 @@ local.get $2 global.set $class-overloading/which ) - (func $class-overloading/C#a (; 13 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/C#a (; 16 ;) (param $0 i32) (param $1 i32) (local $2 i32) local.get $0 local.get $1 @@ -414,7 +443,7 @@ if i32.const 0 i32.const 112 - i32.const 23 + i32.const 52 i32.const 5 call $~lib/builtins/abort unreachable @@ -426,7 +455,35 @@ local.get $2 global.set $class-overloading/which ) - (func $class-overloading/D#constructor (; 14 ;) (param $0 i32) (result i32) + (func $class-overloading/C#b (; 17 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 176 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/C#get:c (; 18 ;) (param $0 i32) (result i32) + (local $1 i32) + i32.const 176 + local.set $1 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $1 + global.set $class-overloading/which + i32.const 0 + ) + (func $class-overloading/C#set:c (; 19 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 176 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/D#constructor (; 20 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -441,7 +498,7 @@ local.set $0 local.get $0 ) - (func $class-overloading/E#constructor (; 15 ;) (param $0 i32) (result i32) + (func $class-overloading/E#constructor (; 21 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -456,7 +513,7 @@ local.set $0 local.get $0 ) - (func $class-overloading/F#constructor (; 16 ;) (param $0 i32) (result i32) + (func $class-overloading/F#constructor (; 22 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -471,7 +528,7 @@ local.set $0 local.get $0 ) - (func $class-overloading/IB#constructor (; 17 ;) (param $0 i32) (result i32) + (func $class-overloading/IB#constructor (; 23 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -483,10 +540,10 @@ end local.get $0 ) - (func $class-overloading/IA#foo (; 18 ;) (param $0 i32) + (func $class-overloading/IA#foo (; 24 ;) (param $0 i32) unreachable ) - (func $start:class-overloading (; 19 ;) + (func $start:class-overloading (; 25 ;) (local $0 i32) global.get $~lib/heap/__heap_base i32.const 15 @@ -511,7 +568,70 @@ if i32.const 0 i32.const 112 - i32.const 18 + i32.const 38 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 41 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + drop + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 44 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#set:c|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 47 i32.const 1 call $~lib/builtins/abort unreachable @@ -519,6 +639,12 @@ i32.const 0 call $class-overloading/C#constructor global.set $class-overloading/c + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which global.get $class-overloading/c i32.const 1 call $class-overloading/C#a @@ -529,7 +655,64 @@ if i32.const 0 i32.const 112 - i32.const 31 + i32.const 71 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/c + i32.const 1 + call $class-overloading/C#b + global.get $class-overloading/which + i32.const 176 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 74 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/c + call $class-overloading/C#get:c + drop + global.get $class-overloading/which + i32.const 176 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 77 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $class-overloading/c + i32.const 1 + call $class-overloading/C#set:c + global.get $class-overloading/which + i32.const 176 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 79 i32.const 1 call $~lib/builtins/abort unreachable @@ -541,6 +724,12 @@ call $~lib/rt/stub/__release local.get $0 global.set $class-overloading/a + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which global.get $class-overloading/a i32.const 1 call $class-overloading/A#a|virtual @@ -551,7 +740,64 @@ if i32.const 0 i32.const 112 - i32.const 40 + i32.const 89 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 92 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + drop + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 95 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#set:c|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 97 i32.const 1 call $~lib/builtins/abort unreachable @@ -563,6 +809,12 @@ call $~lib/rt/stub/__release local.get $0 global.set $class-overloading/a + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which global.get $class-overloading/a i32.const 1 call $class-overloading/A#a|virtual @@ -573,7 +825,64 @@ if i32.const 0 i32.const 112 - i32.const 49 + i32.const 107 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 110 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + drop + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 113 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#set:c|virtual + global.get $class-overloading/which + i32.const 80 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 115 i32.const 1 call $~lib/builtins/abort unreachable @@ -585,6 +894,12 @@ call $~lib/rt/stub/__release local.get $0 global.set $class-overloading/a + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which global.get $class-overloading/a i32.const 1 call $class-overloading/A#a|virtual @@ -595,7 +910,28 @@ if i32.const 0 i32.const 112 - i32.const 60 + i32.const 137 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 208 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 140 i32.const 1 call $~lib/builtins/abort unreachable @@ -603,6 +939,12 @@ i32.const 0 call $class-overloading/IB#constructor global.set $class-overloading/ia + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which global.get $class-overloading/ia call $class-overloading/IA#foo|virtual global.get $class-overloading/which @@ -612,16 +954,23 @@ if i32.const 0 i32.const 112 - i32.const 74 + i32.const 162 i32.const 1 call $~lib/builtins/abort unreachable end ) - (func $~start (; 20 ;) + (func $~start (; 26 ;) + global.get $~started + if + return + else + i32.const 1 + global.set $~started + end call $start:class-overloading ) - (func $class-overloading/F#a (; 21 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/F#a (; 27 ;) (param $0 i32) (param $1 i32) (local $2 i32) i32.const 208 local.set $2 @@ -630,7 +979,7 @@ local.get $2 global.set $class-overloading/which ) - (func $class-overloading/A#a|virtual (; 22 ;) (param $0 i32) (param $1 i32) + (func $class-overloading/A#a|virtual (; 28 ;) (param $0 i32) (param $1 i32) (local $2 i32) block $default block $case2 @@ -682,7 +1031,231 @@ local.get $1 call $class-overloading/A#a ) - (func $class-overloading/IB#foo (; 23 ;) (param $0 i32) + (func $class-overloading/B#b (; 29 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 80 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/F#b (; 30 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 208 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/A#b|virtual (; 31 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + block $default + block $case2 + block $case1 + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $2 + local.get $2 + i32.const 4 + i32.eq + br_if $case0 + local.get $2 + i32.const 6 + i32.eq + br_if $case0 + local.get $2 + i32.const 7 + i32.eq + br_if $case0 + local.get $2 + i32.const 5 + i32.eq + br_if $case1 + local.get $2 + i32.const 8 + i32.eq + br_if $case2 + br $default + end + local.get $0 + local.get $1 + call $class-overloading/B#b + return + end + local.get $0 + local.get $1 + call $class-overloading/C#b + return + end + local.get $0 + local.get $1 + call $class-overloading/F#b + return + end + local.get $0 + local.get $1 + call $class-overloading/A#b + ) + (func $class-overloading/B#get:c (; 32 ;) (param $0 i32) (result i32) + (local $1 i32) + i32.const 80 + local.set $1 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $1 + global.set $class-overloading/which + i32.const 0 + ) + (func $class-overloading/F#get:c (; 33 ;) (param $0 i32) (result i32) + (local $1 i32) + i32.const 208 + local.set $1 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $1 + global.set $class-overloading/which + i32.const 0 + ) + (func $class-overloading/A#get:c|virtual (; 34 ;) (param $0 i32) (result i32) + (local $1 i32) + block $default + block $case2 + block $case1 + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $1 + local.get $1 + i32.const 4 + i32.eq + br_if $case0 + local.get $1 + i32.const 5 + i32.eq + br_if $case0 + local.get $1 + i32.const 6 + i32.eq + br_if $case0 + local.get $1 + i32.const 7 + i32.eq + br_if $case0 + local.get $1 + i32.const 8 + i32.eq + br_if $case0 + local.get $1 + i32.const 5 + i32.eq + br_if $case1 + local.get $1 + i32.const 8 + i32.eq + br_if $case2 + br $default + end + local.get $0 + call $class-overloading/B#get:c + return + end + local.get $0 + call $class-overloading/C#get:c + return + end + local.get $0 + call $class-overloading/F#get:c + return + end + local.get $0 + call $class-overloading/A#get:c + ) + (func $class-overloading/B#set:c (; 35 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 80 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/F#set:c (; 36 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + i32.const 208 + local.set $2 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $2 + global.set $class-overloading/which + ) + (func $class-overloading/A#set:c|virtual (; 37 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + block $default + block $case2 + block $case1 + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $2 + local.get $2 + i32.const 4 + i32.eq + br_if $case0 + local.get $2 + i32.const 5 + i32.eq + br_if $case0 + local.get $2 + i32.const 6 + i32.eq + br_if $case0 + local.get $2 + i32.const 7 + i32.eq + br_if $case0 + local.get $2 + i32.const 8 + i32.eq + br_if $case0 + local.get $2 + i32.const 5 + i32.eq + br_if $case1 + local.get $2 + i32.const 8 + i32.eq + br_if $case2 + br $default + end + local.get $0 + local.get $1 + call $class-overloading/B#set:c + return + end + local.get $0 + local.get $1 + call $class-overloading/C#set:c + return + end + local.get $0 + local.get $1 + call $class-overloading/F#set:c + return + end + local.get $0 + local.get $1 + call $class-overloading/A#set:c + ) + (func $class-overloading/IB#foo (; 38 ;) (param $0 i32) (local $1 i32) i32.const 240 local.set $1 @@ -691,7 +1264,7 @@ local.get $1 global.set $class-overloading/which ) - (func $class-overloading/IA#foo|virtual (; 24 ;) (param $0 i32) + (func $class-overloading/IA#foo|virtual (; 39 ;) (param $0 i32) (local $1 i32) block $default block $case0 From afbf9a9a996e504cec693c56c17725b8beb3227f Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 16 Apr 2020 23:10:56 +0200 Subject: [PATCH 16/24] fix property issue --- src/compiler.ts | 6 +- src/program.ts | 5 + .../compiler/class-overloading.optimized.wat | 100 +++++++----------- tests/compiler/class-overloading.ts | 13 ++- .../compiler/class-overloading.untouched.wat | 60 ++++++++--- 5 files changed, 98 insertions(+), 86 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index fbd0181513..fc02f90a1d 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -725,7 +725,11 @@ export class Compiler extends DiagnosticEmitter { } builder.addCase(classInstance.id, stmts); // Also alias each extendee inheriting this exact overload - let extendees = classInstance.getAllExtendees(instance.prototype.name); + let extendees = classInstance.getAllExtendees( + isProperty + ? unboundOverloadParent.name + : instance.prototype.name + ); for (let _values = Set_values(extendees), a = 0, b = _values.length; a < b; ++a) { let extendee = _values[a]; builder.addCase(extendee.id, stmts); diff --git a/src/program.ts b/src/program.ts index e8c81d4e63..d9f1553055 100644 --- a/src/program.ts +++ b/src/program.ts @@ -4353,6 +4353,11 @@ export function mangleInternalName(name: string, parent: Element, isInstance: bo assert(!isInstance); return parent.internalName + INNER_DELIMITER + name; } + case ElementKind.PROPERTY_PROTOTYPE: + case ElementKind.PROPERTY: { + parent = parent.parent; + // fall-through + } default: { return mangleInternalName(parent.name, parent.parent, parent.is(CommonFlags.INSTANCE), asGlobal) + (isInstance ? INSTANCE_DELIMITER : STATIC_DELIMITER) + name; diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index f5175e78c5..2682e64f59 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -299,7 +299,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#b|virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -315,7 +315,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#b|virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -431,7 +431,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#b|virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -445,7 +445,7 @@ unreachable end global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#b|virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -496,7 +496,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#b|virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -510,7 +510,7 @@ unreachable end global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#b|virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -559,6 +559,38 @@ call $~lib/builtins/abort unreachable end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 1216 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 143 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#b|virtual + global.get $class-overloading/which + i32.const 1216 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 146 + i32.const 1 + call $~lib/builtins/abort + unreachable + end i32.const 10 call $~lib/rt/stub/__alloc global.set $class-overloading/ia @@ -585,7 +617,7 @@ if i32.const 0 i32.const 1120 - i32.const 162 + i32.const 161 i32.const 1 call $~lib/builtins/abort unreachable @@ -680,58 +712,4 @@ i32.const 1056 global.set $class-overloading/which ) - (func $class-overloading/A#get:c|virtual (param $0 i32) - block $default - block $case2 - block $case1 - local.get $0 - i32.const 8 - i32.sub - i32.load - local.tee $0 - i32.const 4 - i32.eq - local.get $0 - i32.const 5 - i32.eq - i32.or - local.get $0 - i32.const 6 - i32.eq - local.get $0 - i32.const 7 - i32.eq - i32.or - i32.or - local.get $0 - i32.const 8 - i32.eq - i32.or - i32.eqz - if - local.get $0 - i32.const 5 - i32.eq - br_if $case1 - local.get $0 - i32.const 8 - i32.eq - br_if $case2 - br $default - end - i32.const 1088 - global.set $class-overloading/which - return - end - i32.const 1184 - global.set $class-overloading/which - return - end - i32.const 1216 - global.set $class-overloading/which - return - end - i32.const 1056 - global.set $class-overloading/which - ) ) diff --git a/tests/compiler/class-overloading.ts b/tests/compiler/class-overloading.ts index 6bd4ccbc24..a83bfee2ce 100644 --- a/tests/compiler/class-overloading.ts +++ b/tests/compiler/class-overloading.ts @@ -138,13 +138,12 @@ assert(which == "F"); which = ""; a.b(1); assert(which == "F"); - -// FIXME -// which = ""; -// a.c; -// assert(which == "F"); -// a.c = 1; -// assert(which == "F"); +which = ""; +a.c; +assert(which == "F"); +which = ""; +a.c = 1; +assert(which == "F"); interface IA { foo(): void; diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index 43bbc27ea3..a0ed0f8a6d 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -936,6 +936,48 @@ call $~lib/builtins/abort unreachable end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + call $class-overloading/A#get:c|virtual + drop + global.get $class-overloading/which + i32.const 208 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 143 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/a + i32.const 1 + call $class-overloading/A#set:c|virtual + global.get $class-overloading/which + i32.const 208 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 146 + i32.const 1 + call $~lib/builtins/abort + unreachable + end i32.const 0 call $class-overloading/IB#constructor global.set $class-overloading/ia @@ -954,7 +996,7 @@ if i32.const 0 i32.const 112 - i32.const 162 + i32.const 161 i32.const 1 call $~lib/builtins/abort unreachable @@ -1137,10 +1179,6 @@ i32.eq br_if $case0 local.get $1 - i32.const 5 - i32.eq - br_if $case0 - local.get $1 i32.const 6 i32.eq br_if $case0 @@ -1149,10 +1187,6 @@ i32.eq br_if $case0 local.get $1 - i32.const 8 - i32.eq - br_if $case0 - local.get $1 i32.const 5 i32.eq br_if $case1 @@ -1211,10 +1245,6 @@ i32.eq br_if $case0 local.get $2 - i32.const 5 - i32.eq - br_if $case0 - local.get $2 i32.const 6 i32.eq br_if $case0 @@ -1223,10 +1253,6 @@ i32.eq br_if $case0 local.get $2 - i32.const 8 - i32.eq - br_if $case0 - local.get $2 i32.const 5 i32.eq br_if $case1 From 289c26f1c1b911c57ff40e774fd7e17d0e8ee865 Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 16 Apr 2020 23:34:50 +0200 Subject: [PATCH 17/24] fix related --- tests/compiler/getter-setter.untouched.wat | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/compiler/getter-setter.untouched.wat b/tests/compiler/getter-setter.untouched.wat index be6c6a5130..5c91033b3e 100644 --- a/tests/compiler/getter-setter.untouched.wat +++ b/tests/compiler/getter-setter.untouched.wat @@ -10,15 +10,15 @@ (global $getter-setter/Foo._bar (mut i32) (i32.const 0)) (export "memory" (memory $0)) (start $~start) - (func $getter-setter/Foo.bar.get:bar (result i32) + (func $getter-setter/Foo.get:bar (result i32) global.get $getter-setter/Foo._bar ) - (func $getter-setter/Foo.bar.set:bar (param $0 i32) + (func $getter-setter/Foo.set:bar (param $0 i32) local.get $0 global.set $getter-setter/Foo._bar ) (func $start:getter-setter - call $getter-setter/Foo.bar.get:bar + call $getter-setter/Foo.get:bar i32.const 0 i32.eq i32.eqz @@ -31,8 +31,8 @@ unreachable end i32.const 1 - call $getter-setter/Foo.bar.set:bar - call $getter-setter/Foo.bar.get:bar + call $getter-setter/Foo.set:bar + call $getter-setter/Foo.get:bar i32.const 1 i32.eq i32.eqz @@ -45,8 +45,8 @@ unreachable end i32.const 2 - call $getter-setter/Foo.bar.set:bar - call $getter-setter/Foo.bar.get:bar + call $getter-setter/Foo.set:bar + call $getter-setter/Foo.get:bar i32.const 2 i32.eq i32.eqz From 73e9c3477aff1771f5fe35236becfcaf7279569b Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 18 Apr 2020 00:21:29 +0200 Subject: [PATCH 18/24] interface impls, fix assignability check --- src/program.ts | 15 ++-- src/resolver.ts | 49 ++++++----- src/types.ts | 58 ++++++++++--- tests/compiler/builtins.optimized.wat | 6 +- tests/compiler/builtins.untouched.wat | 8 +- .../compiler/class-overloading.optimized.wat | 66 ++++++++++---- tests/compiler/class-overloading.ts | 20 ++++- .../compiler/class-overloading.untouched.wat | 87 +++++++++++++++---- 8 files changed, 230 insertions(+), 79 deletions(-) diff --git a/src/program.ts b/src/program.ts index d9f1553055..2051a51fc1 100644 --- a/src/program.ts +++ b/src/program.ts @@ -2651,11 +2651,9 @@ export abstract class DeclaredElement extends Element { /** Checks if this element is a compatible override of the specified. */ isCompatibleOverride(base: DeclaredElement): bool { var self: DeclaredElement = this; // TS - if (self.kind != base.kind) return false; - switch (self.kind) { - case ElementKind.FUNCTION: { - return (self).signature.equals((base).signature); - } + var kind = self.kind; + if (kind == base.kind && kind == ElementKind.FUNCTION) { + return (self).signature.isAssignableTo((base).signature, /* sameSize */ true); } return false; } @@ -3918,7 +3916,12 @@ export class Class extends TypedElement { if (current == target) return true; if (target.kind == ElementKind.INTERFACE) { let interfaces = current.interfaces; - if (interfaces !== null && interfaces.has(target)) return true; + if (interfaces) { + for (let _values = Set_values(interfaces), i = 0, k = _values.length; i < k; ++i) { + let iface = _values[i]; + if (iface.isAssignableTo(target)) return true; + } + } } current = current.base; } while (current); diff --git a/src/resolver.ts b/src/resolver.ts index 6855de3699..1ef1605c49 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -2872,7 +2872,7 @@ export class Resolver extends DiagnosticEmitter { } /** Currently resolving classes. */ - private resolveClassPending: Class[] = []; + private resolveClassPending: Set = new Set(); /** Resolves a class prototype using the specified concrete type arguments. */ resolveClass( @@ -2902,7 +2902,7 @@ export class Resolver extends DiagnosticEmitter { } prototype.setResolvedInstance(instanceKey, instance); var pendingClasses = this.resolveClassPending; - pendingClasses.push(instance); + pendingClasses.add(instance); // Insert contextual type arguments for this operation. Internally, this method is always // called with matching type parameter / argument counts. @@ -2920,6 +2920,8 @@ export class Resolver extends DiagnosticEmitter { } instance.contextualTypeArguments = ctxTypes; + var anyPending = false; + // Resolve base class if applicable var basePrototype = prototype.basePrototype; if (basePrototype) { @@ -2951,13 +2953,12 @@ export class Resolver extends DiagnosticEmitter { // derived classes once the base class's `finishResolveClass` is done. // This is guaranteed to never happen at the entry of the recursion, i.e. // where `resolveClass` is called from other code. - if (pendingClasses.includes(base)) return instance; + if (pendingClasses.has(base)) anyPending = true; } // Resolve interfaces if applicable var interfacePrototypes = prototype.interfacePrototypes; if (interfacePrototypes) { - let anyPending = false; for (let i = 0, k = interfacePrototypes.length; i < k; ++i) { let interfacePrototype = interfacePrototypes[i]; let current: ClassPrototype | null = interfacePrototype; @@ -2984,12 +2985,12 @@ export class Resolver extends DiagnosticEmitter { if (!iface) return null; assert(iface.kind == ElementKind.INTERFACE); instance.addInterface(iface); - if (pendingClasses.includes(iface)) anyPending = true; - } - // Like above, if any implemented interface is still pending, yield - if (anyPending) return instance; + // Like above, if any implemented interface is still pending, yield + if (pendingClasses.has(iface)) anyPending = true; + } } + if (anyPending) return instance; // We only get here if the base class has been fully resolved already. this.finishResolveClass(instance, reportMode); @@ -3006,7 +3007,7 @@ export class Resolver extends DiagnosticEmitter { var instanceMembers = instance.members; if (!instanceMembers) instance.members = instanceMembers = new Map(); - var pending = this.resolveClassPending; + var pendingClasses = this.resolveClassPending; var unimplemented = new Map(); // Alias interface members @@ -3014,7 +3015,7 @@ export class Resolver extends DiagnosticEmitter { if (interfaces) { for (let _values = Set_values(interfaces), i = 0, k = _values.length; i < k; ++i) { let iface = _values[i]; - assert(!pending.includes(iface)); + assert(!pendingClasses.has(iface)); let ifaceMembers = iface.members; if (ifaceMembers) { for (let _keys = Map_keys(ifaceMembers), i = 0, k = _keys.length; i < k; ++i) { @@ -3041,7 +3042,7 @@ export class Resolver extends DiagnosticEmitter { var memoryOffset: u32 = 0; var base = instance.base; if (base) { - assert(!pending.includes(base)); + assert(!pendingClasses.has(base)); let baseMembers = base.members; if (baseMembers) { // TODO: for (let [baseMemberName, baseMember] of baseMembers) { @@ -3293,21 +3294,27 @@ export class Resolver extends DiagnosticEmitter { } // Remove this class from pending - var pendingIndex = pending.indexOf(instance); - assert(~pendingIndex); // must be pending - pending.splice(pendingIndex, 1); + assert(pendingClasses.has(instance)); // must be pending + pendingClasses.delete(instance); // Finish derived classes that we postponed in `resolveClass` due to the // base class still being pending, again triggering `finishResolveClass` // of any classes derived from those classes, ultimately leading to all // pending classes being resolved. - var derivedPendingClasses = new Array(); - for (let i = 0, k = pending.length; i < k; ++i) { - let other = pending[i]; - if (instance == other.base) derivedPendingClasses.push(other); - } - for (let i = 0, k = derivedPendingClasses.length; i < k; ++i) { - this.finishResolveClass(derivedPendingClasses[i], reportMode); + for (let _values = Set_values(pendingClasses), i = 0, k = _values.length; i < k; ++i) { + let pending = _values[i]; + let dependsOnInstance = pending.base === instance; + let interfaces = pending.interfaces; + if (interfaces) { + let anyPending = false; + for (let _values2 = Set_values(interfaces), j = 0, l = _values2.length; j < l; ++j) { + let iface = _values2[j]; + if (iface === instance) dependsOnInstance = true; + else if (pendingClasses.has(iface)) anyPending = true; + } + if (anyPending) continue; + } + if (dependsOnInstance) this.finishResolveClass(pending, reportMode); } } diff --git a/src/types.ts b/src/types.ts index a0b0f862fb..a9d68b64f8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -223,6 +223,19 @@ export class Type { return cachedNullableType; } + /** Tests if this type equals the specified. */ + equals(other: Type): bool { + if (this.kind != other.kind) return false; + if (this.is(TypeFlags.REFERENCE)) { + return ( + this.classReference == other.classReference && + this.signatureReference == other.signatureReference && + this.is(TypeFlags.NULLABLE) == other.is(TypeFlags.NULLABLE) + ); + } + return true; + } + /** Tests if a value of this type is assignable to the target type incl. implicit conversion. */ isAssignableTo(target: Type, signednessIsRelevant: bool = false): bool { var currentClass: Class | null; @@ -613,19 +626,40 @@ export class Signature { : getDefaultParameterName(index); } - /** Tests if a value of this function type is assignable to a target of the specified function type. */ - isAssignableTo(target: Signature): bool { - // TODO: allow additional optional parameters - return this.equals(target); + /** Tests if this signature equals the specified. */ + equals(other: Signature): bool { + + // check `this` type + var thisThisType = this.thisType; + var otherThisType = other.thisType; + if (thisThisType !== null) { + if (otherThisType === null || !thisThisType.equals(otherThisType)) return false; + } else if (otherThisType) { + return false; + } + + // check rest parameter + if (this.hasRest != other.hasRest) return false; + + // check parameter types + var thisParameterTypes = this.parameterTypes; + var otherParameterTypes = other.parameterTypes; + var numParameters = thisParameterTypes.length; + if (numParameters != otherParameterTypes.length) return false; + for (let i = 0; i < numParameters; ++i) { + if (!thisParameterTypes[i].equals(otherParameterTypes[i])) return false; + } + + // check return type + return this.returnType.equals(other.returnType); } - /** Tests to see if a signature equals another signature. */ - equals(value: Signature): bool { - // TODO: maybe cache results? + /** Tests if a value of this function type is assignable to a target of the specified function type. */ + isAssignableTo(target: Signature, requireSameSize: bool = false): bool { // check `this` type var thisThisType = this.thisType; - var targetThisType = value.thisType; + var targetThisType = target.thisType; if (thisThisType !== null) { if (targetThisType === null || !thisThisType.isAssignableTo(targetThisType)) return false; } else if (targetThisType) { @@ -633,13 +667,13 @@ export class Signature { } // check rest parameter - if (this.hasRest != value.hasRest) return false; // TODO + if (this.hasRest != target.hasRest) return false; // TODO // check parameter types var thisParameterTypes = this.parameterTypes; - var targetParameterTypes = value.parameterTypes; + var targetParameterTypes = target.parameterTypes; var numParameters = thisParameterTypes.length; - if (numParameters != targetParameterTypes.length) return false; + if (numParameters != targetParameterTypes.length) return false; // TODO for (let i = 0; i < numParameters; ++i) { let thisParameterType = thisParameterTypes[i]; let targetParameterType = targetParameterTypes[i]; @@ -648,7 +682,7 @@ export class Signature { // check return type var thisReturnType = this.returnType; - var targetReturnType = value.returnType; + var targetReturnType = target.returnType; return thisReturnType == targetReturnType || thisReturnType.isAssignableTo(targetReturnType); } diff --git a/tests/compiler/builtins.optimized.wat b/tests/compiler/builtins.optimized.wat index 6519d8b304..231b370383 100644 --- a/tests/compiler/builtins.optimized.wat +++ b/tests/compiler/builtins.optimized.wat @@ -592,9 +592,9 @@ i32.const 5 f64.const 0 f64.const 0 - f64.const 12 - f64.const 25 - f64.const 25 + f64.const 29 + f64.const 30 + f64.const 30 call $~lib/builtins/trace i32.const 1216 i32.const 1216 diff --git a/tests/compiler/builtins.untouched.wat b/tests/compiler/builtins.untouched.wat index 6198203d17..681b05101f 100644 --- a/tests/compiler/builtins.untouched.wat +++ b/tests/compiler/builtins.untouched.wat @@ -1561,11 +1561,11 @@ local.set $0 i32.const 0 local.set $1 - i32.const 12 + i32.const 29 local.set $6 - i32.const 25 + i32.const 30 local.set $7 - i32.const 25 + i32.const 30 local.set $8 i32.const 128 i32.const 5 @@ -1605,7 +1605,7 @@ unreachable end local.get $6 - i32.const 12 + i32.const 29 i32.eq i32.eqz if diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index 2682e64f59..15d5a27171 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -14,10 +14,12 @@ (data (i32.const 1168) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00C") (data (i32.const 1200) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00F") (data (i32.const 1232) "\04\00\00\00\01\00\00\00\01\00\00\00\04\00\00\00I\00B") + (data (i32.const 1264) "\04\00\00\00\01\00\00\00\01\00\00\00\04\00\00\00I\00C") (global $class-overloading/which (mut i32) (i32.const 1040)) (global $~lib/rt/stub/offset (mut i32) (i32.const 0)) (global $class-overloading/a (mut i32) (i32.const 0)) (global $class-overloading/ia (mut i32) (i32.const 0)) + (global $class-overloading/ic (mut i32) (i32.const 0)) (global $~started (mut i32) (i32.const 0)) (export "_start" (func $~start)) (export "memory" (memory $0)) @@ -261,7 +263,7 @@ call $class-overloading/D#constructor ) (func $start:class-overloading - i32.const 1264 + i32.const 1296 global.set $~lib/rt/stub/offset i32.const 0 call $class-overloading/B#constructor @@ -596,28 +598,35 @@ global.set $class-overloading/ia i32.const 1040 global.set $class-overloading/which - block $__inlined_func$class-overloading/IA#foo|virtual - global.get $class-overloading/ia - i32.const 8 - i32.sub - i32.load - i32.const 10 - i32.eq - if - i32.const 1248 - global.set $class-overloading/which - br $__inlined_func$class-overloading/IA#foo|virtual - end + global.get $class-overloading/ia + call $class-overloading/IA#foo|virtual + global.get $class-overloading/which + i32.const 1248 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 1120 + i32.const 162 + i32.const 1 + call $~lib/builtins/abort unreachable end + i32.const 12 + call $~lib/rt/stub/__alloc + global.set $class-overloading/ic + i32.const 1040 + global.set $class-overloading/which + global.get $class-overloading/ic + call $class-overloading/IA#foo|virtual global.get $class-overloading/which - i32.const 1248 + i32.const 1280 call $~lib/string/String.__eq i32.eqz if i32.const 0 i32.const 1120 - i32.const 161 + i32.const 177 i32.const 1 call $~lib/builtins/abort unreachable @@ -712,4 +721,31 @@ i32.const 1056 global.set $class-overloading/which ) + (func $class-overloading/IA#foo|virtual (param $0 i32) + block $default + block $case1 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.tee $0 + i32.const 10 + i32.ne + if + local.get $0 + i32.const 12 + i32.eq + br_if $case1 + br $default + end + i32.const 1248 + global.set $class-overloading/which + return + end + i32.const 1280 + global.set $class-overloading/which + return + end + unreachable + ) ) diff --git a/tests/compiler/class-overloading.ts b/tests/compiler/class-overloading.ts index a83bfee2ce..d8f9cf1241 100644 --- a/tests/compiler/class-overloading.ts +++ b/tests/compiler/class-overloading.ts @@ -145,17 +145,33 @@ which = ""; a.c = 1; assert(which == "F"); +// Should work with interfaces interface IA { foo(): void; } -class IB implements IA { +class CA implements IA { foo(): void { which = "IB"; } } -var ia: IA = new IB(); +var ia: IA = new CA(); which = ""; ia.foo(); assert(which == "IB"); + +// Should work with extended interfaces +interface IC extends IA { +} + +class CC implements IC { + foo(): void { + which = "IC"; + } +} + +var ic: IC = new CC(); +which = ""; +ic.foo(); +assert(which == "IC"); diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index a0ed0f8a6d..807c001c80 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -15,6 +15,7 @@ (data (i32.const 160) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00C\00") (data (i32.const 192) "\02\00\00\00\01\00\00\00\01\00\00\00\02\00\00\00F\00") (data (i32.const 224) "\04\00\00\00\01\00\00\00\01\00\00\00\04\00\00\00I\00B\00") + (data (i32.const 256) "\04\00\00\00\01\00\00\00\01\00\00\00\04\00\00\00I\00C\00") (table $0 1 funcref) (global $class-overloading/which (mut i32) (i32.const 32)) (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0)) @@ -23,8 +24,9 @@ (global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0)) (global $class-overloading/c (mut i32) (i32.const 0)) (global $class-overloading/ia (mut i32) (i32.const 0)) + (global $class-overloading/ic (mut i32) (i32.const 0)) (global $~started (mut i32) (i32.const 0)) - (global $~lib/heap/__heap_base i32 (i32.const 244)) + (global $~lib/heap/__heap_base i32 (i32.const 276)) (export "_start" (func $~start)) (export "memory" (memory $0)) (func $~lib/rt/stub/maybeGrowMemory (param $0 i32) @@ -528,7 +530,7 @@ local.set $0 local.get $0 ) - (func $class-overloading/IB#constructor (param $0 i32) (result i32) + (func $class-overloading/CA#constructor (param $0 i32) (result i32) local.get $0 i32.eqz if @@ -543,6 +545,18 @@ (func $class-overloading/IA#foo (param $0 i32) unreachable ) + (func $class-overloading/CC#constructor (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 12 + call $~lib/rt/stub/__alloc + call $~lib/rt/stub/__retain + local.set $0 + end + local.get $0 + ) (func $start:class-overloading (local $0 i32) global.get $~lib/heap/__heap_base @@ -979,7 +993,7 @@ unreachable end i32.const 0 - call $class-overloading/IB#constructor + call $class-overloading/CA#constructor global.set $class-overloading/ia i32.const 32 local.set $0 @@ -996,7 +1010,30 @@ if i32.const 0 i32.const 112 - i32.const 161 + i32.const 162 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + i32.const 0 + call $class-overloading/CC#constructor + global.set $class-overloading/ic + i32.const 32 + local.set $0 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $0 + global.set $class-overloading/which + global.get $class-overloading/ic + call $class-overloading/IA#foo|virtual + global.get $class-overloading/which + i32.const 272 + call $~lib/string/String.__eq + i32.eqz + if + i32.const 0 + i32.const 112 + i32.const 177 i32.const 1 call $~lib/builtins/abort unreachable @@ -1281,7 +1318,7 @@ local.get $1 call $class-overloading/A#set:c ) - (func $class-overloading/IB#foo (param $0 i32) + (func $class-overloading/CA#foo (param $0 i32) (local $1 i32) i32.const 240 local.set $1 @@ -1290,23 +1327,41 @@ local.get $1 global.set $class-overloading/which ) + (func $class-overloading/CC#foo (param $0 i32) + (local $1 i32) + i32.const 272 + local.set $1 + global.get $class-overloading/which + call $~lib/rt/stub/__release + local.get $1 + global.set $class-overloading/which + ) (func $class-overloading/IA#foo|virtual (param $0 i32) (local $1 i32) block $default - block $case0 + block $case1 + block $case0 + local.get $0 + i32.const 8 + i32.sub + i32.load + local.set $1 + local.get $1 + i32.const 10 + i32.eq + br_if $case0 + local.get $1 + i32.const 12 + i32.eq + br_if $case1 + br $default + end local.get $0 - i32.const 8 - i32.sub - i32.load - local.set $1 - local.get $1 - i32.const 10 - i32.eq - br_if $case0 - br $default + call $class-overloading/CA#foo + return end local.get $0 - call $class-overloading/IB#foo + call $class-overloading/CC#foo return end unreachable From af882030529efd33f5edf1dec924407ed244d84c Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 18 Apr 2020 04:37:50 +0200 Subject: [PATCH 19/24] abstract checks --- src/compiler.ts | 7 ++++ src/diagnosticMessages.generated.ts | 2 ++ src/diagnosticMessages.json | 1 + src/diagnostics.ts | 44 +++++++++++++++++------ src/parser.ts | 2 +- src/program.ts | 41 +++++++++++++++++---- src/resolver.ts | 20 +++++------ src/tokenizer.ts | 4 +++ tests/compiler/class-abstract-errors.json | 11 ++++++ tests/compiler/class-abstract-errors.ts | 29 +++++++++++++++ tests/parser/class-abstract.ts | 3 ++ tests/parser/class-abstract.ts.fixture.ts | 4 +++ 12 files changed, 140 insertions(+), 28 deletions(-) create mode 100644 tests/compiler/class-abstract-errors.json create mode 100644 tests/compiler/class-abstract-errors.ts create mode 100644 tests/parser/class-abstract.ts create mode 100644 tests/parser/class-abstract.ts.fixture.ts diff --git a/src/compiler.ts b/src/compiler.ts index fc02f90a1d..f58e4f5d92 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -8930,6 +8930,13 @@ export class Compiler extends DiagnosticEmitter { ); return this.module.unreachable(); } + if (target.is(CommonFlags.ABSTRACT)) { + this.error( + DiagnosticCode.Cannot_create_an_instance_of_an_abstract_class, + expression.typeName.range + ); + return this.module.unreachable(); + } var classPrototype = target; var classInstance: Class | null = null; var typeArguments = expression.typeArguments; diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index cd78c52749..9d54793471 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -143,6 +143,7 @@ export enum DiagnosticCode { In_const_enum_declarations_member_initializer_must_be_constant_expression = 2474, Export_declaration_conflicts_with_exported_declaration_of_0 = 2484, _0_is_referenced_directly_or_indirectly_in_its_own_base_expression = 2506, + Cannot_create_an_instance_of_an_abstract_class = 2511, Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_2 = 2515, Object_is_possibly_null = 2531, Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property = 2540, @@ -305,6 +306,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2474: return "In 'const' enum declarations member initializer must be constant expression."; case 2484: return "Export declaration conflicts with exported declaration of '{0}'."; case 2506: return "'{0}' is referenced directly or indirectly in its own base expression."; + case 2511: return "Cannot create an instance of an abstract class."; case 2515: return "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from '{2}'."; case 2531: return "Object is possibly 'null'."; case 2540: return "Cannot assign to '{0}' because it is a constant or a read-only property."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 13d590e687..9fb87a0e31 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -139,6 +139,7 @@ "In 'const' enum declarations member initializer must be constant expression.": 2474, "Export declaration conflicts with exported declaration of '{0}'.": 2484, "'{0}' is referenced directly or indirectly in its own base expression.": 2506, + "Cannot create an instance of an abstract class.": 2511, "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from '{2}'.": 2515, "Object is possibly 'null'.": 2531, "Cannot assign to '{0}' because it is a constant or a read-only property.": 2540, diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 9b0a393971..5ae875b2b8 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -88,7 +88,7 @@ export class DiagnosticMessage { /** Respective source range, if any. */ range: Range | null = null; /** Related range, if any. */ - relatedRange: Range | null = null; + relatedRange: Range | null = null; // TODO: Make this a related message for chains? /** Constructs a new diagnostic message. */ private constructor(code: i32, category: DiagnosticCategory, message: string) { @@ -112,6 +112,26 @@ export class DiagnosticMessage { return new DiagnosticMessage(code, category, message); } + /** Tests if this message equals the specified. */ + equals(other: DiagnosticMessage): bool { + if (this.code != other.code) return false; + var thisRange = this.range; + var otherRange = other.range; + if (thisRange) { + if (!otherRange || !thisRange.equals(otherRange)) return false; + } else if (otherRange) { + return false; + } + var thisRelatedRange = this.relatedRange; + var otherRelatedRange = other.relatedRange; + if (thisRelatedRange) { + if (!otherRelatedRange || !thisRelatedRange.equals(otherRelatedRange)) return false; + } else if (otherRange) { + return false; + } + return this.message == other.message; + } + /** Adds a source range to this message. */ withRange(range: Range): this { this.range = range; @@ -248,7 +268,7 @@ export abstract class DiagnosticEmitter { /** Diagnostic messages emitted so far. */ diagnostics: DiagnosticMessage[]; /** Diagnostic messages already seen, by range. */ - private seen: Map> = new Map(); + private seen: Map> = new Map(); /** Initializes this diagnostic emitter. */ protected constructor(diagnostics: DiagnosticMessage[] | null = null) { @@ -265,6 +285,9 @@ export abstract class DiagnosticEmitter { arg1: string | null = null, arg2: string | null = null ): void { + var message = DiagnosticMessage.create(code, category, arg0, arg1, arg2); + if (range) message = message.withRange(range); + if (relatedRange) message.relatedRange = relatedRange; // It is possible that the same diagnostic is emitted twice, for example // when compiling generics with different types or when recompiling a loop // because our initial assumptions didn't hold. It is even possible to get @@ -274,21 +297,20 @@ export abstract class DiagnosticEmitter { if (seen.has(range.source)) { let seenInSource = assert(seen.get(range.source)); if (seenInSource.has(range.start)) { - let seenCodesAtPos = assert(seenInSource.get(range.start)); - if (seenCodesAtPos.includes(code)) return; - seenCodesAtPos.push(code); + let seenMessagesAtPos = assert(seenInSource.get(range.start)); + for (let i = 0, k = seenMessagesAtPos.length; i < k; ++i) { + if (seenMessagesAtPos[i].equals(message)) return; + } + seenMessagesAtPos.push(message); } else { - seenInSource.set(range.start, [ code ]); + seenInSource.set(range.start, [ message ]); } } else { - let seenInSource = new Map(); - seenInSource.set(range.start, [ code ]); + let seenInSource = new Map(); + seenInSource.set(range.start, [ message ]); seen.set(range.source, seenInSource); } } - var message = DiagnosticMessage.create(code, category, arg0, arg1, arg2); - if (range) message = message.withRange(range); - if (relatedRange) message.relatedRange = relatedRange; this.diagnostics.push(message); // console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary // console.log(new Error("stack").stack); diff --git a/src/parser.ts b/src/parser.ts index 914a6a71ea..045d08ffc3 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1856,7 +1856,7 @@ export class Parser extends DiagnosticEmitter { } else { flags |= CommonFlags.INSTANCE; if (tn.skip(Token.ABSTRACT)) { - if (isInterface) { + if (isInterface || !parent.is(CommonFlags.ABSTRACT)) { this.error( DiagnosticCode._0_modifier_cannot_be_used_here, tn.range(), "abstract" diff --git a/src/program.ts b/src/program.ts index 2051a51fc1..d855480b69 100644 --- a/src/program.ts +++ b/src/program.ts @@ -2634,13 +2634,15 @@ export abstract class DeclaredElement extends Element { return this.declaration.name; } - /** Gets the signature node, if applicable, otherwise the identifier node. */ - get signatureOrIdentifierNode(): Node { + /** Gets the signature node, if applicable, along the identifier node. */ + get identifierAndSignatureRange(): Range { var declaration = this.declaration; + var identifierNode = declaration.name; if (declaration.kind == NodeKind.FUNCTIONDECLARATION || declaration.kind == NodeKind.METHODDECLARATION) { - return (declaration).signature; + let signatureNode = (declaration).signature; + return Range.join(identifierNode.range, signatureNode.range); } - return declaration.name; + return identifierNode.range; } /** Gets the assiciated decorator nodes. */ @@ -2652,8 +2654,35 @@ export abstract class DeclaredElement extends Element { isCompatibleOverride(base: DeclaredElement): bool { var self: DeclaredElement = this; // TS var kind = self.kind; - if (kind == base.kind && kind == ElementKind.FUNCTION) { - return (self).signature.isAssignableTo((base).signature, /* sameSize */ true); + if (kind == base.kind) { + switch (kind) { + case ElementKind.FUNCTION: { + return (self).signature.isAssignableTo((base).signature, /* sameSize */ true); + } + case ElementKind.PROPERTY: { + let selfProperty = self; + let baseProperty = base; + let selfGetter = selfProperty.getterInstance; + let baseGetter = baseProperty.getterInstance; + if (selfGetter) { + if (!baseGetter || !selfGetter.signature.isAssignableTo(baseGetter.signature, true)) { + return false; + } + } else if (baseGetter) { + return false; + } + let selfSetter = selfProperty.setterInstance; + let baseSetter = baseProperty.setterInstance; + if (selfSetter) { + if (!baseSetter || !selfSetter.signature.isAssignableTo(baseSetter.signature, true)) { + return false; + } + } else if (baseSetter) { + return false; + } + return true; + } + } } return false; } diff --git a/src/resolver.ts b/src/resolver.ts index 1ef1605c49..f6b374280f 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -3004,8 +3004,8 @@ export class Resolver extends DiagnosticEmitter { /** How to proceed with eventual diagnostics. */ reportMode: ReportMode ): void { - var instanceMembers = instance.members; - if (!instanceMembers) instance.members = instanceMembers = new Map(); + var members = instance.members; + if (!members) instance.members = members = new Map(); var pendingClasses = this.resolveClassPending; var unimplemented = new Map(); @@ -3021,17 +3021,17 @@ export class Resolver extends DiagnosticEmitter { for (let _keys = Map_keys(ifaceMembers), i = 0, k = _keys.length; i < k; ++i) { let memberName = unchecked(_keys[i]); let member = assert(ifaceMembers.get(memberName)); - if (instanceMembers.has(memberName)) { - let existing = assert(instanceMembers.get(memberName)); + if (members.has(memberName)) { + let existing = assert(members.get(memberName)); if (!member.isCompatibleOverride(existing)) { this.errorRelated( DiagnosticCode.This_overload_signature_is_not_compatible_with_its_implementation_signature, - member.signatureOrIdentifierNode.range, existing.signatureOrIdentifierNode.range + member.identifierAndSignatureRange, existing.identifierAndSignatureRange ); continue; } } - instanceMembers.set(memberName, member); + members.set(memberName, member); unimplemented.set(memberName, member); } } @@ -3049,17 +3049,17 @@ export class Resolver extends DiagnosticEmitter { for (let _keys = Map_keys(baseMembers), i = 0, k = _keys.length; i < k; ++i) { let memberName = unchecked(_keys[i]); let member = assert(baseMembers.get(memberName)); - if (instanceMembers.has(memberName)) { - let existing = assert(instanceMembers.get(memberName)); + if (members.has(memberName)) { + let existing = assert(members.get(memberName)); if (!member.isCompatibleOverride(existing)) { this.errorRelated( DiagnosticCode.This_overload_signature_is_not_compatible_with_its_implementation_signature, - member.signatureOrIdentifierNode.range, existing.signatureOrIdentifierNode.range + member.identifierAndSignatureRange, existing.identifierAndSignatureRange ); continue; } } - instanceMembers.set(memberName, member); + members.set(memberName, member); if (member.is(CommonFlags.ABSTRACT)) { unimplemented.set(memberName, member); } else { diff --git a/src/tokenizer.ts b/src/tokenizer.ts index c0235bd9cb..c0565c1f86 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -418,6 +418,10 @@ export class Range { ); } + equals(other: Range): bool { + return this.source == other.source && this.start == other.start && this.end == other.end; + } + get atStart(): Range { return new Range(this.source, this.start, this.start); } diff --git a/tests/compiler/class-abstract-errors.json b/tests/compiler/class-abstract-errors.json new file mode 100644 index 0000000000..348da60657 --- /dev/null +++ b/tests/compiler/class-abstract-errors.json @@ -0,0 +1,11 @@ +{ + "asc_flags": [ + "--runtime none" + ], + "stderr": [ + "TS2511: Cannot create an instance of an abstract class.", + "TS2515: Non-abstract class 'class-abstract-errors/Baz' does not implement inherited abstract member 'bar'", + "TS2515: Non-abstract class 'class-abstract-errors/Baz' does not implement inherited abstract member 'a'", + "EOF" + ] +} \ No newline at end of file diff --git a/tests/compiler/class-abstract-errors.ts b/tests/compiler/class-abstract-errors.ts new file mode 100644 index 0000000000..76441f9e6e --- /dev/null +++ b/tests/compiler/class-abstract-errors.ts @@ -0,0 +1,29 @@ +abstract class Foo { + abstract bar(): void; + abstract get a(): i32; + abstract set a(a: i32); +} + +new Foo(); // TS2511: Cannot create an instance of an abstract class. + +class Baz extends Foo { + // TS2515: Non-abstract class 'Baz' does not implement inherited abstract member 'bar' from 'Foo' + // TS2515: Non-abstract class 'Baz' does not implement inherited abstract member 'a' from 'Foo' +} + +new Baz(); + +class Qux extends Foo { + bar(): i32 { + return 1; + } + get a(): i32 { return 0; } + set a(a: i32) {} +} + +// TODO: This does not check .bar overload +var qux = new Qux(); +// But this does: var qux: Foo = new Qux(); +qux.bar(); + +ERROR("EOF"); diff --git a/tests/parser/class-abstract.ts b/tests/parser/class-abstract.ts new file mode 100644 index 0000000000..1de205573b --- /dev/null +++ b/tests/parser/class-abstract.ts @@ -0,0 +1,3 @@ +class Foo { + abstract bar(): void; +} diff --git a/tests/parser/class-abstract.ts.fixture.ts b/tests/parser/class-abstract.ts.fixture.ts new file mode 100644 index 0000000000..46329b94dc --- /dev/null +++ b/tests/parser/class-abstract.ts.fixture.ts @@ -0,0 +1,4 @@ +class Foo { + abstract bar(): void; +} +// ERROR 1042: "'abstract' modifier cannot be used here." in class-abstract.ts:2:3 From aac2271b5ddc38d60de4fdb833ce9eaf6988d066 Mon Sep 17 00:00:00 2001 From: dcode Date: Sun, 19 Apr 2020 06:20:07 +0200 Subject: [PATCH 20/24] interface error tests, set stealth fix --- src/diagnosticMessages.generated.ts | 2 + src/diagnosticMessages.json | 1 + src/diagnostics.ts | 9 +- src/parser.ts | 66 +- std/assembly/set.ts | 1 + tests/compiler/std/set.optimized.wat | 690 ++++++++++-------- tests/compiler/std/set.untouched.wat | 162 +++- tests/parser/class-abstract.ts.fixture.ts | 5 +- tests/parser/class.ts.fixture.ts | 16 +- tests/parser/continue-on-error.ts.fixture.ts | 4 +- ...efinite-assignment-assertion.ts.fixture.ts | 6 +- tests/parser/function-type.ts.fixture.ts | 2 +- tests/parser/interface-errors.ts | 22 + tests/parser/interface-errors.ts.fixture.ts | 29 + tests/parser/namespace.ts.fixture.ts | 4 +- tests/parser/numeric-separators.ts.fixture.ts | 16 +- tests/parser/optional-property.ts.fixture.ts | 2 +- .../optional-typeparameters.ts.fixture.ts | 2 +- tests/parser/parameter-order.ts.fixture.ts | 6 +- tests/parser/regexp.ts.fixture.ts | 10 +- tests/parser/var.ts.fixture.ts | 4 +- 21 files changed, 685 insertions(+), 374 deletions(-) create mode 100644 tests/parser/interface-errors.ts create mode 100644 tests/parser/interface-errors.ts.fixture.ts diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index 9d54793471..36543a0d23 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -42,6 +42,7 @@ export enum DiagnosticCode { Expression_resolves_to_unusual_type_0 = 226, Function_0_is_virtual_and_will_not_be_inlined = 227, Property_0_only_has_a_setter_and_is_missing_a_getter = 228, + _0_keyword_cannot_be_used_here = 229, Type_0_is_cyclic_Module_will_include_deferred_garbage_collection = 900, Importing_the_table_disables_some_indirect_call_optimizations = 901, Exporting_the_table_disables_some_indirect_call_optimizations = 902, @@ -205,6 +206,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 226: return "Expression resolves to unusual type '{0}'."; case 227: return "Function '{0}' is virtual and will not be inlined."; case 228: return "Property '{0}' only has a setter and is missing a getter."; + case 229: return "'{0}' keyword cannot be used here."; case 900: return "Type '{0}' is cyclic. Module will include deferred garbage collection."; case 901: return "Importing the table disables some indirect call optimizations."; case 902: return "Exporting the table disables some indirect call optimizations."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 9fb87a0e31..9b3d73245e 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -35,6 +35,7 @@ "Expression resolves to unusual type '{0}'.": 226, "Function '{0}' is virtual and will not be inlined.": 227, "Property '{0}' only has a setter and is missing a getter.": 228, + "'{0}' keyword cannot be used here.": 229, "Type '{0}' is cyclic. Module will include deferred garbage collection.": 900, "Importing the table disables some indirect call optimizations.": 901, diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 5ae875b2b8..f32723fba3 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -157,10 +157,13 @@ export class DiagnosticMessage { this.message + "\" in " + source.normalizedPath + - ":" + + "(" + source.lineAt(range.start).toString() + - ":" + - source.columnAt().toString() + "," + + source.columnAt().toString() + + "+" + + (range.end - range.start).toString() + + ")" ); } return ( diff --git a/src/parser.ts b/src/parser.ts index 045d08ffc3..791c4f0eb6 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -256,7 +256,21 @@ export class Parser extends DiagnosticEmitter { case Token.ABSTRACT: { let state = tn.mark(); tn.next(); - if (!tn.skip(Token.CLASS)) { + let abstractStart = tn.tokenPos; + let abstractEnd = tn.pos; + let next = tn.peek(true); + if (tn.nextTokenOnNewLine) { + tn.reset(state); + statement = this.parseStatement(tn, true); + break; + } + if (next != Token.CLASS) { + if (next == Token.INTERFACE) { + this.error( + DiagnosticCode._abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration, + tn.range(abstractStart, abstractEnd) + ); + } tn.reset(state); statement = this.parseStatement(tn, true); break; @@ -1809,33 +1823,36 @@ export class Parser extends DiagnosticEmitter { DiagnosticCode._0_modifier_cannot_be_used_here, tn.range(), "public" ); + } else { + flags |= CommonFlags.PUBLIC; + accessStart = tn.tokenPos; + accessEnd = tn.pos; } - flags |= CommonFlags.PUBLIC; - accessStart = tn.tokenPos; - accessEnd = tn.pos; - if (!startPos) startPos = accessStart; + if (!startPos) startPos = tn.tokenPos; } else if (tn.skip(Token.PRIVATE)) { if (isInterface) { this.error( DiagnosticCode._0_modifier_cannot_be_used_here, tn.range(), "private" ); + } else { + flags |= CommonFlags.PRIVATE; + accessStart = tn.tokenPos; + accessEnd = tn.pos; } - flags |= CommonFlags.PRIVATE; - accessStart = tn.tokenPos; - accessEnd = tn.pos; - if (!startPos) startPos = accessStart; + if (!startPos) startPos = tn.tokenPos; } else if (tn.skip(Token.PROTECTED)) { if (isInterface) { this.error( DiagnosticCode._0_modifier_cannot_be_used_here, tn.range(), "protected" ); + } else { + flags |= CommonFlags.PROTECTED; + accessStart = tn.tokenPos; + accessEnd = tn.pos; } - flags |= CommonFlags.PROTECTED; - accessStart = tn.tokenPos; - accessEnd = tn.pos; - if (!startPos) startPos = accessStart; + if (!startPos) startPos = tn.tokenPos; } var staticStart = 0; @@ -1848,11 +1865,12 @@ export class Parser extends DiagnosticEmitter { DiagnosticCode._0_modifier_cannot_be_used_here, tn.range(), "static" ); + } else { + flags |= CommonFlags.STATIC; + staticStart = tn.tokenPos; + staticEnd = tn.pos; } - flags |= CommonFlags.STATIC; - staticStart = tn.tokenPos; - staticEnd = tn.pos; - if (!startPos) startPos = staticStart; + if (!startPos) startPos = tn.tokenPos; } else { flags |= CommonFlags.INSTANCE; if (tn.skip(Token.ABSTRACT)) { @@ -1861,11 +1879,12 @@ export class Parser extends DiagnosticEmitter { DiagnosticCode._0_modifier_cannot_be_used_here, tn.range(), "abstract" ); + } else { + flags |= CommonFlags.ABSTRACT; + abstractStart = tn.tokenPos; + abstractEnd = tn.pos; } - flags |= CommonFlags.ABSTRACT; - abstractStart = tn.tokenPos; - abstractEnd = tn.pos; - if (!startPos) startPos = abstractStart; + if (!startPos) startPos = tn.tokenPos; } if (parent.flags & CommonFlags.GENERIC) flags |= CommonFlags.GENERIC_CONTEXT; } @@ -2079,6 +2098,11 @@ export class Parser extends DiagnosticEmitter { name.range ); } + } else if (name.text == "constructor") { + this.error( + DiagnosticCode._0_keyword_cannot_be_used_here, + name.range, "constructor" + ); } let returnType: TypeNode | null = null; diff --git a/std/assembly/set.ts b/std/assembly/set.ts index ca2a1ca299..17925f702b 100644 --- a/std/assembly/set.ts +++ b/std/assembly/set.ts @@ -191,6 +191,7 @@ export class Set { values[length++] = entry.key; } } + values.length = length; return values; } diff --git a/tests/compiler/std/set.optimized.wat b/tests/compiler/std/set.optimized.wat index 1c7f265d9b..b1ea7b863b 100644 --- a/tests/compiler/std/set.optimized.wat +++ b/tests/compiler/std/set.optimized.wat @@ -2069,6 +2069,18 @@ local.get $2 i32.store8 ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + local.get $0 + i32.load offset=12 + drop + local.get $0 + local.get $1 + i32.const 0 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -2080,11 +2092,11 @@ (local $8 i32) local.get $0 i32.load offset=8 - local.set $6 + local.set $5 local.get $0 i32.load offset=16 - local.tee $7 local.tee $4 + local.tee $8 i32.const 1073741808 i32.gt_u if @@ -2095,11 +2107,11 @@ call $~lib/builtins/abort unreachable end - local.get $4 + local.get $8 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $4 + local.tee $2 + local.get $8 call $~lib/memory/memory.fill i32.const 16 i32.const 4 @@ -2117,39 +2129,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $8 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $8 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $4 + local.get $8 i32.store offset=8 local.get $0 - local.get $4 + local.get $8 i32.store offset=12 loop $for-loop|0 - local.get $5 - local.get $7 + local.get $6 + local.get $4 i32.lt_s if - local.get $6 local.get $5 + local.get $6 i32.const 3 i32.shl i32.add @@ -2159,25 +2171,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $7 local.get $2 i32.load8_s call $~lib/array/Array#__set + local.get $7 + i32.const 1 + i32.add + local.set $7 end - local.get $5 + local.get $6 i32.const 1 i32.add - local.set $5 + local.set $6 br $for-loop|0 end end local.get $0 + local.get $7 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result i32) local.get $1 @@ -2844,11 +2858,11 @@ (local $8 i32) local.get $0 i32.load offset=8 - local.set $6 + local.set $5 local.get $0 i32.load offset=16 - local.tee $7 local.tee $4 + local.tee $8 i32.const 1073741808 i32.gt_u if @@ -2859,11 +2873,11 @@ call $~lib/builtins/abort unreachable end - local.get $4 + local.get $8 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $4 + local.tee $2 + local.get $8 call $~lib/memory/memory.fill i32.const 16 i32.const 6 @@ -2881,39 +2895,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $8 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $8 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $4 + local.get $8 i32.store offset=8 local.get $0 - local.get $4 + local.get $8 i32.store offset=12 loop $for-loop|0 - local.get $5 - local.get $7 + local.get $6 + local.get $4 i32.lt_s if - local.get $6 local.get $5 + local.get $6 i32.const 3 i32.shl i32.add @@ -2923,25 +2937,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $7 local.get $2 i32.load8_u call $~lib/array/Array#__set + local.get $7 + i32.const 1 + i32.add + local.set $7 end - local.get $5 + local.get $6 i32.const 1 i32.add - local.set $5 + local.set $6 br $for-loop|0 end end local.get $0 + local.get $7 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result i32) local.get $1 @@ -3687,6 +3703,18 @@ local.get $2 i32.store16 ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + local.get $0 + i32.load offset=12 + drop + local.get $0 + local.get $1 + i32.const 1 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -3699,12 +3727,12 @@ (local $9 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $4 local.get $0 i32.load offset=16 - local.tee $5 + local.tee $7 local.set $6 - local.get $5 + local.get $7 i32.const 536870904 i32.gt_u if @@ -3718,11 +3746,11 @@ local.get $6 i32.const 1 i32.shl - local.tee $7 + local.tee $5 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $7 + local.tee $2 + local.get $5 call $~lib/memory/memory.fill i32.const 16 i32.const 8 @@ -3740,39 +3768,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $9 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $9 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $7 + local.get $5 i32.store offset=8 local.get $0 local.get $6 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 + local.get $8 + local.get $7 i32.lt_s if - local.get $8 local.get $4 + local.get $8 i32.const 3 i32.shl i32.add @@ -3782,25 +3810,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $9 local.get $2 i32.load16_s call $~lib/array/Array#__set + local.get $9 + i32.const 1 + i32.add + local.set $9 end - local.get $4 + local.get $8 i32.const 1 i32.add - local.set $4 + local.set $8 br $for-loop|0 end end local.get $0 + local.get $9 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result i32) local.get $1 @@ -4470,12 +4500,12 @@ (local $9 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $4 local.get $0 i32.load offset=16 - local.tee $5 + local.tee $7 local.set $6 - local.get $5 + local.get $7 i32.const 536870904 i32.gt_u if @@ -4489,11 +4519,11 @@ local.get $6 i32.const 1 i32.shl - local.tee $7 + local.tee $5 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $7 + local.tee $2 + local.get $5 call $~lib/memory/memory.fill i32.const 16 i32.const 10 @@ -4511,39 +4541,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $9 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $9 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $7 + local.get $5 i32.store offset=8 local.get $0 local.get $6 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 + local.get $8 + local.get $7 i32.lt_s if - local.get $8 local.get $4 + local.get $8 i32.const 3 i32.shl i32.add @@ -4553,25 +4583,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $9 local.get $2 i32.load16_u call $~lib/array/Array#__set + local.get $9 + i32.const 1 + i32.add + local.set $9 end - local.get $4 + local.get $8 i32.const 1 i32.add - local.set $4 + local.set $8 br $for-loop|0 end end local.get $0 + local.get $9 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result i32) local.get $1 @@ -5325,6 +5357,18 @@ local.get $2 i32.store ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + local.get $0 + i32.load offset=12 + drop + local.get $0 + local.get $1 + i32.const 2 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -5337,12 +5381,12 @@ (local $9 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $4 local.get $0 i32.load offset=16 - local.tee $5 + local.tee $7 local.set $6 - local.get $5 + local.get $7 i32.const 268435452 i32.gt_u if @@ -5356,11 +5400,11 @@ local.get $6 i32.const 2 i32.shl - local.tee $7 + local.tee $5 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $7 + local.tee $2 + local.get $5 call $~lib/memory/memory.fill i32.const 16 i32.const 12 @@ -5378,39 +5422,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $9 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $9 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $7 + local.get $5 i32.store offset=8 local.get $0 local.get $6 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 - i32.lt_s + local.get $8 + local.get $7 + i32.lt_s if - local.get $8 local.get $4 + local.get $8 i32.const 3 i32.shl i32.add @@ -5420,25 +5464,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $9 local.get $2 i32.load call $~lib/array/Array#__set + local.get $9 + i32.const 1 + i32.add + local.set $9 end - local.get $4 + local.get $8 i32.const 1 i32.add - local.set $4 + local.set $8 br $for-loop|0 end end local.get $0 + local.get $9 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result i32) local.get $1 @@ -5861,12 +5907,12 @@ (local $9 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $4 local.get $0 i32.load offset=16 - local.tee $5 + local.tee $7 local.set $6 - local.get $5 + local.get $7 i32.const 268435452 i32.gt_u if @@ -5880,11 +5926,11 @@ local.get $6 i32.const 2 i32.shl - local.tee $7 + local.tee $5 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $7 + local.tee $2 + local.get $5 call $~lib/memory/memory.fill i32.const 16 i32.const 14 @@ -5902,39 +5948,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $9 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $9 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $7 + local.get $5 i32.store offset=8 local.get $0 local.get $6 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 + local.get $8 + local.get $7 i32.lt_s if - local.get $8 local.get $4 + local.get $8 i32.const 3 i32.shl i32.add @@ -5944,25 +5990,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $9 local.get $2 i32.load call $~lib/array/Array#__set + local.get $9 + i32.const 1 + i32.add + local.set $9 end - local.get $4 + local.get $8 i32.const 1 i32.add - local.set $4 + local.set $8 br $for-loop|0 end end local.get $0 + local.get $9 + call $~lib/array/Array#set:length + local.get $0 ) (func $std/set/testNumeric (local $0 i32) @@ -6694,6 +6742,18 @@ local.get $2 i64.store ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + local.get $0 + i32.load offset=12 + drop + local.get $0 + local.get $1 + i32.const 3 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -6706,12 +6766,12 @@ (local $9 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $4 local.get $0 i32.load offset=16 - local.tee $5 + local.tee $7 local.set $6 - local.get $5 + local.get $7 i32.const 134217726 i32.gt_u if @@ -6725,11 +6785,11 @@ local.get $6 i32.const 3 i32.shl - local.tee $7 + local.tee $5 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $7 + local.tee $2 + local.get $5 call $~lib/memory/memory.fill i32.const 16 i32.const 16 @@ -6747,39 +6807,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $9 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $9 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $7 + local.get $5 i32.store offset=8 local.get $0 local.get $6 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 + local.get $8 + local.get $7 i32.lt_s if - local.get $8 local.get $4 + local.get $8 i32.const 4 i32.shl i32.add @@ -6789,25 +6849,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $9 local.get $2 i64.load call $~lib/array/Array#__set + local.get $9 + i32.const 1 + i32.add + local.set $9 end - local.get $4 + local.get $8 i32.const 1 i32.add - local.set $4 + local.set $8 br $for-loop|0 end end local.get $0 + local.get $9 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result i64) local.get $1 @@ -7232,12 +7294,12 @@ (local $9 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $4 local.get $0 i32.load offset=16 - local.tee $5 + local.tee $7 local.set $6 - local.get $5 + local.get $7 i32.const 134217726 i32.gt_u if @@ -7251,11 +7313,11 @@ local.get $6 i32.const 3 i32.shl - local.tee $7 + local.tee $5 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $1 - local.get $7 + local.tee $2 + local.get $5 call $~lib/memory/memory.fill i32.const 16 i32.const 18 @@ -7273,39 +7335,39 @@ local.get $0 i32.const 0 i32.store offset=12 - local.get $1 - local.set $2 - local.get $1 + local.get $2 + local.set $1 + local.get $2 local.get $0 i32.load - local.tee $9 + local.tee $3 i32.ne if - local.get $2 + local.get $1 call $~lib/rt/pure/__retain - local.set $2 - local.get $9 + local.set $1 + local.get $3 call $~lib/rt/pure/__release end local.get $0 - local.get $2 + local.get $1 i32.store local.get $0 - local.get $1 + local.get $2 i32.store offset=4 local.get $0 - local.get $7 + local.get $5 i32.store offset=8 local.get $0 local.get $6 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 + local.get $8 + local.get $7 i32.lt_s if - local.get $8 local.get $4 + local.get $8 i32.const 4 i32.shl i32.add @@ -7315,25 +7377,27 @@ i32.and i32.eqz if - local.get $3 - local.tee $1 - i32.const 1 - i32.add - local.set $3 local.get $0 - local.get $1 + local.get $9 local.get $2 i64.load call $~lib/array/Array#__set + local.get $9 + i32.const 1 + i32.add + local.set $9 end - local.get $4 + local.get $8 i32.const 1 i32.add - local.set $4 + local.set $8 br $for-loop|0 end end local.get $0 + local.get $9 + call $~lib/array/Array#set:length + local.get $0 ) (func $std/set/testNumeric (local $0 i64) @@ -7935,22 +7999,22 @@ (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) - (local $3 i32) + (local $3 f32) (local $4 i32) (local $5 i32) (local $6 i32) (local $7 i32) (local $8 i32) (local $9 i32) - (local $10 f32) + (local $10 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $5 local.get $0 i32.load offset=16 - local.tee $5 - local.set $6 - local.get $5 + local.tee $8 + local.set $7 + local.get $8 i32.const 268435452 i32.gt_u if @@ -7961,87 +8025,82 @@ call $~lib/builtins/abort unreachable end - local.get $6 + local.get $7 i32.const 2 i32.shl - local.tee $7 + local.tee $6 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $0 - local.get $7 + local.tee $2 + local.get $6 call $~lib/memory/memory.fill i32.const 16 i32.const 20 call $~lib/rt/tlsf/__alloc call $~lib/rt/pure/__retain - local.tee $3 + local.tee $0 i32.const 0 i32.store - local.get $3 + local.get $0 i32.const 0 i32.store offset=4 - local.get $3 + local.get $0 i32.const 0 i32.store offset=8 - local.get $3 + local.get $0 i32.const 0 i32.store offset=12 - local.get $0 + local.get $2 local.set $1 + local.get $2 local.get $0 - local.get $3 i32.load - local.tee $9 + local.tee $4 i32.ne if local.get $1 call $~lib/rt/pure/__retain local.set $1 - local.get $9 + local.get $4 call $~lib/rt/pure/__release end - local.get $3 + local.get $0 local.get $1 i32.store - local.get $3 local.get $0 + local.get $2 i32.store offset=4 - local.get $3 - local.get $7 - i32.store offset=8 - local.get $3 + local.get $0 local.get $6 + i32.store offset=8 + local.get $0 + local.get $7 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 + local.get $9 + local.get $8 i32.lt_s if - local.get $8 - local.get $4 + local.get $5 + local.get $9 i32.const 3 i32.shl i32.add - local.tee $1 + local.tee $2 i32.load offset=4 i32.const 1 i32.and i32.eqz if local.get $2 - local.tee $0 - i32.const 1 - i32.add - local.set $2 - local.get $1 f32.load - local.set $10 + local.set $3 + local.get $10 local.get $0 - local.get $3 i32.load offset=12 i32.ge_u if - local.get $0 + local.get $10 i32.const 0 i32.lt_s if @@ -8052,34 +8111,41 @@ call $~lib/builtins/abort unreachable end - local.get $3 local.get $0 + local.get $10 i32.const 1 i32.add - local.tee $1 + local.tee $2 i32.const 2 call $~lib/array/ensureSize - local.get $3 - local.get $1 + local.get $0 + local.get $2 i32.store offset=12 end - local.get $3 - i32.load offset=4 local.get $0 + i32.load offset=4 + local.get $10 i32.const 2 i32.shl i32.add - local.get $10 + local.get $3 f32.store + local.get $10 + i32.const 1 + i32.add + local.set $10 end - local.get $4 + local.get $9 i32.const 1 i32.add - local.set $4 + local.set $9 br $for-loop|0 end end - local.get $3 + local.get $0 + local.get $10 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result f32) local.get $1 @@ -8763,22 +8829,22 @@ (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) - (local $3 i32) + (local $3 f64) (local $4 i32) (local $5 i32) (local $6 i32) (local $7 i32) (local $8 i32) (local $9 i32) - (local $10 f64) + (local $10 i32) local.get $0 i32.load offset=8 - local.set $8 + local.set $5 local.get $0 i32.load offset=16 - local.tee $5 - local.set $6 - local.get $5 + local.tee $8 + local.set $7 + local.get $8 i32.const 134217726 i32.gt_u if @@ -8789,87 +8855,82 @@ call $~lib/builtins/abort unreachable end - local.get $6 + local.get $7 i32.const 3 i32.shl - local.tee $7 + local.tee $6 i32.const 0 call $~lib/rt/tlsf/__alloc - local.tee $0 - local.get $7 + local.tee $2 + local.get $6 call $~lib/memory/memory.fill i32.const 16 i32.const 22 call $~lib/rt/tlsf/__alloc call $~lib/rt/pure/__retain - local.tee $3 + local.tee $0 i32.const 0 i32.store - local.get $3 + local.get $0 i32.const 0 i32.store offset=4 - local.get $3 + local.get $0 i32.const 0 i32.store offset=8 - local.get $3 + local.get $0 i32.const 0 i32.store offset=12 - local.get $0 + local.get $2 local.set $1 + local.get $2 local.get $0 - local.get $3 i32.load - local.tee $9 + local.tee $4 i32.ne if local.get $1 call $~lib/rt/pure/__retain local.set $1 - local.get $9 + local.get $4 call $~lib/rt/pure/__release end - local.get $3 + local.get $0 local.get $1 i32.store - local.get $3 local.get $0 + local.get $2 i32.store offset=4 - local.get $3 - local.get $7 - i32.store offset=8 - local.get $3 + local.get $0 local.get $6 + i32.store offset=8 + local.get $0 + local.get $7 i32.store offset=12 loop $for-loop|0 - local.get $4 - local.get $5 + local.get $9 + local.get $8 i32.lt_s if - local.get $8 - local.get $4 + local.get $5 + local.get $9 i32.const 4 i32.shl i32.add - local.tee $1 + local.tee $2 i32.load offset=8 i32.const 1 i32.and i32.eqz if local.get $2 - local.tee $0 - i32.const 1 - i32.add - local.set $2 - local.get $1 f64.load - local.set $10 + local.set $3 + local.get $10 local.get $0 - local.get $3 i32.load offset=12 i32.ge_u if - local.get $0 + local.get $10 i32.const 0 i32.lt_s if @@ -8880,34 +8941,41 @@ call $~lib/builtins/abort unreachable end - local.get $3 local.get $0 + local.get $10 i32.const 1 i32.add - local.tee $1 + local.tee $2 i32.const 3 call $~lib/array/ensureSize - local.get $3 - local.get $1 + local.get $0 + local.get $2 i32.store offset=12 end - local.get $3 - i32.load offset=4 local.get $0 + i32.load offset=4 + local.get $10 i32.const 3 i32.shl i32.add - local.get $10 + local.get $3 f64.store + local.get $10 + i32.const 1 + i32.add + local.set $10 end - local.get $4 + local.get $9 i32.const 1 i32.add - local.set $4 + local.set $9 br $for-loop|0 end end - local.get $3 + local.get $0 + local.get $10 + call $~lib/array/Array#set:length + local.get $0 ) (func $~lib/array/Array#__get (param $0 i32) (param $1 i32) (result f64) local.get $1 diff --git a/tests/compiler/std/set.untouched.wat b/tests/compiler/std/set.untouched.wat index 8e0d545835..81ece6587b 100644 --- a/tests/compiler/std/set.untouched.wat +++ b/tests/compiler/std/set.untouched.wat @@ -1,7 +1,7 @@ (module + (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_none (func (param i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_none (func)) @@ -3740,6 +3740,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 0 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -3801,6 +3814,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -4780,6 +4796,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 0 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -4841,6 +4870,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -5838,6 +5870,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 1 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -5899,6 +5944,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -6878,6 +6926,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 1 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -6939,6 +7000,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -7944,6 +8008,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 2 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -8005,6 +8082,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -8954,6 +9034,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 2 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -9015,6 +9108,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -10054,6 +10150,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 3 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -10115,6 +10224,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -11068,6 +11180,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 3 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -11129,6 +11254,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -12085,6 +12213,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 2 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -12146,6 +12287,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 @@ -13103,6 +13247,19 @@ local.get $2 call $~lib/array/Array#__unchecked_set ) + (func $~lib/array/Array#set:length (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=12 + local.set $2 + local.get $0 + local.get $1 + i32.const 3 + call $~lib/array/ensureSize + local.get $0 + local.get $1 + i32.store offset=12 + ) (func $~lib/set/Set#values (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -13164,6 +13321,9 @@ end end local.get $3 + local.get $4 + call $~lib/array/Array#set:length + local.get $3 ) (func $~lib/array/Array#get:length (param $0 i32) (result i32) local.get $0 diff --git a/tests/parser/class-abstract.ts.fixture.ts b/tests/parser/class-abstract.ts.fixture.ts index 46329b94dc..d7c6bea0a7 100644 --- a/tests/parser/class-abstract.ts.fixture.ts +++ b/tests/parser/class-abstract.ts.fixture.ts @@ -1,4 +1,5 @@ class Foo { - abstract bar(): void; + bar(): void; } -// ERROR 1042: "'abstract' modifier cannot be used here." in class-abstract.ts:2:3 +// ERROR 1042: "'abstract' modifier cannot be used here." in class-abstract.ts(2,3+8) +// ERROR 2391: "Function implementation is missing or not immediately following the declaration." in class-abstract.ts(2,19+4) diff --git a/tests/parser/class.ts.fixture.ts b/tests/parser/class.ts.fixture.ts index a76ddb7202..dfdd064c5b 100644 --- a/tests/parser/class.ts.fixture.ts +++ b/tests/parser/class.ts.fixture.ts @@ -15,11 +15,11 @@ export class Invalid { get instanceGetter(a: i32) {} set instanceSetter() {} } -// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts:15:14 -// ERROR 1110: "Type expected." in class.ts:18:21 -// ERROR 1094: "An accessor cannot have type parameters." in class.ts:23:21 -// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts:23:7 -// ERROR 1110: "Type expected." in class.ts:23:32 -// ERROR 1094: "An accessor cannot have type parameters." in class.ts:28:21 -// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts:28:7 -// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts:28:26 +// ERROR 1092: "Type parameters cannot appear on a constructor declaration." in class.ts(15,14+3) +// ERROR 1110: "Type expected." in class.ts(18,21+0) +// ERROR 1094: "An accessor cannot have type parameters." in class.ts(23,21+3) +// ERROR 1054: "A 'get' accessor cannot have parameters." in class.ts(23,7+14) +// ERROR 1110: "Type expected." in class.ts(23,32+0) +// ERROR 1094: "An accessor cannot have type parameters." in class.ts(28,21+3) +// ERROR 1049: "A 'set' accessor must have exactly one parameter." in class.ts(28,7+14) +// ERROR 1095: "A 'set' accessor cannot have a return type annotation." in class.ts(28,26+1) diff --git a/tests/parser/continue-on-error.ts.fixture.ts b/tests/parser/continue-on-error.ts.fixture.ts index c33b319a21..a10d400f0f 100644 --- a/tests/parser/continue-on-error.ts.fixture.ts +++ b/tests/parser/continue-on-error.ts.fixture.ts @@ -5,5 +5,5 @@ from; do { ; } while (false); -// ERROR 1003: "Identifier expected." in continue-on-error.ts:2:1 -// ERROR 1005: "'(' expected." in continue-on-error.ts:4:1 +// ERROR 1003: "Identifier expected." in continue-on-error.ts(2,1+3) +// ERROR 1005: "'(' expected." in continue-on-error.ts(4,1+5) diff --git a/tests/parser/definite-assignment-assertion.ts.fixture.ts b/tests/parser/definite-assignment-assertion.ts.fixture.ts index 996e11f598..0d4b0e0405 100644 --- a/tests/parser/definite-assignment-assertion.ts.fixture.ts +++ b/tests/parser/definite-assignment-assertion.ts.fixture.ts @@ -7,6 +7,6 @@ function f(): void { let x!: i32; let x!: i32 = 0; } -// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts:3:3 -// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts:4:3 -// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts:8:7 +// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts(3,3+11) +// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts(4,3+14) +// ERROR 1255: "A definite assignment assertion '!' is not permitted in this context." in definite-assignment-assertion.ts(8,7+11) diff --git a/tests/parser/function-type.ts.fixture.ts b/tests/parser/function-type.ts.fixture.ts index f048a24713..da4cc376b9 100644 --- a/tests/parser/function-type.ts.fixture.ts +++ b/tests/parser/function-type.ts.fixture.ts @@ -2,4 +2,4 @@ var a: () => void; var b: (a: i32, b: i32) => void; var c: (a: i32, b: i32) => (a: i32, b: i32) => void; var d: (a) => void; -// ERROR 1110: "Type expected." in function-type.ts:4:10 +// ERROR 1110: "Type expected." in function-type.ts(4,10+0) diff --git a/tests/parser/interface-errors.ts b/tests/parser/interface-errors.ts new file mode 100644 index 0000000000..902a3822b8 --- /dev/null +++ b/tests/parser/interface-errors.ts @@ -0,0 +1,22 @@ +abstract interface Foo { // ERROR 1242: "'abstract' modifier can only appear on a class, method, or property declaration +} + +abstract +interface Foo { // no error +} + +interface Foo implements Bar { // ERROR 1176: "Interface declaration cannot have 'implements' clause." +} + +interface Foo extends Bar { // no error +} + +interface Foo { + abstract a: i32; // ERROR 1042: "'abstract' modifier cannot be used here." (TS1070) + private b: i32; // ERROR 1042: "'private' modifier cannot be used here." (TS1070) + protected c: i32; // ERROR 1042: "'protected' modifier cannot be used here." + public c: i32; // ERROR 1042: "'public' modifier cannot be used here." + static d: i32; // ERROR 1042: "'static' modifier cannot be used here." + constructor(): i32; // ERROR 229: "'constructor' keyword cannot be used here." (TS: none?) + constructor(); // ^ + ERROR 1110: "Type expected." +} diff --git a/tests/parser/interface-errors.ts.fixture.ts b/tests/parser/interface-errors.ts.fixture.ts new file mode 100644 index 0000000000..1085f3cd50 --- /dev/null +++ b/tests/parser/interface-errors.ts.fixture.ts @@ -0,0 +1,29 @@ +abstract; +interface Foo { +} +abstract; +interface Foo { +} +interface Foo { +} +interface Foo extends Bar { +} +interface Foo { + a: i32; + b: i32; + c: i32; + c: i32; + d: i32; + constructor(): i32; + constructor(); +} +// ERROR 1242: "'abstract' modifier can only appear on a class, method, or property declaration." in interface-errors.ts(1,1+8) +// ERROR 1176: "Interface declaration cannot have 'implements' clause." in interface-errors.ts(8,15+10) +// ERROR 1042: "'abstract' modifier cannot be used here." in interface-errors.ts(15,3+8) +// ERROR 1042: "'private' modifier cannot be used here." in interface-errors.ts(16,3+7) +// ERROR 1042: "'protected' modifier cannot be used here." in interface-errors.ts(17,3+9) +// ERROR 1042: "'public' modifier cannot be used here." in interface-errors.ts(18,3+6) +// ERROR 1042: "'static' modifier cannot be used here." in interface-errors.ts(19,3+6) +// ERROR 229: "'constructor' keyword cannot be used here." in interface-errors.ts(20,3+11) +// ERROR 229: "'constructor' keyword cannot be used here." in interface-errors.ts(21,3+11) +// ERROR 1110: "Type expected." in interface-errors.ts(21,16+0) diff --git a/tests/parser/namespace.ts.fixture.ts b/tests/parser/namespace.ts.fixture.ts index d755fa9edd..8ef853742f 100644 --- a/tests/parser/namespace.ts.fixture.ts +++ b/tests/parser/namespace.ts.fixture.ts @@ -14,5 +14,5 @@ declare namespace A { } } } -// ERROR 1039: "Initializers are not allowed in ambient contexts." in namespace.ts:6:32 -// ERROR 1183: "An implementation cannot be declared in ambient contexts." in namespace.ts:8:37 +// ERROR 1039: "Initializers are not allowed in ambient contexts." in namespace.ts(6,32+1) +// ERROR 1183: "An implementation cannot be declared in ambient contexts." in namespace.ts(8,37+1) diff --git a/tests/parser/numeric-separators.ts.fixture.ts b/tests/parser/numeric-separators.ts.fixture.ts index 9834231900..57af00bb90 100644 --- a/tests/parser/numeric-separators.ts.fixture.ts +++ b/tests/parser/numeric-separators.ts.fixture.ts @@ -10,11 +10,11 @@ 41610; 2302755; 2302755; -// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts:8:9 -// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts:9:4 -// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts:11:11 -// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts:12:6 -// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts:14:11 -// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts:15:6 -// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts:17:11 -// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts:18:6 +// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts(8,9+0) +// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts(9,4+0) +// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts(11,11+0) +// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts(12,6+0) +// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts(14,11+0) +// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts(15,6+0) +// ERROR 6188: "Numeric separators are not allowed here." in numeric-separators.ts(17,11+0) +// ERROR 6189: "Multiple consecutive numeric separators are not permitted." in numeric-separators.ts(18,6+0) diff --git a/tests/parser/optional-property.ts.fixture.ts b/tests/parser/optional-property.ts.fixture.ts index efb508774a..dc81ce8c07 100644 --- a/tests/parser/optional-property.ts.fixture.ts +++ b/tests/parser/optional-property.ts.fixture.ts @@ -1,4 +1,4 @@ class C { x: i32; } -// ERROR 219: "Optional properties are not supported." in optional-property.ts:2:3 +// ERROR 219: "Optional properties are not supported." in optional-property.ts(2,3+2) diff --git a/tests/parser/optional-typeparameters.ts.fixture.ts b/tests/parser/optional-typeparameters.ts.fixture.ts index 9a6935aafd..05cf48a0d0 100644 --- a/tests/parser/optional-typeparameters.ts.fixture.ts +++ b/tests/parser/optional-typeparameters.ts.fixture.ts @@ -7,4 +7,4 @@ function a(): T { function a(): T { return 0; } -// ERROR 2706: "Required type parameters may not follow optional type parameters." in optional-typeparameters.ts:3:20 +// ERROR 2706: "Required type parameters may not follow optional type parameters." in optional-typeparameters.ts(3,20+1) diff --git a/tests/parser/parameter-order.ts.fixture.ts b/tests/parser/parameter-order.ts.fixture.ts index 587b2069da..5398bfffe2 100644 --- a/tests/parser/parameter-order.ts.fixture.ts +++ b/tests/parser/parameter-order.ts.fixture.ts @@ -3,6 +3,6 @@ function optionalValid(a: i32, b?: i32): void {} function restParameterMustBeLast(...a: Array, b: i32): void {} function optionalCannotPrecedeRequired(a?: i32, b: i32): void {} function optionalWithInitializerCannotPrecedeRequired(a?: i32 = 1, b: i32): void {} -// ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts:5:37 -// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:8:49 -// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts:11:67 +// ERROR 1014: "A rest parameter must be last in a parameter list." in parameter-order.ts(5,37+1) +// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(8,49+1) +// ERROR 1016: "A required parameter cannot follow an optional parameter." in parameter-order.ts(11,67+1) diff --git a/tests/parser/regexp.ts.fixture.ts b/tests/parser/regexp.ts.fixture.ts index edd623ef5a..43cf5d3225 100644 --- a/tests/parser/regexp.ts.fixture.ts +++ b/tests/parser/regexp.ts.fixture.ts @@ -6,8 +6,8 @@ b / ig; /(abc)\//iig; /(abc)\//iX; false && /abc/gX.test(someString) || true; -// ERROR 1161: "Unterminated regular expression literal." in regexp.ts:5:2 -// ERROR 1005: "'/' expected." in regexp.ts:5:1 -// ERROR 209: "Invalid regular expression flags." in regexp.ts:8:10 -// ERROR 209: "Invalid regular expression flags." in regexp.ts:9:10 -// ERROR 209: "Invalid regular expression flags." in regexp.ts:10:15 +// ERROR 1161: "Unterminated regular expression literal." in regexp.ts(5,2+1) +// ERROR 1005: "'/' expected." in regexp.ts(5,1+2) +// ERROR 209: "Invalid regular expression flags." in regexp.ts(8,10+3) +// ERROR 209: "Invalid regular expression flags." in regexp.ts(9,10+2) +// ERROR 209: "Invalid regular expression flags." in regexp.ts(10,15+2) diff --git a/tests/parser/var.ts.fixture.ts b/tests/parser/var.ts.fixture.ts index d4b0a1148a..500482186d 100644 --- a/tests/parser/var.ts.fixture.ts +++ b/tests/parser/var.ts.fixture.ts @@ -5,5 +5,5 @@ var d = 2; var e; const f: i32; const t = 0 < (c / 10); -// ERROR 1110: "Type expected." in var.ts:7:6 -// ERROR 1155: "'const' declarations must be initialized." in var.ts:10:7 +// ERROR 1110: "Type expected." in var.ts(7,6+0) +// ERROR 1155: "'const' declarations must be initialized." in var.ts(10,7+1) From 49728599fb552d8df8a53963782c0c71bca8a2bc Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 22 Apr 2020 19:45:42 +0200 Subject: [PATCH 21/24] fix affected parser test --- tests/parser/interface-errors.ts.fixture.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/parser/interface-errors.ts.fixture.ts b/tests/parser/interface-errors.ts.fixture.ts index 1085f3cd50..bc1285e3d3 100644 --- a/tests/parser/interface-errors.ts.fixture.ts +++ b/tests/parser/interface-errors.ts.fixture.ts @@ -24,6 +24,6 @@ interface Foo { // ERROR 1042: "'protected' modifier cannot be used here." in interface-errors.ts(17,3+9) // ERROR 1042: "'public' modifier cannot be used here." in interface-errors.ts(18,3+6) // ERROR 1042: "'static' modifier cannot be used here." in interface-errors.ts(19,3+6) -// ERROR 229: "'constructor' keyword cannot be used here." in interface-errors.ts(20,3+11) -// ERROR 229: "'constructor' keyword cannot be used here." in interface-errors.ts(21,3+11) +// ERROR 230: "'constructor' keyword cannot be used here." in interface-errors.ts(20,3+11) +// ERROR 230: "'constructor' keyword cannot be used here." in interface-errors.ts(21,3+11) // ERROR 1110: "Type expected." in interface-errors.ts(21,16+0) From 99681ba69d240b9b320e181f40c91d3cb222bec1 Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 27 Apr 2020 10:11:47 +0200 Subject: [PATCH 22/24] use proper stubs --- src/common.ts | 6 +- src/compiler.ts | 477 +++++++++--------- src/program.ts | 22 +- src/types.ts | 21 + tests/compiler/call-inferred.untouched.wat | 4 +- tests/compiler/call-optional.optimized.wat | 12 +- tests/compiler/call-optional.untouched.wat | 8 +- .../compiler/class-overloading.optimized.wat | 42 +- .../compiler/class-overloading.untouched.wat | 46 +- tests/compiler/exports.optimized.wat | 12 +- tests/compiler/exports.untouched.wat | 12 +- tests/compiler/function-types.untouched.wat | 4 +- tests/compiler/std/array.untouched.wat | 24 +- tests/compiler/std/arraybuffer.untouched.wat | 4 +- tests/compiler/std/dataview.untouched.wat | 4 +- tests/compiler/std/string.optimized.wat | 8 +- tests/compiler/std/string.untouched.wat | 8 +- tests/compiler/std/typedarray.optimized.wat | 108 ++-- tests/compiler/std/typedarray.untouched.wat | 162 +++--- 19 files changed, 518 insertions(+), 466 deletions(-) diff --git a/src/common.ts b/src/common.ts index b8594fead5..dc0a90daf5 100644 --- a/src/common.ts +++ b/src/common.ts @@ -66,8 +66,8 @@ export enum CommonFlags { INLINED = 1 << 23, /** Is scoped. */ SCOPED = 1 << 24, - /** Is a trampoline. */ - TRAMPOLINE = 1 << 25, + /** Is a stub. */ + STUB = 1 << 25, /** Is a virtual method. */ VIRTUAL = 1 << 26, /** Is (part of) a closure. */ @@ -99,6 +99,8 @@ export const LIBRARY_SUBST = "~lib"; export const LIBRARY_PREFIX = LIBRARY_SUBST + PATH_DELIMITER; /** Path index suffix. */ export const INDEX_SUFFIX = PATH_DELIMITER + "index"; +/** Stub function delimiter. */ +export const STUB_DELIMITER = "@"; /** Common names. */ export namespace CommonNames { diff --git a/src/compiler.ts b/src/compiler.ts index 5236f356b6..89b7a0433c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -62,8 +62,9 @@ import { STATIC_DELIMITER, GETTER_PREFIX, SETTER_PREFIX, - CommonNames, + STUB_DELIMITER, INDEX_SUFFIX, + CommonNames, Feature, Target, featureToString @@ -506,13 +507,13 @@ export class Compiler extends DiagnosticEmitter { let instance = functionTable[i]; if (instance.is(CommonFlags.VIRTUAL)) { assert(instance.is(CommonFlags.INSTANCE)); - this.makeVirtual(instance); + this.finalizeVirtualStub(instance); } } var virtualCalls = this.virtualCalls; for (let _values = Set_values(virtualCalls), i = 0, k = _values.length; i < k; ++i) { let instance = unchecked(_values[i]); - this.makeVirtual(instance); + this.finalizeVirtualStub(instance); } // finalize runtime features @@ -608,167 +609,6 @@ export class Compiler extends DiagnosticEmitter { return module; } - /** Makes a normally compiled function callable virtually. */ - private makeVirtual(instance: Function): void { - if (instance.virtualRef) return; - - // Wouldn't be here if there wasn't at least one overload - var overloadPrototypes = assert(instance.prototype.overloads); - - var module = this.module; - var usizeType = this.options.usizeType; - var nativeSizeType = usizeType.toNativeType(); - var parameterTypes = instance.signature.parameterTypes; - var returnType = instance.signature.returnType; - var numParameters = parameterTypes.length; - var tempIndex = 1 + parameterTypes.length; // incl. `this` - - // Switch over this's rtId and map it to the respective overload - var builder = new SwitchBuilder(this.module, - module.load(4, false, - module.binary( - nativeSizeType == NativeType.I64 - ? BinaryOp.SubI64 - : BinaryOp.SubI32, - module.local_get(0, nativeSizeType), - nativeSizeType == NativeType.I64 - ? module.i64(8) // rtId offset = -8 - : module.i32(8) - ), - NativeType.I32 - ) - ); - - // A method's `overloads` property contains its unbound overload prototypes - // so we first have to find the concrete classes it became bound to, obtain - // their bound prototypes and make sure these are resolved and compiled as - // we are going to call them conditionally based on this's class id. - for (let _values = Set_values(overloadPrototypes), i = 0, k = _values.length; i < k; ++i) { - let unboundOverloadPrototype = _values[i]; - assert(!unboundOverloadPrototype.isBound); - let unboundOverloadParent = unboundOverloadPrototype.parent; - let isProperty = unboundOverloadParent.kind == ElementKind.PROPERTY_PROTOTYPE; - let classInstances: Map | null; - if (isProperty) { - let propertyParent = (unboundOverloadParent).parent; - assert(propertyParent.kind == ElementKind.CLASS_PROTOTYPE); - classInstances = (propertyParent).instances; - } else { - assert(unboundOverloadParent.kind == ElementKind.CLASS_PROTOTYPE); - classInstances = (unboundOverloadParent).instances; - } - if (classInstances) { - for (let _values = Map_values(classInstances), j = 0, l = _values.length; j < l; ++j) { - let classInstance = _values[j]; - let overloadInstance: Function | null; - if (isProperty) { - let boundProperty = assert(classInstance.members!.get(unboundOverloadParent.name)); - assert(boundProperty.kind == ElementKind.PROPERTY); - if (instance.is(CommonFlags.GET)) { - overloadInstance = (boundProperty).getterInstance; - } else { - assert(instance.is(CommonFlags.SET)); - overloadInstance = (boundProperty).setterInstance; - } - } else { - let boundPrototype = assert(classInstance.members!.get(unboundOverloadPrototype.name)); - assert(boundPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); - overloadInstance = this.resolver.resolveFunction(boundPrototype, instance.typeArguments); - } - if (!overloadInstance || !this.compileFunction(overloadInstance)) continue; - let overloadType = overloadInstance.type; - let originalType = instance.type; - if (!overloadType.isAssignableTo(originalType)) { - this.error( - DiagnosticCode.Type_0_is_not_assignable_to_type_1, - overloadInstance.identifierNode.range, overloadType.toString(), originalType.toString() - ); - continue; - } - // TODO: additional optional parameters are not permitted by `isAssignableTo` yet - let overloadSignature = overloadInstance.signature; - let overloadParameterTypes = overloadSignature.parameterTypes; - let overloadNumParameters = overloadParameterTypes.length; - let paramExprs = new Array(1 + overloadNumParameters); - paramExprs[0] = module.local_get(0, nativeSizeType); // this - for (let n = 0; n < numParameters; ++n) { - paramExprs[1 + n] = module.local_get(1 + n, parameterTypes[n].toNativeType()); - } - let needsTrampoline = false; - for (let n = numParameters; n < overloadNumParameters; ++n) { - // TODO: inline constant initializers and skip trampoline - paramExprs[1 + n] = this.makeZero(overloadParameterTypes[n]); - needsTrampoline = true; - } - let calledName = needsTrampoline - ? this.ensureTrampoline(overloadInstance).internalName - : overloadInstance.internalName; - let nativeReturnType = overloadSignature.returnType.toNativeType(); - let stmts = new Array(); - if (needsTrampoline) { - this.ensureBuiltinArgumentsLength(); - // Safe to prepend since paramExprs are local.get's - stmts.push(module.global_set(BuiltinNames.argumentsLength, module.i32(numParameters))); - } - if (returnType == Type.void) { - stmts.push( - module.call(calledName, paramExprs, nativeReturnType) - ); - stmts.push( - module.return() - ); - } else { - stmts.push( - module.return( - module.call(calledName, paramExprs, nativeReturnType) - ) - ); - } - builder.addCase(classInstance.id, stmts); - // Also alias each extendee inheriting this exact overload - let extendees = classInstance.getAllExtendees( - isProperty - ? unboundOverloadParent.name - : instance.prototype.name - ); - for (let _values = Set_values(extendees), a = 0, b = _values.length; a < b; ++a) { - let extendee = _values[a]; - builder.addCase(extendee.id, stmts); - } - } - } - } - - // Call the original function if no other id matches and the method is not - // abstract or part of an interface. Note that doing so will not catch an - // invalid id, but can reduce code size significantly since we also don't - // have to add branches for extendees inheriting the original function. - var body: ExpressionRef; - if (instance.prototype.bodyNode) { - let paramExprs = new Array(numParameters); - paramExprs[0] = module.local_get(0, nativeSizeType); // this - for (let i = 0, k = parameterTypes.length; i < k; ++i) { - paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); - } - body = module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()); - - // Otherwise trap - } else { - body = module.unreachable(); - } - - // Make the virtual wrapper - var originalRef = instance.ref; - instance.virtualRef = module.addFunction( - instance.internalName + "|virtual", - getFunctionParams(originalRef), getFunctionResults(originalRef), [ NativeType.I32 ], - module.block(null, [ - builder.render(tempIndex), - body - ], returnType.toNativeType()) - ); - } - // === Exports ================================================================================== /** Applies the respective module exports for the specified file. */ @@ -867,9 +707,9 @@ export class Compiler extends DiagnosticEmitter { if (!functionInstance.hasDecorator(DecoratorFlags.BUILTIN)) { let signature = functionInstance.signature; if (signature.requiredParameters < signature.parameterTypes.length) { - // utilize trampoline to fill in omitted arguments - functionInstance = this.ensureTrampoline(functionInstance); - this.ensureBuiltinArgumentsLength(); + // utilize varargs stub to fill in omitted arguments + functionInstance = this.ensureVarargsStub(functionInstance); + this.ensureArgumentsLength(); } if (functionInstance.is(CommonFlags.COMPILED)) this.module.addFunctionExport(functionInstance.internalName, prefix + name); } @@ -1999,9 +1839,9 @@ export class Compiler extends DiagnosticEmitter { var tableBase = this.options.tableBase; if (!tableBase) tableBase = 1; // leave first elem blank index = tableBase + functionTable.length; - if (!instance.is(CommonFlags.TRAMPOLINE) && instance.signature.requiredParameters < instance.signature.parameterTypes.length) { - // insert the trampoline if the function has optional parameters - instance = this.ensureTrampoline(instance); + if (!instance.is(CommonFlags.STUB) && instance.signature.requiredParameters < instance.signature.parameterTypes.length) { + // insert the varargs stub if the function has optional parameters + instance = this.ensureVarargsStub(instance); } functionTable.push(instance); instance.functionTableIndex = index; @@ -6852,7 +6692,7 @@ export class Compiler extends DiagnosticEmitter { // Inline if explicitly requested if (instance.hasDecorator(DecoratorFlags.INLINE)) { - assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense + assert(!instance.is(CommonFlags.STUB)); // doesn't make sense let inlineStack = this.inlineStack; if (inlineStack.includes(instance)) { this.warning( @@ -7022,24 +6862,37 @@ export class Compiler extends DiagnosticEmitter { return expr; } - /** Gets the trampoline for the specified function. */ - ensureTrampoline(original: Function): Function { - // A trampoline is a function that takes a fixed amount of operands with some of them possibly - // being zeroed. It takes one additional argument denoting the number of actual operands - // provided to the call, and takes appropriate steps to initialize zeroed operands to their - // default values using the optional parameter initializers of the original function. Doing so - // allows calls to functions with optional parameters to circumvent the trampoline when all - // parameters are provided as a fast route, respectively setting up omitted operands in a proper - // context otherwise. - var trampoline = original.trampoline; - if (trampoline) return trampoline; + /** Makes sure that the arguments length helper global is present. */ + ensureArgumentsLength(): void { + if (!this.builtinArgumentsLength) { + let module = this.module; + this.builtinArgumentsLength = module.addGlobal(BuiltinNames.argumentsLength, NativeType.I32, true, module.i32(0)); + // TODO: Enable this once mutable globals are the default nearly everywhere. + // if (this.options.hasFeature(Feature.MUTABLE_GLOBALS)) { + // module.addGlobalExport(BuiltinNames.argumentsLength, ExportNames.argumentsLength); + // } else { + module.addFunction(BuiltinNames.setArgumentsLength, NativeType.I32, NativeType.None, null, + module.global_set(BuiltinNames.argumentsLength, module.local_get(0, NativeType.I32)) + ); + module.addFunctionExport(BuiltinNames.setArgumentsLength, ExportNames.setArgumentsLength); + // } + } + } + + /** Ensures compilation of the varargs stub for the specified function. */ + ensureVarargsStub(original: Function): Function { + // A varargs stub is a function called with omitted arguments being zeroed, + // reading the `argumentsLength` helper global to decide which initializers + // to inject before calling the original function. It is typically attempted + // to circumvent the varargs stub where possible, for example where omitted + // arguments are constants and can be inlined into the original call. + var stub = original.varargsStub; + if (stub) return stub; var originalSignature = original.signature; - var originalName = original.internalName; var originalParameterTypes = originalSignature.parameterTypes; var originalParameterDeclarations = original.prototype.functionTypeNode.parameters; var returnType = originalSignature.returnType; - var thisType = originalSignature.thisType; var isInstance = original.is(CommonFlags.INSTANCE); // arguments excl. `this`, operands incl. `this` @@ -7069,24 +6922,15 @@ export class Compiler extends DiagnosticEmitter { } assert(operandIndex == minOperands); - // create the trampoline element - var trampolineSignature = new Signature(this.program, originalParameterTypes, returnType, thisType); - trampolineSignature.requiredParameters = maxArguments; - trampolineSignature.parameterNames = originalSignature.parameterNames; - trampoline = new Function( - original.name + "|trampoline", - original.prototype, - original.typeArguments, - trampolineSignature, - original.contextualTypeArguments - ); - trampoline.set(original.flags | CommonFlags.TRAMPOLINE | CommonFlags.COMPILED); - original.trampoline = trampoline; + // create the varargs stub + stub = original.newStub("varargs"); + stub.signature.requiredParameters = maxArguments; + original.varargsStub = stub; - // compile initializers of omitted arguments in scope of the trampoline function - // this is necessary because initializers might need additional locals and a proper this context + // compile initializers of omitted arguments in the scope of the stub, + // accounting for additional locals and a proper `this` context. var previousFlow = this.currentFlow; - var flow = trampoline.flow; + var flow = stub.flow; this.currentFlow = flow; // create a br_table switching over the number of optional parameters provided @@ -7141,7 +6985,7 @@ export class Compiler extends DiagnosticEmitter { assert(operandIndex == maxOperands); var stmts: ExpressionRef[] = [ body ]; - var theCall = module.call(originalName, forwardedOperands, returnType.toNativeType()); + var theCall = module.call(original.internalName, forwardedOperands, returnType.toNativeType()); if (returnType != Type.void) { this.performAutoreleasesWithValue(flow, theCall, returnType, stmts); } else { @@ -7152,31 +6996,204 @@ export class Compiler extends DiagnosticEmitter { this.currentFlow = previousFlow; var funcRef = module.addFunction( - trampoline.internalName, - trampolineSignature.nativeParams, - trampolineSignature.nativeResults, - typesToNativeTypes(trampoline.additionalLocals), + stub.internalName, + stub.signature.nativeParams, + stub.signature.nativeResults, + typesToNativeTypes(stub.additionalLocals), module.flatten(stmts, returnType.toNativeType()) ); - trampoline.finalize(module, funcRef); - return trampoline; + stub.set(CommonFlags.COMPILED); + stub.finalize(module, funcRef); + return stub; + } + + /** Ensures compilation of the virtual stub for the specified function. */ + ensureVirtualStub(original: Function): Function { + // A virtual stub is a function redirecting virtual calls to the actual + // overload targeted by the call. It utilizes varargs stubs where necessary + // and as such has the same semantics as one. Here, we only make sure that + // a placeholder exist, with actual code being generated as a finalization + // step once module compilation is otherwise complete. + var stub = original.virtualStub; + if (stub) return stub; + stub = original.newStub("virtual"); + original.virtualStub = stub; + var module = this.module; + stub.ref = module.addFunction( + stub.internalName, + stub.signature.nativeParams, + stub.signature.nativeResults, + null, + module.unreachable() + ); + this.virtualCalls.add(original); + return stub; } - /** Makes sure that the arguments length helper global is present. */ - ensureBuiltinArgumentsLength(): void { - if (!this.builtinArgumentsLength) { - let module = this.module; - this.builtinArgumentsLength = module.addGlobal(BuiltinNames.argumentsLength, NativeType.I32, true, module.i32(0)); - // TODO: Enable this once mutable globals are the default nearly everywhere. - // if (this.options.hasFeature(Feature.MUTABLE_GLOBALS)) { - // module.addGlobalExport(BuiltinNames.argumentsLength, ExportNames.argumentsLength); - // } else { - module.addFunction(BuiltinNames.setArgumentsLength, NativeType.I32, NativeType.None, null, - module.global_set(BuiltinNames.argumentsLength, module.local_get(0, NativeType.I32)) - ); - module.addFunctionExport(BuiltinNames.setArgumentsLength, ExportNames.setArgumentsLength); - // } + /** Finalizes the virtual stub of the specified function. */ + private finalizeVirtualStub(instance: Function): void { + var stub = this.ensureVirtualStub(instance); + if (stub.is(CommonFlags.COMPILED)) return; + + // Wouldn't be here if there wasn't at least one overload + var overloadPrototypes = assert(instance.prototype.overloads); + + var module = this.module; + var usizeType = this.options.usizeType; + var nativeSizeType = usizeType.toNativeType(); + var parameterTypes = instance.signature.parameterTypes; + var returnType = instance.signature.returnType; + var numParameters = parameterTypes.length; + var tempIndex = 1 + parameterTypes.length; // incl. `this` + + // Switch over this's rtId and map it to the respective overload + var builder = new SwitchBuilder(this.module, + module.load(4, false, + module.binary( + nativeSizeType == NativeType.I64 + ? BinaryOp.SubI64 + : BinaryOp.SubI32, + module.local_get(0, nativeSizeType), + nativeSizeType == NativeType.I64 + ? module.i64(8) // rtId offset = -8 + : module.i32(8) + ), + NativeType.I32 + ) + ); + + // A method's `overloads` property contains its unbound overload prototypes + // so we first have to find the concrete classes it became bound to, obtain + // their bound prototypes and make sure these are resolved and compiled as + // we are going to call them conditionally based on this's class id. + for (let _values = Set_values(overloadPrototypes), i = 0, k = _values.length; i < k; ++i) { + let unboundOverloadPrototype = _values[i]; + assert(!unboundOverloadPrototype.isBound); + let unboundOverloadParent = unboundOverloadPrototype.parent; + let isProperty = unboundOverloadParent.kind == ElementKind.PROPERTY_PROTOTYPE; + let classInstances: Map | null; + if (isProperty) { + let propertyParent = (unboundOverloadParent).parent; + assert(propertyParent.kind == ElementKind.CLASS_PROTOTYPE); + classInstances = (propertyParent).instances; + } else { + assert(unboundOverloadParent.kind == ElementKind.CLASS_PROTOTYPE); + classInstances = (unboundOverloadParent).instances; + } + if (classInstances) { + for (let _values = Map_values(classInstances), j = 0, l = _values.length; j < l; ++j) { + let classInstance = _values[j]; + let overloadInstance: Function | null; + if (isProperty) { + let boundProperty = assert(classInstance.members!.get(unboundOverloadParent.name)); + assert(boundProperty.kind == ElementKind.PROPERTY); + if (instance.is(CommonFlags.GET)) { + overloadInstance = (boundProperty).getterInstance; + } else { + assert(instance.is(CommonFlags.SET)); + overloadInstance = (boundProperty).setterInstance; + } + } else { + let boundPrototype = assert(classInstance.members!.get(unboundOverloadPrototype.name)); + assert(boundPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); + overloadInstance = this.resolver.resolveFunction(boundPrototype, instance.typeArguments); + } + if (!overloadInstance || !this.compileFunction(overloadInstance)) continue; + let overloadType = overloadInstance.type; + let originalType = instance.type; + if (!overloadType.isAssignableTo(originalType)) { + this.error( + DiagnosticCode.Type_0_is_not_assignable_to_type_1, + overloadInstance.identifierNode.range, overloadType.toString(), originalType.toString() + ); + continue; + } + // TODO: additional optional parameters are not permitted by `isAssignableTo` yet + let overloadSignature = overloadInstance.signature; + let overloadParameterTypes = overloadSignature.parameterTypes; + let overloadNumParameters = overloadParameterTypes.length; + let paramExprs = new Array(1 + overloadNumParameters); + paramExprs[0] = module.local_get(0, nativeSizeType); // this + for (let n = 0; n < numParameters; ++n) { + paramExprs[1 + n] = module.local_get(1 + n, parameterTypes[n].toNativeType()); + } + let needsVarargsStub = false; + for (let n = numParameters; n < overloadNumParameters; ++n) { + // TODO: inline constant initializers and skip varargs stub + paramExprs[1 + n] = this.makeZero(overloadParameterTypes[n]); + needsVarargsStub = true; + } + let calledName = needsVarargsStub + ? this.ensureVarargsStub(overloadInstance).internalName + : overloadInstance.internalName; + let nativeReturnType = overloadSignature.returnType.toNativeType(); + let stmts = new Array(); + if (needsVarargsStub) { + this.ensureArgumentsLength(); + // Safe to prepend since paramExprs are local.get's + stmts.push(module.global_set(BuiltinNames.argumentsLength, module.i32(numParameters))); + } + if (returnType == Type.void) { + stmts.push( + module.call(calledName, paramExprs, nativeReturnType) + ); + stmts.push( + module.return() + ); + } else { + stmts.push( + module.return( + module.call(calledName, paramExprs, nativeReturnType) + ) + ); + } + builder.addCase(classInstance.id, stmts); + // Also alias each extendee inheriting this exact overload + let extendees = classInstance.getAllExtendees( + isProperty + ? unboundOverloadParent.name + : instance.prototype.name + ); + for (let _values = Set_values(extendees), a = 0, b = _values.length; a < b; ++a) { + let extendee = _values[a]; + builder.addCase(extendee.id, stmts); + } + } + } + } + + // Call the original function if no other id matches and the method is not + // abstract or part of an interface. Note that doing so will not catch an + // invalid id, but can reduce code size significantly since we also don't + // have to add branches for extendees inheriting the original function. + var body: ExpressionRef; + if (instance.prototype.bodyNode) { + let paramExprs = new Array(numParameters); + paramExprs[0] = module.local_get(0, nativeSizeType); // this + for (let i = 0, k = parameterTypes.length; i < k; ++i) { + paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); + } + body = module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()); + + // Otherwise trap + } else { + body = module.unreachable(); } + + // Create the virtual stub function + var ref = stub.ref; + if (ref) module.removeFunction(stub.internalName); + stub.ref = module.addFunction( + stub.internalName, + stub.signature.nativeParams, + stub.signature.nativeResults, + [ NativeType.I32 ], + module.block(null, [ + builder.render(tempIndex), + body + ], returnType.toNativeType()) + ); + stub.set(CommonFlags.COMPILED); } // @@ -7487,7 +7504,7 @@ export class Compiler extends DiagnosticEmitter { ): ExpressionRef { if (instance.hasDecorator(DecoratorFlags.INLINE)) { if (!instance.is(CommonFlags.VIRTUAL)) { - assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense + assert(!instance.is(CommonFlags.STUB)); // doesn't make sense let inlineStack = this.inlineStack; if (inlineStack.includes(instance)) { this.warning( @@ -7588,7 +7605,7 @@ export class Compiler extends DiagnosticEmitter { if (!allOptionalsAreConstant) { if (!instance.is(CommonFlags.MODULE_IMPORT)) { let original = instance; - instance = this.ensureTrampoline(instance); + instance = this.ensureVarargsStub(instance); if (!this.compileFunction(instance)) return module.unreachable(); instance.flow.flags = original.flow.flags; let nativeReturnType = returnType.toNativeType(); @@ -7613,23 +7630,21 @@ export class Compiler extends DiagnosticEmitter { this.skippedAutoreleases.add(expr); } } - this.ensureBuiltinArgumentsLength(); + this.ensureArgumentsLength(); return expr; } } } // Call the virtual stub with the vtable if the function has overloads - var calledName = instance.internalName; if (instance.is(CommonFlags.VIRTUAL) && !reportNode.isCallOnSuper) { - calledName += "|virtual"; - this.virtualCalls.add(instance); + instance = this.ensureVirtualStub(instance); } // If the return value is of a reference type it has not yet been released but is in flight // which is equivalent to a skipped autorelease. Hence, insert either a release if it is // dropped anyway, preserve the skipped autorelease if explicitly requested or autorelease now. - var expr = module.call(calledName, operands, returnType.toNativeType()); + var expr = module.call(instance.internalName, operands, returnType.toNativeType()); this.currentType = returnType; if (returnType.isManaged) { if (immediatelyDropped) { @@ -7718,10 +7733,10 @@ export class Compiler extends DiagnosticEmitter { indexArg = module.unary(UnaryOp.WrapI64, indexArg); } - // We might be calling a trampoline here, even if all operands have been - // provided, so we must set ~argumentsLength in any case. Inject setting it + // We might be calling a varargs stub here, even if all operands have been + // provided, so we must set `argumentsLength` in any case. Inject setting it // into the index argument, which becomes executed last after any operands. - this.ensureBuiltinArgumentsLength(); + this.ensureArgumentsLength(); if (getSideEffects(indexArg) & SideEffects.WritesGlobal) { let flow = this.currentFlow; let temp = flow.getTempLocal(Type.i32, findUsedLocals(indexArg)); diff --git a/src/program.ts b/src/program.ts index d855480b69..35d02af920 100644 --- a/src/program.ts +++ b/src/program.ts @@ -47,6 +47,7 @@ import { INNER_DELIMITER, LIBRARY_SUBST, INDEX_SUFFIX, + STUB_DELIMITER, CommonNames, Feature, Target @@ -3276,12 +3277,12 @@ export class Function extends TypedElement { debugLocations: Range[] = []; /** Function reference, if compiled. */ ref: FunctionRef = 0; - /** Function reference of the virtual stub, if compiled. */ - virtualRef: FunctionRef = 0; /** Function table index, if any. */ functionTableIndex: i32 = -1; - /** Trampoline function for calling with omitted arguments. */ - trampoline: Function | null = null; + /** Varargs stub for calling with omitted arguments. */ + varargsStub: Function | null = null; + /** Virtual stub for calling overloads. */ + virtualStub: Function | null = null; /** Counting id of inline operations involving this function. */ nextInlineId: i32 = 0; @@ -3349,6 +3350,19 @@ export class Function extends TypedElement { registerConcreteElement(program, this); } + /** Creates a stub for use with this function, i.e. for varargs or virtual calls. */ + newStub(postfix: string): Function { + var stub = new Function( + this.name + STUB_DELIMITER + postfix, + this.prototype, + this.typeArguments, + this.signature.clone(), + this.contextualTypeArguments + ); + stub.set(this.flags & ~CommonFlags.COMPILED | CommonFlags.STUB); + return stub; + } + /** Adds a local of the specified type, with an optional name. */ addLocal(type: Type, name: string | null = null, declaration: VariableDeclaration | null = null): Local { // if it has a name, check previously as this method will throw otherwise diff --git a/src/types.ts b/src/types.ts index a9d68b64f8..88598358a0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -719,6 +719,27 @@ export class Signature { sb.push(this.returnType.toString()); return sb.join(""); } + + /** Creates a clone of this signature that is safe to modify. */ + clone(): Signature { + var parameterTypes = this.parameterTypes; + var numParameterTypes = parameterTypes.length; + var cloneParameterTypes = new Array(numParameterTypes); + for (let i = 0; i < numParameterTypes; ++i) { + cloneParameterTypes[i] = parameterTypes[i]; + } + var clone = new Signature(this.program, cloneParameterTypes, this.returnType, this.thisType); + var parameterNames = this.parameterNames; + if (parameterNames) { + let numParameterNames = parameterNames.length; + let cloneParameterNames = new Array(numParameterNames); + for (let i = 0; i < numParameterNames; ++i) { + cloneParameterNames[i] = parameterNames[i]; + } + clone.parameterNames = cloneParameterNames; + } + return clone; + } } // helpers diff --git a/tests/compiler/call-inferred.untouched.wat b/tests/compiler/call-inferred.untouched.wat index 2a9e74fe9a..63567615f7 100644 --- a/tests/compiler/call-inferred.untouched.wat +++ b/tests/compiler/call-inferred.untouched.wat @@ -25,7 +25,7 @@ (func $call-inferred/bar (param $0 f32) (result f32) local.get $0 ) - (func $call-inferred/bar|trampoline (param $0 f32) (result f32) + (func $call-inferred/bar@varargs (param $0 f32) (result f32) block $1of1 block $0of1 block $outOfRange @@ -87,7 +87,7 @@ i32.const 0 global.set $~argumentsLength f32.const 0 - call $call-inferred/bar|trampoline + call $call-inferred/bar@varargs f32.const 42 f32.eq i32.eqz diff --git a/tests/compiler/call-optional.optimized.wat b/tests/compiler/call-optional.optimized.wat index eb1d84cfa9..a552c118cc 100644 --- a/tests/compiler/call-optional.optimized.wat +++ b/tests/compiler/call-optional.optimized.wat @@ -17,7 +17,7 @@ i32.add i32.add ) - (func $call-optional/opt|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $call-optional/opt@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -50,7 +50,7 @@ i32.const 3 i32.const 0 i32.const 0 - call $call-optional/opt|trampoline + call $call-optional/opt@varargs if i32.const 0 i32.const 1040 @@ -64,7 +64,7 @@ i32.const 3 i32.const 4 i32.const 0 - call $call-optional/opt|trampoline + call $call-optional/opt@varargs i32.const 5 i32.ne if @@ -94,7 +94,7 @@ i32.const 3 i32.const 0 i32.const 0 - call $call-optional/opt|trampoline + call $call-optional/opt@varargs if i32.const 0 i32.const 1040 @@ -108,7 +108,7 @@ i32.const 3 i32.const 4 i32.const 0 - call $call-optional/opt|trampoline + call $call-optional/opt@varargs i32.const 5 i32.ne if @@ -124,7 +124,7 @@ i32.const 3 i32.const 4 i32.const 5 - call $call-optional/opt|trampoline + call $call-optional/opt@varargs i32.const 12 i32.ne if diff --git a/tests/compiler/call-optional.untouched.wat b/tests/compiler/call-optional.untouched.wat index 6fc0a1ab5b..ab1629daf4 100644 --- a/tests/compiler/call-optional.untouched.wat +++ b/tests/compiler/call-optional.untouched.wat @@ -7,7 +7,7 @@ (memory $0 1) (data (i32.const 16) " \00\00\00\01\00\00\00\01\00\00\00 \00\00\00c\00a\00l\00l\00-\00o\00p\00t\00i\00o\00n\00a\00l\00.\00t\00s\00") (table $0 2 funcref) - (elem (i32.const 1) $call-optional/opt|trampoline) + (elem (i32.const 1) $call-optional/opt@varargs) (global $~argumentsLength (mut i32) (i32.const 0)) (global $call-optional/optIndirect (mut i32) (i32.const 1)) (export "__setArgumentsLength" (func $~setArgumentsLength)) @@ -20,7 +20,7 @@ local.get $2 i32.add ) - (func $call-optional/opt|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $call-optional/opt@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -53,7 +53,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $call-optional/opt|trampoline + call $call-optional/opt@varargs i32.const 0 i32.eq i32.eqz @@ -70,7 +70,7 @@ i32.const 2 global.set $~argumentsLength i32.const 0 - call $call-optional/opt|trampoline + call $call-optional/opt@varargs i32.const 5 i32.eq i32.eqz diff --git a/tests/compiler/class-overloading.optimized.wat b/tests/compiler/class-overloading.optimized.wat index 9676d44e04..68a6b7efce 100644 --- a/tests/compiler/class-overloading.optimized.wat +++ b/tests/compiler/class-overloading.optimized.wat @@ -267,7 +267,7 @@ call $class-overloading/B#constructor global.set $class-overloading/a global.get $class-overloading/a - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -283,7 +283,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -299,7 +299,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -315,7 +315,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -399,7 +399,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -415,7 +415,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -431,7 +431,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -445,7 +445,7 @@ unreachable end global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -464,7 +464,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -480,7 +480,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -496,7 +496,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -510,7 +510,7 @@ unreachable end global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1088 call $~lib/string/String.__eq @@ -530,7 +530,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 1216 call $~lib/string/String.__eq @@ -546,7 +546,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1216 call $~lib/string/String.__eq @@ -562,7 +562,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1216 call $~lib/string/String.__eq @@ -578,7 +578,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 1216 call $~lib/string/String.__eq @@ -597,7 +597,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/ia - call $class-overloading/IA#foo|virtual + call $class-overloading/IA#foo@virtual global.get $class-overloading/which i32.const 1248 call $~lib/string/String.__eq @@ -616,7 +616,7 @@ i32.const 1040 global.set $class-overloading/which global.get $class-overloading/ic - call $class-overloading/IA#foo|virtual + call $class-overloading/IA#foo@virtual global.get $class-overloading/which i32.const 1280 call $~lib/string/String.__eq @@ -640,7 +640,7 @@ end call $start:class-overloading ) - (func $class-overloading/A#a|virtual (param $0 i32) + (func $class-overloading/A#a@virtual (param $0 i32) block $default block $case2 block $case1 @@ -679,7 +679,7 @@ i32.const 1056 global.set $class-overloading/which ) - (func $class-overloading/A#b|virtual (param $0 i32) + (func $class-overloading/A#b@virtual (param $0 i32) block $default block $case2 block $case1 @@ -719,7 +719,7 @@ i32.const 1056 global.set $class-overloading/which ) - (func $class-overloading/IA#foo|virtual (param $0 i32) + (func $class-overloading/IA#foo@virtual (param $0 i32) block $default block $case1 local.get $0 diff --git a/tests/compiler/class-overloading.untouched.wat b/tests/compiler/class-overloading.untouched.wat index 807c001c80..2890186552 100644 --- a/tests/compiler/class-overloading.untouched.wat +++ b/tests/compiler/class-overloading.untouched.wat @@ -574,7 +574,7 @@ global.set $class-overloading/a global.get $class-overloading/a i32.const 1 - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -595,7 +595,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -615,7 +615,7 @@ local.get $0 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#get:c@virtual drop global.get $class-overloading/which i32.const 80 @@ -637,7 +637,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#set:c|virtual + call $class-overloading/A#set:c@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -746,7 +746,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -767,7 +767,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -787,7 +787,7 @@ local.get $0 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#get:c@virtual drop global.get $class-overloading/which i32.const 80 @@ -803,7 +803,7 @@ end global.get $class-overloading/a i32.const 1 - call $class-overloading/A#set:c|virtual + call $class-overloading/A#set:c@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -831,7 +831,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -852,7 +852,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -872,7 +872,7 @@ local.get $0 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#get:c@virtual drop global.get $class-overloading/which i32.const 80 @@ -888,7 +888,7 @@ end global.get $class-overloading/a i32.const 1 - call $class-overloading/A#set:c|virtual + call $class-overloading/A#set:c@virtual global.get $class-overloading/which i32.const 80 call $~lib/string/String.__eq @@ -916,7 +916,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#a|virtual + call $class-overloading/A#a@virtual global.get $class-overloading/which i32.const 208 call $~lib/string/String.__eq @@ -937,7 +937,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#b|virtual + call $class-overloading/A#b@virtual global.get $class-overloading/which i32.const 208 call $~lib/string/String.__eq @@ -957,7 +957,7 @@ local.get $0 global.set $class-overloading/which global.get $class-overloading/a - call $class-overloading/A#get:c|virtual + call $class-overloading/A#get:c@virtual drop global.get $class-overloading/which i32.const 208 @@ -979,7 +979,7 @@ global.set $class-overloading/which global.get $class-overloading/a i32.const 1 - call $class-overloading/A#set:c|virtual + call $class-overloading/A#set:c@virtual global.get $class-overloading/which i32.const 208 call $~lib/string/String.__eq @@ -1002,7 +1002,7 @@ local.get $0 global.set $class-overloading/which global.get $class-overloading/ia - call $class-overloading/IA#foo|virtual + call $class-overloading/IA#foo@virtual global.get $class-overloading/which i32.const 240 call $~lib/string/String.__eq @@ -1025,7 +1025,7 @@ local.get $0 global.set $class-overloading/which global.get $class-overloading/ic - call $class-overloading/IA#foo|virtual + call $class-overloading/IA#foo@virtual global.get $class-overloading/which i32.const 272 call $~lib/string/String.__eq @@ -1058,7 +1058,7 @@ local.get $2 global.set $class-overloading/which ) - (func $class-overloading/A#a|virtual (param $0 i32) (param $1 i32) + (func $class-overloading/A#a@virtual (param $0 i32) (param $1 i32) (local $2 i32) block $default block $case2 @@ -1128,7 +1128,7 @@ local.get $2 global.set $class-overloading/which ) - (func $class-overloading/A#b|virtual (param $0 i32) (param $1 i32) + (func $class-overloading/A#b@virtual (param $0 i32) (param $1 i32) (local $2 i32) block $default block $case2 @@ -1200,7 +1200,7 @@ global.set $class-overloading/which i32.const 0 ) - (func $class-overloading/A#get:c|virtual (param $0 i32) (result i32) + (func $class-overloading/A#get:c@virtual (param $0 i32) (result i32) (local $1 i32) block $default block $case2 @@ -1266,7 +1266,7 @@ local.get $2 global.set $class-overloading/which ) - (func $class-overloading/A#set:c|virtual (param $0 i32) (param $1 i32) + (func $class-overloading/A#set:c@virtual (param $0 i32) (param $1 i32) (local $2 i32) block $default block $case2 @@ -1336,7 +1336,7 @@ local.get $1 global.set $class-overloading/which ) - (func $class-overloading/IA#foo|virtual (param $0 i32) + (func $class-overloading/IA#foo@virtual (param $0 i32) (local $1 i32) block $default block $case1 diff --git a/tests/compiler/exports.optimized.wat b/tests/compiler/exports.optimized.wat index dd9f0d2a4d..f9d5a4c462 100644 --- a/tests/compiler/exports.optimized.wat +++ b/tests/compiler/exports.optimized.wat @@ -20,7 +20,7 @@ (export "memory" (memory $0)) (export "add" (func $exports/add)) (export "__setArgumentsLength" (func $~setArgumentsLength)) - (export "subOpt" (func $exports/subOpt|trampoline)) + (export "subOpt" (func $exports/subOpt@varargs)) (export "math.sub" (func $exports/subOpt)) (export "Animal.CAT" (global $exports/Animal.CAT)) (export "Animal.DOG" (global $exports/Animal.DOG)) @@ -29,7 +29,7 @@ (export "Car" (global $exports/Car)) (export "Car#get:doors" (func $exports/Car#get:doors)) (export "Car#set:doors" (func $exports/Car#set:doors)) - (export "Car#constructor" (func $exports/Car#constructor|trampoline)) + (export "Car#constructor" (func $exports/Car#constructor@varargs)) (export "Car#get:numDoors" (func $exports/Car#get:doors)) (export "Car#set:numDoors" (func $exports/Car#set:doors)) (export "Car#openDoors" (func $exports/Car#openDoors)) @@ -38,7 +38,7 @@ (export "vehicles.Car" (global $exports/vehicles.Car)) (export "vehicles.Car#get:doors" (func $exports/Car#get:doors)) (export "vehicles.Car#set:doors" (func $exports/Car#set:doors)) - (export "vehicles.Car#constructor" (func $exports/vehicles.Car#constructor|trampoline)) + (export "vehicles.Car#constructor" (func $exports/vehicles.Car#constructor@varargs)) (export "vehicles.Car#get:numDoors" (func $exports/Car#get:doors)) (export "vehicles.Car#set:numDoors" (func $exports/Car#set:doors)) (export "vehicles.Car#openDoors" (func $exports/Car#openDoors)) @@ -141,7 +141,7 @@ i32.const 1024 global.set $~lib/rt/stub/offset ) - (func $exports/subOpt|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $exports/subOpt@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -163,7 +163,7 @@ local.get $0 global.set $~argumentsLength ) - (func $exports/Car#constructor|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $exports/Car#constructor@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -190,7 +190,7 @@ i32.store local.get $0 ) - (func $exports/vehicles.Car#constructor|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $exports/vehicles.Car#constructor@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange diff --git a/tests/compiler/exports.untouched.wat b/tests/compiler/exports.untouched.wat index c8c364dc88..b91e3516dd 100644 --- a/tests/compiler/exports.untouched.wat +++ b/tests/compiler/exports.untouched.wat @@ -23,7 +23,7 @@ (export "memory" (memory $0)) (export "add" (func $exports/add)) (export "__setArgumentsLength" (func $~setArgumentsLength)) - (export "subOpt" (func $exports/subOpt|trampoline)) + (export "subOpt" (func $exports/subOpt@varargs)) (export "math.sub" (func $exports/math.sub)) (export "Animal.CAT" (global $exports/Animal.CAT)) (export "Animal.DOG" (global $exports/Animal.DOG)) @@ -32,7 +32,7 @@ (export "Car" (global $exports/Car)) (export "Car#get:doors" (func $exports/Car#get:doors)) (export "Car#set:doors" (func $exports/Car#set:doors)) - (export "Car#constructor" (func $exports/Car#constructor|trampoline)) + (export "Car#constructor" (func $exports/Car#constructor@varargs)) (export "Car#get:numDoors" (func $exports/Car#get:numDoors)) (export "Car#set:numDoors" (func $exports/Car#set:numDoors)) (export "Car#openDoors" (func $exports/Car#openDoors)) @@ -41,7 +41,7 @@ (export "vehicles.Car" (global $exports/vehicles.Car)) (export "vehicles.Car#get:doors" (func $exports/vehicles.Car#get:doors)) (export "vehicles.Car#set:doors" (func $exports/vehicles.Car#set:doors)) - (export "vehicles.Car#constructor" (func $exports/vehicles.Car#constructor|trampoline)) + (export "vehicles.Car#constructor" (func $exports/vehicles.Car#constructor@varargs)) (export "vehicles.Car#get:numDoors" (func $exports/vehicles.Car#get:numDoors)) (export "vehicles.Car#set:numDoors" (func $exports/vehicles.Car#set:numDoors)) (export "vehicles.Car#openDoors" (func $exports/vehicles.Car#openDoors)) @@ -270,7 +270,7 @@ global.get $~lib/rt/stub/startOffset global.set $~lib/rt/stub/offset ) - (func $exports/subOpt|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $exports/subOpt@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -292,7 +292,7 @@ local.get $0 global.set $~argumentsLength ) - (func $exports/Car#constructor|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $exports/Car#constructor@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -308,7 +308,7 @@ local.get $1 call $exports/Car#constructor ) - (func $exports/vehicles.Car#constructor|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $exports/vehicles.Car#constructor@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange diff --git a/tests/compiler/function-types.untouched.wat b/tests/compiler/function-types.untouched.wat index 6079e14183..152d0540ce 100644 --- a/tests/compiler/function-types.untouched.wat +++ b/tests/compiler/function-types.untouched.wat @@ -75,7 +75,7 @@ local.get $2 call_indirect (type $i32_i32_=>_i32) ) - (func $function-types/makeAndAdd|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $function-types/makeAndAdd@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -199,7 +199,7 @@ i32.const 2 global.set $~argumentsLength i32.const 0 - call $function-types/makeAndAdd|trampoline + call $function-types/makeAndAdd@varargs i32.const 3 i32.eq i32.eqz diff --git a/tests/compiler/std/array.untouched.wat b/tests/compiler/std/array.untouched.wat index 487d2af82e..3f8dade7c4 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -7527,7 +7527,7 @@ i32.lt_s i32.sub ) - (func $~lib/array/Array#sort|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/array/Array#sort@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -8140,7 +8140,7 @@ i64.lt_s i32.sub ) - (func $~lib/array/Array#sort|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/array/Array#sort@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -8756,7 +8756,7 @@ local.get $1 i32.sub ) - (func $~lib/array/Array#sort|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/array/Array#sort@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -9236,7 +9236,7 @@ i32.lt_u i32.sub ) - (func $~lib/array/Array#sort|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/array/Array#sort@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -11078,7 +11078,7 @@ call $~lib/rt/pure/__release local.get $2 ) - (func $std/array/assertSorted<~lib/string/String | null>|trampoline (param $0 i32) (param $1 i32) + (func $std/array/assertSorted<~lib/string/String | null>@varargs (param $0 i32) (param $1 i32) block $1of1 block $0of1 block $outOfRange @@ -12074,7 +12074,7 @@ call $~lib/rt/pure/__release local.get $2 ) - (func $std/array/assertSorted<~lib/string/String>|trampoline (param $0 i32) (param $1 i32) + (func $std/array/assertSorted<~lib/string/String>@varargs (param $0 i32) (param $1 i32) block $1of1 block $0of1 block $outOfRange @@ -23068,7 +23068,7 @@ i32.const 0 global.set $~argumentsLength i32.const 0 - call $~lib/array/Array#sort|trampoline + call $~lib/array/Array#sort@varargs call $~lib/rt/pure/__release local.get $50 i32.const 8 @@ -23100,7 +23100,7 @@ i32.const 0 global.set $~argumentsLength i32.const 0 - call $~lib/array/Array#sort|trampoline + call $~lib/array/Array#sort@varargs call $~lib/rt/pure/__release local.get $49 i32.const 8 @@ -23132,7 +23132,7 @@ i32.const 0 global.set $~argumentsLength i32.const 0 - call $~lib/array/Array#sort|trampoline + call $~lib/array/Array#sort@varargs call $~lib/rt/pure/__release local.get $47 i32.const 5 @@ -23164,7 +23164,7 @@ i32.const 0 global.set $~argumentsLength i32.const 0 - call $~lib/array/Array#sort|trampoline + call $~lib/array/Array#sort@varargs call $~lib/rt/pure/__release local.get $41 i32.const 5 @@ -23452,7 +23452,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $std/array/assertSorted<~lib/string/String | null>|trampoline + call $std/array/assertSorted<~lib/string/String | null>@varargs local.get $31 local.get $34 i32.const 0 @@ -23473,7 +23473,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $std/array/assertSorted<~lib/string/String>|trampoline + call $std/array/assertSorted<~lib/string/String>@varargs local.get $31 call $~lib/rt/pure/__release local.get $34 diff --git a/tests/compiler/std/arraybuffer.untouched.wat b/tests/compiler/std/arraybuffer.untouched.wat index b12ae25cac..802984cb65 100644 --- a/tests/compiler/std/arraybuffer.untouched.wat +++ b/tests/compiler/std/arraybuffer.untouched.wat @@ -3397,7 +3397,7 @@ call $~lib/rt/pure/__release local.get $0 ) - (func $~lib/dataview/DataView#constructor|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (func $~lib/dataview/DataView#constructor@varargs (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -3784,7 +3784,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/dataview/DataView#constructor|trampoline + call $~lib/dataview/DataView#constructor@varargs local.tee $5 call $~lib/arraybuffer/ArrayBuffer.isView<~lib/dataview/DataView> i32.eqz diff --git a/tests/compiler/std/dataview.untouched.wat b/tests/compiler/std/dataview.untouched.wat index d48e6417fe..6ce13a84ba 100644 --- a/tests/compiler/std/dataview.untouched.wat +++ b/tests/compiler/std/dataview.untouched.wat @@ -2647,7 +2647,7 @@ end i64.store ) - (func $~lib/dataview/DataView#constructor|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (func $~lib/dataview/DataView#constructor@varargs (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -4375,7 +4375,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/dataview/DataView#constructor|trampoline + call $~lib/dataview/DataView#constructor@varargs local.set $2 local.get $1 call $~lib/rt/pure/__release diff --git a/tests/compiler/std/string.optimized.wat b/tests/compiler/std/string.optimized.wat index 5cc59379de..0644843b30 100644 --- a/tests/compiler/std/string.optimized.wat +++ b/tests/compiler/std/string.optimized.wat @@ -1619,7 +1619,7 @@ local.get $2 call $~lib/rt/pure/__retain ) - (func $~lib/string/String.fromCharCode|trampoline (param $0 i32) (result i32) + (func $~lib/string/String.fromCharCode@varargs (param $0 i32) (result i32) (local $1 i32) block $1of1 block $0of1 @@ -7079,7 +7079,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/string/String.fromCharCode|trampoline + call $~lib/string/String.fromCharCode@varargs local.tee $41 i32.const 1296 call $~lib/string/String.__eq @@ -7095,7 +7095,7 @@ i32.const 1 global.set $~argumentsLength i32.const 54 - call $~lib/string/String.fromCharCode|trampoline + call $~lib/string/String.fromCharCode@varargs local.tee $42 i32.const 1472 call $~lib/string/String.__eq @@ -7111,7 +7111,7 @@ i32.const 1 global.set $~argumentsLength i32.const 65590 - call $~lib/string/String.fromCharCode|trampoline + call $~lib/string/String.fromCharCode@varargs local.tee $43 i32.const 1472 call $~lib/string/String.__eq diff --git a/tests/compiler/std/string.untouched.wat b/tests/compiler/std/string.untouched.wat index aef4456fc9..7db290ef1e 100644 --- a/tests/compiler/std/string.untouched.wat +++ b/tests/compiler/std/string.untouched.wat @@ -2111,7 +2111,7 @@ local.get $3 call $~lib/rt/pure/__retain ) - (func $~lib/string/String.fromCharCode|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/string/String.fromCharCode@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -10889,7 +10889,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/string/String.fromCharCode|trampoline + call $~lib/string/String.fromCharCode@varargs local.tee $0 i32.const 288 call $~lib/string/String.__eq @@ -10906,7 +10906,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/string/String.fromCharCode|trampoline + call $~lib/string/String.fromCharCode@varargs local.tee $1 i32.const 464 call $~lib/string/String.__eq @@ -10923,7 +10923,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/string/String.fromCharCode|trampoline + call $~lib/string/String.fromCharCode@varargs local.tee $2 i32.const 464 call $~lib/string/String.__eq diff --git a/tests/compiler/std/typedarray.optimized.wat b/tests/compiler/std/typedarray.optimized.wat index a624366f58..6b54ef7c0b 100644 --- a/tests/compiler/std/typedarray.optimized.wat +++ b/tests/compiler/std/typedarray.optimized.wat @@ -10918,7 +10918,7 @@ end local.get $2 ) - (func $~lib/typedarray/Int8Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/typedarray/Int8Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (result i32) (local $2 i32) block $1of1 block $0of1 @@ -11102,7 +11102,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -11115,7 +11115,7 @@ global.set $~argumentsLength local.get $0 i32.const 11 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -11130,7 +11130,7 @@ global.set $~argumentsLength local.get $0 i32.const -1 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -11145,7 +11145,7 @@ global.set $~argumentsLength local.get $0 i32.const 3 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -11520,7 +11520,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -11533,7 +11533,7 @@ global.set $~argumentsLength local.get $0 i32.const 11 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -11548,7 +11548,7 @@ global.set $~argumentsLength local.get $0 i32.const -1 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -11563,7 +11563,7 @@ global.set $~argumentsLength local.get $0 i32.const 3 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -11937,7 +11937,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -11950,7 +11950,7 @@ global.set $~argumentsLength local.get $0 i32.const 11 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -11965,7 +11965,7 @@ global.set $~argumentsLength local.get $0 i32.const -1 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -11980,7 +11980,7 @@ global.set $~argumentsLength local.get $0 i32.const 3 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -12320,7 +12320,7 @@ end local.get $2 ) - (func $~lib/typedarray/Int16Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/typedarray/Int16Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (result i32) (local $2 i32) block $1of1 block $0of1 @@ -12506,7 +12506,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -12519,7 +12519,7 @@ global.set $~argumentsLength local.get $0 i32.const 11 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -12534,7 +12534,7 @@ global.set $~argumentsLength local.get $0 i32.const -1 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -12549,7 +12549,7 @@ global.set $~argumentsLength local.get $0 i32.const 3 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -12923,7 +12923,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -12936,7 +12936,7 @@ global.set $~argumentsLength local.get $0 i32.const 11 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -12951,7 +12951,7 @@ global.set $~argumentsLength local.get $0 i32.const -1 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -12966,7 +12966,7 @@ global.set $~argumentsLength local.get $0 i32.const 3 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -13302,7 +13302,7 @@ end local.get $2 ) - (func $~lib/typedarray/Int32Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/typedarray/Int32Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (result i32) (local $2 i32) block $1of1 block $0of1 @@ -13484,7 +13484,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -13497,7 +13497,7 @@ global.set $~argumentsLength local.get $0 i32.const 11 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -13512,7 +13512,7 @@ global.set $~argumentsLength local.get $0 i32.const -1 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -13527,7 +13527,7 @@ global.set $~argumentsLength local.get $0 i32.const 3 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -13900,7 +13900,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -13913,7 +13913,7 @@ global.set $~argumentsLength local.get $0 i32.const 11 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -13928,7 +13928,7 @@ global.set $~argumentsLength local.get $0 i32.const -1 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -13943,7 +13943,7 @@ global.set $~argumentsLength local.get $0 i32.const 3 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -14279,7 +14279,7 @@ end local.get $2 ) - (func $~lib/typedarray/Int64Array#lastIndexOf|trampoline (param $0 i32) (param $1 i64) (result i32) + (func $~lib/typedarray/Int64Array#lastIndexOf@varargs (param $0 i32) (param $1 i64) (result i32) (local $2 i32) block $1of1 block $0of1 @@ -14462,7 +14462,7 @@ global.set $~argumentsLength local.get $0 i64.const 0 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -14475,7 +14475,7 @@ global.set $~argumentsLength local.get $0 i64.const 11 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -14490,7 +14490,7 @@ global.set $~argumentsLength local.get $0 i64.const -1 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -14505,7 +14505,7 @@ global.set $~argumentsLength local.get $0 i64.const 3 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -14878,7 +14878,7 @@ global.set $~argumentsLength local.get $0 i64.const 0 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -14891,7 +14891,7 @@ global.set $~argumentsLength local.get $0 i64.const 11 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -14906,7 +14906,7 @@ global.set $~argumentsLength local.get $0 i64.const -1 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -14921,7 +14921,7 @@ global.set $~argumentsLength local.get $0 i64.const 3 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -15257,7 +15257,7 @@ end local.get $2 ) - (func $~lib/typedarray/Float32Array#lastIndexOf|trampoline (param $0 i32) (param $1 f32) (result i32) + (func $~lib/typedarray/Float32Array#lastIndexOf@varargs (param $0 i32) (param $1 f32) (result i32) (local $2 i32) block $1of1 block $0of1 @@ -15440,7 +15440,7 @@ global.set $~argumentsLength local.get $0 f32.const 0 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -15453,7 +15453,7 @@ global.set $~argumentsLength local.get $0 f32.const 11 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -15468,7 +15468,7 @@ global.set $~argumentsLength local.get $0 f32.const -1 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -15483,7 +15483,7 @@ global.set $~argumentsLength local.get $0 f32.const 3 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -15819,7 +15819,7 @@ end local.get $2 ) - (func $~lib/typedarray/Float64Array#lastIndexOf|trampoline (param $0 i32) (param $1 f64) (result i32) + (func $~lib/typedarray/Float64Array#lastIndexOf@varargs (param $0 i32) (param $1 f64) (result i32) (local $2 i32) block $1of1 block $0of1 @@ -16002,7 +16002,7 @@ global.set $~argumentsLength local.get $0 f64.const 0 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs if i32.const 0 i32.const 1312 @@ -16015,7 +16015,7 @@ global.set $~argumentsLength local.get $0 f64.const 11 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -16030,7 +16030,7 @@ global.set $~argumentsLength local.get $0 f64.const -1 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs i32.const -1 i32.ne if @@ -16045,7 +16045,7 @@ global.set $~argumentsLength local.get $0 f64.const 3 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs i32.const 3 i32.ne if @@ -19354,7 +19354,7 @@ local.get $1 call $~lib/rt/pure/__retain ) - (func $~lib/typedarray/Uint8Array.wrap|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/typedarray/Uint8Array.wrap@varargs (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) block $2of2 @@ -19676,7 +19676,7 @@ global.set $~argumentsLength local.get $0 i32.const 0 - call $~lib/typedarray/Uint8Array.wrap|trampoline + call $~lib/typedarray/Uint8Array.wrap@varargs local.set $4 loop $for-loop|1 local.get $2 @@ -31653,7 +31653,7 @@ global.set $~argumentsLength local.get $1 i32.const 0 - call $~lib/typedarray/Uint8Array.wrap|trampoline + call $~lib/typedarray/Uint8Array.wrap@varargs local.tee $30 i32.load offset=8 if @@ -31673,7 +31673,7 @@ global.set $~argumentsLength local.get $0 i32.const 2 - call $~lib/typedarray/Uint8Array.wrap|trampoline + call $~lib/typedarray/Uint8Array.wrap@varargs local.set $1 local.get $30 call $~lib/rt/pure/__release diff --git a/tests/compiler/std/typedarray.untouched.wat b/tests/compiler/std/typedarray.untouched.wat index 6658c73841..083309d93f 100644 --- a/tests/compiler/std/typedarray.untouched.wat +++ b/tests/compiler/std/typedarray.untouched.wat @@ -3569,7 +3569,7 @@ i64.lt_s i32.sub ) - (func $~lib/typedarray/Float64Array#sort|trampoline (param $0 i32) (param $1 i32) (result i32) + (func $~lib/typedarray/Float64Array#sort@varargs (param $0 i32) (param $1 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -24117,7 +24117,7 @@ local.get $9 end ) - (func $~lib/typedarray/Int8Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Int8Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -24323,7 +24323,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -24340,7 +24340,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -24357,7 +24357,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -24374,7 +24374,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int8Array#lastIndexOf|trampoline + call $~lib/typedarray/Int8Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -24802,7 +24802,7 @@ local.get $9 end ) - (func $~lib/typedarray/Uint8Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint8Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -25006,7 +25006,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint8Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -25023,7 +25023,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint8Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -25040,7 +25040,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint8Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -25057,7 +25057,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint8Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -25485,7 +25485,7 @@ local.get $9 end ) - (func $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint8ClampedArray#lastIndexOf@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -25689,7 +25689,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline + call $~lib/typedarray/Uint8ClampedArray#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -25706,7 +25706,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline + call $~lib/typedarray/Uint8ClampedArray#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -25723,7 +25723,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline + call $~lib/typedarray/Uint8ClampedArray#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -25740,7 +25740,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8ClampedArray#lastIndexOf|trampoline + call $~lib/typedarray/Uint8ClampedArray#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -26172,7 +26172,7 @@ local.get $9 end ) - (func $~lib/typedarray/Int16Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Int16Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -26378,7 +26378,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -26395,7 +26395,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -26412,7 +26412,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -26429,7 +26429,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int16Array#lastIndexOf|trampoline + call $~lib/typedarray/Int16Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -26857,7 +26857,7 @@ local.get $9 end ) - (func $~lib/typedarray/Uint16Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint16Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -27061,7 +27061,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint16Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -27078,7 +27078,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint16Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -27095,7 +27095,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint16Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -27112,7 +27112,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint16Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint16Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -27536,7 +27536,7 @@ local.get $9 end ) - (func $~lib/typedarray/Int32Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Int32Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -27738,7 +27738,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -27755,7 +27755,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -27772,7 +27772,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -27789,7 +27789,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int32Array#lastIndexOf|trampoline + call $~lib/typedarray/Int32Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -28213,7 +28213,7 @@ local.get $9 end ) - (func $~lib/typedarray/Uint32Array#lastIndexOf|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint32Array#lastIndexOf@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -28415,7 +28415,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint32Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -28432,7 +28432,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint32Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -28449,7 +28449,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint32Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -28466,7 +28466,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint32Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint32Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -28890,7 +28890,7 @@ local.get $9 end ) - (func $~lib/typedarray/Int64Array#lastIndexOf|trampoline (param $0 i32) (param $1 i64) (param $2 i32) (result i32) + (func $~lib/typedarray/Int64Array#lastIndexOf@varargs (param $0 i32) (param $1 i64) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -29093,7 +29093,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -29110,7 +29110,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -29127,7 +29127,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -29144,7 +29144,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int64Array#lastIndexOf|trampoline + call $~lib/typedarray/Int64Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -29568,7 +29568,7 @@ local.get $9 end ) - (func $~lib/typedarray/Uint64Array#lastIndexOf|trampoline (param $0 i32) (param $1 i64) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint64Array#lastIndexOf@varargs (param $0 i32) (param $1 i64) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -29771,7 +29771,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint64Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -29788,7 +29788,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint64Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -29805,7 +29805,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint64Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -29822,7 +29822,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint64Array#lastIndexOf|trampoline + call $~lib/typedarray/Uint64Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -30246,7 +30246,7 @@ local.get $9 end ) - (func $~lib/typedarray/Float32Array#lastIndexOf|trampoline (param $0 i32) (param $1 f32) (param $2 i32) (result i32) + (func $~lib/typedarray/Float32Array#lastIndexOf@varargs (param $0 i32) (param $1 f32) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -30449,7 +30449,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -30466,7 +30466,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -30483,7 +30483,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -30500,7 +30500,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float32Array#lastIndexOf|trampoline + call $~lib/typedarray/Float32Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -30924,7 +30924,7 @@ local.get $9 end ) - (func $~lib/typedarray/Float64Array#lastIndexOf|trampoline (param $0 i32) (param $1 f64) (param $2 i32) (result i32) + (func $~lib/typedarray/Float64Array#lastIndexOf@varargs (param $0 i32) (param $1 f64) (param $2 i32) (result i32) block $1of1 block $0of1 block $outOfRange @@ -31127,7 +31127,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs i32.const 0 i32.eq i32.eqz @@ -31144,7 +31144,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -31161,7 +31161,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs i32.const -1 i32.eq i32.eqz @@ -31178,7 +31178,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float64Array#lastIndexOf|trampoline + call $~lib/typedarray/Float64Array#lastIndexOf@varargs i32.const 3 i32.eq i32.eqz @@ -37125,7 +37125,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Uint8Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint8Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -37352,7 +37352,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Int8Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Int8Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -37440,7 +37440,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int8Array.wrap|trampoline + call $~lib/typedarray/Int8Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -37552,7 +37552,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8Array.wrap|trampoline + call $~lib/typedarray/Uint8Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -37722,7 +37722,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Uint8ClampedArray.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint8ClampedArray.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -37808,7 +37808,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8ClampedArray.wrap|trampoline + call $~lib/typedarray/Uint8ClampedArray.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -37978,7 +37978,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Int16Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Int16Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -38066,7 +38066,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int16Array.wrap|trampoline + call $~lib/typedarray/Int16Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -38236,7 +38236,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Uint16Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint16Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -38322,7 +38322,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint16Array.wrap|trampoline + call $~lib/typedarray/Uint16Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -38492,7 +38492,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Int32Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Int32Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -38576,7 +38576,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int32Array.wrap|trampoline + call $~lib/typedarray/Int32Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -38746,7 +38746,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Uint32Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint32Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -38830,7 +38830,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint32Array.wrap|trampoline + call $~lib/typedarray/Uint32Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -39000,7 +39000,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Int64Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Int64Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -39085,7 +39085,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Int64Array.wrap|trampoline + call $~lib/typedarray/Int64Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -39255,7 +39255,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Uint64Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Uint64Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -39340,7 +39340,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint64Array.wrap|trampoline + call $~lib/typedarray/Uint64Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -39510,7 +39510,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Float32Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Float32Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -39595,7 +39595,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float32Array.wrap|trampoline + call $~lib/typedarray/Float32Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -39765,7 +39765,7 @@ call $~lib/rt/pure/__release local.get $8 ) - (func $~lib/typedarray/Float64Array.wrap|trampoline (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $~lib/typedarray/Float64Array.wrap@varargs (param $0 i32) (param $1 i32) (param $2 i32) (result i32) block $2of2 block $1of2 block $0of2 @@ -39850,7 +39850,7 @@ i32.const 1 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float64Array.wrap|trampoline + call $~lib/typedarray/Float64Array.wrap@varargs local.set $5 local.get $7 call $~lib/rt/pure/__release @@ -50855,7 +50855,7 @@ i32.const 0 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Float64Array#sort|trampoline + call $~lib/typedarray/Float64Array#sort@varargs call $~lib/rt/pure/__release local.get $0 i32.const 0 @@ -52603,7 +52603,7 @@ i32.const 2 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8Array.wrap|trampoline + call $~lib/typedarray/Uint8Array.wrap@varargs local.set $22 local.get $22 call $~lib/typedarray/Uint8Array#get:length @@ -52631,7 +52631,7 @@ i32.const 2 global.set $~argumentsLength i32.const 0 - call $~lib/typedarray/Uint8Array.wrap|trampoline + call $~lib/typedarray/Uint8Array.wrap@varargs local.set $3 local.get $22 call $~lib/rt/pure/__release From acc9862fe218ce4be628f2564a415a150cd51581 Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 27 Apr 2020 11:50:36 +0200 Subject: [PATCH 23/24] fix bootstrap --- cli/asc.js | 75 ++++++++++++++++++---------------------- lib/loader/index.d.ts | 7 ++-- src/compiler.ts | 9 ++--- src/index.ts | 4 +-- src/program.ts | 7 ++-- tests/bootstrap/index.ts | 39 +++++++++++---------- 6 files changed, 65 insertions(+), 76 deletions(-) diff --git a/cli/asc.js b/cli/asc.js index 28d06d2075..a38a183b7f 100644 --- a/cli/asc.js +++ b/cli/asc.js @@ -375,7 +375,10 @@ exports.main = function main(argv, options, callback) { let transform = transforms[i]; if (typeof transform[name] === "function") { try { - transform[name](...args); + stats.transformCount++; + stats.transfromTime += measure(() => { + transform[name](...args); + }); } catch (e) { return e; } @@ -605,29 +608,11 @@ exports.main = function main(argv, options, callback) { return callback(null); } - // Set up optimization levels - var optimizeLevel = 0; - var shrinkLevel = 0; - if (args.optimize) { - optimizeLevel = exports.defaultOptimizeLevel; - shrinkLevel = exports.defaultShrinkLevel; - } - if (typeof args.optimizeLevel === "number") { - optimizeLevel = args.optimizeLevel; - } - if (typeof args.shrinkLevel === "number") { - shrinkLevel = args.shrinkLevel; - } - optimizeLevel = Math.min(Math.max(optimizeLevel, 0), 3); - shrinkLevel = Math.min(Math.max(shrinkLevel, 0), 2); - - try { - stats.compileTime += measure(() => { - assemblyscript.initializeProgram(program, compilerOptions); - }); - } catch(e) { - return callback(e); - } + // Pre-emptively initialize the program + stats.initializeCount++; + stats.initializeTime += measure(() => { + assemblyscript.initializeProgram(program); + }); // Call afterInitialize transform hook { @@ -637,13 +622,9 @@ exports.main = function main(argv, options, callback) { var module; stats.compileCount++; - try { - stats.compileTime += measure(() => { - module = assemblyscript.compile(program); - }); - } catch (e) { - return callback(e); - } + stats.compileTime += measure(() => { + module = assemblyscript.compile(program); + }); var numErrors = checkDiagnostics(program, stderr); if (numErrors) { if (module) module.dispose(); @@ -907,6 +888,7 @@ exports.main = function main(argv, options, callback) { function listFilesNode(dirname, baseDir) { var files; try { + stats.readCount++; stats.readTime += measure(() => { files = fs.readdirSync(path.join(baseDir, dirname)).filter(file => extension.re_except_d.test(file)) }); @@ -958,6 +940,8 @@ function createStats() { writeCount: 0, parseTime: 0, parseCount: 0, + initializeTime: 0, + initializeCount: 0, compileTime: 0, compileCount: 0, emitTime: 0, @@ -965,7 +949,9 @@ function createStats() { validateTime: 0, validateCount: 0, optimizeTime: 0, - optimizeCount: 0 + optimizeCount: 0, + transformTime: 0, + transformCount: 0 }; } @@ -983,9 +969,14 @@ function measure(fn) { exports.measure = measure; +function pad(str, len) { + while (str.length < len) str = " " + str; + return str; +} + /** Formats a high resolution time to a human readable string. */ function formatTime(time) { - return time ? (time / 1e6).toFixed(3) + " ms" : "N/A"; + return time ? (time / 1e6).toFixed(3) + " ms" : "n/a"; } exports.formatTime = formatTime; @@ -993,16 +984,18 @@ exports.formatTime = formatTime; /** Formats and prints out the contents of a set of stats. */ function printStats(stats, output) { function format(time, count) { - return formatTime(time); + return pad(formatTime(time), 12) + " n=" + count; } (output || process.stdout).write([ - "I/O Read : " + format(stats.readTime, stats.readCount), - "I/O Write : " + format(stats.writeTime, stats.writeCount), - "Parse : " + format(stats.parseTime, stats.parseCount), - "Compile : " + format(stats.compileTime, stats.compileCount), - "Emit : " + format(stats.emitTime, stats.emitCount), - "Validate : " + format(stats.validateTime, stats.validateCount), - "Optimize : " + format(stats.optimizeTime, stats.optimizeCount) + "I/O Read : " + format(stats.readTime, stats.readCount), + "I/O Write : " + format(stats.writeTime, stats.writeCount), + "Parse : " + format(stats.parseTime, stats.parseCount), + "Initialize : " + format(stats.initializeTime, stats.initializeCount), + "Compile : " + format(stats.compileTime, stats.compileCount), + "Emit : " + format(stats.emitTime, stats.emitCount), + "Validate : " + format(stats.validateTime, stats.validateCount), + "Optimize : " + format(stats.optimizeTime, stats.optimizeCount), + "Transform : " + format(stats.transformTime, stats.transformCount) ].join(EOL) + EOL); } diff --git a/lib/loader/index.d.ts b/lib/loader/index.d.ts index 812f1443b1..59abe7d3d2 100644 --- a/lib/loader/index.d.ts +++ b/lib/loader/index.d.ts @@ -5,18 +5,17 @@ export interface ResultObject { instance: WebAssembly.Instance; } -type ImportValue = Function | WebAssembly.Global | WebAssembly.Memory | WebAssembly.Table | number; - /** WebAssembly imports with two levels of nesting. */ export type Imports = { + [key: string]: object, env?: { memory?: WebAssembly.Memory; table?: WebAssembly.Table; seed?(): number; abort?(msg: number, file: number, line: number, column: number): void; trace?(msg: number, numArgs?: number, ...args: number[]): void; - } & Record; -} & Record>; + }; +}; /** Utility mixed in by the loader. */ export interface ASUtil { diff --git a/src/compiler.ts b/src/compiler.ts index e88d0bf5b3..a2cda74f3c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -392,19 +392,14 @@ export class Compiler extends DiagnosticEmitter { module.setFeatures(featureFlags); } - initializeProgram(): void { - // initialize lookup maps, built-ins, imports, exports, etc. - this.program.initialize(this.options); - } - /** Performs compilation of the underlying {@link Program} to a {@link Module}. */ compile(): Module { var options = this.options; var module = this.module; var program = this.program; - // check and perform this program initialization if it hasn't been done - this.initializeProgram(); + // initialize lookup maps, built-ins, imports, exports, etc. + this.program.initialize(); // set up the main start function var startFunctionInstance = program.makeNativeFunction(BuiltinNames.start, new Signature(program, [], Type.void)); diff --git a/src/index.ts b/src/index.ts index cb191ae928..4fe1195880 100644 --- a/src/index.ts +++ b/src/index.ts @@ -222,8 +222,8 @@ export function getDependee(program: Program, file: string): string | null { // Compiler /** Initializes the program pre-emptively for transform hooks. */ -export function initializeProgram(program: Program, options: Options): void { - program.initialize(options); +export function initializeProgram(program: Program): void { + program.initialize(); } /** Compiles the parsed sources to a module. */ diff --git a/src/program.ts b/src/program.ts index e24470a7bb..648384e01c 100644 --- a/src/program.ts +++ b/src/program.ts @@ -680,12 +680,11 @@ export class Program extends DiagnosticEmitter { } /** Initializes the program and its elements prior to compilation. */ - initialize(options: Options): void { - // Initialize only once + initialize(): void { if (this.initialized) return; - this.initialized = true; - this.options = options; + + var options = this.options; // register native types this.registerNativeType(CommonNames.i8, Type.i8); diff --git a/tests/bootstrap/index.ts b/tests/bootstrap/index.ts index e3020f423c..098b8c0dd6 100644 --- a/tests/bootstrap/index.ts +++ b/tests/bootstrap/index.ts @@ -11,7 +11,7 @@ Error.stackTraceLimit = Infinity; // Load stdlib const libDir = path.join(__dirname, "..", "..", "std", "assembly"); const libraryFiles = {}; -find.files(libDir, find.TS_EXCEPT_DTS).forEach((file: string) => { +find.files(libDir, /^(?!.*\.d\.ts$).*\.ts$/).forEach((file: string) => { libraryFiles[file.replace(/\.ts$/, "")] = fs.readFileSync(path.join(libDir, file), "utf8" ); }); @@ -25,29 +25,33 @@ async function test(build: string): Promise { console.log(util.inspect(asc, true)); const cachedStrings = new Map(); - function allocString(text: string): number { + function cachedString(text: string): number { if (cachedStrings.has(text)) return cachedStrings.get(text); var ptr = asc.__retain(asc.__allocString(text)); cachedStrings.set(text, ptr); return ptr; } - const optionsPtr = asc.newOptions(); - const programPtr = asc.newProgram(optionsPtr); + const programPtr = ((): number => { + const optionsPtr = asc.newOptions(); + const ptr = asc.newProgram(optionsPtr); + asc.__release(optionsPtr); + return ptr; + })(); console.log("\nParsing standard library ..."); Object.keys(libraryFiles).forEach((libPath: string) => { if (libPath.indexOf("/") >= 0) return; - const textPtr = allocString(libraryFiles[libPath]); - const pathPtr = allocString("~lib/" + libPath + ".ts"); + const textPtr = cachedString(libraryFiles[libPath]); + const pathPtr = cachedString("~lib/" + libPath + ".ts"); console.log(" " + asc.__getString(pathPtr)); asc.parse(programPtr, textPtr, pathPtr, false); }); console.log("\nParsing runtime ..."); { - const textPtr = allocString(libraryFiles["rt/index-stub"]); - const pathPtr = allocString("~lib/rt/index-stub"); + const textPtr = cachedString(libraryFiles["rt/index-stub"]); + const pathPtr = cachedString("~lib/rt/index-stub.ts"); console.log(" " + asc.__getString(pathPtr)); asc.parse(programPtr, textPtr, pathPtr, true); } @@ -59,8 +63,8 @@ async function test(build: string): Promise { if (!nextFile.startsWith("~lib/")) throw Error("unexpected file: " + nextFile); const text = libraryFiles[nextFile.substring(5)]; if (text == null) throw Error("missing file: " + nextFile); - const textPtr = allocString(libraryFiles[nextFile.substring(5)]); - const pathPtr = allocString(nextFile + ".ts"); + const textPtr = cachedString(libraryFiles[nextFile.substring(5)]); + const pathPtr = cachedString(nextFile + ".ts"); console.log(" " + asc.__getString(pathPtr)); asc.parse(programPtr, textPtr, pathPtr, false); asc.__release(nextFilePtr); @@ -69,24 +73,23 @@ async function test(build: string): Promise { console.log("\nParsing entry file ..."); { - const textPtr = allocString("export function add(a: i32, b: i32): i32 { return a + b; }\n"); - const pathPtr = allocString("index.ts"); + const textPtr = cachedString("export function add(a: i32, b: i32): i32 { return a + b; }\n"); + const pathPtr = cachedString("index.ts"); console.log(" " + asc.__getString(pathPtr)); asc.parse(programPtr, textPtr, pathPtr, true); } - try { - console.log("\nInitializing program ..."); - asc.initializeProgram(programPtr, optionsPtr); + console.log("\nInitializing program ..."); + { + asc.initializeProgram(programPtr); console.log("\nCompiling program ..."); const modulePtr = asc.compile(programPtr); const moduleRef = new Uint32Array(asc.memory.buffer, modulePtr)[0]; console.log(binaryen.wrapModule(moduleRef).emitText()); - // Wow! - } catch (e) { - console.log("\nTODO: " + e.stack); + asc.__release(modulePtr); } + asc.__release(programPtr); cachedStrings.forEach(asc.__release); console.log("\nSo far, so good."); From a391a4a9b3f6d07a6763589b51c6538b8d4cd59c Mon Sep 17 00:00:00 2001 From: dcode Date: Mon, 27 Apr 2020 20:50:54 +0200 Subject: [PATCH 24/24] deal with table stubs during finalization --- src/compiler.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index a2cda74f3c..d58380c8a8 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -500,7 +500,10 @@ export class Compiler extends DiagnosticEmitter { let instance = functionTable[i]; if (instance.is(CommonFlags.VIRTUAL)) { assert(instance.is(CommonFlags.INSTANCE)); + functionTable[i] = this.ensureVirtualStub(instance); // incl. varargs this.finalizeVirtualStub(instance); + } else if (instance.signature.requiredParameters < instance.signature.parameterTypes.length) { + functionTable[i] = this.ensureVarargsStub(instance); } } var virtualCalls = this.virtualCalls; @@ -1834,17 +1837,13 @@ export class Compiler extends DiagnosticEmitter { /** Ensures that a table entry exists for the specified function and returns its index. */ ensureFunctionTableEntry(instance: Function): i32 { - assert(instance.is(CommonFlags.COMPILED)); + assert(instance.is(CommonFlags.COMPILED) && !instance.is(CommonFlags.STUB)); var index = instance.functionTableIndex; if (index >= 0) return index; var functionTable = this.functionTable; var tableBase = this.options.tableBase; if (!tableBase) tableBase = 1; // leave first elem blank index = tableBase + functionTable.length; - if (!instance.is(CommonFlags.STUB) && instance.signature.requiredParameters < instance.signature.parameterTypes.length) { - // insert the varargs stub if the function has optional parameters - instance = this.ensureVarargsStub(instance); - } functionTable.push(instance); instance.functionTableIndex = index; return index; @@ -7146,7 +7145,7 @@ export class Compiler extends DiagnosticEmitter { for (let i = 0, k = parameterTypes.length; i < k; ++i) { paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toNativeType()); } - body = module.call(instance.internalName, paramExprs, instance.signature.returnType.toNativeType()); + body = module.call(instance.internalName, paramExprs, returnType.toNativeType()); // Otherwise trap } else {