diff --git a/src/ast.ts b/src/ast.ts index d5abb7f7..383d49d1 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -363,12 +363,12 @@ export abstract class Node { stmt.decoratorKind = DecoratorKind.OPERATOR; break; - case "struct": - stmt.decoratorKind = DecoratorKind.STRUCT; + case "explicit": + stmt.decoratorKind = DecoratorKind.EXPLICIT; break; - case "size": - stmt.decoratorKind = DecoratorKind.SIZE; + case "offset": + stmt.decoratorKind = DecoratorKind.OFFSET; break; default: @@ -1382,8 +1382,8 @@ export const enum DecoratorKind { CUSTOM, GLOBAL, OPERATOR, - STRUCT, - SIZE + EXPLICIT, + OFFSET } /** Depresents a decorator. */ diff --git a/src/builtins.ts b/src/builtins.ts index 760e7960..fd0aedd3 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -1349,7 +1349,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty } arg0 = compiler.compileExpression(operands[0], usizeType); compiler.currentType = typeArguments[0]; - return module.createLoad(typeArguments[0].size >>> 3, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0, typeArguments[0].toNativeType()); + return module.createLoad(typeArguments[0].byteSize, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0, typeArguments[0].toNativeType()); case "store": // store(offset: usize, value: T) -> void compiler.currentType = Type.void; @@ -1372,7 +1372,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty } type = compiler.currentType; compiler.currentType = Type.void; - return module.createStore(type.size >>> 3, arg0, arg1, type.toNativeType()); + return module.createStore(type.byteSize, arg0, arg1, type.toNativeType()); case "sizeof": // sizeof() -> usize compiler.currentType = usizeType; diff --git a/src/compiler.ts b/src/compiler.ts index ff29563d..0d696dbd 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -2217,6 +2217,16 @@ export class Compiler extends DiagnosticEmitter { this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (element).internalName); return this.module.createUnreachable(); + case ElementKind.FUNCTION_PROTOTYPE: + if (expression.kind == NodeKind.ELEMENTACCESS) { // @operator("[]") + assert(resolved.target && resolved.target.kind == ElementKind.CLASS && element.simpleName == (resolved.target).prototype.fnIndexedGet) + var resolvedIndexedSet = (element).resolve(null); + if (resolvedIndexedSet) { + elementType = resolvedIndexedSet.returnType; + break; + } + } + // fall-through default: this.error(DiagnosticCode.Operation_not_supported, expression.range); return this.module.createUnreachable(); @@ -2275,11 +2285,11 @@ export class Compiler extends DiagnosticEmitter { this.currentType = tee ? (element).type : Type.void; var elementNativeType = (element).type.toNativeType(); if (!tee) - return this.module.createStore((element).type.byteSize, targetExpr, valueWithCorrectType, elementNativeType, (element).memoryOffset); + return this.module.createStore((element).type.size >> 3, targetExpr, valueWithCorrectType, elementNativeType, (element).memoryOffset); tempLocal = this.currentFunction.getAndFreeTempLocal((element).type); return this.module.createBlock(null, [ // TODO: simplify if valueWithCorrectType has no side effects this.module.createSetLocal(tempLocal.index, valueWithCorrectType), - this.module.createStore((element).type.byteSize, targetExpr, this.module.createGetLocal(tempLocal.index, elementNativeType), elementNativeType, (element).memoryOffset), + this.module.createStore((element).type.size >> 3, targetExpr, this.module.createGetLocal(tempLocal.index, elementNativeType), elementNativeType, (element).memoryOffset), this.module.createGetLocal(tempLocal.index, elementNativeType) ], elementNativeType); @@ -2325,6 +2335,38 @@ export class Compiler extends DiagnosticEmitter { } else this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (element).internalName); return this.module.createUnreachable(); + + case ElementKind.FUNCTION_PROTOTYPE: + if (expression.kind == NodeKind.ELEMENTACCESS) { // @operator("[]") + assert(resolved.target && resolved.target.kind == ElementKind.CLASS); + var resolvedIndexedGet = (element).resolve(); + if (!resolvedIndexedGet) + return this.module.createUnreachable(); + var indexedSetName = (resolved.target).prototype.fnIndexedSet; + var indexedSet: Element | null; + if (indexedSetName != null && (resolved.target).members && (indexedSet = (>(resolved.target).members).get(indexedSetName)) && indexedSet.kind == ElementKind.FUNCTION_PROTOTYPE) { // @operator("[]=") + var resolvedIndexedSet = (indexedSet).resolve(); + if (!resolvedIndexedSet) + return this.module.createUnreachable(); + targetExpr = this.compileExpression(resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32, ConversionKind.NONE); + assert(this.currentType.classType); + var elementExpr = this.compileExpression((expression).elementExpression, Type.i32); + if (!tee) { + this.currentType = resolvedIndexedSet.returnType; + return this.makeCall(resolvedIndexedSet, [ targetExpr, elementExpr, valueWithCorrectType ]); + } + this.currentType = resolvedIndexedGet.returnType; + tempLocal = this.currentFunction.getAndFreeTempLocal(this.currentType); + return this.module.createBlock(null, [ + this.makeCall(resolvedIndexedSet, [ targetExpr, elementExpr, this.module.createTeeLocal(tempLocal.index, valueWithCorrectType) ]), + this.module.createGetLocal(tempLocal.index, tempLocal.type.toNativeType()) // TODO: could be different from an actual __get (needs 2 temp locals) + ], this.currentType.toNativeType()); + } else { + this.error(DiagnosticCode.Index_signature_in_type_0_only_permits_reading, expression.range, (resolved.target).internalName); + return this.module.createUnreachable(); + } + } + // fall-through } this.error(DiagnosticCode.Operation_not_supported, expression.range); return this.module.createUnreachable(); @@ -2465,8 +2507,11 @@ export class Compiler extends DiagnosticEmitter { var resolved = this.program.resolveElementAccess(expression, this.currentFunction); // reports if (!resolved) return this.module.createUnreachable(); - - throw new Error("not implemented"); // TODO + assert(resolved.element.kind == ElementKind.FUNCTION_PROTOTYPE && resolved.target && resolved.target.kind == ElementKind.CLASS); + var instance = (resolved.element).resolve(null, (resolved.target).contextualTypeArguments); + if (!instance) + return this.module.createUnreachable(); + return this.compileCall(instance, [ expression.expression, expression.elementExpression ], expression); } compileIdentifierExpression(expression: IdentifierExpression, contextualType: Type): ExpressionRef { @@ -2632,7 +2677,7 @@ export class Compiler extends DiagnosticEmitter { assert((element).memoryOffset >= 0); targetExpr = this.compileExpression(resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32); this.currentType = (element).type; - return this.module.createLoad((element).type.byteSize, (element).type.is(TypeFlags.SIGNED | TypeFlags.INTEGER), + return this.module.createLoad((element).type.size >> 3, (element).type.is(TypeFlags.SIGNED | TypeFlags.INTEGER), targetExpr, (element).type.toNativeType(), (element).memoryOffset diff --git a/src/constants.ts b/src/constants.ts index 205980c3..c596b068 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,8 +1,14 @@ // internal naming scheme +/** Path delimited inserted between file system levels. */ export const PATH_DELIMITER = "/"; +/** Substitution used to indicate the parent directory. */ export const PARENT_SUBST = ".."; +/** Function name prefix used for getters. */ export const GETTER_PREFIX = "get:"; +/** Function name prefix used for setters. */ export const SETTER_PREFIX = "set:"; +/** Delimiter used between class names and instance members. */ export const INSTANCE_DELIMITER = "#"; +/** Delimited used between class and namespace names and static members. */ export const STATIC_DELIMITER = "."; diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index cb20ec77..2a6c9f4e 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -79,6 +79,7 @@ export enum DiagnosticCode { Export_declaration_conflicts_with_exported_declaration_of_0 = 2484, 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, + Index_signature_in_type_0_only_permits_reading = 2542, Expected_0_arguments_but_got_1 = 2554, Expected_at_least_0_arguments_but_got_1 = 2555, Expected_0_type_arguments_but_got_1 = 2558, @@ -166,6 +167,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 2484: return "Export declaration conflicts with exported declaration of '{0}'."; 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."; + case 2542: return "Index signature in type '{0}' only permits reading."; case 2554: return "Expected {0} arguments, but got {1}."; case 2555: return "Expected at least {0} arguments, but got {1}."; case 2558: return "Expected {0} type arguments, but got {1}."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index a91c46ac..ef824f3e 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -79,6 +79,7 @@ "Export declaration conflicts with exported declaration of '{0}'.": 2484, "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, + "Index signature in type '{0}' only permits reading.": 2542, "Expected {0} arguments, but got {1}.": 2554, "Expected at least {0} arguments, but got {1}.": 2555, "Expected {0} type arguments, but got {1}.": 2558, diff --git a/src/parser.ts b/src/parser.ts index 80acd2e7..a61cb28e 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1580,6 +1580,19 @@ export class Parser extends DiagnosticEmitter { var startPos = expr.range.start; + // ElementAccessExpression + if (tn.skip(Token.OPENBRACKET)) { + next = this.parseExpression(tn); // resets precedence + if (!next) + return null; + if (tn.skip(Token.CLOSEBRACKET)) + expr = Node.createElementAccessExpression(expr, next, tn.range(startPos, tn.pos)); + else { + this.error(DiagnosticCode._0_expected, tn.range(), "]"); + return null; + } + } + // CallExpression var typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn); // skips '(' on success // there might be better ways to distinguish a LESSTHAN from a CALL with type arguments @@ -1593,7 +1606,6 @@ export class Parser extends DiagnosticEmitter { var token: Token; var next: Expression | null = null; var nextPrecedence: Precedence; - while ((nextPrecedence = determinePrecedence(token = tn.peek())) >= precedence) { // precedence climbing tn.next(); @@ -1604,19 +1616,6 @@ export class Parser extends DiagnosticEmitter { return null; expr = Node.createAssertionExpression(AssertionKind.AS, expr, toType, tn.range(startPos, tn.pos)); - // ElementAccessExpression - } else if (token == Token.OPENBRACKET) { - next = this.parseExpression(tn); // resets precedence - if (!next) - return null; - - if (tn.skip(Token.CLOSEBRACKET)) - expr = Node.createElementAccessExpression(expr, next, tn.range(startPos, tn.pos)); - else { - this.error(DiagnosticCode._0_expected, tn.range(), "]"); - return null; - } - // UnaryPostfixExpression } else if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS) { if (expr.kind != NodeKind.IDENTIFIER && expr.kind != NodeKind.ELEMENTACCESS && expr.kind != NodeKind.PROPERTYACCESS) diff --git a/src/program.ts b/src/program.ts index 6570186a..5907e2bd 100644 --- a/src/program.ts +++ b/src/program.ts @@ -290,8 +290,8 @@ export class Program extends DiagnosticEmitter { this.checkGlobalAlias(prototype, declaration); - if (hasDecorator("struct", declaration.decorators)) { - prototype.isStruct = true; + if (hasDecorator("explicit", declaration.decorators)) { + prototype.isExplicit = true; if (declaration.implementsTypes && declaration.implementsTypes.length) this.error(DiagnosticCode.Structs_cannot_implement_interfaces, Range.join(declaration.name.range, declaration.implementsTypes[declaration.implementsTypes.length - 1].range)); } else if (declaration.implementsTypes.length) @@ -413,8 +413,8 @@ export class Program extends DiagnosticEmitter { } else classPrototype.instanceMembers = new Map(); instancePrototype = new FunctionPrototype(this, name, internalName, declaration, classPrototype); - // if (classPrototype.isStruct && instancePrototype.isAbstract) { - // this.error( Structs cannot declare abstract methods. ); + // if (classPrototype.isExplicit && instancePrototype.isAbstract) { + // this.error( Explicit classes cannot declare abstract methods. ); // } classPrototype.instanceMembers.set(name, instancePrototype); } @@ -436,19 +436,19 @@ export class Program extends DiagnosticEmitter { switch ((firstArg).value) { case "[]": - classPrototype.opIndexedGet = instancePrototype; + classPrototype.fnIndexedGet = instancePrototype.simpleName; break; case "[]=": - classPrototype.opIndexedSet = instancePrototype; + classPrototype.fnIndexedSet = instancePrototype.simpleName; break; case "+": - classPrototype.opConcat = instancePrototype; + classPrototype.fnConcat = instancePrototype.simpleName; break; case "==": - classPrototype.opEquals = instancePrototype; + classPrototype.fnEquals = instancePrototype.simpleName; break; default: // TBD: does it make sense to provide more, even though not JS/TS-compatible? @@ -1078,13 +1078,15 @@ export class Program extends DiagnosticEmitter { var target = resolvedElement.element; switch (target.kind) { - // TBD: should indexed access on static classes, like `Heap`, be a supported as well? - case ElementKind.CLASS: - var type = (target).type; + case ElementKind.GLOBAL: + case ElementKind.LOCAL: + case ElementKind.FIELD: + var type = (target).type; if (type.classType) { - var indexedGet: FunctionPrototype | null; - if (indexedGet = (target = type.classType).prototype.opIndexedGet) - return resolvedElement.set(indexedGet).withTarget(target, targetExpression); + var indexedGetName = (target = type.classType).prototype.fnIndexedGet; + var indexedGet: Element | null; + if (indexedGetName != null && target.members && (indexedGet = target.members.get(indexedGetName)) && indexedGet.kind == ElementKind.FUNCTION_PROTOTYPE) + return resolvedElement.set(indexedGet).withTarget(type.classType, targetExpression); } break; } @@ -1221,8 +1223,8 @@ export enum ElementFlags { PRIVATE = 1 << 15, /** Is an abstract member. */ ABSTRACT = 1 << 16, - /** Is a struct-like class with limited capabilites. */ - STRUCT = 1 << 17, + /** Is an explicitly layed out and allocated class with limited capabilites. */ + EXPLICIT = 1 << 17, /** Has already inherited base class static members. */ HAS_STATIC_BASE_MEMBERS = 1 << 18 } @@ -1877,13 +1879,13 @@ export class ClassPrototype extends Element { basePrototype: ClassPrototype | null = null; // set in Program#initialize /** Overloaded indexed get method, if any. */ - opIndexedGet: FunctionPrototype | null = null; // TODO: indexedGet and indexedSet as an accessor? + fnIndexedGet: string | null = null; /** Overloaded indexed set method, if any. */ - opIndexedSet: FunctionPrototype | null = null; + fnIndexedSet: string | null = null; /** Overloaded concatenation method, if any. */ - opConcat: FunctionPrototype | null = null; + fnConcat: string | null = null; /** Overloaded equality comparison method, if any. */ - opEquals: FunctionPrototype | null = null; + fnEquals: string | null = null; constructor(program: Program, simpleName: string, internalName: string, declaration: ClassDeclaration | null = null) { super(program, simpleName, internalName); @@ -1903,9 +1905,9 @@ export class ClassPrototype extends Element { } } - /** Whether a struct-like class with limited capabilities or not. */ - get isStruct(): bool { return (this.flags & ElementFlags.STRUCT) != 0; } - set isStruct(is: bool) { if (is) this.flags |= ElementFlags.STRUCT; else this.flags &= ~ElementFlags.STRUCT; } + /** Whether explicitly layed out and allocated */ + get isExplicit(): bool { return (this.flags & ElementFlags.EXPLICIT) != 0; } + set isExplicit(is: bool) { if (is) this.flags |= ElementFlags.EXPLICIT; else this.flags &= ~ElementFlags.EXPLICIT; } resolve(typeArguments: Type[] | null, contextualTypeArguments: Map | null = null): Class | null { var instanceKey = typeArguments ? typesToString(typeArguments) : ""; @@ -1933,7 +1935,7 @@ export class ClassPrototype extends Element { this.program.error(DiagnosticCode.A_class_may_only_extend_another_class, declaration.extendsType.range); return null; } - if (baseClass.prototype.isStruct != this.isStruct) { + if (baseClass.prototype.isExplicit != this.isExplicit) { this.program.error(DiagnosticCode.Structs_cannot_extend_classes_and_vice_versa, Range.join(declaration.name.range, declaration.extendsType.range)); return null; } @@ -1957,9 +1959,9 @@ export class ClassPrototype extends Element { instance.contextualTypeArguments = contextualTypeArguments; this.instances.set(instanceKey, instance); - var memoryOffset: i32 = 0; + var memoryOffset: u32 = 0; if (baseClass) { - memoryOffset = baseClass.type.byteSize; + memoryOffset = baseClass.currentMemoryOffset; if (baseClass.members) { if (!instance.members) instance.members = new Map(); @@ -1983,7 +1985,7 @@ export class ClassPrototype extends Element { var fieldType = this.program.resolveType(fieldDeclaration.type, instance.contextualTypeArguments); // reports if (fieldType) { var fieldInstance = new Field(member, (member).internalName, fieldType); - switch (fieldType.size >> 3) { // align (byteSize might vary if a class type) + switch (fieldType.byteSize) { // align case 1: break; case 2: if (memoryOffset & 1) ++memoryOffset; break; case 4: if (memoryOffset & 3) memoryOffset = (memoryOffset | 3) + 1; break; @@ -2015,7 +2017,7 @@ export class ClassPrototype extends Element { } } - instance.type.byteSize = memoryOffset; // sizeof() is its byte size in memory + instance.currentMemoryOffset = memoryOffset; // sizeof() is its byte size in memory return instance; } @@ -2051,6 +2053,8 @@ export class Class extends Element { base: Class | null; /** Contextual type arguments for fields and methods. */ contextualTypeArguments: Map | null = null; + /** Current member memory offset. */ + currentMemoryOffset: u32 = 0; /** Constructs a new class. */ constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] | null = null, base: Class | null = null) { diff --git a/src/types.ts b/src/types.ts index 58b30d2b..c04ea0d8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -76,8 +76,8 @@ export class Type { /** Type flags. */ flags: TypeFlags; /** Size in bits. */ - size: i32; - /** Size in bytes. */ + size: u32; + /** Size in bytes. Ceiled to 8-bits. */ byteSize: i32; /** Underlying class type, if a class type. */ classType: Class | null; diff --git a/std/assembly.d.ts b/std/assembly.d.ts index 0dbd48de..da856b9a 100644 --- a/std/assembly.d.ts +++ b/std/assembly.d.ts @@ -202,6 +202,12 @@ declare class Array { constructor(capacity?: i32); } +/** Class representing a C-like array of values of type `T` with limited capabilities. */ +declare class CArray { + [key: number]: T; + private constructor(); +} + /** Class representing a sequence of characters. */ declare class String { @@ -281,13 +287,16 @@ interface Number {} interface Object {} interface RegExp {} -// Internal decorators (not yet implemented) +// Internal decorators -/** Annotates an element being part of the global namespace. */ +/** Annotates an element as a program global. */ declare function global(target: Function): any; -/** Annotates a method being an operator overload. */ +/** Annotates a method as an operator overload. */ declare function operator(token: string): any; -declare function struct(target: Function): any; -declare function size(size: usize): any; +/** Annotates a class as explicitly layed out and allocated. */ +declare function explicit(target: Function): any; + +/** Annoates a class field with an explicit offset. */ +declare function offset(offset: usize): any; diff --git a/std/assembly/array.ts b/std/assembly/array.ts index 42d35eb8..d62d57de 100644 --- a/std/assembly/array.ts +++ b/std/assembly/array.ts @@ -1,44 +1,92 @@ export class Array { - private ptr: usize; - - readonly capacity: i32; + private __memory: usize; + private __capacity: i32; length: i32; constructor(capacity: i32 = 0) { if (capacity < 0) throw new RangeError("invalid array length"); - this.capacity = this.length = capacity; - if (capacity > 0) { - this.ptr = Heap.allocate(capacity); - } else { - this.ptr = 0; - } + this.__capacity = this.length = capacity; + this.__memory = capacity > 0 ? Heap.allocate(capacity * sizeof()) : 0; } @operator("[]") private __get(index: i32): T { - assert(index > 0 && index < this.capacity); - throw new Error("not implemented"); + if (index >= this.__capacity) + throw new RangeError("index out of range"); + return load(this.__memory + index * sizeof()); } @operator("[]=") private __set(index: i32, value: T): void { - assert(index > 0 && index < this.capacity); - throw new Error("not implemented"); + if (index >= this.__capacity) + throw new RangeError("index out of range"); + store(this.__memory + index * sizeof(), value); } - dispose(): void { - store(changetype(this), 0); - Heap.dispose(this.ptr); - this.ptr = 0; - Heap.dispose(changetype(this)); + indexOf(searchElement: T, fromIndex: i32 = 0): i32 { + if (fromIndex >= this.__capacity) + throw new RangeError("fromIndex out of range"); + for (var index: usize = fromIndex, length: usize = min(this.length, this.__capacity); index < length; ++index) + if (load(this.__memory + index * sizeof()) == searchElement) + return index; + return -1; } - // TODO + private __grow(capacity: i32): void { + assert(capacity > this.__capacity); + var newMemory = Heap.allocate((capacity * sizeof())); + if (this.__memory) + Heap.copy(newMemory, this.__memory, this.__capacity * sizeof()); + Heap.dispose(this.__memory); + this.__memory = newMemory; + this.__capacity = capacity; + } + + push(element: T): i32 { + if (this.length >= this.__capacity) + this.__grow(max(this.length + 1, this.__capacity * 2)); + store(this.__memory + this.length * sizeof(), element); + return ++this.length; + } + + pop(): T { + if (this.length < 1 || this.length > this.__capacity) + throw new RangeError("index out of range"); + --this.length; + return load(this.__memory + this.length * sizeof()); + } + + shift(): T { + if (this.length < 1 || this.length > this.__capacity) + throw new RangeError("index out of range"); + var element = load(this.__memory); + Heap.copy(this.__memory, this.__memory + sizeof(), (this.__capacity - 1) * sizeof()); + Heap.fill(this.__memory + (this.__capacity - 1) * sizeof(), 0, sizeof()); + --this.length; + return element; + } + + unshift(element: T): i32 { + var capacity = this.__capacity; + if (this.length >= capacity) + this.__grow(max(this.length + 1, capacity * 2)); + + // FIXME: needs memmove (Heap.copy is just memcpy). it's also inefficient because + // __grow copies and then unshift copies again. + // Heap.copy(this.__memory + sizeof(), this.__memory, capacity * sizeof()); + + if (capacity) + for (var index: usize = capacity; index > 0; --index) + store(this.__memory + index * sizeof(), load(this.__memory + (index - 1) * sizeof())); + + store(this.__memory, element); + return ++this.length; + } } -@struct +@explicit export class CArray { private constructor() {} diff --git a/tests/compiler.js b/tests/compiler.js index 9cfec7be..9aa71cf6 100644 --- a/tests/compiler.js +++ b/tests/compiler.js @@ -72,11 +72,15 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => { var wasmModule = new WebAssembly.Module(binary); var wasmInstance = new WebAssembly.Instance(wasmModule, { env: { - externalFunc: function() {}, + externalFunc: function(arg0, arg1, arg2) { + console.log("env.externalFunc called with: " + arg0 + ", " + arg1 + ", " + arg2); + }, externalConst: 1 }, external: { - externalFunc: function() {}, + externalFunc: function(arg0, arg1, arg2) { + console.log("external.externalFunc called with: " + arg0 + ", " + arg1 + ", " + arg2); + }, externalConst: 2 } }); diff --git a/tests/compiler/class.ts b/tests/compiler/class.ts index ed66240e..80355753 100644 --- a/tests/compiler/class.ts +++ b/tests/compiler/class.ts @@ -10,7 +10,7 @@ class Animal { instanceSub(a: T, b: T): T { return a - b + Animal.ONE; } // tsc does not allow this } -assert(sizeof>() == 7); +assert(sizeof>() == sizeof()); Animal.ONE; Animal.add(1,2); diff --git a/tests/compiler/class.wast b/tests/compiler/class.wast index 2a4972c0..eb088a4b 100644 --- a/tests/compiler/class.wast +++ b/tests/compiler/class.wast @@ -145,8 +145,8 @@ (if (i32.eqz (i32.eq - (i32.const 7) - (i32.const 7) + (i32.const 4) + (i32.const 4) ) ) (unreachable) diff --git a/tests/compiler/std/array.optimized-inlined.wast b/tests/compiler/std/array.optimized-inlined.wast new file mode 100644 index 00000000..4b0efda5 --- /dev/null +++ b/tests/compiler/std/array.optimized-inlined.wast @@ -0,0 +1,2918 @@ +(module + (type $ii (func (param i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) + (type $iv (func (param i32))) + (type $iiv (func (param i32 i32))) + (type $iii (func (param i32 i32) (result i32))) + (type $v (func)) + (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) + (global $std/array/arr (mut i32) (i32.const 0)) + (global $std/array/i (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 4)) + (memory $0 1) + (export "memory" (memory $0)) + (start $start) + (func $std:heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eqz + (get_local $0) + ) + (return + (i32.const 0) + ) + ) + (set_local $1 + (current_memory) + ) + (if + (i32.gt_u + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + (i32.shl + (get_local $1) + (i32.const 16) + ) + ) + (if + (i32.lt_s + (grow_memory + (select + (tee_local $2 + (i32.trunc_s/f64 + (f64.ceil + (f64.div + (f64.convert_u/i32 + (get_local $0) + ) + (f64.const 65536) + ) + ) + ) + ) + (tee_local $1 + (i32.sub + (i32.mul + (get_local $1) + (i32.const 2) + ) + (get_local $1) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $1) + ) + ) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_local $1 + (get_global $std:heap/HEAP_OFFSET) + ) + (if + (block (result i32) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + ) + (i32.and + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + ) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (i32.or + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + (i32.const 1) + ) + ) + ) + (get_local $1) + ) + (func $std:heap/Heap.copy (; 1 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.lt_u + (get_local $0) + (get_global $HEAP_BASE) + ) + (unreachable) + ) + (set_local $4 + (get_local $0) + ) + (loop $continue|0 + (if + (if (result i32) + (get_local $2) + (i32.rem_u + (get_local $1) + (i32.const 4) + ) + (get_local $2) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + (if + (i32.eqz + (i32.rem_u + (get_local $4) + (i32.const 4) + ) + ) + (block + (loop $continue|1 + (if + (i32.ge_u + (get_local $2) + (i32.const 16) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 12) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|1) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 8) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 4) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (i32.store16 + (get_local $4) + (i32.load16_u + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 2) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (block + (set_local $3 + (get_local $4) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $3 + (get_local $1) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + ) + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block $break|2 + (block $case2|2 + (block $case1|2 + (block $case0|2 + (block $tablify|0 + (br_table $case0|2 $case1|2 $case2|2 $tablify|0 + (i32.sub + (i32.rem_u + (get_local $4) + (i32.const 4) + ) + (i32.const 1) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 3) + ) + ) + (loop $continue|3 + (if + (i32.ge_u + (get_local $2) + (i32.const 17) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 24) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 5) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 9) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 24) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 13) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|3) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 2) + ) + ) + (loop $continue|4 + (if + (i32.ge_u + (get_local $2) + (i32.const 18) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 16) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 6) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 10) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 16) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 14) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|4) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (loop $continue|5 + (if + (i32.ge_u + (get_local $2) + (i32.const 19) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 3) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 8) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 7) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 11) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 8) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 15) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|5) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 16) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (block + (set_local $3 + (get_local $4) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $3 + (get_local $1) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (get_local $0) + ) + (func $std:array/Array#__grow (; 2 ;) (type $iiv) (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (if + (i32.le_s + (get_local $1) + (i32.load offset=4 + (get_local $0) + ) + ) + (unreachable) + ) + (set_local $2 + (call $std:heap/Heap.allocate + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + (if + (i32.load + (get_local $0) + ) + (drop + (call $std:heap/Heap.copy + (get_local $2) + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.const 4) + ) + ) + ) + ) + (block + (block $__inlined_func$std:heap/Heap.dispose + (set_local $3 + (i32.load + (get_local $0) + ) + ) + (nop) + ) + ) + (i32.store + (get_local $0) + (get_local $2) + ) + (i32.store offset=4 + (get_local $0) + (get_local $1) + ) + ) + (func $std:array/Array#push (; 3 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (if + (i32.ge_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + (call $std:array/Array#__grow + (get_local $0) + (select + (tee_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (tee_local $3 + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.const 2) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $3) + ) + ) + ) + ) + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=8 + (get_local $0) + ) + (i32.const 4) + ) + ) + (get_local $1) + ) + (i32.store offset=8 + (get_local $0) + (tee_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + ) + (get_local $2) + ) + (func $std:array/Array#__get (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (if + (i32.ge_u + (get_local $1) + (i32.load offset=4 + (get_local $0) + ) + ) + (unreachable) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (func $std:array/Array#pop (; 5 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (if + (i32.and + (if (result i32) + (tee_local $1 + (i32.lt_s + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (get_local $1) + (i32.gt_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (i32.const 1) + ) + (unreachable) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=8 + (get_local $0) + ) + (i32.const 4) + ) + ) + ) + ) + (func $std:array/Array#unshift (; 6 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (if + (i32.ge_u + (i32.load offset=8 + (get_local $0) + ) + (tee_local $2 + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (call $std:array/Array#__grow + (get_local $0) + (select + (tee_local $3 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (tee_local $4 + (i32.mul + (get_local $2) + (i32.const 2) + ) + ) + (i32.gt_s + (get_local $3) + (get_local $4) + ) + ) + ) + ) + (if + (get_local $2) + (loop $continue|0 + (if + (i32.gt_u + (get_local $2) + (i32.const 0) + ) + (block + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.sub + (get_local $2) + (i32.const 1) + ) + (i32.const 4) + ) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (i32.store + (i32.load + (get_local $0) + ) + (get_local $1) + ) + (i32.store offset=8 + (get_local $0) + (tee_local $3 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + ) + (get_local $3) + ) + (func $std:heap/Heap.fill (; 7 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i64) + (local $5 i32) + (if + (i32.lt_u + (get_local $0) + (get_global $HEAP_BASE) + ) + (unreachable) + ) + (if + (i32.eqz + (get_local $2) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (tee_local $3 + (get_local $0) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 1) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 2) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 1) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 3) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 6) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 3) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (tee_local $3 + (i32.add + (get_local $3) + (tee_local $5 + (i32.and + (i32.sub + (i32.const 0) + (get_local $3) + ) + (i32.const 3) + ) + ) + ) + ) + (tee_local $1 + (i32.mul + (get_local $1) + (i32.const 16843009) + ) + ) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (tee_local $2 + (i32.and + (i32.sub + (get_local $2) + (get_local $5) + ) + (i32.const -4) + ) + ) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 12) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 8) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 24) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 20) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 28) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 24) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 20) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 16) + ) + (get_local $1) + ) + (set_local $3 + (i32.add + (get_local $3) + (tee_local $5 + (i32.add + (i32.and + (get_local $3) + (i32.const 4) + ) + (i32.const 24) + ) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (get_local $5) + ) + ) + (set_local $4 + (i64.or + (i64.extend_u/i32 + (get_local $1) + ) + (i64.shl + (i64.extend_u/i32 + (get_local $1) + ) + (i64.const 32) + ) + ) + ) + (loop $continue|0 + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block + (i64.store + (get_local $3) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $4) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 32) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 32) + ) + ) + (br $continue|0) + ) + ) + ) + (get_local $0) + ) + (func $std:array/Array#shift (; 8 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (if + (i32.and + (if (result i32) + (tee_local $1 + (i32.lt_s + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (get_local $1) + (i32.gt_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (i32.const 1) + ) + (unreachable) + ) + (set_local $1 + (i32.load + (i32.load + (get_local $0) + ) + ) + ) + (drop + (call $std:heap/Heap.copy + (i32.load + (get_local $0) + ) + (i32.add + (i32.load + (get_local $0) + ) + (i32.const 4) + ) + (i32.mul + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.const 1) + ) + (i32.const 4) + ) + ) + ) + (drop + (call $std:heap/Heap.fill + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.const 1) + ) + (i32.const 4) + ) + ) + (i32.const 0) + (i32.const 4) + ) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (get_local $1) + ) + (func $start (; 9 ;) (type $v) + (set_global $std:heap/HEAP_OFFSET + (get_global $HEAP_BASE) + ) + (set_global $std/array/arr + (call $std:heap/Heap.allocate + (i32.const 12) + ) + ) + (if + (i32.load offset=8 + (get_global $std/array/arr) + ) + (unreachable) + ) + (if + (i32.load offset=4 + (get_global $std/array/arr) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 42) + ) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#pop + (get_global $std/array/arr) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.load offset=8 + (get_global $std/array/arr) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 43) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 44) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 2) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 2) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 44) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 45) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 3) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 45) + ) + (unreachable) + ) + (drop + (call $std:array/Array#unshift + (get_global $std/array/arr) + (i32.const 42) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 45) + ) + (unreachable) + ) + (drop + (call $std:array/Array#unshift + (get_global $std/array/arr) + (i32.const 41) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 5) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 41) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 4) + ) + (i32.const 45) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#shift + (get_global $std/array/arr) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const 41) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 45) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#pop + (get_global $std/array/arr) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const 45) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 3) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + (unreachable) + ) + ) +) diff --git a/tests/compiler/std/array.optimized.wast b/tests/compiler/std/array.optimized.wast index 7a4e7940..0c9e3bc4 100644 --- a/tests/compiler/std/array.optimized.wast +++ b/tests/compiler/std/array.optimized.wast @@ -1,4 +1,2915 @@ (module + (type $ii (func (param i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) + (type $iv (func (param i32))) + (type $iiv (func (param i32 i32))) + (type $iii (func (param i32 i32) (result i32))) + (type $v (func)) + (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) + (global $std/array/arr (mut i32) (i32.const 0)) + (global $std/array/i (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) (export "memory" (memory $0)) + (start $start) + (func $std:heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eqz + (get_local $0) + ) + (return + (i32.const 0) + ) + ) + (set_local $1 + (current_memory) + ) + (if + (i32.gt_u + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + (i32.shl + (get_local $1) + (i32.const 16) + ) + ) + (if + (i32.lt_s + (grow_memory + (select + (tee_local $2 + (i32.trunc_s/f64 + (f64.ceil + (f64.div + (f64.convert_u/i32 + (get_local $0) + ) + (f64.const 65536) + ) + ) + ) + ) + (tee_local $1 + (i32.sub + (i32.mul + (get_local $1) + (i32.const 2) + ) + (get_local $1) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $1) + ) + ) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + (set_local $1 + (get_global $std:heap/HEAP_OFFSET) + ) + (if + (block (result i32) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + ) + (i32.and + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + ) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (i32.or + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + (i32.const 1) + ) + ) + ) + (get_local $1) + ) + (func $std:heap/Heap.copy (; 1 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.lt_u + (get_local $0) + (get_global $HEAP_BASE) + ) + (unreachable) + ) + (set_local $4 + (get_local $0) + ) + (loop $continue|0 + (if + (if (result i32) + (get_local $2) + (i32.rem_u + (get_local $1) + (i32.const 4) + ) + (get_local $2) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + (if + (i32.eqz + (i32.rem_u + (get_local $4) + (i32.const 4) + ) + ) + (block + (loop $continue|1 + (if + (i32.ge_u + (get_local $2) + (i32.const 16) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 12) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|1) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 8) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (i32.store + (get_local $4) + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 4) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (i32.store16 + (get_local $4) + (i32.load16_u + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 2) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (block + (set_local $3 + (get_local $4) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $3 + (get_local $1) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + ) + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block $break|2 + (block $case2|2 + (block $case1|2 + (block $case0|2 + (block $tablify|0 + (br_table $case0|2 $case1|2 $case2|2 $tablify|0 + (i32.sub + (i32.rem_u + (get_local $4) + (i32.const 4) + ) + (i32.const 1) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 3) + ) + ) + (loop $continue|3 + (if + (i32.ge_u + (get_local $2) + (i32.const 17) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 24) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 5) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 9) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 24) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 13) + ) + ) + ) + (i32.const 8) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|3) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 2) + ) + ) + (loop $continue|4 + (if + (i32.ge_u + (get_local $2) + (i32.const 18) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 16) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 6) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 10) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 16) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 14) + ) + ) + ) + (i32.const 16) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|4) + ) + ) + ) + (br $break|2) + ) + (set_local $5 + (i32.load + (get_local $1) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (loop $continue|5 + (if + (i32.ge_u + (get_local $2) + (i32.const 19) + ) + (block + (i32.store + (get_local $4) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 3) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 8) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 7) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (tee_local $3 + (i32.load + (i32.add + (get_local $1) + (i32.const 11) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (i32.store + (i32.add + (get_local $4) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $3) + (i32.const 8) + ) + (i32.shl + (tee_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 15) + ) + ) + ) + (i32.const 24) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $4 + (i32.add + (get_local $4) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + (br $continue|5) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 16) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + (set_local $4 + (i32.add + (tee_local $3 + (get_local $4) + ) + (i32.const 1) + ) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $1 + (i32.add + (tee_local $3 + (get_local $1) + ) + (i32.const 1) + ) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (block + (set_local $3 + (get_local $4) + ) + (i32.store8 + (get_local $3) + (block (result i32) + (set_local $3 + (get_local $1) + ) + (i32.load8_u + (get_local $3) + ) + ) + ) + ) + ) + (get_local $0) + ) + (func $std:heap/Heap.dispose (; 2 ;) (type $iv) (param $0 i32) + (nop) + ) + (func $std:array/Array#__grow (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32) + (local $2 i32) + (if + (i32.le_s + (get_local $1) + (i32.load offset=4 + (get_local $0) + ) + ) + (unreachable) + ) + (set_local $2 + (call $std:heap/Heap.allocate + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + (if + (i32.load + (get_local $0) + ) + (drop + (call $std:heap/Heap.copy + (get_local $2) + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.const 4) + ) + ) + ) + ) + (call $std:heap/Heap.dispose + (i32.load + (get_local $0) + ) + ) + (i32.store + (get_local $0) + (get_local $2) + ) + (i32.store offset=4 + (get_local $0) + (get_local $1) + ) + ) + (func $std:array/Array#push (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (if + (i32.ge_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + (call $std:array/Array#__grow + (get_local $0) + (select + (tee_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (tee_local $3 + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.const 2) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $3) + ) + ) + ) + ) + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=8 + (get_local $0) + ) + (i32.const 4) + ) + ) + (get_local $1) + ) + (i32.store offset=8 + (get_local $0) + (tee_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + ) + (get_local $2) + ) + (func $std:array/Array#__get (; 5 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (if + (i32.ge_u + (get_local $1) + (i32.load offset=4 + (get_local $0) + ) + ) + (unreachable) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (func $std:array/Array#pop (; 6 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (if + (i32.and + (if (result i32) + (tee_local $1 + (i32.lt_s + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (get_local $1) + (i32.gt_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (i32.const 1) + ) + (unreachable) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=8 + (get_local $0) + ) + (i32.const 4) + ) + ) + ) + ) + (func $std:array/Array#unshift (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (if + (i32.ge_u + (i32.load offset=8 + (get_local $0) + ) + (tee_local $2 + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (call $std:array/Array#__grow + (get_local $0) + (select + (tee_local $3 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (tee_local $4 + (i32.mul + (get_local $2) + (i32.const 2) + ) + ) + (i32.gt_s + (get_local $3) + (get_local $4) + ) + ) + ) + ) + (if + (get_local $2) + (loop $continue|0 + (if + (i32.gt_u + (get_local $2) + (i32.const 0) + ) + (block + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $2) + (i32.const 4) + ) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.sub + (get_local $2) + (i32.const 1) + ) + (i32.const 4) + ) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (i32.store + (i32.load + (get_local $0) + ) + (get_local $1) + ) + (i32.store offset=8 + (get_local $0) + (tee_local $3 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + ) + (get_local $3) + ) + (func $std:heap/Heap.fill (; 8 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i64) + (local $5 i32) + (if + (i32.lt_u + (get_local $0) + (get_global $HEAP_BASE) + ) + (unreachable) + ) + (if + (i32.eqz + (get_local $2) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (tee_local $3 + (get_local $0) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 1) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 2) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 1) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 3) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 6) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 3) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (tee_local $3 + (i32.add + (get_local $3) + (tee_local $5 + (i32.and + (i32.sub + (i32.const 0) + (get_local $3) + ) + (i32.const 3) + ) + ) + ) + ) + (tee_local $1 + (i32.mul + (get_local $1) + (i32.const 16843009) + ) + ) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (tee_local $2 + (i32.and + (i32.sub + (get_local $2) + (get_local $5) + ) + (i32.const -4) + ) + ) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 12) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 8) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 24) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 20) + ) + (get_local $1) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 28) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 24) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 20) + ) + (get_local $1) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 16) + ) + (get_local $1) + ) + (set_local $3 + (i32.add + (get_local $3) + (tee_local $5 + (i32.add + (i32.and + (get_local $3) + (i32.const 4) + ) + (i32.const 24) + ) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (get_local $5) + ) + ) + (set_local $4 + (i64.or + (i64.extend_u/i32 + (get_local $1) + ) + (i64.shl + (i64.extend_u/i32 + (get_local $1) + ) + (i64.const 32) + ) + ) + ) + (loop $continue|0 + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block + (i64.store + (get_local $3) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $4) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $4) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 32) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 32) + ) + ) + (br $continue|0) + ) + ) + ) + (get_local $0) + ) + (func $std:array/Array#shift (; 9 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (if + (i32.and + (if (result i32) + (tee_local $1 + (i32.lt_s + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (get_local $1) + (i32.gt_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (i32.const 1) + ) + (unreachable) + ) + (set_local $1 + (i32.load + (i32.load + (get_local $0) + ) + ) + ) + (drop + (call $std:heap/Heap.copy + (i32.load + (get_local $0) + ) + (i32.add + (i32.load + (get_local $0) + ) + (i32.const 4) + ) + (i32.mul + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.const 1) + ) + (i32.const 4) + ) + ) + ) + (drop + (call $std:heap/Heap.fill + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.const 1) + ) + (i32.const 4) + ) + ) + (i32.const 0) + (i32.const 4) + ) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (get_local $1) + ) + (func $start (; 10 ;) (type $v) + (set_global $std:heap/HEAP_OFFSET + (get_global $HEAP_BASE) + ) + (set_global $std/array/arr + (call $std:heap/Heap.allocate + (i32.const 12) + ) + ) + (if + (i32.load offset=8 + (get_global $std/array/arr) + ) + (unreachable) + ) + (if + (i32.load offset=4 + (get_global $std/array/arr) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 42) + ) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#pop + (get_global $std/array/arr) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.load offset=8 + (get_global $std/array/arr) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 43) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 44) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 2) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 2) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 44) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 45) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 3) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 45) + ) + (unreachable) + ) + (drop + (call $std:array/Array#unshift + (get_global $std/array/arr) + (i32.const 42) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 45) + ) + (unreachable) + ) + (drop + (call $std:array/Array#unshift + (get_global $std/array/arr) + (i32.const 41) + ) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 5) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 41) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 4) + ) + (i32.const 45) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#shift + (get_global $std/array/arr) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const 41) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 45) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#pop + (get_global $std/array/arr) + ) + ) + (if + (i32.ne + (get_global $std/array/i) + (i32.const 45) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 3) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + (unreachable) + ) + ) ) diff --git a/tests/compiler/std/array.ts b/tests/compiler/std/array.ts index 7c464175..31b5c0e4 100644 --- a/tests/compiler/std/array.ts +++ b/tests/compiler/std/array.ts @@ -1 +1,75 @@ -// Array.fromPtr(1); +var arr = changetype(Heap.allocate(sizeof() + 2 * sizeof())); + +assert(arr.length == 0); +assert(arr.__capacity == 0); + +arr.push(42); + +assert(arr[0] == 42); +assert(arr.length == 1); +assert(arr.__capacity == 1); + +var i = arr.pop(); + +assert(i == 42); +assert(arr.length == 0); +assert(arr.__capacity == 1); + +arr.push(43); + +assert(arr.length == 1); +assert(arr.__capacity == 1); +assert(arr[0] == 43); + +arr.push(44); + +assert(arr.length == 2); +assert(arr.__capacity == 2); +assert(arr[0] == 43); +assert(arr[1] == 44); + +arr.push(45); + +assert(arr.length == 3); +assert(arr.__capacity == 4); +assert(arr[0] == 43); +assert(arr[1] == 44); +assert(arr[2] == 45); + +arr.unshift(42); // see FIXME in std:array + +assert(arr.length == 4); +assert(arr.__capacity == 4); +assert(arr[0] == 42); +assert(arr[1] == 43); +assert(arr[2] == 44); +assert(arr[3] == 45); + +arr.unshift(41); + +assert(arr.length == 5); +assert(arr.__capacity == 8); +assert(arr[0] == 41); +assert(arr[1] == 42); +assert(arr[2] == 43); +assert(arr[3] == 44); +assert(arr[4] == 45); + +i = arr.shift(); + +assert(i == 41); +assert(arr.length == 4); +assert(arr.__capacity == 8); +assert(arr[0] == 42); +assert(arr[1] == 43); +assert(arr[2] == 44); +assert(arr[3] == 45); + +i = arr.pop(); + +assert(i == 45); +assert(arr.length == 3); +assert(arr.__capacity == 8); +assert(arr[0] == 42); +assert(arr[1] == 43); +assert(arr[2] == 44); diff --git a/tests/compiler/std/array.wast b/tests/compiler/std/array.wast index 03f8e437..265e87d3 100644 --- a/tests/compiler/std/array.wast +++ b/tests/compiler/std/array.wast @@ -1,7 +1,3340 @@ (module + (type $i (func (result i32))) + (type $ii (func (param i32) (result i32))) + (type $iiii (func (param i32 i32 i32) (result i32))) + (type $iv (func (param i32))) + (type $iiv (func (param i32 i32))) + (type $iii (func (param i32 i32) (result i32))) + (type $v (func)) + (global $std:heap/HEAP_OFFSET (mut i32) (i32.const 0)) + (global $std:heap/ALIGN_LOG2 i32 (i32.const 3)) + (global $std:heap/ALIGN_SIZE i32 (i32.const 8)) + (global $std:heap/ALIGN_MASK i32 (i32.const 7)) + (global $std/array/arr (mut i32) (i32.const 0)) + (global $std/array/i (mut i32) (i32.const 0)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) (export "memory" (memory $0)) + (start $start) + (func $std:heap/Heap.allocate (; 0 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (if + (i32.eqz + (get_local $0) + ) + (return + (i32.const 0) + ) + ) + (block + (set_local $1 + (current_memory) + ) + ) + (if + (i32.gt_u + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + (i32.shl + (get_local $1) + (i32.const 16) + ) + ) + (if + (i32.lt_s + (grow_memory + (select + (tee_local $2 + (i32.trunc_s/f64 + (f64.ceil + (f64.div + (f64.convert_u/i32 + (get_local $0) + ) + (f64.const 65536) + ) + ) + ) + ) + (tee_local $3 + (i32.sub + (i32.mul + (get_local $1) + (i32.const 2) + ) + (get_local $1) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $3) + ) + ) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + (block + (set_local $4 + (get_global $std:heap/HEAP_OFFSET) + ) + ) + (if + (i32.and + (block (result i32) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (get_global $std:heap/HEAP_OFFSET) + (get_local $0) + ) + ) + (get_global $std:heap/HEAP_OFFSET) + ) + (i32.const 7) + ) + (set_global $std:heap/HEAP_OFFSET + (i32.add + (i32.or + (get_global $std:heap/HEAP_OFFSET) + (i32.const 7) + ) + (i32.const 1) + ) + ) + ) + (return + (get_local $4) + ) + ) + (func $std:heap/Heap.copy (; 1 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.eqz + (i32.ge_u + (get_local $0) + (get_global $HEAP_BASE) + ) + ) + (unreachable) + ) + (block + (set_local $3 + (get_local $0) + ) + ) + (nop) + (block $break|0 + (loop $continue|0 + (if + (if (result i32) + (i32.ne + (get_local $2) + (i32.const 0) + ) + (i32.rem_u + (get_local $1) + (i32.const 4) + ) + (get_local $2) + ) + (block + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (if + (i32.eq + (i32.rem_u + (get_local $3) + (i32.const 4) + ) + (i32.const 0) + ) + (block + (block $break|1 + (loop $continue|1 + (if + (i32.ge_u + (get_local $2) + (i32.const 16) + ) + (block + (block + (i32.store + (get_local $3) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 12) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|1) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (i32.store + (get_local $3) + (i32.load + (get_local $1) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.load + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 8) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (i32.store + (get_local $3) + (i32.load + (get_local $1) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 4) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (i32.store16 + (get_local $3) + (i32.load16_u + (get_local $1) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 2) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + ) + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block $break|2 + (block $case2|2 + (block $case1|2 + (block $case0|2 + (set_local $6 + (i32.rem_u + (get_local $3) + (i32.const 4) + ) + ) + (br_if $case0|2 + (i32.eq + (get_local $6) + (i32.const 1) + ) + ) + (br_if $case1|2 + (i32.eq + (get_local $6) + (i32.const 2) + ) + ) + (br_if $case2|2 + (i32.eq + (get_local $6) + (i32.const 3) + ) + ) + (br $break|2) + ) + (set_local $4 + (i32.load + (get_local $1) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 3) + ) + ) + (block $break|3 + (loop $continue|3 + (if + (i32.ge_u + (get_local $2) + (i32.const 17) + ) + (block + (block + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + ) + (i32.store + (get_local $3) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 24) + ) + (i32.shl + (get_local $5) + (i32.const 8) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 5) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (get_local $4) + (i32.const 8) + ) + ) + ) + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 9) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 24) + ) + (i32.shl + (get_local $5) + (i32.const 8) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 13) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 24) + ) + (i32.shl + (get_local $4) + (i32.const 8) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|3) + ) + ) + ) + ) + (br $break|2) + ) + (set_local $4 + (i32.load + (get_local $1) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 2) + ) + ) + (block $break|4 + (loop $continue|4 + (if + (i32.ge_u + (get_local $2) + (i32.const 18) + ) + (block + (block + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 2) + ) + ) + ) + (i32.store + (get_local $3) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 16) + ) + (i32.shl + (get_local $5) + (i32.const 16) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 6) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (get_local $4) + (i32.const 16) + ) + ) + ) + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 10) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 16) + ) + (i32.shl + (get_local $5) + (i32.const 16) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 14) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 16) + ) + (i32.shl + (get_local $4) + (i32.const 16) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|4) + ) + ) + ) + ) + (br $break|2) + ) + (set_local $4 + (i32.load + (get_local $1) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 1) + ) + ) + (block $break|5 + (loop $continue|5 + (if + (i32.ge_u + (get_local $2) + (i32.const 19) + ) + (block + (block + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 3) + ) + ) + ) + (i32.store + (get_local $3) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 8) + ) + (i32.shl + (get_local $5) + (i32.const 24) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 7) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (get_local $4) + (i32.const 24) + ) + ) + ) + (set_local $5 + (i32.load + (i32.add + (get_local $1) + (i32.const 11) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (i32.or + (i32.shr_u + (get_local $4) + (i32.const 8) + ) + (i32.shl + (get_local $5) + (i32.const 24) + ) + ) + ) + (set_local $4 + (i32.load + (i32.add + (get_local $1) + (i32.const 15) + ) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (i32.or + (i32.shr_u + (get_local $5) + (i32.const 8) + ) + (i32.shl + (get_local $4) + (i32.const 24) + ) + ) + ) + (set_local $1 + (i32.add + (get_local $1) + (i32.const 16) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 16) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 16) + ) + ) + ) + (br $continue|5) + ) + ) + ) + ) + (br $break|2) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 16) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 8) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 4) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 2) + ) + (block + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + ) + (if + (i32.and + (get_local $2) + (i32.const 1) + ) + (i32.store8 + (block (result i32) + (set_local $6 + (get_local $3) + ) + (set_local $3 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + (i32.load8_u + (block (result i32) + (set_local $6 + (get_local $1) + ) + (set_local $1 + (i32.add + (get_local $6) + (i32.const 1) + ) + ) + (get_local $6) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + (func $std:heap/Heap.dispose (; 2 ;) (type $iv) (param $0 i32) + ) + (func $std:array/Array#__grow (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32) + (local $2 i32) + (if + (i32.eqz + (i32.gt_s + (get_local $1) + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (unreachable) + ) + (block + (set_local $2 + (call $std:heap/Heap.allocate + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.load + (get_local $0) + ) + (drop + (call $std:heap/Heap.copy + (get_local $2) + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.const 4) + ) + ) + ) + ) + (call $std:heap/Heap.dispose + (i32.load + (get_local $0) + ) + ) + (i32.store + (get_local $0) + (get_local $2) + ) + (i32.store offset=4 + (get_local $0) + (get_local $1) + ) + ) + (func $std:array/Array#push (; 4 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (if + (i32.ge_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + (call $std:array/Array#__grow + (get_local $0) + (select + (tee_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (tee_local $3 + (i32.mul + (i32.load offset=4 + (get_local $0) + ) + (i32.const 2) + ) + ) + (i32.gt_s + (get_local $2) + (get_local $3) + ) + ) + ) + ) + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=8 + (get_local $0) + ) + (i32.const 4) + ) + ) + (get_local $1) + ) + (return + (block (result i32) + (set_local $2 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (i32.store offset=8 + (get_local $0) + (get_local $2) + ) + (get_local $2) + ) + ) + ) + (func $std:array/Array#__get (; 5 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (if + (i32.ge_u + (get_local $1) + (i32.load offset=4 + (get_local $0) + ) + ) + (unreachable) + ) + (return + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + ) + (func $std:array/Array#pop (; 6 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (if + (i32.and + (if (result i32) + (i32.ne + (tee_local $1 + (i32.lt_s + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (i32.const 0) + ) + (get_local $1) + (i32.gt_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (i32.const 1) + ) + (unreachable) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (return + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.load offset=8 + (get_local $0) + ) + (i32.const 4) + ) + ) + ) + ) + ) + (func $std:array/Array#unshift (; 7 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (set_local $2 + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (if + (i32.ge_u + (i32.load offset=8 + (get_local $0) + ) + (get_local $2) + ) + (call $std:array/Array#__grow + (get_local $0) + (select + (tee_local $3 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (tee_local $4 + (i32.mul + (get_local $2) + (i32.const 2) + ) + ) + (i32.gt_s + (get_local $3) + (get_local $4) + ) + ) + ) + ) + (if + (get_local $2) + (block $break|0 + (block + (set_local $5 + (get_local $2) + ) + ) + (loop $continue|0 + (if + (i32.gt_u + (get_local $5) + (i32.const 0) + ) + (block + (i32.store + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (get_local $5) + (i32.const 4) + ) + ) + (i32.load + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.sub + (get_local $5) + (i32.const 1) + ) + (i32.const 4) + ) + ) + ) + ) + (set_local $5 + (i32.sub + (get_local $5) + (i32.const 1) + ) + ) + (br $continue|0) + ) + ) + ) + ) + ) + (i32.store + (i32.load + (get_local $0) + ) + (get_local $1) + ) + (return + (block (result i32) + (set_local $3 + (i32.add + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (i32.store offset=8 + (get_local $0) + (get_local $3) + ) + (get_local $3) + ) + ) + ) + (func $std:heap/Heap.fill (; 8 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i64) + (if + (i32.eqz + (i32.ge_u + (get_local $0) + (get_global $HEAP_BASE) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (get_local $2) + ) + (return + (get_local $0) + ) + ) + (block + (set_local $3 + (get_local $0) + ) + ) + (i32.store8 + (get_local $3) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 1) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 2) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 1) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 2) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 3) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 6) + ) + (return + (get_local $0) + ) + ) + (i32.store8 + (i32.add + (get_local $3) + (i32.const 3) + ) + (get_local $1) + ) + (i32.store8 + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 4) + ) + (get_local $1) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (block + (set_local $4 + (i32.and + (i32.sub + (i32.const 0) + (get_local $3) + ) + (i32.const 3) + ) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (get_local $4) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (get_local $4) + ) + ) + (set_local $2 + (i32.and + (get_local $2) + (i32.sub + (i32.const 0) + (i32.const 4) + ) + ) + ) + (block + (set_local $5 + (i32.mul + (i32.div_u + (i32.sub + (i32.const 0) + (i32.const 1) + ) + (i32.const 255) + ) + (get_local $1) + ) + ) + ) + (i32.store + (get_local $3) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 4) + ) + (get_local $5) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 8) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 4) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 12) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 8) + ) + (get_local $5) + ) + (if + (i32.le_u + (get_local $2) + (i32.const 24) + ) + (return + (get_local $0) + ) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 12) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 20) + ) + (get_local $5) + ) + (i32.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 28) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 24) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 20) + ) + (get_local $5) + ) + (i32.store + (i32.sub + (i32.add + (get_local $3) + (get_local $2) + ) + (i32.const 16) + ) + (get_local $5) + ) + (set_local $4 + (i32.add + (i32.const 24) + (i32.and + (get_local $3) + (i32.const 4) + ) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (get_local $4) + ) + ) + (set_local $2 + (i32.sub + (get_local $2) + (get_local $4) + ) + ) + (block + (set_local $6 + (i64.or + (i64.extend_u/i32 + (get_local $5) + ) + (i64.shl + (i64.extend_u/i32 + (get_local $5) + ) + (i64.const 32) + ) + ) + ) + ) + (block $break|0 + (loop $continue|0 + (if + (i32.ge_u + (get_local $2) + (i32.const 32) + ) + (block + (block + (i64.store + (get_local $3) + (get_local $6) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 8) + ) + (get_local $6) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 16) + ) + (get_local $6) + ) + (i64.store + (i32.add + (get_local $3) + (i32.const 24) + ) + (get_local $6) + ) + (set_local $2 + (i32.sub + (get_local $2) + (i32.const 32) + ) + ) + (set_local $3 + (i32.add + (get_local $3) + (i32.const 32) + ) + ) + ) + (br $continue|0) + ) + ) + ) + ) + (return + (get_local $0) + ) + ) + (func $std:array/Array#shift (; 9 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (if + (i32.and + (if (result i32) + (i32.ne + (tee_local $1 + (i32.lt_s + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (i32.const 0) + ) + (get_local $1) + (i32.gt_u + (i32.load offset=8 + (get_local $0) + ) + (i32.load offset=4 + (get_local $0) + ) + ) + ) + (i32.const 1) + ) + (unreachable) + ) + (block + (set_local $2 + (i32.load + (i32.load + (get_local $0) + ) + ) + ) + ) + (drop + (call $std:heap/Heap.copy + (i32.load + (get_local $0) + ) + (i32.add + (i32.load + (get_local $0) + ) + (i32.const 4) + ) + (i32.mul + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.const 1) + ) + (i32.const 4) + ) + ) + ) + (drop + (call $std:heap/Heap.fill + (i32.add + (i32.load + (get_local $0) + ) + (i32.mul + (i32.sub + (i32.load offset=4 + (get_local $0) + ) + (i32.const 1) + ) + (i32.const 4) + ) + ) + (i32.const 0) + (i32.const 4) + ) + ) + (i32.store offset=8 + (get_local $0) + (i32.sub + (i32.load offset=8 + (get_local $0) + ) + (i32.const 1) + ) + ) + (return + (get_local $2) + ) + ) + (func $start (; 10 ;) (type $v) + (set_global $std:heap/HEAP_OFFSET + (get_global $HEAP_BASE) + ) + (set_global $std/array/arr + (call $std:heap/Heap.allocate + (i32.add + (i32.const 4) + (i32.mul + (i32.const 2) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 42) + ) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#pop + (get_global $std/array/arr) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/array/i) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 43) + ) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 44) + ) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 2) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 2) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + (drop + (call $std:array/Array#push + (get_global $std/array/arr) + (i32.const 45) + ) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 3) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 45) + ) + ) + (unreachable) + ) + (drop + (call $std:array/Array#unshift + (get_global $std/array/arr) + (i32.const 42) + ) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 45) + ) + ) + (unreachable) + ) + (drop + (call $std:array/Array#unshift + (get_global $std/array/arr) + (i32.const 41) + ) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 5) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 41) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 4) + ) + (i32.const 45) + ) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#shift + (get_global $std/array/arr) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/array/i) + (i32.const 41) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 4) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 3) + ) + (i32.const 45) + ) + ) + (unreachable) + ) + (set_global $std/array/i + (call $std:array/Array#pop + (get_global $std/array/arr) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $std/array/i) + (i32.const 45) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=8 + (get_global $std/array/arr) + ) + (i32.const 3) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load offset=4 + (get_global $std/array/arr) + ) + (i32.const 8) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 0) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 1) + ) + (i32.const 43) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/Array#__get + (get_global $std/array/arr) + (i32.const 2) + ) + (i32.const 44) + ) + ) + (unreachable) + ) + ) ) (; [program.elements] @@ -83,6 +3416,8 @@ FUNCTION_PROTOTYPE: parseInt FUNCTION_PROTOTYPE: std:string/parseFloat FUNCTION_PROTOTYPE: parseFloat + GLOBAL: std/array/arr + GLOBAL: std/array/i [program.exports] CLASS_PROTOTYPE: std:array/Array CLASS_PROTOTYPE: std:array/CArray diff --git a/tests/compiler/std/carray.optimized.wast b/tests/compiler/std/carray.optimized.wast new file mode 100644 index 00000000..4247e770 --- /dev/null +++ b/tests/compiler/std/carray.optimized.wast @@ -0,0 +1,157 @@ +(module + (type $iii (func (param i32 i32) (result i32))) + (type $iiiv (func (param i32 i32 i32))) + (type $v (func)) + (global $std/carray/arr (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 4)) + (memory $0 1) + (export "memory" (memory $0)) + (start $start) + (func $std:array/CArray#__get (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (i32.load + (i32.add + (get_local $0) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + (func $std:array/CArray#__set (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (i32.store + (i32.add + (get_local $0) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + (get_local $2) + ) + ) + (func $start (; 2 ;) (type $v) + (local $0 i32) + (set_global $std/carray/arr + (get_global $HEAP_BASE) + ) + (if + (i32.load + (get_global $HEAP_BASE) + ) + (unreachable) + ) + (if + (i32.load + (i32.add + (get_global $HEAP_BASE) + (i32.const 4) + ) + ) + (unreachable) + ) + (if + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 0) + ) + (unreachable) + ) + (if + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 1) + ) + (unreachable) + ) + (call $std:array/CArray#__set + (get_global $std/carray/arr) + (i32.const 0) + (i32.const 42) + ) + (call $std:array/CArray#__set + (get_global $std/carray/arr) + (i32.const 1) + (i32.const 24) + ) + (if + (i32.ne + (i32.load + (get_global $HEAP_BASE) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load + (i32.add + (get_global $HEAP_BASE) + (i32.const 4) + ) + ) + (i32.const 24) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 0) + ) + (i32.const 42) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 1) + ) + (i32.const 24) + ) + (unreachable) + ) + (if + (block (result i32) + (call $std:array/CArray#__set + (get_global $std/carray/arr) + (i32.const 3) + (tee_local $0 + (i32.const 9000) + ) + ) + (i32.ne + (get_local $0) + (i32.const 9000) + ) + ) + (unreachable) + ) + (if + (i32.ne + (i32.load + (i32.add + (get_global $HEAP_BASE) + (i32.const 12) + ) + ) + (i32.const 9000) + ) + (unreachable) + ) + (if + (i32.ne + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 3) + ) + (i32.const 9000) + ) + (unreachable) + ) + ) +) diff --git a/tests/compiler/std/carray.ts b/tests/compiler/std/carray.ts new file mode 100644 index 00000000..5b7277a3 --- /dev/null +++ b/tests/compiler/std/carray.ts @@ -0,0 +1,26 @@ +// TBD: While this is useful as long as the pointer is just a local or global, +// things go haywire, compared to C, as soon as the CArray is a member of a +// class. Also, multi dimensional arrays cannot be implemented C-like because +// their length isn't known at compile time. + +var arr: CArray = changetype>(HEAP_BASE); + +assert(load(HEAP_BASE) == 0); +assert(load(HEAP_BASE + 4) == 0); + +assert(arr[0] == 0); +assert(arr[1] == 0); + +arr[0] = 42; +arr[1] = 24; + +assert(load(HEAP_BASE) == 42); +assert(load(HEAP_BASE + 4) == 24); + +assert(arr[0] == 42); +assert(arr[1] == 24); + +assert((arr[3] = 9000) == 9000); + +assert(load(HEAP_BASE + 12) == 9000); +assert(arr[3] == 9000); diff --git a/tests/compiler/std/carray.wast b/tests/compiler/std/carray.wast new file mode 100644 index 00000000..651ea64b --- /dev/null +++ b/tests/compiler/std/carray.wast @@ -0,0 +1,287 @@ +(module + (type $iii (func (param i32 i32) (result i32))) + (type $iiiv (func (param i32 i32 i32))) + (type $v (func)) + (global $std/carray/arr (mut i32) (i32.const 0)) + (global $HEAP_BASE i32 (i32.const 4)) + (memory $0 1) + (export "memory" (memory $0)) + (start $start) + (func $std:array/CArray#__get (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (return + (i32.load + (i32.add + (get_local $0) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + ) + ) + ) + (func $std:array/CArray#__set (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32) + (i32.store + (i32.add + (get_local $0) + (i32.mul + (get_local $1) + (i32.const 4) + ) + ) + (get_local $2) + ) + ) + (func $start (; 2 ;) (type $v) + (local $0 i32) + (set_global $std/carray/arr + (get_global $HEAP_BASE) + ) + (if + (i32.eqz + (i32.eq + (i32.load + (get_global $HEAP_BASE) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load + (i32.add + (get_global $HEAP_BASE) + (i32.const 4) + ) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 0) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 1) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (call $std:array/CArray#__set + (get_global $std/carray/arr) + (i32.const 0) + (i32.const 42) + ) + (call $std:array/CArray#__set + (get_global $std/carray/arr) + (i32.const 1) + (i32.const 24) + ) + (if + (i32.eqz + (i32.eq + (i32.load + (get_global $HEAP_BASE) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load + (i32.add + (get_global $HEAP_BASE) + (i32.const 4) + ) + ) + (i32.const 24) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 0) + ) + (i32.const 42) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 1) + ) + (i32.const 24) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (block (result i32) + (call $std:array/CArray#__set + (get_global $std/carray/arr) + (i32.const 3) + (tee_local $0 + (i32.const 9000) + ) + ) + (get_local $0) + ) + (i32.const 9000) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (i32.load + (i32.add + (get_global $HEAP_BASE) + (i32.const 12) + ) + ) + (i32.const 9000) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (call $std:array/CArray#__get + (get_global $std/carray/arr) + (i32.const 3) + ) + (i32.const 9000) + ) + ) + (unreachable) + ) + ) +) +(; +[program.elements] + GLOBAL: NaN + GLOBAL: Infinity + FUNCTION_PROTOTYPE: isNaN + FUNCTION_PROTOTYPE: isFinite + FUNCTION_PROTOTYPE: clz + FUNCTION_PROTOTYPE: ctz + FUNCTION_PROTOTYPE: popcnt + FUNCTION_PROTOTYPE: rotl + FUNCTION_PROTOTYPE: rotr + FUNCTION_PROTOTYPE: abs + FUNCTION_PROTOTYPE: max + FUNCTION_PROTOTYPE: min + FUNCTION_PROTOTYPE: ceil + FUNCTION_PROTOTYPE: floor + FUNCTION_PROTOTYPE: copysign + FUNCTION_PROTOTYPE: nearest + FUNCTION_PROTOTYPE: reinterpret + FUNCTION_PROTOTYPE: sqrt + FUNCTION_PROTOTYPE: trunc + FUNCTION_PROTOTYPE: load + FUNCTION_PROTOTYPE: store + FUNCTION_PROTOTYPE: sizeof + FUNCTION_PROTOTYPE: select + FUNCTION_PROTOTYPE: unreachable + FUNCTION_PROTOTYPE: current_memory + FUNCTION_PROTOTYPE: grow_memory + FUNCTION_PROTOTYPE: changetype + FUNCTION_PROTOTYPE: assert + FUNCTION_PROTOTYPE: i8 + FUNCTION_PROTOTYPE: i16 + FUNCTION_PROTOTYPE: i32 + FUNCTION_PROTOTYPE: i64 + FUNCTION_PROTOTYPE: u8 + FUNCTION_PROTOTYPE: u16 + FUNCTION_PROTOTYPE: u32 + FUNCTION_PROTOTYPE: u64 + FUNCTION_PROTOTYPE: bool + FUNCTION_PROTOTYPE: f32 + FUNCTION_PROTOTYPE: f64 + FUNCTION_PROTOTYPE: isize + FUNCTION_PROTOTYPE: usize + GLOBAL: HEAP_BASE + CLASS_PROTOTYPE: std:array/Array + CLASS_PROTOTYPE: Array + CLASS_PROTOTYPE: std:array/CArray + CLASS_PROTOTYPE: CArray + CLASS_PROTOTYPE: std:error/Error + CLASS_PROTOTYPE: Error + CLASS_PROTOTYPE: std:error/RangeError + CLASS_PROTOTYPE: RangeError + GLOBAL: std:heap/ALIGN_LOG2 + GLOBAL: std:heap/ALIGN_SIZE + GLOBAL: std:heap/ALIGN_MASK + GLOBAL: std:heap/HEAP_OFFSET + CLASS_PROTOTYPE: std:heap/Heap + CLASS_PROTOTYPE: Heap + PROPERTY: std:heap/Heap.used + PROPERTY: std:heap/Heap.free + PROPERTY: std:heap/Heap.size + FUNCTION_PROTOTYPE: std:heap/Heap.allocate + FUNCTION_PROTOTYPE: std:heap/Heap.dispose + FUNCTION_PROTOTYPE: std:heap/Heap.copy + FUNCTION_PROTOTYPE: std:heap/Heap.fill + FUNCTION_PROTOTYPE: std:heap/Heap.compare + CLASS_PROTOTYPE: std:map/Map + CLASS_PROTOTYPE: Map + CLASS_PROTOTYPE: std:regexp/RegExp + CLASS_PROTOTYPE: RegExp + CLASS_PROTOTYPE: std:set/Set + CLASS_PROTOTYPE: Set + GLOBAL: std:string/EMPTY + CLASS_PROTOTYPE: std:string/String + CLASS_PROTOTYPE: String + FUNCTION_PROTOTYPE: std:string/isWhiteSpaceOrLineTerminator + FUNCTION_PROTOTYPE: std:string/parseInt + FUNCTION_PROTOTYPE: parseInt + FUNCTION_PROTOTYPE: std:string/parseFloat + FUNCTION_PROTOTYPE: parseFloat + GLOBAL: std/carray/arr +[program.exports] + CLASS_PROTOTYPE: std:array/Array + CLASS_PROTOTYPE: std:array/CArray + CLASS_PROTOTYPE: std:error/Error + CLASS_PROTOTYPE: std:error/RangeError + CLASS_PROTOTYPE: std:heap/Heap + CLASS_PROTOTYPE: std:map/Map + CLASS_PROTOTYPE: std:regexp/RegExp + CLASS_PROTOTYPE: std:set/Set + CLASS_PROTOTYPE: std:string/String + FUNCTION_PROTOTYPE: std:string/parseInt + FUNCTION_PROTOTYPE: std:string/parseFloat +;)