diff --git a/src/builtins.ts b/src/builtins.ts index 4e98301230..8e0f3c4736 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -2170,7 +2170,7 @@ export function compileCall( } // otherwise call abort if the assertion is false-ish - let abort = compileAbort(compiler, operands.length == 2 ? operands[1] : null, reportNode); + let abort = compiler.makeAbort(operands.length == 2 ? operands[1] : null, reportNode); compiler.currentType = type.nonNullableType; if (contextualType == Type.void) { // simplify if dropped anyway compiler.currentType = Type.void; @@ -4726,49 +4726,6 @@ function deferASM( ); } -/** Compiles an abort wired to the conditionally imported 'abort' function. */ -export function compileAbort( - compiler: Compiler, - message: Expression | null, - reportNode: Node -): ExpressionRef { - var program = compiler.program; - var module = compiler.module; - - var stringInstance = compiler.program.stringInstance; - if (!stringInstance) return module.unreachable(); - - var abortInstance = program.abortInstance; - if (!(abortInstance && compiler.compileFunction(abortInstance))) return module.unreachable(); - - var messageArg: ExpressionRef; - if (message !== null) { - // The message argument works much like an arm of an IF that does not become executed if the - // assertion succeeds respectively is only being computed if the program actually crashes. - // Hence, let's make it so that the autorelease is skipped at the end of the current block, - // essentially ignoring the message GC-wise. Doesn't matter anyway on a crash. - messageArg = compiler.compileExpression(message, stringInstance.type, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN); - } else { - messageArg = compiler.makeZero(stringInstance.type); - } - - var filenameArg = compiler.ensureStaticString(reportNode.range.source.normalizedPath); - - compiler.currentType = Type.void; - return module.block(null, [ - module.call( - abortInstance.internalName, [ - messageArg, - filenameArg, - module.i32(reportNode.range.line), - module.i32(reportNode.range.column) - ], - NativeType.None - ), - module.unreachable() - ]); -} - /** Compiles the `visit_globals` function. */ export function compileVisitGlobals(compiler: Compiler): void { var module = compiler.module; diff --git a/src/compiler.ts b/src/compiler.ts index 2c68a86340..1e81094c4e 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -6,7 +6,6 @@ import { BuiltinNames, compileCall as compileBuiltinCall, - compileAbort, compileVisitGlobals, compileVisitMembers, compileRTTI, @@ -2499,7 +2498,9 @@ export class Compiler extends DiagnosticEmitter { let newArgs = (value).arguments; if (newArgs.length) message = newArgs[0]; // FIXME: naively assumes type string } - stmts.push(compileAbort(this, message, statement)); + stmts.push( + this.makeAbort(message, statement) + ); return this.module.flatten(stmts); } @@ -3125,21 +3126,48 @@ export class Compiler extends DiagnosticEmitter { // any to void if (toType.kind == TypeKind.VOID) return module.drop(expr); - if (this.currentFlow.isNonnull(expr, fromType)) fromType = fromType.nonNullableType; + // reference involved + if (fromType.is(TypeFlags.REFERENCE) || toType.is(TypeFlags.REFERENCE)) { + if (this.currentFlow.isNonnull(expr, fromType)) { + fromType = fromType.nonNullableType; + } else if (explicit && fromType.is(TypeFlags.NULLABLE) && !toType.is(TypeFlags.NULLABLE)) { + // explicit conversion from nullable to non-nullable requires a runtime + // check here because nonnull state above already didn't know better + if (!this.options.noAssert) { + expr = this.makeRuntimeNonNullCheck(expr, fromType, reportNode); + } + fromType = fromType.nonNullableType; + } + if (fromType.isAssignableTo(toType)) { // downcast or same + assert(fromType.kind == toType.kind); + this.currentType = toType; + return expr; + } + if (explicit && toType.nonNullableType.isAssignableTo(fromType)) { // upcast + // (maybeCat) + assert(fromType.kind == toType.kind); + if (!this.options.noAssert) { + expr = this.makeRuntimeUpcastCheck(expr, fromType, toType, reportNode); + } + this.currentType = toType; + return expr; + } + this.error( + DiagnosticCode.Type_0_is_not_assignable_to_type_1, + reportNode.range, fromType.toString(), toType.toString() + ); + this.currentType = toType; + return module.unreachable(); + } + + // not dealing with references from here on if (!fromType.isAssignableTo(toType)) { if (!explicit) { - if (fromType.nonNullableType == toType) { - this.error( - DiagnosticCode.Object_is_possibly_null, - reportNode.range - ); // recoverable - } else { - this.error( - DiagnosticCode.Conversion_from_type_0_to_1_requires_an_explicit_cast, - reportNode.range, fromType.toString(), toType.toString() - ); // recoverable - } + this.error( + DiagnosticCode.Conversion_from_type_0_to_1_requires_an_explicit_cast, + reportNode.range, fromType.toString(), toType.toString() + ); // recoverable } } @@ -3319,19 +3347,9 @@ export class Compiler extends DiagnosticEmitter { expression.expression.range ); } else if (!this.options.noAssert) { - let module = this.module; - let flow = this.currentFlow; - let temp = flow.getTempLocal(type); - if (!flow.canOverflow(expr, type)) flow.setLocalFlag(temp.index, LocalFlags.WRAPPED); - flow.setLocalFlag(temp.index, LocalFlags.NONNULL); - expr = module.if( - module.local_tee(temp.index, expr), - module.local_get(temp.index, type.toNativeType()), - module.unreachable() - ); - flow.freeTempLocal(temp); + expr = this.makeRuntimeNonNullCheck(expr, type, expression); } - this.currentType = this.currentType.nonNullableType; + this.currentType = type.nonNullableType; return expr; } default: assert(false); @@ -9376,6 +9394,98 @@ export class Compiler extends DiagnosticEmitter { } return stmts; } + + /** Makes a call to `abort`, if present, otherwise creates a trap. */ + makeAbort( + /** Message argument of type string, if any. */ + message: Expression | null, + /** Code location to report when aborting. */ + codeLocation: Node + ): ExpressionRef { + var program = this.program; + var module = this.module; + var stringInstance = program.stringInstance; + var abortInstance = program.abortInstance; + if (!abortInstance || !this.compileFunction(abortInstance)) return module.unreachable(); + + var messageArg: ExpressionRef; + if (message !== null) { + // The message argument works much like an arm of an IF that does not become executed if the + // assertion succeeds respectively is only being computed if the program actually crashes. + // Hence, let's make it so that the autorelease is skipped at the end of the current block, + // essentially ignoring the message GC-wise. Doesn't matter anyway on a crash. + messageArg = this.compileExpression(message, stringInstance.type, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN); + } else { + messageArg = this.makeZero(stringInstance.type); + } + + var filenameArg = this.ensureStaticString(codeLocation.range.source.normalizedPath); + return module.block(null, [ + module.call( + abortInstance.internalName, [ + messageArg, + filenameArg, + module.i32(codeLocation.range.line), + module.i32(codeLocation.range.column) + ], + NativeType.None + ), + module.unreachable() + ]); + } + + /** Makes a runtime non-null check, e.g. on `possiblyNull` or `possiblyNull!`. */ + makeRuntimeNonNullCheck( + /** Expression being checked. */ + expr: ExpressionRef, + /** Type of the expression. */ + type: Type, + /** Report node. */ + reportNode: Node + ): ExpressionRef { + assert(type.is(TypeFlags.NULLABLE | TypeFlags.REFERENCE)); + var module = this.module; + var flow = this.currentFlow; + var temp = flow.getTempLocal(type); + if (!flow.canOverflow(expr, type)) flow.setLocalFlag(temp.index, LocalFlags.WRAPPED); + flow.setLocalFlag(temp.index, LocalFlags.NONNULL); + expr = module.if( + module.local_tee(temp.index, expr), + module.local_get(temp.index, type.toNativeType()), + this.makeAbort(null, reportNode) // TODO: throw + ); + flow.freeTempLocal(temp); + return expr; + } + + /** Makes a runtime upcast check, e.g. on `parent`. */ + makeRuntimeUpcastCheck( + /** Expression being upcast. */ + expr: ExpressionRef, + /** Type of the expression. */ + type: Type, + /** Type casting to. */ + toType: Type, + /** Report node. */ + reportNode: Node + ): ExpressionRef { + assert(toType.is(TypeFlags.REFERENCE) && toType.nonNullableType.isAssignableTo(type)); + var module = this.module; + var flow = this.currentFlow; + var temp = flow.getTempLocal(type); + var instanceofInstance = this.program.instanceofInstance; + assert(this.compileFunction(instanceofInstance)); + expr = module.if( + module.call(instanceofInstance.internalName, [ + module.local_tee(temp.index, expr), + module.i32(assert(toType.classReference).id) + ], NativeType.I32), + module.local_get(temp.index, type.toNativeType()), + this.makeAbort(null, reportNode) // TODO: throw + ); + flow.freeTempLocal(temp); + return expr; + } } // helpers diff --git a/std/assembly/rt/tlsf.ts b/std/assembly/rt/tlsf.ts index e325225018..c6adeb910f 100644 --- a/std/assembly/rt/tlsf.ts +++ b/std/assembly/rt/tlsf.ts @@ -498,12 +498,12 @@ export function allocateBlock(root: Root, size: usize): Block { block = searchBlock(root, payloadSize); if (!block) { growMemory(root, payloadSize); - block = searchBlock(root, payloadSize); + block = changetype(searchBlock(root, payloadSize)); if (DEBUG) assert(block); // must be found now } } else { growMemory(root, payloadSize); - block = searchBlock(root, payloadSize); + block = changetype(searchBlock(root, payloadSize)); if (DEBUG) assert(block); // must be found now } } diff --git a/tests/compiler/assert-nonnull.optimized.wat b/tests/compiler/assert-nonnull.optimized.wat index 536902c55e..1de0e970bc 100644 --- a/tests/compiler/assert-nonnull.optimized.wat +++ b/tests/compiler/assert-nonnull.optimized.wat @@ -4,9 +4,10 @@ (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (memory $0 1) - (data (i32.const 16) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e") - (data (i32.const 80) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s") - (data (i32.const 128) "^\00\00\00\01\00\00\00\01\00\00\00^\00\00\00E\00l\00e\00m\00e\00n\00t\00 \00t\00y\00p\00e\00 \00m\00u\00s\00t\00 \00b\00e\00 \00n\00u\00l\00l\00a\00b\00l\00e\00 \00i\00f\00 \00a\00r\00r\00a\00y\00 \00i\00s\00 \00h\00o\00l\00e\00y") + (data (i32.const 16) "\"\00\00\00\01\00\00\00\01\00\00\00\"\00\00\00a\00s\00s\00e\00r\00t\00-\00n\00o\00n\00n\00u\00l\00l\00.\00t\00s") + (data (i32.const 80) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e") + (data (i32.const 144) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s") + (data (i32.const 192) "^\00\00\00\01\00\00\00\01\00\00\00^\00\00\00E\00l\00e\00m\00e\00n\00t\00 \00t\00y\00p\00e\00 \00m\00u\00s\00t\00 \00b\00e\00 \00n\00u\00l\00l\00a\00b\00l\00e\00 \00i\00f\00 \00a\00r\00r\00a\00y\00 \00i\00s\00 \00h\00o\00l\00e\00y") (table $0 1 funcref) (global $~argumentsLength (mut i32) (i32.const 0)) (export "__argumentsLength" (global $~argumentsLength)) @@ -17,7 +18,7 @@ (export "testArr" (func $assert-nonnull/testArr)) (export "testElem" (func $assert-nonnull/testElem)) (export "testAll" (func $assert-nonnull/testAll)) - (export "testAll2" (func $assert-nonnull/testAll)) + (export "testAll2" (func $assert-nonnull/testAll2)) (export "testFn" (func $assert-nonnull/testFn)) (export "testFn2" (func $assert-nonnull/testFn2)) (export "testRet" (func $assert-nonnull/testRet)) @@ -27,6 +28,11 @@ local.get $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 2 + i32.const 9 + call $~lib/builtins/abort unreachable end local.get $0 @@ -35,6 +41,11 @@ local.get $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 11 + i32.const 9 + call $~lib/builtins/abort unreachable end local.get $0 @@ -46,6 +57,11 @@ local.tee $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 15 + i32.const 9 + call $~lib/builtins/abort unreachable end local.get $0 @@ -61,8 +77,8 @@ i32.load offset=12 i32.ge_u if - i32.const 32 i32.const 96 + i32.const 160 i32.const 93 i32.const 41 call $~lib/builtins/abort @@ -73,8 +89,8 @@ local.tee $0 i32.eqz if - i32.const 144 - i32.const 96 + i32.const 208 + i32.const 160 i32.const 97 i32.const 39 call $~lib/builtins/abort @@ -86,6 +102,11 @@ local.get $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 19 + i32.const 9 + call $~lib/builtins/abort unreachable end local.get $0 @@ -97,8 +118,8 @@ i32.load offset=12 i32.ge_u if - i32.const 32 i32.const 96 + i32.const 160 i32.const 93 i32.const 41 call $~lib/builtins/abort @@ -113,43 +134,82 @@ local.tee $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 23 + i32.const 9 + call $~lib/builtins/abort unreachable end local.get $0 ) (func $assert-nonnull/testAll (; 9 ;) (param $0 i32) (result i32) (local $1 i32) - local.get $0 - i32.eqz - if - unreachable - end - local.get $0 - call $~lib/array/Array#__get - local.tee $0 - local.get $0 - i32.eqz - if - unreachable + block $folding-inner0 + local.get $0 + i32.eqz + br_if $folding-inner0 + local.get $0 + call $~lib/array/Array#__get + local.tee $0 + local.get $0 + i32.eqz + br_if $folding-inner0 + i32.load + local.tee $0 + i32.eqz + br_if $folding-inner0 + local.get $0 + return end - i32.load - local.tee $0 - i32.eqz - if - unreachable + i32.const 0 + i32.const 32 + i32.const 27 + i32.const 9 + call $~lib/builtins/abort + unreachable + ) + (func $assert-nonnull/testAll2 (; 10 ;) (param $0 i32) (result i32) + (local $1 i32) + block $folding-inner0 + local.get $0 + i32.eqz + br_if $folding-inner0 + local.get $0 + call $~lib/array/Array#__get + local.tee $0 + local.get $0 + i32.eqz + br_if $folding-inner0 + i32.load + local.tee $0 + i32.eqz + br_if $folding-inner0 + local.get $0 + return end - local.get $0 + i32.const 0 + i32.const 32 + i32.const 31 + i32.const 9 + call $~lib/builtins/abort + unreachable ) - (func $assert-nonnull/testFn (; 10 ;) (param $0 i32) (result i32) + (func $assert-nonnull/testFn (; 11 ;) (param $0 i32) (result i32) i32.const 0 global.set $~argumentsLength local.get $0 call_indirect (type $none_=>_i32) ) - (func $assert-nonnull/testFn2 (; 11 ;) (param $0 i32) (result i32) + (func $assert-nonnull/testFn2 (; 12 ;) (param $0 i32) (result i32) local.get $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 39 + i32.const 12 + call $~lib/builtins/abort unreachable end i32.const 0 @@ -157,7 +217,7 @@ local.get $0 call_indirect (type $none_=>_i32) ) - (func $assert-nonnull/testRet (; 12 ;) (param $0 i32) (result i32) + (func $assert-nonnull/testRet (; 13 ;) (param $0 i32) (result i32) (local $1 i32) i32.const 0 global.set $~argumentsLength @@ -167,17 +227,22 @@ local.get $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 44 + i32.const 9 + call $~lib/builtins/abort unreachable end ) - (func $assert-nonnull/testObjFn (; 13 ;) (param $0 i32) (result i32) + (func $assert-nonnull/testObjFn (; 14 ;) (param $0 i32) (result i32) i32.const 0 global.set $~argumentsLength local.get $0 i32.load offset=4 call_indirect (type $none_=>_i32) ) - (func $assert-nonnull/testObjRet (; 14 ;) (param $0 i32) (result i32) + (func $assert-nonnull/testObjRet (; 15 ;) (param $0 i32) (result i32) (local $1 i32) i32.const 0 global.set $~argumentsLength @@ -188,6 +253,11 @@ local.get $0 i32.eqz if + i32.const 0 + i32.const 32 + i32.const 52 + i32.const 9 + call $~lib/builtins/abort unreachable end ) diff --git a/tests/compiler/assert-nonnull.untouched.wat b/tests/compiler/assert-nonnull.untouched.wat index 88bea7f8a1..6c56578575 100644 --- a/tests/compiler/assert-nonnull.untouched.wat +++ b/tests/compiler/assert-nonnull.untouched.wat @@ -6,9 +6,10 @@ (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (memory $0 1) - (data (i32.const 16) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00") - (data (i32.const 80) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00") - (data (i32.const 128) "^\00\00\00\01\00\00\00\01\00\00\00^\00\00\00E\00l\00e\00m\00e\00n\00t\00 \00t\00y\00p\00e\00 \00m\00u\00s\00t\00 \00b\00e\00 \00n\00u\00l\00l\00a\00b\00l\00e\00 \00i\00f\00 \00a\00r\00r\00a\00y\00 \00i\00s\00 \00h\00o\00l\00e\00y\00") + (data (i32.const 16) "\"\00\00\00\01\00\00\00\01\00\00\00\"\00\00\00a\00s\00s\00e\00r\00t\00-\00n\00o\00n\00n\00u\00l\00l\00.\00t\00s\00") + (data (i32.const 80) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00") + (data (i32.const 144) "\1a\00\00\00\01\00\00\00\01\00\00\00\1a\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00") + (data (i32.const 192) "^\00\00\00\01\00\00\00\01\00\00\00^\00\00\00E\00l\00e\00m\00e\00n\00t\00 \00t\00y\00p\00e\00 \00m\00u\00s\00t\00 \00b\00e\00 \00n\00u\00l\00l\00a\00b\00l\00e\00 \00i\00f\00 \00a\00r\00r\00a\00y\00 \00i\00s\00 \00h\00o\00l\00e\00y\00") (table $0 1 funcref) (global $~argumentsLength (mut i32) (i32.const 0)) (export "__argumentsLength" (global $~argumentsLength)) @@ -41,6 +42,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 2 + i32.const 9 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain @@ -59,6 +65,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 11 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.load @@ -79,6 +90,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 15 + i32.const 9 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain @@ -104,8 +120,8 @@ i32.load offset=12 i32.ge_u if - i32.const 32 i32.const 96 + i32.const 160 i32.const 93 i32.const 41 call $~lib/builtins/abort @@ -120,8 +136,8 @@ if local.get $2 call $~lib/rt/stub/__release - i32.const 144 - i32.const 96 + i32.const 208 + i32.const 160 i32.const 97 i32.const 39 call $~lib/builtins/abort @@ -139,6 +155,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 19 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.const 0 @@ -165,8 +186,8 @@ i32.load offset=12 i32.ge_u if - i32.const 32 i32.const 96 + i32.const 160 i32.const 93 i32.const 41 call $~lib/builtins/abort @@ -190,6 +211,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 23 + i32.const 9 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain @@ -209,6 +235,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 27 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.const 0 @@ -218,6 +249,11 @@ if (result i32) local.get $2 else + i32.const 0 + i32.const 32 + i32.const 27 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.load @@ -225,6 +261,11 @@ if (result i32) local.get $2 else + i32.const 0 + i32.const 32 + i32.const 27 + i32.const 9 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain @@ -246,6 +287,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 31 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.const 0 @@ -255,6 +301,11 @@ if (result i32) local.get $2 else + i32.const 0 + i32.const 32 + i32.const 31 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.load @@ -262,6 +313,11 @@ if (result i32) local.get $2 else + i32.const 0 + i32.const 32 + i32.const 31 + i32.const 9 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain @@ -288,6 +344,11 @@ if (result i32) local.get $1 else + i32.const 0 + i32.const 32 + i32.const 39 + i32.const 12 + call $~lib/builtins/abort unreachable end local.set $2 @@ -309,6 +370,11 @@ if (result i32) local.get $2 else + i32.const 0 + i32.const 32 + i32.const 44 + i32.const 9 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain @@ -350,6 +416,11 @@ if (result i32) local.get $2 else + i32.const 0 + i32.const 32 + i32.const 52 + i32.const 9 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain diff --git a/tests/compiler/managed-cast.json b/tests/compiler/managed-cast.json new file mode 100644 index 0000000000..59c251c705 --- /dev/null +++ b/tests/compiler/managed-cast.json @@ -0,0 +1,7 @@ +{ + "asc_flags": [ + "--runtime half", + "--explicitStart", + "--use ASC_RTRACE=1" + ] +} \ No newline at end of file diff --git a/tests/compiler/managed-cast.optimized.wat b/tests/compiler/managed-cast.optimized.wat new file mode 100644 index 0000000000..c0b359a1fc --- /dev/null +++ b/tests/compiler/managed-cast.optimized.wat @@ -0,0 +1,2036 @@ +(module + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (import "rtrace" "onfree" (func $~lib/rt/rtrace/onfree (param i32))) + (import "rtrace" "onalloc" (func $~lib/rt/rtrace/onalloc (param i32))) + (import "rtrace" "onincrement" (func $~lib/rt/rtrace/onincrement (param i32))) + (import "rtrace" "ondecrement" (func $~lib/rt/rtrace/ondecrement (param i32))) + (memory $0 1) + (data (i32.const 16) "\1e\00\00\00\01\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s") + (data (i32.const 64) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00a\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e") + (data (i32.const 128) "\1e\00\00\00\01\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00p\00u\00r\00e\00.\00t\00s") + (data (i32.const 176) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e") + (data (i32.const 240) "\14\00\00\00\01\00\00\00\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s") + (data (i32.const 288) "\1e\00\00\00\01\00\00\00\01\00\00\00\1e\00\00\00m\00a\00n\00a\00g\00e\00d\00-\00c\00a\00s\00t\00.\00t\00s") + (data (i32.const 336) "\05\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\04\00\00\00\10") + (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) + (global $~lib/rt/tlsf/collectLock (mut i32) (i32.const 0)) + (global $~lib/rt/pure/ROOTS (mut i32) (i32.const 0)) + (global $~lib/rt/pure/CUR (mut i32) (i32.const 0)) + (global $~lib/rt/pure/END (mut i32) (i32.const 0)) + (global $~started (mut i32) (i32.const 0)) + (export "_start" (func $~start)) + (export "memory" (memory $0)) + (func $~lib/rt/tlsf/removeBlock (; 5 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + local.get $1 + i32.load + local.tee $3 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 277 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const -4 + i32.and + local.tee $2 + i32.const 16 + i32.ge_u + if (result i32) + local.get $2 + i32.const 1073741808 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 279 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 256 + i32.lt_u + if (result i32) + local.get $2 + i32.const 4 + i32.shr_u + local.set $2 + i32.const 0 + else + local.get $2 + i32.const 31 + local.get $2 + i32.clz + i32.sub + local.tee $3 + i32.const 4 + i32.sub + i32.shr_u + i32.const 16 + i32.xor + local.set $2 + local.get $3 + i32.const 7 + i32.sub + end + local.tee $3 + i32.const 23 + i32.lt_u + if (result i32) + local.get $2 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 292 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load offset=20 + local.set $4 + local.get $1 + i32.load offset=16 + local.tee $5 + if + local.get $5 + local.get $4 + i32.store offset=20 + end + local.get $4 + if + local.get $4 + local.get $5 + i32.store offset=16 + end + local.get $1 + local.get $0 + local.get $2 + local.get $3 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + i32.eq + if + local.get $0 + local.get $2 + local.get $3 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + i32.add + local.get $4 + i32.store offset=96 + local.get $4 + i32.eqz + if + local.get $0 + local.get $3 + i32.const 2 + i32.shl + i32.add + local.get $0 + local.get $3 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + i32.const 1 + local.get $2 + i32.shl + i32.const -1 + i32.xor + i32.and + local.tee $1 + i32.store offset=4 + local.get $1 + i32.eqz + if + local.get $0 + local.get $0 + i32.load + i32.const 1 + local.get $3 + i32.shl + i32.const -1 + i32.xor + i32.and + i32.store + end + end + end + ) + (func $~lib/rt/tlsf/insertBlock (; 6 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + local.get $1 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 205 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load + local.tee $3 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 207 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 16 + i32.add + local.get $1 + i32.load + i32.const -4 + i32.and + i32.add + local.tee $4 + i32.load + local.tee $5 + i32.const 1 + i32.and + if + local.get $3 + i32.const -4 + i32.and + i32.const 16 + i32.add + local.get $5 + i32.const -4 + i32.and + i32.add + local.tee $2 + i32.const 1073741808 + i32.lt_u + if + local.get $0 + local.get $4 + call $~lib/rt/tlsf/removeBlock + local.get $1 + local.get $2 + local.get $3 + i32.const 3 + i32.and + i32.or + local.tee $3 + i32.store + local.get $1 + i32.const 16 + i32.add + local.get $1 + i32.load + i32.const -4 + i32.and + i32.add + local.tee $4 + i32.load + local.set $5 + end + end + local.get $3 + i32.const 2 + i32.and + if + local.get $1 + i32.const 4 + i32.sub + i32.load + local.tee $2 + i32.load + local.tee $6 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 228 + i32.const 15 + call $~lib/builtins/abort + unreachable + end + local.get $6 + i32.const -4 + i32.and + i32.const 16 + i32.add + local.get $3 + i32.const -4 + i32.and + i32.add + local.tee $7 + i32.const 1073741808 + i32.lt_u + if + local.get $0 + local.get $2 + call $~lib/rt/tlsf/removeBlock + local.get $2 + local.get $7 + local.get $6 + i32.const 3 + i32.and + i32.or + local.tee $3 + i32.store + local.get $2 + local.set $1 + end + end + local.get $4 + local.get $5 + i32.const 2 + i32.or + i32.store + local.get $3 + i32.const -4 + i32.and + local.tee $2 + i32.const 16 + i32.ge_u + if (result i32) + local.get $2 + i32.const 1073741808 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 243 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $2 + local.get $1 + i32.const 16 + i32.add + i32.add + local.get $4 + i32.ne + if + i32.const 0 + i32.const 32 + i32.const 244 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $4 + i32.const 4 + i32.sub + local.get $1 + i32.store + local.get $2 + i32.const 256 + i32.lt_u + if (result i32) + local.get $2 + i32.const 4 + i32.shr_u + local.set $4 + i32.const 0 + else + local.get $2 + i32.const 31 + local.get $2 + i32.clz + i32.sub + local.tee $2 + i32.const 4 + i32.sub + i32.shr_u + i32.const 16 + i32.xor + local.set $4 + local.get $2 + i32.const 7 + i32.sub + end + local.tee $3 + i32.const 23 + i32.lt_u + if (result i32) + local.get $4 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 260 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $4 + local.get $3 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + local.set $2 + local.get $1 + i32.const 0 + i32.store offset=16 + local.get $1 + local.get $2 + i32.store offset=20 + local.get $2 + if + local.get $2 + local.get $1 + i32.store offset=16 + end + local.get $0 + local.get $4 + local.get $3 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + i32.add + local.get $1 + i32.store offset=96 + local.get $0 + local.get $0 + i32.load + i32.const 1 + local.get $3 + i32.shl + i32.or + i32.store + local.get $0 + local.get $3 + i32.const 2 + i32.shl + i32.add + local.get $0 + local.get $3 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + i32.const 1 + local.get $4 + i32.shl + i32.or + i32.store offset=4 + ) + (func $~lib/rt/tlsf/addMemory (; 7 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + local.get $2 + i32.const 15 + i32.and + i32.eqz + i32.const 0 + local.get $1 + i32.const 15 + i32.and + i32.eqz + i32.const 0 + local.get $1 + local.get $2 + i32.le_u + select + select + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 386 + i32.const 4 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.load offset=1568 + local.tee $3 + if + local.get $1 + local.get $3 + i32.const 16 + i32.add + i32.lt_u + if + i32.const 0 + i32.const 32 + i32.const 396 + i32.const 15 + call $~lib/builtins/abort + unreachable + end + local.get $3 + local.get $1 + i32.const 16 + i32.sub + i32.eq + if + local.get $3 + i32.load + local.set $4 + local.get $1 + i32.const 16 + i32.sub + local.set $1 + end + else + local.get $1 + local.get $0 + i32.const 1572 + i32.add + i32.lt_u + if + i32.const 0 + i32.const 32 + i32.const 408 + i32.const 4 + call $~lib/builtins/abort + unreachable + end + end + local.get $2 + local.get $1 + i32.sub + local.tee $2 + i32.const 48 + i32.lt_u + if + return + end + local.get $1 + local.get $4 + i32.const 2 + i32.and + local.get $2 + i32.const 32 + i32.sub + i32.const 1 + i32.or + i32.or + i32.store + local.get $1 + i32.const 0 + i32.store offset=16 + local.get $1 + i32.const 0 + i32.store offset=20 + local.get $1 + local.get $2 + i32.add + i32.const 16 + i32.sub + local.tee $2 + i32.const 2 + i32.store + local.get $0 + local.get $2 + i32.store offset=1568 + local.get $0 + local.get $1 + call $~lib/rt/tlsf/insertBlock + ) + (func $~lib/rt/tlsf/maybeInitialize (; 8 ;) (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + global.get $~lib/rt/tlsf/ROOT + local.tee $0 + i32.eqz + if + i32.const 1 + memory.size + local.tee $0 + i32.gt_s + if (result i32) + i32.const 1 + local.get $0 + i32.sub + memory.grow + i32.const 0 + i32.lt_s + else + i32.const 0 + end + if + unreachable + end + i32.const 384 + local.tee $0 + i32.const 0 + i32.store + i32.const 1952 + i32.const 0 + i32.store + loop $for-loop|0 + local.get $1 + i32.const 23 + i32.lt_u + if + local.get $1 + i32.const 2 + i32.shl + i32.const 384 + i32.add + i32.const 0 + i32.store offset=4 + i32.const 0 + local.set $2 + loop $for-loop|1 + local.get $2 + i32.const 16 + i32.lt_u + if + local.get $1 + i32.const 4 + i32.shl + local.get $2 + i32.add + i32.const 2 + i32.shl + i32.const 384 + i32.add + i32.const 0 + i32.store offset=96 + local.get $2 + i32.const 1 + i32.add + local.set $2 + br $for-loop|1 + end + end + local.get $1 + i32.const 1 + i32.add + local.set $1 + br $for-loop|0 + end + end + i32.const 384 + i32.const 1968 + memory.size + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + i32.const 384 + global.set $~lib/rt/tlsf/ROOT + end + local.get $0 + ) + (func $~lib/rt/tlsf/prepareSize (; 9 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 1073741808 + i32.ge_u + if + i32.const 80 + i32.const 32 + i32.const 457 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.const 15 + i32.add + i32.const -16 + i32.and + local.tee $0 + i32.const 16 + local.get $0 + i32.const 16 + i32.gt_u + select + ) + (func $~lib/rt/tlsf/searchBlock (; 10 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + local.get $1 + i32.const 256 + i32.lt_u + if (result i32) + local.get $1 + i32.const 4 + i32.shr_u + local.set $1 + i32.const 0 + else + local.get $1 + i32.const 536870904 + i32.lt_u + if + local.get $1 + i32.const 1 + i32.const 27 + local.get $1 + i32.clz + i32.sub + i32.shl + i32.add + i32.const 1 + i32.sub + local.set $1 + end + local.get $1 + i32.const 31 + local.get $1 + i32.clz + i32.sub + local.tee $2 + i32.const 4 + i32.sub + i32.shr_u + i32.const 16 + i32.xor + local.set $1 + local.get $2 + i32.const 7 + i32.sub + end + local.tee $2 + i32.const 23 + i32.lt_u + if (result i32) + local.get $1 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 338 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $2 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + i32.const -1 + local.get $1 + i32.shl + i32.and + local.tee $1 + if (result i32) + local.get $0 + local.get $1 + i32.ctz + local.get $2 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + else + local.get $0 + i32.load + i32.const -1 + local.get $2 + i32.const 1 + i32.add + i32.shl + i32.and + local.tee $1 + if (result i32) + local.get $0 + local.get $1 + i32.ctz + local.tee $1 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + local.tee $2 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 351 + i32.const 17 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $2 + i32.ctz + local.get $1 + i32.const 4 + i32.shl + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + else + i32.const 0 + end + end + ) + (func $~lib/rt/pure/markGray (; 11 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.tee $1 + i32.const 1879048192 + i32.and + i32.const 268435456 + i32.ne + if + local.get $0 + local.get $1 + i32.const -1879048193 + i32.and + i32.const 268435456 + i32.or + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 2 + call $~lib/rt/__visit_members + end + ) + (func $~lib/rt/tlsf/freeBlock (; 12 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $1 + i32.load + local.tee $2 + i32.const 1 + i32.and + if + i32.const 0 + i32.const 32 + i32.const 569 + i32.const 2 + call $~lib/builtins/abort + unreachable + end + local.get $1 + local.get $2 + i32.const 1 + i32.or + i32.store + local.get $0 + local.get $1 + call $~lib/rt/tlsf/insertBlock + local.get $1 + call $~lib/rt/rtrace/onfree + ) + (func $~lib/rt/pure/scanBlack (; 13 ;) (param $0 i32) + local.get $0 + local.get $0 + i32.load offset=4 + i32.const -1879048193 + i32.and + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 4 + call $~lib/rt/__visit_members + ) + (func $~lib/rt/pure/scan (; 14 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.tee $1 + i32.const 1879048192 + i32.and + i32.const 268435456 + i32.eq + if + local.get $1 + i32.const 268435455 + i32.and + i32.const 0 + i32.gt_u + if + local.get $0 + call $~lib/rt/pure/scanBlack + else + local.get $0 + local.get $1 + i32.const -1879048193 + i32.and + i32.const 536870912 + i32.or + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 3 + call $~lib/rt/__visit_members + end + end + ) + (func $~lib/rt/pure/collectWhite (; 15 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.tee $1 + i32.const 1879048192 + i32.and + i32.const 536870912 + i32.eq + if (result i32) + local.get $1 + i32.const -2147483648 + i32.and + i32.eqz + else + i32.const 0 + end + if + local.get $0 + local.get $1 + i32.const -1879048193 + i32.and + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 5 + call $~lib/rt/__visit_members + global.get $~lib/rt/tlsf/ROOT + local.get $0 + call $~lib/rt/tlsf/freeBlock + end + ) + (func $~lib/rt/pure/__collect (; 16 ;) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + global.get $~lib/rt/pure/ROOTS + local.tee $5 + local.tee $2 + local.set $3 + global.get $~lib/rt/pure/CUR + local.set $0 + loop $for-loop|0 + local.get $3 + local.get $0 + i32.lt_u + if + local.get $3 + i32.load + local.tee $4 + i32.load offset=4 + local.tee $1 + i32.const 1879048192 + i32.and + i32.const 805306368 + i32.eq + if (result i32) + local.get $1 + i32.const 268435455 + i32.and + i32.const 0 + i32.gt_u + else + i32.const 0 + end + if + local.get $4 + call $~lib/rt/pure/markGray + local.get $2 + local.get $4 + i32.store + local.get $2 + i32.const 4 + i32.add + local.set $2 + else + i32.const 0 + local.get $1 + i32.const 268435455 + i32.and + i32.eqz + local.get $1 + i32.const 1879048192 + i32.and + select + if + global.get $~lib/rt/tlsf/ROOT + local.get $4 + call $~lib/rt/tlsf/freeBlock + else + local.get $4 + local.get $1 + i32.const 2147483647 + i32.and + i32.store offset=4 + end + end + local.get $3 + i32.const 4 + i32.add + local.set $3 + br $for-loop|0 + end + end + local.get $2 + global.set $~lib/rt/pure/CUR + local.get $5 + local.set $0 + loop $for-loop|1 + local.get $0 + local.get $2 + i32.lt_u + if + local.get $0 + i32.load + call $~lib/rt/pure/scan + local.get $0 + i32.const 4 + i32.add + local.set $0 + br $for-loop|1 + end + end + local.get $5 + local.set $0 + loop $for-loop|2 + local.get $0 + local.get $2 + i32.lt_u + if + local.get $0 + i32.load + local.tee $1 + local.get $1 + i32.load offset=4 + i32.const 2147483647 + i32.and + i32.store offset=4 + local.get $1 + call $~lib/rt/pure/collectWhite + local.get $0 + i32.const 4 + i32.add + local.set $0 + br $for-loop|2 + end + end + local.get $5 + global.set $~lib/rt/pure/CUR + ) + (func $~lib/rt/tlsf/growMemory (; 17 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + memory.size + local.tee $2 + i32.const 16 + local.get $0 + i32.load offset=1568 + local.get $2 + i32.const 16 + i32.shl + i32.const 16 + i32.sub + i32.ne + i32.shl + local.get $1 + i32.const 1 + i32.const 27 + local.get $1 + i32.clz + i32.sub + i32.shl + i32.const 1 + i32.sub + i32.add + local.get $1 + local.get $1 + i32.const 536870904 + i32.lt_u + select + i32.add + i32.const 65535 + i32.add + i32.const -65536 + i32.and + i32.const 16 + i32.shr_u + local.tee $1 + local.get $2 + local.get $1 + i32.gt_s + select + memory.grow + i32.const 0 + i32.lt_s + if + local.get $1 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + local.get $0 + local.get $2 + i32.const 16 + i32.shl + memory.size + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + ) + (func $~lib/rt/tlsf/prepareBlock (; 18 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + local.get $1 + i32.load + local.set $3 + local.get $2 + i32.const 15 + i32.and + if + i32.const 0 + i32.const 32 + i32.const 365 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const -4 + i32.and + local.get $2 + i32.sub + local.tee $4 + i32.const 32 + i32.ge_u + if + local.get $1 + local.get $2 + local.get $3 + i32.const 2 + i32.and + i32.or + i32.store + local.get $2 + local.get $1 + i32.const 16 + i32.add + i32.add + local.tee $1 + local.get $4 + i32.const 16 + i32.sub + i32.const 1 + i32.or + i32.store + local.get $0 + local.get $1 + call $~lib/rt/tlsf/insertBlock + else + local.get $1 + local.get $3 + i32.const -2 + i32.and + i32.store + local.get $1 + i32.const 16 + i32.add + local.get $1 + i32.load + i32.const -4 + i32.and + i32.add + local.get $1 + i32.const 16 + i32.add + local.get $1 + i32.load + i32.const -4 + i32.and + i32.add + i32.load + i32.const -3 + i32.and + i32.store + end + ) + (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + global.get $~lib/rt/tlsf/collectLock + if + i32.const 0 + i32.const 32 + i32.const 490 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $1 + call $~lib/rt/tlsf/prepareSize + local.tee $3 + call $~lib/rt/tlsf/searchBlock + local.tee $2 + i32.eqz + if + i32.const 1 + global.set $~lib/rt/tlsf/collectLock + call $~lib/rt/pure/__collect + i32.const 0 + global.set $~lib/rt/tlsf/collectLock + local.get $0 + local.get $3 + call $~lib/rt/tlsf/searchBlock + local.tee $2 + i32.eqz + if + local.get $0 + local.get $3 + call $~lib/rt/tlsf/growMemory + local.get $0 + local.get $3 + call $~lib/rt/tlsf/searchBlock + local.tee $2 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 502 + i32.const 19 + call $~lib/builtins/abort + unreachable + end + end + end + local.get $2 + i32.load + i32.const -4 + i32.and + local.get $3 + i32.lt_u + if + i32.const 0 + i32.const 32 + i32.const 510 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 0 + i32.store offset=4 + local.get $2 + local.get $1 + i32.store offset=12 + local.get $0 + local.get $2 + call $~lib/rt/tlsf/removeBlock + local.get $0 + local.get $2 + local.get $3 + call $~lib/rt/tlsf/prepareBlock + local.get $2 + call $~lib/rt/rtrace/onalloc + local.get $2 + ) + (func $~lib/rt/tlsf/__alloc (; 20 ;) (param $0 i32) (param $1 i32) (result i32) + call $~lib/rt/tlsf/maybeInitialize + local.get $0 + call $~lib/rt/tlsf/allocateBlock + local.tee $0 + local.get $1 + i32.store offset=8 + local.get $0 + i32.const 16 + i32.add + ) + (func $~lib/rt/pure/increment (; 21 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.tee $1 + i32.const -268435456 + i32.and + local.get $1 + i32.const 1 + i32.add + i32.const -268435456 + i32.and + i32.ne + if + i32.const 0 + i32.const 144 + i32.const 104 + i32.const 2 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $1 + i32.const 1 + i32.add + i32.store offset=4 + local.get $0 + call $~lib/rt/rtrace/onincrement + local.get $0 + i32.load + i32.const 1 + i32.and + if + i32.const 0 + i32.const 144 + i32.const 107 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + ) + (func $~lib/rt/pure/__retain (; 22 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 380 + i32.gt_u + if + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/pure/increment + end + local.get $0 + ) + (func $managed-cast/Cat#constructor (; 23 ;) (result i32) + (local $0 i32) + i32.const 0 + i32.const 3 + call $~lib/rt/tlsf/__alloc + call $~lib/rt/pure/__retain + local.tee $0 + i32.eqz + if + i32.const 0 + i32.const 4 + call $~lib/rt/tlsf/__alloc + call $~lib/rt/pure/__retain + local.set $0 + end + local.get $0 + ) + (func $~lib/rt/__typeinfo (; 24 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 336 + i32.load + i32.gt_u + if + i32.const 192 + i32.const 256 + i32.const 22 + i32.const 27 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.const 3 + i32.shl + i32.const 340 + i32.add + i32.load + ) + (func $~lib/memory/memory.copy (; 25 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + block $~lib/util/memory/memmove|inlined.0 + local.get $2 + local.set $3 + local.get $0 + local.get $1 + i32.eq + br_if $~lib/util/memory/memmove|inlined.0 + local.get $0 + local.get $1 + i32.lt_u + if + local.get $1 + i32.const 7 + i32.and + local.get $0 + i32.const 7 + i32.and + i32.eq + if + loop $while-continue|0 + local.get $0 + i32.const 7 + i32.and + if + local.get $3 + i32.eqz + br_if $~lib/util/memory/memmove|inlined.0 + local.get $3 + i32.const 1 + i32.sub + local.set $3 + local.get $0 + local.tee $2 + i32.const 1 + i32.add + local.set $0 + local.get $1 + local.tee $4 + i32.const 1 + i32.add + local.set $1 + local.get $2 + local.get $4 + i32.load8_u + i32.store8 + br $while-continue|0 + end + end + loop $while-continue|1 + local.get $3 + i32.const 8 + i32.ge_u + if + local.get $0 + local.get $1 + i64.load + i64.store + local.get $3 + i32.const 8 + i32.sub + local.set $3 + local.get $0 + i32.const 8 + i32.add + local.set $0 + local.get $1 + i32.const 8 + i32.add + local.set $1 + br $while-continue|1 + end + end + end + loop $while-continue|2 + local.get $3 + if + local.get $0 + local.tee $2 + i32.const 1 + i32.add + local.set $0 + local.get $1 + local.tee $4 + i32.const 1 + i32.add + local.set $1 + local.get $2 + local.get $4 + i32.load8_u + i32.store8 + local.get $3 + i32.const 1 + i32.sub + local.set $3 + br $while-continue|2 + end + end + else + local.get $1 + i32.const 7 + i32.and + local.get $0 + i32.const 7 + i32.and + i32.eq + if + loop $while-continue|3 + local.get $0 + local.get $3 + i32.add + i32.const 7 + i32.and + if + local.get $3 + i32.eqz + br_if $~lib/util/memory/memmove|inlined.0 + local.get $3 + i32.const 1 + i32.sub + local.tee $3 + local.get $0 + i32.add + local.get $1 + local.get $3 + i32.add + i32.load8_u + i32.store8 + br $while-continue|3 + end + end + loop $while-continue|4 + local.get $3 + i32.const 8 + i32.ge_u + if + local.get $3 + i32.const 8 + i32.sub + local.tee $3 + local.get $0 + i32.add + local.get $1 + local.get $3 + i32.add + i64.load + i64.store + br $while-continue|4 + end + end + end + loop $while-continue|5 + local.get $3 + if + local.get $3 + i32.const 1 + i32.sub + local.tee $3 + local.get $0 + i32.add + local.get $1 + local.get $3 + i32.add + i32.load8_u + i32.store8 + br $while-continue|5 + end + end + end + end + ) + (func $~lib/rt/tlsf/__free (; 26 ;) (param $0 i32) + local.get $0 + i32.const 15 + i32.and + i32.eqz + i32.const 0 + local.get $0 + select + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 593 + i32.const 2 + call $~lib/builtins/abort + unreachable + end + call $~lib/rt/tlsf/maybeInitialize + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/tlsf/freeBlock + ) + (func $~lib/rt/pure/growRoots (; 27 ;) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + global.get $~lib/rt/pure/CUR + global.get $~lib/rt/pure/ROOTS + local.tee $1 + i32.sub + local.tee $2 + i32.const 1 + i32.shl + local.tee $0 + i32.const 256 + local.get $0 + i32.const 256 + i32.gt_u + select + local.tee $3 + i32.const 0 + call $~lib/rt/tlsf/__alloc + local.tee $0 + i32.const 16 + i32.sub + call $~lib/rt/rtrace/onfree + local.get $0 + local.get $1 + local.get $2 + call $~lib/memory/memory.copy + local.get $1 + if + local.get $1 + i32.const 16 + i32.sub + call $~lib/rt/rtrace/onalloc + local.get $1 + call $~lib/rt/tlsf/__free + end + local.get $0 + global.set $~lib/rt/pure/ROOTS + local.get $0 + local.get $2 + i32.add + global.set $~lib/rt/pure/CUR + local.get $0 + local.get $3 + i32.add + global.set $~lib/rt/pure/END + ) + (func $~lib/rt/pure/appendRoot (; 28 ;) (param $0 i32) + (local $1 i32) + global.get $~lib/rt/pure/CUR + local.tee $1 + global.get $~lib/rt/pure/END + i32.ge_u + if + call $~lib/rt/pure/growRoots + global.get $~lib/rt/pure/CUR + local.set $1 + end + local.get $1 + local.get $0 + i32.store + local.get $1 + i32.const 4 + i32.add + global.set $~lib/rt/pure/CUR + ) + (func $~lib/rt/pure/decrement (; 29 ;) (param $0 i32) + (local $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=4 + local.tee $2 + i32.const 268435455 + i32.and + local.set $1 + local.get $0 + call $~lib/rt/rtrace/ondecrement + local.get $0 + i32.load + i32.const 1 + i32.and + if + i32.const 0 + i32.const 144 + i32.const 115 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 1 + i32.eq + if + local.get $0 + i32.const 16 + i32.add + i32.const 1 + call $~lib/rt/__visit_members + local.get $2 + i32.const -2147483648 + i32.and + if + local.get $0 + i32.const -2147483648 + i32.store offset=4 + else + global.get $~lib/rt/tlsf/ROOT + local.get $0 + call $~lib/rt/tlsf/freeBlock + end + else + local.get $1 + i32.const 0 + i32.le_u + if + i32.const 0 + i32.const 144 + i32.const 124 + i32.const 15 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.load offset=8 + call $~lib/rt/__typeinfo + i32.const 16 + i32.and + if + local.get $0 + local.get $1 + i32.const 1 + i32.sub + local.get $2 + i32.const -268435456 + i32.and + i32.or + i32.store offset=4 + else + local.get $0 + local.get $1 + i32.const 1 + i32.sub + i32.const -1342177280 + i32.or + i32.store offset=4 + local.get $2 + i32.const -2147483648 + i32.and + i32.eqz + if + local.get $0 + call $~lib/rt/pure/appendRoot + end + end + end + ) + (func $~lib/rt/pure/__release (; 30 ;) (param $0 i32) + local.get $0 + i32.const 380 + i32.gt_u + if + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/pure/decrement + end + ) + (func $~lib/rt/__instanceof (; 31 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 16 + i32.sub + i32.load offset=8 + local.tee $0 + i32.const 336 + i32.load + i32.le_u + if + loop $do-continue|0 + local.get $0 + i32.const 3 + i32.eq + if + i32.const 1 + return + end + local.get $0 + i32.const 3 + i32.shl + i32.const 340 + i32.add + i32.load offset=4 + local.tee $0 + br_if $do-continue|0 + end + end + i32.const 0 + ) + (func $managed-cast/testUpcastFromNullable (; 32 ;) (param $0 i32) + block $folding-inner0 + local.get $0 + i32.eqz + br_if $folding-inner0 + local.get $0 + call $~lib/rt/__instanceof + i32.eqz + br_if $folding-inner0 + return + end + i32.const 0 + i32.const 304 + i32.const 36 + i32.const 8 + call $~lib/builtins/abort + unreachable + ) + (func $start:managed-cast (; 33 ;) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + call $managed-cast/Cat#constructor + call $managed-cast/Cat#constructor + local.tee $1 + i32.eqz + if + i32.const 0 + i32.const 304 + i32.const 14 + i32.const 11 + call $~lib/builtins/abort + unreachable + end + call $managed-cast/Cat#constructor + local.set $2 + call $managed-cast/Cat#constructor + local.set $3 + call $managed-cast/Cat#constructor + local.tee $4 + call $~lib/rt/__instanceof + i32.eqz + if + i32.const 0 + i32.const 304 + i32.const 31 + i32.const 8 + call $~lib/builtins/abort + unreachable + end + call $managed-cast/Cat#constructor + local.tee $5 + call $managed-cast/testUpcastFromNullable + call $managed-cast/Cat#constructor + local.tee $6 + call $~lib/rt/__instanceof + i32.eqz + if + i32.const 0 + i32.const 304 + i32.const 41 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + call $managed-cast/Cat#constructor + local.tee $7 + call $~lib/rt/__instanceof + i32.eqz + if + i32.const 0 + i32.const 304 + i32.const 47 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + call $~lib/rt/pure/__release + local.get $1 + call $~lib/rt/pure/__release + local.get $2 + call $~lib/rt/pure/__release + local.get $3 + call $~lib/rt/pure/__release + local.get $4 + call $~lib/rt/pure/__release + local.get $5 + call $~lib/rt/pure/__release + local.get $6 + call $~lib/rt/pure/__release + local.get $7 + call $~lib/rt/pure/__release + ) + (func $~start (; 34 ;) + global.get $~started + if + return + else + i32.const 1 + global.set $~started + end + call $start:managed-cast + ) + (func $~lib/rt/pure/__visit (; 35 ;) (param $0 i32) (param $1 i32) + local.get $0 + i32.const 380 + i32.lt_u + if + return + end + local.get $0 + i32.const 16 + i32.sub + local.set $0 + block $break|0 + block $case5|0 + block $case4|0 + block $case3|0 + block $case2|0 + block $case1|0 + local.get $1 + i32.const 1 + i32.ne + if + local.get $1 + i32.const 2 + i32.sub + br_table $case1|0 $case2|0 $case3|0 $case4|0 $case5|0 + end + local.get $0 + call $~lib/rt/pure/decrement + br $break|0 + end + local.get $0 + i32.load offset=4 + i32.const 268435455 + i32.and + i32.const 0 + i32.le_u + if + i32.const 0 + i32.const 144 + i32.const 75 + i32.const 17 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $0 + i32.load offset=4 + i32.const 1 + i32.sub + i32.store offset=4 + local.get $0 + call $~lib/rt/pure/markGray + br $break|0 + end + local.get $0 + call $~lib/rt/pure/scan + br $break|0 + end + local.get $0 + i32.load offset=4 + local.tee $1 + i32.const -268435456 + i32.and + local.get $1 + i32.const 1 + i32.add + i32.const -268435456 + i32.and + i32.ne + if + i32.const 0 + i32.const 144 + i32.const 86 + i32.const 6 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $1 + i32.const 1 + i32.add + i32.store offset=4 + local.get $1 + i32.const 1879048192 + i32.and + if + local.get $0 + call $~lib/rt/pure/scanBlack + end + br $break|0 + end + local.get $0 + call $~lib/rt/pure/collectWhite + br $break|0 + end + i32.const 0 + i32.const 144 + i32.const 97 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + ) + (func $~lib/rt/__visit_members (; 36 ;) (param $0 i32) (param $1 i32) + block $switch$1$default + block $switch$1$case$4 + block $switch$1$case$2 + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $switch$1$case$2 $switch$1$case$2 $switch$1$case$4 $switch$1$case$2 $switch$1$case$2 $switch$1$default + end + return + end + local.get $0 + i32.load + local.tee $0 + if + local.get $0 + local.get $1 + call $~lib/rt/pure/__visit + end + return + end + unreachable + ) +) diff --git a/tests/compiler/managed-cast.ts b/tests/compiler/managed-cast.ts new file mode 100644 index 0000000000..d3ea53b229 --- /dev/null +++ b/tests/compiler/managed-cast.ts @@ -0,0 +1,50 @@ +class Animal { + tame(): void {} +} +class Cat extends Animal { + meow(): void {} +} + +function testDowncast(cat: Cat): void { + (cat).tame(); +} +testDowncast(new Cat()); + +function testDowncastFromNullable(cat: Cat | null): void { + (cat).tame(); +} +testDowncastFromNullable(new Cat()); + +function testDowncastToNullable(cat: Cat): void { + var maybeAnimal = cat; + if (maybeAnimal) maybeAnimal.tame(); +} +testDowncastToNullable(new Cat()); + +function testDowncastFromToNullable(cat: Cat | null): void { + var maybeAnimal = cat; + if (maybeAnimal) maybeAnimal.tame(); +} +testDowncastFromToNullable(new Cat()); + +function testUpcast(animal: Animal): void { + (animal).meow(); +} +testUpcast(new Cat()); + +function testUpcastFromNullable(animal: Animal | null): void { + (animal).meow(); +} +testUpcastFromNullable(new Cat()); + +function testUpcastToNullable(animal: Animal): void { + var maybeCat = animal; + if (maybeCat) maybeCat.meow(); +} +testUpcastToNullable(new Cat()); + +function testUpcastFromToNullable(animal: Animal | null): void { + var maybeCat = animal; + if (maybeCat) maybeCat.meow(); +} +testUpcastFromToNullable(new Cat()); diff --git a/tests/compiler/managed-cast.untouched.wat b/tests/compiler/managed-cast.untouched.wat new file mode 100644 index 0000000000..e67dc6eab6 --- /dev/null +++ b/tests/compiler/managed-cast.untouched.wat @@ -0,0 +1,3725 @@ +(module + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) + (import "rtrace" "onfree" (func $~lib/rt/rtrace/onfree (param i32))) + (import "rtrace" "onalloc" (func $~lib/rt/rtrace/onalloc (param i32))) + (import "rtrace" "onincrement" (func $~lib/rt/rtrace/onincrement (param i32))) + (import "rtrace" "ondecrement" (func $~lib/rt/rtrace/ondecrement (param i32))) + (memory $0 1) + (data (i32.const 16) "\1e\00\00\00\01\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s\00") + (data (i32.const 64) "(\00\00\00\01\00\00\00\01\00\00\00(\00\00\00a\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e\00") + (data (i32.const 128) "\1e\00\00\00\01\00\00\00\01\00\00\00\1e\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00p\00u\00r\00e\00.\00t\00s\00") + (data (i32.const 176) "$\00\00\00\01\00\00\00\01\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00") + (data (i32.const 240) "\14\00\00\00\01\00\00\00\01\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s\00") + (data (i32.const 288) "\1e\00\00\00\01\00\00\00\01\00\00\00\1e\00\00\00m\00a\00n\00a\00g\00e\00d\00-\00c\00a\00s\00t\00.\00t\00s\00") + (data (i32.const 336) "\05\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\04\00\00\00\10\00\00\00\00\00\00\00") + (table $0 1 funcref) + (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) + (global $~lib/rt/tlsf/collectLock (mut i32) (i32.const 0)) + (global $~lib/gc/gc.auto (mut i32) (i32.const 1)) + (global $~lib/rt/pure/ROOTS (mut i32) (i32.const 0)) + (global $~lib/rt/pure/CUR (mut i32) (i32.const 0)) + (global $~lib/rt/pure/END (mut i32) (i32.const 0)) + (global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0)) + (global $~started (mut i32) (i32.const 0)) + (global $~lib/rt/__rtti_base i32 (i32.const 336)) + (global $~lib/heap/__heap_base i32 (i32.const 380)) + (export "_start" (func $~start)) + (export "memory" (memory $0)) + (func $~lib/rt/tlsf/removeBlock (; 5 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + local.get $1 + i32.load + local.set $2 + local.get $2 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 277 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.set $3 + local.get $3 + i32.const 16 + i32.ge_u + if (result i32) + local.get $3 + i32.const 1073741808 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 279 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const 256 + i32.lt_u + if + i32.const 0 + local.set $4 + local.get $3 + i32.const 4 + i32.shr_u + local.set $5 + else + i32.const 31 + local.get $3 + i32.clz + i32.sub + local.set $4 + local.get $3 + local.get $4 + i32.const 4 + i32.sub + i32.shr_u + i32.const 1 + i32.const 4 + i32.shl + i32.xor + local.set $5 + local.get $4 + i32.const 8 + i32.const 1 + i32.sub + i32.sub + local.set $4 + end + local.get $4 + i32.const 23 + i32.lt_u + if (result i32) + local.get $5 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 292 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load offset=16 + local.set $6 + local.get $1 + i32.load offset=20 + local.set $7 + local.get $6 + if + local.get $6 + local.get $7 + i32.store offset=20 + end + local.get $7 + if + local.get $7 + local.get $6 + i32.store offset=16 + end + local.get $1 + local.get $0 + local.set $10 + local.get $4 + local.set $9 + local.get $5 + local.set $8 + local.get $10 + local.get $9 + i32.const 4 + i32.shl + local.get $8 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + i32.eq + if + local.get $0 + local.set $11 + local.get $4 + local.set $10 + local.get $5 + local.set $9 + local.get $7 + local.set $8 + local.get $11 + local.get $10 + i32.const 4 + i32.shl + local.get $9 + i32.add + i32.const 2 + i32.shl + i32.add + local.get $8 + i32.store offset=96 + local.get $7 + i32.eqz + if + local.get $0 + local.set $9 + local.get $4 + local.set $8 + local.get $9 + local.get $8 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + local.set $9 + local.get $0 + local.set $8 + local.get $4 + local.set $11 + local.get $9 + i32.const 1 + local.get $5 + i32.shl + i32.const -1 + i32.xor + i32.and + local.tee $9 + local.set $10 + local.get $8 + local.get $11 + i32.const 2 + i32.shl + i32.add + local.get $10 + i32.store offset=4 + local.get $9 + i32.eqz + if + local.get $0 + local.get $0 + i32.load + i32.const 1 + local.get $4 + i32.shl + i32.const -1 + i32.xor + i32.and + i32.store + end + end + end + ) + (func $~lib/rt/tlsf/insertBlock (; 6 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + local.get $1 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 205 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.load + local.set $2 + local.get $2 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 207 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + local.set $3 + local.get $3 + i32.const 16 + i32.add + local.get $3 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.set $4 + local.get $4 + i32.load + local.set $5 + local.get $5 + i32.const 1 + i32.and + if + local.get $2 + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.add + local.get $5 + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.set $3 + local.get $3 + i32.const 1073741808 + i32.lt_u + if + local.get $0 + local.get $4 + call $~lib/rt/tlsf/removeBlock + local.get $1 + local.get $2 + i32.const 3 + i32.and + local.get $3 + i32.or + local.tee $2 + i32.store + local.get $1 + local.set $6 + local.get $6 + i32.const 16 + i32.add + local.get $6 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.set $4 + local.get $4 + i32.load + local.set $5 + end + end + local.get $2 + i32.const 2 + i32.and + if + local.get $1 + local.set $6 + local.get $6 + i32.const 4 + i32.sub + i32.load + local.set $6 + local.get $6 + i32.load + local.set $3 + local.get $3 + i32.const 1 + i32.and + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 228 + i32.const 15 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.add + local.get $2 + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.set $7 + local.get $7 + i32.const 1073741808 + i32.lt_u + if + local.get $0 + local.get $6 + call $~lib/rt/tlsf/removeBlock + local.get $6 + local.get $3 + i32.const 3 + i32.and + local.get $7 + i32.or + local.tee $2 + i32.store + local.get $6 + local.set $1 + end + end + local.get $4 + local.get $5 + i32.const 2 + i32.or + i32.store + local.get $2 + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.set $8 + local.get $8 + i32.const 16 + i32.ge_u + if (result i32) + local.get $8 + i32.const 1073741808 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 243 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 16 + i32.add + local.get $8 + i32.add + local.get $4 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 244 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $4 + i32.const 4 + i32.sub + local.get $1 + i32.store + local.get $8 + i32.const 256 + i32.lt_u + if + i32.const 0 + local.set $9 + local.get $8 + i32.const 4 + i32.shr_u + local.set $10 + else + i32.const 31 + local.get $8 + i32.clz + i32.sub + local.set $9 + local.get $8 + local.get $9 + i32.const 4 + i32.sub + i32.shr_u + i32.const 1 + i32.const 4 + i32.shl + i32.xor + local.set $10 + local.get $9 + i32.const 8 + i32.const 1 + i32.sub + i32.sub + local.set $9 + end + local.get $9 + i32.const 23 + i32.lt_u + if (result i32) + local.get $10 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 260 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.set $7 + local.get $9 + local.set $3 + local.get $10 + local.set $6 + local.get $7 + local.get $3 + i32.const 4 + i32.shl + local.get $6 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + local.set $11 + local.get $1 + i32.const 0 + i32.store offset=16 + local.get $1 + local.get $11 + i32.store offset=20 + local.get $11 + if + local.get $11 + local.get $1 + i32.store offset=16 + end + local.get $0 + local.set $12 + local.get $9 + local.set $7 + local.get $10 + local.set $3 + local.get $1 + local.set $6 + local.get $12 + local.get $7 + i32.const 4 + i32.shl + local.get $3 + i32.add + i32.const 2 + i32.shl + i32.add + local.get $6 + i32.store offset=96 + local.get $0 + local.get $0 + i32.load + i32.const 1 + local.get $9 + i32.shl + i32.or + i32.store + local.get $0 + local.set $13 + local.get $9 + local.set $12 + local.get $0 + local.set $3 + local.get $9 + local.set $6 + local.get $3 + local.get $6 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + i32.const 1 + local.get $10 + i32.shl + i32.or + local.set $7 + local.get $13 + local.get $12 + i32.const 2 + i32.shl + i32.add + local.get $7 + i32.store offset=4 + ) + (func $~lib/rt/tlsf/addMemory (; 7 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + local.get $1 + local.get $2 + i32.le_u + if (result i32) + local.get $1 + i32.const 15 + i32.and + i32.eqz + else + i32.const 0 + end + if (result i32) + local.get $2 + i32.const 15 + i32.and + i32.eqz + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 386 + i32.const 4 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.set $3 + local.get $3 + i32.load offset=1568 + local.set $4 + i32.const 0 + local.set $5 + local.get $4 + if + local.get $1 + local.get $4 + i32.const 16 + i32.add + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 396 + i32.const 15 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 16 + i32.sub + local.get $4 + i32.eq + if + local.get $1 + i32.const 16 + i32.sub + local.set $1 + local.get $4 + i32.load + local.set $5 + else + nop + end + else + local.get $1 + local.get $0 + i32.const 1572 + i32.add + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 408 + i32.const 4 + call $~lib/builtins/abort + unreachable + end + end + local.get $2 + local.get $1 + i32.sub + local.set $6 + local.get $6 + i32.const 48 + i32.lt_u + if + i32.const 0 + return + end + local.get $6 + i32.const 16 + i32.const 1 + i32.shl + i32.sub + local.set $7 + local.get $1 + local.set $8 + local.get $8 + local.get $7 + i32.const 1 + i32.or + local.get $5 + i32.const 2 + i32.and + i32.or + i32.store + local.get $8 + i32.const 0 + i32.store offset=16 + local.get $8 + i32.const 0 + i32.store offset=20 + local.get $1 + local.get $6 + i32.add + i32.const 16 + i32.sub + local.set $4 + local.get $4 + i32.const 0 + i32.const 2 + i32.or + i32.store + local.get $0 + local.set $9 + local.get $4 + local.set $3 + local.get $9 + local.get $3 + i32.store offset=1568 + local.get $0 + local.get $8 + call $~lib/rt/tlsf/insertBlock + i32.const 1 + ) + (func $~lib/rt/tlsf/maybeInitialize (; 8 ;) (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + global.get $~lib/rt/tlsf/ROOT + local.set $0 + local.get $0 + i32.eqz + if + global.get $~lib/heap/__heap_base + i32.const 15 + i32.add + i32.const -16 + i32.and + local.set $1 + memory.size + local.set $2 + local.get $1 + i32.const 1572 + i32.add + i32.const 65535 + i32.add + i32.const 65535 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.shr_u + local.set $3 + local.get $3 + local.get $2 + i32.gt_s + if (result i32) + local.get $3 + local.get $2 + i32.sub + memory.grow + i32.const 0 + i32.lt_s + else + i32.const 0 + end + if + unreachable + end + local.get $1 + local.set $0 + local.get $0 + i32.const 0 + i32.store + local.get $0 + local.set $5 + i32.const 0 + local.set $4 + local.get $5 + local.get $4 + i32.store offset=1568 + i32.const 0 + local.set $5 + loop $for-loop|0 + local.get $5 + i32.const 23 + i32.lt_u + local.set $4 + local.get $4 + if + local.get $0 + local.set $8 + local.get $5 + local.set $7 + i32.const 0 + local.set $6 + local.get $8 + local.get $7 + i32.const 2 + i32.shl + i32.add + local.get $6 + i32.store offset=4 + i32.const 0 + local.set $8 + loop $for-loop|1 + local.get $8 + i32.const 16 + i32.lt_u + local.set $7 + local.get $7 + if + local.get $0 + local.set $11 + local.get $5 + local.set $10 + local.get $8 + local.set $9 + i32.const 0 + local.set $6 + local.get $11 + local.get $10 + i32.const 4 + i32.shl + local.get $9 + i32.add + i32.const 2 + i32.shl + i32.add + local.get $6 + i32.store offset=96 + local.get $8 + i32.const 1 + i32.add + local.set $8 + br $for-loop|1 + end + end + local.get $5 + i32.const 1 + i32.add + local.set $5 + br $for-loop|0 + end + end + local.get $0 + local.get $1 + i32.const 1572 + i32.add + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + memory.size + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + drop + local.get $0 + global.set $~lib/rt/tlsf/ROOT + end + local.get $0 + ) + (func $~lib/rt/tlsf/prepareSize (; 9 ;) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + local.get $0 + i32.const 1073741808 + i32.ge_u + if + i32.const 80 + i32.const 32 + i32.const 457 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.const 15 + i32.add + i32.const 15 + i32.const -1 + i32.xor + i32.and + local.tee $1 + i32.const 16 + local.tee $2 + local.get $1 + local.get $2 + i32.gt_u + select + ) + (func $~lib/rt/tlsf/searchBlock (; 10 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + local.get $1 + i32.const 256 + i32.lt_u + if + i32.const 0 + local.set $2 + local.get $1 + i32.const 4 + i32.shr_u + local.set $3 + else + local.get $1 + i32.const 536870904 + i32.lt_u + if (result i32) + local.get $1 + i32.const 1 + i32.const 27 + local.get $1 + i32.clz + i32.sub + i32.shl + i32.add + i32.const 1 + i32.sub + else + local.get $1 + end + local.set $4 + i32.const 31 + local.get $4 + i32.clz + i32.sub + local.set $2 + local.get $4 + local.get $2 + i32.const 4 + i32.sub + i32.shr_u + i32.const 1 + i32.const 4 + i32.shl + i32.xor + local.set $3 + local.get $2 + i32.const 8 + i32.const 1 + i32.sub + i32.sub + local.set $2 + end + local.get $2 + i32.const 23 + i32.lt_u + if (result i32) + local.get $3 + i32.const 16 + i32.lt_u + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 338 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.set $5 + local.get $2 + local.set $4 + local.get $5 + local.get $4 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + i32.const 0 + i32.const -1 + i32.xor + local.get $3 + i32.shl + i32.and + local.set $6 + i32.const 0 + local.set $7 + local.get $6 + i32.eqz + if + local.get $0 + i32.load + i32.const 0 + i32.const -1 + i32.xor + local.get $2 + i32.const 1 + i32.add + i32.shl + i32.and + local.set $5 + local.get $5 + i32.eqz + if + i32.const 0 + local.set $7 + else + local.get $5 + i32.ctz + local.set $2 + local.get $0 + local.set $8 + local.get $2 + local.set $4 + local.get $8 + local.get $4 + i32.const 2 + i32.shl + i32.add + i32.load offset=4 + local.set $6 + local.get $6 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 351 + i32.const 17 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.set $9 + local.get $2 + local.set $8 + local.get $6 + i32.ctz + local.set $4 + local.get $9 + local.get $8 + i32.const 4 + i32.shl + local.get $4 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + local.set $7 + end + else + local.get $0 + local.set $9 + local.get $2 + local.set $8 + local.get $6 + i32.ctz + local.set $4 + local.get $9 + local.get $8 + i32.const 4 + i32.shl + local.get $4 + i32.add + i32.const 2 + i32.shl + i32.add + i32.load offset=96 + local.set $7 + end + local.get $7 + ) + (func $~lib/rt/pure/markGray (; 11 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.set $1 + local.get $1 + i32.const 1879048192 + i32.and + i32.const 268435456 + i32.ne + if + local.get $0 + local.get $1 + i32.const 1879048192 + i32.const -1 + i32.xor + i32.and + i32.const 268435456 + i32.or + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 2 + call $~lib/rt/__visit_members + end + ) + (func $~lib/rt/tlsf/freeBlock (; 12 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + local.get $1 + i32.load + local.set $2 + local.get $2 + i32.const 1 + i32.and + i32.eqz + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 569 + i32.const 2 + call $~lib/builtins/abort + unreachable + end + local.get $1 + local.get $2 + i32.const 1 + i32.or + i32.store + local.get $0 + local.get $1 + call $~lib/rt/tlsf/insertBlock + local.get $1 + call $~lib/rt/rtrace/onfree + ) + (func $~lib/rt/pure/scanBlack (; 13 ;) (param $0 i32) + local.get $0 + local.get $0 + i32.load offset=4 + i32.const 1879048192 + i32.const -1 + i32.xor + i32.and + i32.const 0 + i32.or + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 4 + call $~lib/rt/__visit_members + ) + (func $~lib/rt/pure/scan (; 14 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.set $1 + local.get $1 + i32.const 1879048192 + i32.and + i32.const 268435456 + i32.eq + if + local.get $1 + i32.const 268435455 + i32.and + i32.const 0 + i32.gt_u + if + local.get $0 + call $~lib/rt/pure/scanBlack + else + local.get $0 + local.get $1 + i32.const 1879048192 + i32.const -1 + i32.xor + i32.and + i32.const 536870912 + i32.or + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 3 + call $~lib/rt/__visit_members + end + end + ) + (func $~lib/rt/pure/collectWhite (; 15 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.set $1 + local.get $1 + i32.const 1879048192 + i32.and + i32.const 536870912 + i32.eq + if (result i32) + local.get $1 + i32.const -2147483648 + i32.and + i32.eqz + else + i32.const 0 + end + if + local.get $0 + local.get $1 + i32.const 1879048192 + i32.const -1 + i32.xor + i32.and + i32.const 0 + i32.or + i32.store offset=4 + local.get $0 + i32.const 16 + i32.add + i32.const 5 + call $~lib/rt/__visit_members + global.get $~lib/rt/tlsf/ROOT + local.get $0 + call $~lib/rt/tlsf/freeBlock + end + ) + (func $~lib/rt/pure/__collect (; 16 ;) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + global.get $~lib/rt/pure/ROOTS + local.set $0 + local.get $0 + local.set $1 + local.get $1 + local.set $2 + global.get $~lib/rt/pure/CUR + local.set $3 + loop $for-loop|0 + local.get $2 + local.get $3 + i32.lt_u + local.set $4 + local.get $4 + if + local.get $2 + i32.load + local.set $5 + local.get $5 + i32.load offset=4 + local.set $6 + local.get $6 + i32.const 1879048192 + i32.and + i32.const 805306368 + i32.eq + if (result i32) + local.get $6 + i32.const 268435455 + i32.and + i32.const 0 + i32.gt_u + else + i32.const 0 + end + if + local.get $5 + call $~lib/rt/pure/markGray + local.get $1 + local.get $5 + i32.store + local.get $1 + i32.const 4 + i32.add + local.set $1 + else + local.get $6 + i32.const 1879048192 + i32.and + i32.const 0 + i32.eq + if (result i32) + local.get $6 + i32.const 268435455 + i32.and + i32.eqz + else + i32.const 0 + end + if + global.get $~lib/rt/tlsf/ROOT + local.get $5 + call $~lib/rt/tlsf/freeBlock + else + local.get $5 + local.get $6 + i32.const -2147483648 + i32.const -1 + i32.xor + i32.and + i32.store offset=4 + end + end + local.get $2 + i32.const 4 + i32.add + local.set $2 + br $for-loop|0 + end + end + local.get $1 + global.set $~lib/rt/pure/CUR + local.get $0 + local.set $3 + loop $for-loop|1 + local.get $3 + local.get $1 + i32.lt_u + local.set $2 + local.get $2 + if + local.get $3 + i32.load + call $~lib/rt/pure/scan + local.get $3 + i32.const 4 + i32.add + local.set $3 + br $for-loop|1 + end + end + local.get $0 + local.set $3 + loop $for-loop|2 + local.get $3 + local.get $1 + i32.lt_u + local.set $2 + local.get $2 + if + local.get $3 + i32.load + local.set $4 + local.get $4 + local.get $4 + i32.load offset=4 + i32.const -2147483648 + i32.const -1 + i32.xor + i32.and + i32.store offset=4 + local.get $4 + call $~lib/rt/pure/collectWhite + local.get $3 + i32.const 4 + i32.add + local.set $3 + br $for-loop|2 + end + end + local.get $0 + global.set $~lib/rt/pure/CUR + ) + (func $~lib/rt/tlsf/growMemory (; 17 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + local.get $1 + i32.const 536870904 + i32.lt_u + if + local.get $1 + i32.const 1 + i32.const 27 + local.get $1 + i32.clz + i32.sub + i32.shl + i32.const 1 + i32.sub + i32.add + local.set $1 + end + memory.size + local.set $2 + local.get $1 + i32.const 16 + local.get $2 + i32.const 16 + i32.shl + i32.const 16 + i32.sub + local.get $0 + local.set $3 + local.get $3 + i32.load offset=1568 + i32.ne + i32.shl + i32.add + local.set $1 + local.get $1 + i32.const 65535 + i32.add + i32.const 65535 + i32.const -1 + i32.xor + i32.and + i32.const 16 + i32.shr_u + local.set $4 + local.get $2 + local.tee $3 + local.get $4 + local.tee $5 + local.get $3 + local.get $5 + i32.gt_s + select + local.set $6 + local.get $6 + memory.grow + i32.const 0 + i32.lt_s + if + local.get $4 + memory.grow + i32.const 0 + i32.lt_s + if + unreachable + end + end + memory.size + local.set $7 + local.get $0 + local.get $2 + i32.const 16 + i32.shl + local.get $7 + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + drop + ) + (func $~lib/rt/tlsf/prepareBlock (; 18 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + local.get $1 + i32.load + local.set $3 + local.get $2 + i32.const 15 + i32.and + i32.eqz + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 365 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const 3 + i32.const -1 + i32.xor + i32.and + local.get $2 + i32.sub + local.set $4 + local.get $4 + i32.const 32 + i32.ge_u + if + local.get $1 + local.get $2 + local.get $3 + i32.const 2 + i32.and + i32.or + i32.store + local.get $1 + i32.const 16 + i32.add + local.get $2 + i32.add + local.set $5 + local.get $5 + local.get $4 + i32.const 16 + i32.sub + i32.const 1 + i32.or + i32.store + local.get $0 + local.get $5 + call $~lib/rt/tlsf/insertBlock + else + local.get $1 + local.get $3 + i32.const 1 + i32.const -1 + i32.xor + i32.and + i32.store + local.get $1 + local.set $5 + local.get $5 + i32.const 16 + i32.add + local.get $5 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + local.get $1 + local.set $5 + local.get $5 + i32.const 16 + i32.add + local.get $5 + i32.load + i32.const 3 + i32.const -1 + i32.xor + i32.and + i32.add + i32.load + i32.const 2 + i32.const -1 + i32.xor + i32.and + i32.store + end + ) + (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + global.get $~lib/rt/tlsf/collectLock + i32.eqz + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 490 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $1 + call $~lib/rt/tlsf/prepareSize + local.set $2 + local.get $0 + local.get $2 + call $~lib/rt/tlsf/searchBlock + local.set $3 + local.get $3 + i32.eqz + if + global.get $~lib/gc/gc.auto + if + i32.const 1 + global.set $~lib/rt/tlsf/collectLock + call $~lib/rt/pure/__collect + i32.const 0 + global.set $~lib/rt/tlsf/collectLock + local.get $0 + local.get $2 + call $~lib/rt/tlsf/searchBlock + local.set $3 + local.get $3 + i32.eqz + if + local.get $0 + local.get $2 + call $~lib/rt/tlsf/growMemory + local.get $0 + local.get $2 + call $~lib/rt/tlsf/searchBlock + local.set $3 + local.get $3 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 502 + i32.const 19 + call $~lib/builtins/abort + unreachable + end + end + else + local.get $0 + local.get $2 + call $~lib/rt/tlsf/growMemory + local.get $0 + local.get $2 + call $~lib/rt/tlsf/searchBlock + local.set $3 + local.get $3 + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 507 + i32.const 17 + call $~lib/builtins/abort + unreachable + end + end + end + local.get $3 + i32.load + i32.const -4 + i32.and + local.get $2 + i32.ge_u + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 510 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $3 + i32.const 0 + i32.store offset=4 + local.get $3 + local.get $1 + i32.store offset=12 + local.get $0 + local.get $3 + call $~lib/rt/tlsf/removeBlock + local.get $0 + local.get $3 + local.get $2 + call $~lib/rt/tlsf/prepareBlock + local.get $3 + call $~lib/rt/rtrace/onalloc + local.get $3 + ) + (func $~lib/rt/tlsf/__alloc (; 20 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + call $~lib/rt/tlsf/maybeInitialize + local.get $0 + call $~lib/rt/tlsf/allocateBlock + local.set $2 + local.get $2 + local.get $1 + i32.store offset=8 + local.get $2 + i32.const 16 + i32.add + ) + (func $~lib/rt/pure/increment (; 21 ;) (param $0 i32) + (local $1 i32) + local.get $0 + i32.load offset=4 + local.set $1 + local.get $1 + i32.const -268435456 + i32.and + local.get $1 + i32.const 1 + i32.add + i32.const -268435456 + i32.and + i32.eq + i32.eqz + if + i32.const 0 + i32.const 144 + i32.const 104 + i32.const 2 + call $~lib/builtins/abort + unreachable + end + local.get $0 + local.get $1 + i32.const 1 + i32.add + i32.store offset=4 + local.get $0 + call $~lib/rt/rtrace/onincrement + local.get $0 + i32.load + i32.const 1 + i32.and + i32.eqz + i32.eqz + if + i32.const 0 + i32.const 144 + i32.const 107 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + ) + (func $~lib/rt/pure/__retain (; 22 ;) (param $0 i32) (result i32) + local.get $0 + global.get $~lib/heap/__heap_base + i32.gt_u + if + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/pure/increment + end + local.get $0 + ) + (func $managed-cast/Animal#constructor (; 23 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 4 + call $~lib/rt/tlsf/__alloc + call $~lib/rt/pure/__retain + local.set $0 + end + local.get $0 + ) + (func $managed-cast/Cat#constructor (; 24 ;) (param $0 i32) (result i32) + local.get $0 + i32.eqz + if + i32.const 0 + i32.const 3 + call $~lib/rt/tlsf/__alloc + call $~lib/rt/pure/__retain + local.set $0 + end + local.get $0 + call $managed-cast/Animal#constructor + local.set $0 + local.get $0 + ) + (func $managed-cast/Animal#tame (; 25 ;) (param $0 i32) + nop + ) + (func $~lib/rt/__typeinfo (; 26 ;) (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/rt/__rtti_base + local.set $1 + local.get $0 + local.get $1 + i32.load + i32.gt_u + if + i32.const 192 + i32.const 256 + i32.const 22 + i32.const 27 + call $~lib/builtins/abort + unreachable + end + local.get $1 + i32.const 4 + i32.add + local.get $0 + i32.const 8 + i32.mul + i32.add + i32.load + ) + (func $~lib/util/memory/memcpy (; 27 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + loop $while-continue|0 + local.get $2 + if (result i32) + local.get $1 + i32.const 3 + i32.and + else + i32.const 0 + end + local.set $5 + local.get $5 + if + local.get $0 + local.tee $6 + i32.const 1 + i32.add + local.set $0 + local.get $6 + local.get $1 + local.tee $6 + i32.const 1 + i32.add + local.set $1 + local.get $6 + i32.load8_u + i32.store8 + local.get $2 + i32.const 1 + i32.sub + local.set $2 + br $while-continue|0 + end + end + local.get $0 + i32.const 3 + i32.and + i32.const 0 + i32.eq + if + loop $while-continue|1 + local.get $2 + i32.const 16 + i32.ge_u + local.set $5 + local.get $5 + if + local.get $0 + local.get $1 + i32.load + i32.store + local.get $0 + i32.const 4 + i32.add + local.get $1 + i32.const 4 + i32.add + i32.load + i32.store + local.get $0 + i32.const 8 + i32.add + local.get $1 + i32.const 8 + i32.add + i32.load + i32.store + local.get $0 + i32.const 12 + i32.add + local.get $1 + i32.const 12 + i32.add + i32.load + i32.store + local.get $1 + i32.const 16 + i32.add + local.set $1 + local.get $0 + i32.const 16 + i32.add + local.set $0 + local.get $2 + i32.const 16 + i32.sub + local.set $2 + br $while-continue|1 + end + end + local.get $2 + i32.const 8 + i32.and + if + local.get $0 + local.get $1 + i32.load + i32.store + local.get $0 + i32.const 4 + i32.add + local.get $1 + i32.const 4 + i32.add + i32.load + i32.store + local.get $0 + i32.const 8 + i32.add + local.set $0 + local.get $1 + i32.const 8 + i32.add + local.set $1 + end + local.get $2 + i32.const 4 + i32.and + if + local.get $0 + local.get $1 + i32.load + i32.store + local.get $0 + i32.const 4 + i32.add + local.set $0 + local.get $1 + i32.const 4 + i32.add + local.set $1 + end + local.get $2 + i32.const 2 + i32.and + if + local.get $0 + local.get $1 + i32.load16_u + i32.store16 + local.get $0 + i32.const 2 + i32.add + local.set $0 + local.get $1 + i32.const 2 + i32.add + local.set $1 + end + local.get $2 + i32.const 1 + i32.and + if + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + end + return + end + local.get $2 + i32.const 32 + i32.ge_u + if + block $break|2 + block $case2|2 + block $case1|2 + block $case0|2 + local.get $0 + i32.const 3 + i32.and + local.set $5 + local.get $5 + i32.const 1 + i32.eq + br_if $case0|2 + local.get $5 + i32.const 2 + i32.eq + br_if $case1|2 + local.get $5 + i32.const 3 + i32.eq + br_if $case2|2 + br $break|2 + end + local.get $1 + i32.load + local.set $3 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $2 + i32.const 3 + i32.sub + local.set $2 + loop $while-continue|3 + local.get $2 + i32.const 17 + i32.ge_u + local.set $5 + local.get $5 + if + local.get $1 + i32.const 1 + i32.add + i32.load + local.set $4 + local.get $0 + local.get $3 + i32.const 24 + i32.shr_u + local.get $4 + i32.const 8 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 5 + i32.add + i32.load + local.set $3 + local.get $0 + i32.const 4 + i32.add + local.get $4 + i32.const 24 + i32.shr_u + local.get $3 + i32.const 8 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 9 + i32.add + i32.load + local.set $4 + local.get $0 + i32.const 8 + i32.add + local.get $3 + i32.const 24 + i32.shr_u + local.get $4 + i32.const 8 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 13 + i32.add + i32.load + local.set $3 + local.get $0 + i32.const 12 + i32.add + local.get $4 + i32.const 24 + i32.shr_u + local.get $3 + i32.const 8 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 16 + i32.add + local.set $1 + local.get $0 + i32.const 16 + i32.add + local.set $0 + local.get $2 + i32.const 16 + i32.sub + local.set $2 + br $while-continue|3 + end + end + br $break|2 + end + local.get $1 + i32.load + local.set $3 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $2 + i32.const 2 + i32.sub + local.set $2 + loop $while-continue|4 + local.get $2 + i32.const 18 + i32.ge_u + local.set $5 + local.get $5 + if + local.get $1 + i32.const 2 + i32.add + i32.load + local.set $4 + local.get $0 + local.get $3 + i32.const 16 + i32.shr_u + local.get $4 + i32.const 16 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 6 + i32.add + i32.load + local.set $3 + local.get $0 + i32.const 4 + i32.add + local.get $4 + i32.const 16 + i32.shr_u + local.get $3 + i32.const 16 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 10 + i32.add + i32.load + local.set $4 + local.get $0 + i32.const 8 + i32.add + local.get $3 + i32.const 16 + i32.shr_u + local.get $4 + i32.const 16 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 14 + i32.add + i32.load + local.set $3 + local.get $0 + i32.const 12 + i32.add + local.get $4 + i32.const 16 + i32.shr_u + local.get $3 + i32.const 16 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 16 + i32.add + local.set $1 + local.get $0 + i32.const 16 + i32.add + local.set $0 + local.get $2 + i32.const 16 + i32.sub + local.set $2 + br $while-continue|4 + end + end + br $break|2 + end + local.get $1 + i32.load + local.set $3 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $2 + i32.const 1 + i32.sub + local.set $2 + loop $while-continue|5 + local.get $2 + i32.const 19 + i32.ge_u + local.set $5 + local.get $5 + if + local.get $1 + i32.const 3 + i32.add + i32.load + local.set $4 + local.get $0 + local.get $3 + i32.const 8 + i32.shr_u + local.get $4 + i32.const 24 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 7 + i32.add + i32.load + local.set $3 + local.get $0 + i32.const 4 + i32.add + local.get $4 + i32.const 8 + i32.shr_u + local.get $3 + i32.const 24 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 11 + i32.add + i32.load + local.set $4 + local.get $0 + i32.const 8 + i32.add + local.get $3 + i32.const 8 + i32.shr_u + local.get $4 + i32.const 24 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 15 + i32.add + i32.load + local.set $3 + local.get $0 + i32.const 12 + i32.add + local.get $4 + i32.const 8 + i32.shr_u + local.get $3 + i32.const 24 + i32.shl + i32.or + i32.store + local.get $1 + i32.const 16 + i32.add + local.set $1 + local.get $0 + i32.const 16 + i32.add + local.set $0 + local.get $2 + i32.const 16 + i32.sub + local.set $2 + br $while-continue|5 + end + end + br $break|2 + end + end + local.get $2 + i32.const 16 + i32.and + if + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + end + local.get $2 + i32.const 8 + i32.and + if + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + end + local.get $2 + i32.const 4 + i32.and + if + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + end + local.get $2 + i32.const 2 + i32.and + if + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + end + local.get $2 + i32.const 1 + i32.and + if + local.get $0 + local.tee $5 + i32.const 1 + i32.add + local.set $0 + local.get $5 + local.get $1 + local.tee $5 + i32.const 1 + i32.add + local.set $1 + local.get $5 + i32.load8_u + i32.store8 + end + ) + (func $~lib/memory/memory.copy (; 28 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + block $~lib/util/memory/memmove|inlined.0 + local.get $0 + local.set $5 + local.get $1 + local.set $4 + local.get $2 + local.set $3 + local.get $5 + local.get $4 + i32.eq + if + br $~lib/util/memory/memmove|inlined.0 + end + local.get $4 + local.get $3 + i32.add + local.get $5 + i32.le_u + if (result i32) + i32.const 1 + else + local.get $5 + local.get $3 + i32.add + local.get $4 + i32.le_u + end + if + local.get $5 + local.get $4 + local.get $3 + call $~lib/util/memory/memcpy + br $~lib/util/memory/memmove|inlined.0 + end + local.get $5 + local.get $4 + i32.lt_u + if + local.get $4 + i32.const 7 + i32.and + local.get $5 + i32.const 7 + i32.and + i32.eq + if + loop $while-continue|0 + local.get $5 + i32.const 7 + i32.and + local.set $6 + local.get $6 + if + local.get $3 + i32.eqz + if + br $~lib/util/memory/memmove|inlined.0 + end + local.get $3 + i32.const 1 + i32.sub + local.set $3 + local.get $5 + local.tee $7 + i32.const 1 + i32.add + local.set $5 + local.get $7 + local.get $4 + local.tee $7 + i32.const 1 + i32.add + local.set $4 + local.get $7 + i32.load8_u + i32.store8 + br $while-continue|0 + end + end + loop $while-continue|1 + local.get $3 + i32.const 8 + i32.ge_u + local.set $6 + local.get $6 + if + local.get $5 + local.get $4 + i64.load + i64.store + local.get $3 + i32.const 8 + i32.sub + local.set $3 + local.get $5 + i32.const 8 + i32.add + local.set $5 + local.get $4 + i32.const 8 + i32.add + local.set $4 + br $while-continue|1 + end + end + end + loop $while-continue|2 + local.get $3 + local.set $6 + local.get $6 + if + local.get $5 + local.tee $7 + i32.const 1 + i32.add + local.set $5 + local.get $7 + local.get $4 + local.tee $7 + i32.const 1 + i32.add + local.set $4 + local.get $7 + i32.load8_u + i32.store8 + local.get $3 + i32.const 1 + i32.sub + local.set $3 + br $while-continue|2 + end + end + else + local.get $4 + i32.const 7 + i32.and + local.get $5 + i32.const 7 + i32.and + i32.eq + if + loop $while-continue|3 + local.get $5 + local.get $3 + i32.add + i32.const 7 + i32.and + local.set $6 + local.get $6 + if + local.get $3 + i32.eqz + if + br $~lib/util/memory/memmove|inlined.0 + end + local.get $5 + local.get $3 + i32.const 1 + i32.sub + local.tee $3 + i32.add + local.get $4 + local.get $3 + i32.add + i32.load8_u + i32.store8 + br $while-continue|3 + end + end + loop $while-continue|4 + local.get $3 + i32.const 8 + i32.ge_u + local.set $6 + local.get $6 + if + local.get $3 + i32.const 8 + i32.sub + local.set $3 + local.get $5 + local.get $3 + i32.add + local.get $4 + local.get $3 + i32.add + i64.load + i64.store + br $while-continue|4 + end + end + end + loop $while-continue|5 + local.get $3 + local.set $6 + local.get $6 + if + local.get $5 + local.get $3 + i32.const 1 + i32.sub + local.tee $3 + i32.add + local.get $4 + local.get $3 + i32.add + i32.load8_u + i32.store8 + br $while-continue|5 + end + end + end + end + ) + (func $~lib/rt/tlsf/__free (; 29 ;) (param $0 i32) + local.get $0 + i32.const 0 + i32.ne + if (result i32) + local.get $0 + i32.const 15 + i32.and + i32.eqz + else + i32.const 0 + end + i32.eqz + if + i32.const 0 + i32.const 32 + i32.const 593 + i32.const 2 + call $~lib/builtins/abort + unreachable + end + call $~lib/rt/tlsf/maybeInitialize + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/tlsf/freeBlock + ) + (func $~lib/rt/pure/growRoots (; 30 ;) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + global.get $~lib/rt/pure/ROOTS + local.set $0 + global.get $~lib/rt/pure/CUR + local.get $0 + i32.sub + local.set $1 + local.get $1 + i32.const 2 + i32.mul + local.tee $2 + i32.const 64 + i32.const 2 + i32.shl + local.tee $3 + local.get $2 + local.get $3 + i32.gt_u + select + local.set $4 + local.get $4 + i32.const 0 + call $~lib/rt/tlsf/__alloc + local.set $5 + local.get $5 + i32.const 16 + i32.sub + call $~lib/rt/rtrace/onfree + local.get $5 + local.get $0 + local.get $1 + call $~lib/memory/memory.copy + local.get $0 + if + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/rtrace/onalloc + local.get $0 + call $~lib/rt/tlsf/__free + end + local.get $5 + global.set $~lib/rt/pure/ROOTS + local.get $5 + local.get $1 + i32.add + global.set $~lib/rt/pure/CUR + local.get $5 + local.get $4 + i32.add + global.set $~lib/rt/pure/END + ) + (func $~lib/rt/pure/appendRoot (; 31 ;) (param $0 i32) + (local $1 i32) + global.get $~lib/rt/pure/CUR + local.set $1 + local.get $1 + global.get $~lib/rt/pure/END + i32.ge_u + if + call $~lib/rt/pure/growRoots + global.get $~lib/rt/pure/CUR + local.set $1 + end + local.get $1 + local.get $0 + i32.store + local.get $1 + i32.const 4 + i32.add + global.set $~lib/rt/pure/CUR + ) + (func $~lib/rt/pure/decrement (; 32 ;) (param $0 i32) + (local $1 i32) + (local $2 i32) + local.get $0 + i32.load offset=4 + local.set $1 + local.get $1 + i32.const 268435455 + i32.and + local.set $2 + local.get $0 + call $~lib/rt/rtrace/ondecrement + local.get $0 + i32.load + i32.const 1 + i32.and + i32.eqz + i32.eqz + if + i32.const 0 + i32.const 144 + i32.const 115 + i32.const 13 + call $~lib/builtins/abort + unreachable + end + local.get $2 + i32.const 1 + i32.eq + if + local.get $0 + i32.const 16 + i32.add + i32.const 1 + call $~lib/rt/__visit_members + local.get $1 + i32.const -2147483648 + i32.and + i32.eqz + if + global.get $~lib/rt/tlsf/ROOT + local.get $0 + call $~lib/rt/tlsf/freeBlock + else + local.get $0 + i32.const -2147483648 + i32.const 0 + i32.or + i32.const 0 + i32.or + i32.store offset=4 + end + else + local.get $2 + i32.const 0 + i32.gt_u + i32.eqz + if + i32.const 0 + i32.const 144 + i32.const 124 + i32.const 15 + call $~lib/builtins/abort + unreachable + end + local.get $0 + i32.load offset=8 + call $~lib/rt/__typeinfo + i32.const 16 + i32.and + i32.eqz + if + local.get $0 + i32.const -2147483648 + i32.const 805306368 + i32.or + local.get $2 + i32.const 1 + i32.sub + i32.or + i32.store offset=4 + local.get $1 + i32.const -2147483648 + i32.and + i32.eqz + if + local.get $0 + call $~lib/rt/pure/appendRoot + end + else + local.get $0 + local.get $1 + i32.const 268435455 + i32.const -1 + i32.xor + i32.and + local.get $2 + i32.const 1 + i32.sub + i32.or + i32.store offset=4 + end + end + ) + (func $~lib/rt/pure/__release (; 33 ;) (param $0 i32) + local.get $0 + global.get $~lib/heap/__heap_base + i32.gt_u + if + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/pure/decrement + end + ) + (func $managed-cast/testDowncast (; 34 ;) (param $0 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + call $managed-cast/Animal#tame + local.get $0 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testDowncastFromNullable (; 35 ;) (param $0 i32) + (local $1 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + local.tee $1 + if (result i32) + local.get $1 + else + i32.const 0 + i32.const 304 + i32.const 14 + i32.const 11 + call $~lib/builtins/abort + unreachable + end + call $managed-cast/Animal#tame + local.get $0 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testDowncastToNullable (; 36 ;) (param $0 i32) + (local $1 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + call $~lib/rt/pure/__retain + local.set $1 + local.get $1 + if + local.get $1 + call $managed-cast/Animal#tame + end + local.get $0 + call $~lib/rt/pure/__release + local.get $1 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testDowncastFromToNullable (; 37 ;) (param $0 i32) + (local $1 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + call $~lib/rt/pure/__retain + local.set $1 + local.get $1 + if + local.get $1 + call $managed-cast/Animal#tame + end + local.get $0 + call $~lib/rt/pure/__release + local.get $1 + call $~lib/rt/pure/__release + ) + (func $~lib/rt/__instanceof (; 38 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + local.get $0 + i32.const 16 + i32.sub + i32.load offset=8 + local.set $2 + global.get $~lib/rt/__rtti_base + local.set $3 + local.get $2 + local.get $3 + i32.load + i32.le_u + if + loop $do-continue|0 + local.get $2 + local.get $1 + i32.eq + if + i32.const 1 + return + end + local.get $3 + i32.const 4 + i32.add + local.get $2 + i32.const 8 + i32.mul + i32.add + i32.load offset=4 + local.tee $2 + local.set $4 + local.get $4 + br_if $do-continue|0 + end + end + i32.const 0 + ) + (func $managed-cast/Cat#meow (; 39 ;) (param $0 i32) + nop + ) + (func $managed-cast/testUpcast (; 40 ;) (param $0 i32) + (local $1 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + local.tee $1 + i32.const 3 + call $~lib/rt/__instanceof + if (result i32) + local.get $1 + else + i32.const 0 + i32.const 304 + i32.const 31 + i32.const 8 + call $~lib/builtins/abort + unreachable + end + call $managed-cast/Cat#meow + local.get $0 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testUpcastFromNullable (; 41 ;) (param $0 i32) + (local $1 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + local.tee $1 + if (result i32) + local.get $1 + else + i32.const 0 + i32.const 304 + i32.const 36 + i32.const 8 + call $~lib/builtins/abort + unreachable + end + local.tee $1 + i32.const 3 + call $~lib/rt/__instanceof + if (result i32) + local.get $1 + else + i32.const 0 + i32.const 304 + i32.const 36 + i32.const 8 + call $~lib/builtins/abort + unreachable + end + call $managed-cast/Cat#meow + local.get $0 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testUpcastToNullable (; 42 ;) (param $0 i32) + (local $1 i32) + (local $2 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + local.tee $1 + i32.const 3 + call $~lib/rt/__instanceof + if (result i32) + local.get $1 + else + i32.const 0 + i32.const 304 + i32.const 41 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + call $~lib/rt/pure/__retain + local.set $2 + local.get $2 + if + local.get $2 + call $managed-cast/Cat#meow + end + local.get $0 + call $~lib/rt/pure/__release + local.get $2 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testUpcastFromToNullable (; 43 ;) (param $0 i32) + (local $1 i32) + (local $2 i32) + local.get $0 + call $~lib/rt/pure/__retain + local.set $0 + local.get $0 + local.tee $1 + i32.const 3 + call $~lib/rt/__instanceof + if (result i32) + local.get $1 + else + i32.const 0 + i32.const 304 + i32.const 47 + i32.const 29 + call $~lib/builtins/abort + unreachable + end + call $~lib/rt/pure/__retain + local.set $2 + local.get $2 + if + local.get $2 + call $managed-cast/Cat#meow + end + local.get $0 + call $~lib/rt/pure/__release + local.get $2 + call $~lib/rt/pure/__release + ) + (func $start:managed-cast (; 44 ;) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $0 + call $managed-cast/testDowncast + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $1 + call $managed-cast/testDowncastFromNullable + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $2 + call $managed-cast/testDowncastToNullable + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $3 + call $managed-cast/testDowncastFromToNullable + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $4 + call $managed-cast/testUpcast + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $5 + call $managed-cast/testUpcastFromNullable + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $6 + call $managed-cast/testUpcastToNullable + i32.const 0 + call $managed-cast/Cat#constructor + local.tee $7 + call $managed-cast/testUpcastFromToNullable + local.get $0 + call $~lib/rt/pure/__release + local.get $1 + call $~lib/rt/pure/__release + local.get $2 + call $~lib/rt/pure/__release + local.get $3 + call $~lib/rt/pure/__release + local.get $4 + call $~lib/rt/pure/__release + local.get $5 + call $~lib/rt/pure/__release + local.get $6 + call $~lib/rt/pure/__release + local.get $7 + call $~lib/rt/pure/__release + ) + (func $~start (; 45 ;) + global.get $~started + if + return + else + i32.const 1 + global.set $~started + end + call $start:managed-cast + ) + (func $~lib/rt/pure/__visit (; 46 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + local.get $0 + global.get $~lib/heap/__heap_base + i32.lt_u + if + return + end + local.get $0 + i32.const 16 + i32.sub + local.set $2 + block $break|0 + block $case5|0 + block $case4|0 + block $case3|0 + block $case2|0 + block $case1|0 + block $case0|0 + local.get $1 + local.set $3 + local.get $3 + i32.const 1 + i32.eq + br_if $case0|0 + local.get $3 + i32.const 2 + i32.eq + br_if $case1|0 + local.get $3 + i32.const 3 + i32.eq + br_if $case2|0 + local.get $3 + i32.const 4 + i32.eq + br_if $case3|0 + local.get $3 + i32.const 5 + i32.eq + br_if $case4|0 + br $case5|0 + end + local.get $2 + call $~lib/rt/pure/decrement + br $break|0 + end + local.get $2 + i32.load offset=4 + i32.const 268435455 + i32.and + i32.const 0 + i32.gt_u + i32.eqz + if + i32.const 0 + i32.const 144 + i32.const 75 + i32.const 17 + call $~lib/builtins/abort + unreachable + end + local.get $2 + local.get $2 + i32.load offset=4 + i32.const 1 + i32.sub + i32.store offset=4 + local.get $2 + call $~lib/rt/pure/markGray + br $break|0 + end + local.get $2 + call $~lib/rt/pure/scan + br $break|0 + end + local.get $2 + i32.load offset=4 + local.set $3 + local.get $3 + i32.const -268435456 + i32.and + local.get $3 + i32.const 1 + i32.add + i32.const -268435456 + i32.and + i32.eq + i32.eqz + if + i32.const 0 + i32.const 144 + i32.const 86 + i32.const 6 + call $~lib/builtins/abort + unreachable + end + local.get $2 + local.get $3 + i32.const 1 + i32.add + i32.store offset=4 + local.get $3 + i32.const 1879048192 + i32.and + i32.const 0 + i32.ne + if + local.get $2 + call $~lib/rt/pure/scanBlack + end + br $break|0 + end + local.get $2 + call $~lib/rt/pure/collectWhite + br $break|0 + end + i32.const 0 + i32.eqz + if + i32.const 0 + i32.const 144 + i32.const 97 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + end + ) + (func $~lib/rt/__visit_members (; 47 ;) (param $0 i32) (param $1 i32) + (local $2 i32) + block $switch$1$default + block $switch$1$case$4 + block $switch$1$case$2 + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $switch$1$case$2 $switch$1$case$2 $switch$1$case$4 $switch$1$case$2 $switch$1$case$2 $switch$1$default + end + return + end + local.get $0 + i32.load + local.tee $2 + if + local.get $2 + local.get $1 + call $~lib/rt/pure/__visit + end + return + end + unreachable + ) +) diff --git a/tests/compiler/nullable.json b/tests/compiler/nullable.json index 7454efd143..ae5a982120 100644 --- a/tests/compiler/nullable.json +++ b/tests/compiler/nullable.json @@ -3,7 +3,7 @@ "--runtime none" ], "stderr": [ - "TS2531: Object is possibly 'null'.", + "TS2322: Type 'nullable/Example | null' is not assignable to type 'nullable/Example'.", "EOF" ] } \ No newline at end of file diff --git a/tests/compiler/std/array.optimized.wat b/tests/compiler/std/array.optimized.wat index 35faf25e73..5006934d88 100644 --- a/tests/compiler/std/array.optimized.wat +++ b/tests/compiler/std/array.optimized.wat @@ -13930,6 +13930,11 @@ local.get $0 i32.eqz if + i32.const 0 + i32.const 416 + i32.const 434 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.load @@ -13974,6 +13979,11 @@ local.get $3 i32.eqz if + i32.const 0 + i32.const 416 + i32.const 438 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.load diff --git a/tests/compiler/std/array.untouched.wat b/tests/compiler/std/array.untouched.wat index 615b652d86..cbcf719961 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -21744,6 +21744,11 @@ if (result i32) local.get $55 else + i32.const 0 + i32.const 416 + i32.const 434 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.load @@ -21794,6 +21799,11 @@ if (result i32) local.get $62 else + i32.const 0 + i32.const 416 + i32.const 438 + i32.const 9 + call $~lib/builtins/abort unreachable end i32.load diff --git a/tests/compiler/std/symbol.optimized.wat b/tests/compiler/std/symbol.optimized.wat index b035120cc0..5f401ce42c 100644 --- a/tests/compiler/std/symbol.optimized.wat +++ b/tests/compiler/std/symbol.optimized.wat @@ -1610,6 +1610,11 @@ local.tee $0 i32.eqz if + i32.const 0 + i32.const 64 + i32.const 17 + i32.const 11 + call $~lib/builtins/abort unreachable end local.get $0 @@ -1619,6 +1624,11 @@ local.tee $0 i32.eqz if + i32.const 0 + i32.const 64 + i32.const 18 + i32.const 11 + call $~lib/builtins/abort unreachable end local.get $0 diff --git a/tests/compiler/std/symbol.untouched.wat b/tests/compiler/std/symbol.untouched.wat index 2b8f16b117..51d30d5d49 100644 --- a/tests/compiler/std/symbol.untouched.wat +++ b/tests/compiler/std/symbol.untouched.wat @@ -3405,6 +3405,11 @@ if (result i32) local.get $0 else + i32.const 0 + i32.const 64 + i32.const 17 + i32.const 11 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain @@ -3415,6 +3420,11 @@ if (result i32) local.get $0 else + i32.const 0 + i32.const 64 + i32.const 18 + i32.const 11 + call $~lib/builtins/abort unreachable end call $~lib/rt/stub/__retain