From 877b11aa4c6b4d368511a0b349f802ac99fc2fb3 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 15 Jan 2020 15:58:19 +0100 Subject: [PATCH 1/8] Fix missing reference conversion case --- src/compiler.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/compiler.ts b/src/compiler.ts index 2c68a86340..cd79f545e4 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -3128,6 +3128,13 @@ export class Compiler extends DiagnosticEmitter { if (this.currentFlow.isNonnull(expr, fromType)) fromType = fromType.nonNullableType; if (!fromType.isAssignableTo(toType)) { + if (fromType.is(TypeFlags.REFERENCE) || toType.is(TypeFlags.REFERENCE)) { + this.error( + DiagnosticCode.Type_0_is_not_assignable_to_type_1, + reportNode.range, fromType.toString(), toType.toString() + ); + return module.unreachable(); + } if (!explicit) { if (fromType.nonNullableType == toType) { this.error( From 16e91d40689ad879bdfdfcbed16299f46fd26270 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 15 Jan 2020 17:47:00 +0100 Subject: [PATCH 2/8] handle references specifically --- src/compiler.ts | 83 ++++++++++++------- tests/compiler/do.optimized.wat | 5 ++ tests/compiler/do.untouched.wat | 13 +++ .../extends-baseaggregate.optimized.wat | 5 ++ .../extends-baseaggregate.untouched.wat | 13 +++ tests/compiler/for.optimized.wat | 5 ++ tests/compiler/for.untouched.wat | 13 +++ tests/compiler/rc/global-init.untouched.wat | 13 +++ tests/compiler/rc/local-init.optimized.wat | 5 ++ tests/compiler/rc/local-init.untouched.wat | 13 +++ .../rc/logical-and-mismatch.optimized.wat | 5 ++ .../rc/logical-and-mismatch.untouched.wat | 13 +++ .../rc/logical-or-mismatch.optimized.wat | 5 ++ .../rc/logical-or-mismatch.untouched.wat | 13 +++ tests/compiler/rc/optimize.optimized.wat | 5 ++ tests/compiler/rc/optimize.untouched.wat | 13 +++ tests/compiler/rc/rereturn.optimized.wat | 5 ++ tests/compiler/rc/rereturn.untouched.wat | 13 +++ .../rc/ternary-mismatch.optimized.wat | 5 ++ .../rc/ternary-mismatch.untouched.wat | 13 +++ tests/compiler/resolve-ternary.optimized.wat | 5 ++ tests/compiler/resolve-ternary.untouched.wat | 13 +++ .../retain-release-sanity.optimized.wat | 5 ++ .../retain-release-sanity.untouched.wat | 13 +++ tests/compiler/retain-return.optimized.wat | 5 ++ tests/compiler/retain-return.untouched.wat | 13 +++ tests/compiler/runtime-full.optimized.wat | 5 ++ tests/compiler/runtime-full.untouched.wat | 13 +++ .../compiler/std/array-literal.optimized.wat | 5 ++ .../compiler/std/array-literal.untouched.wat | 13 +++ tests/compiler/std/array.optimized.wat | 5 ++ tests/compiler/std/array.untouched.wat | 13 +++ tests/compiler/std/arraybuffer.optimized.wat | 5 ++ tests/compiler/std/arraybuffer.untouched.wat | 13 +++ tests/compiler/std/dataview.optimized.wat | 5 ++ tests/compiler/std/dataview.untouched.wat | 13 +++ tests/compiler/std/map.optimized.wat | 5 ++ tests/compiler/std/map.untouched.wat | 13 +++ tests/compiler/std/set.optimized.wat | 5 ++ tests/compiler/std/set.untouched.wat | 13 +++ .../std/string-encoding.optimized.wat | 5 ++ .../std/string-encoding.untouched.wat | 13 +++ tests/compiler/std/string.optimized.wat | 5 ++ tests/compiler/std/string.untouched.wat | 13 +++ tests/compiler/std/typedarray.optimized.wat | 5 ++ tests/compiler/std/typedarray.untouched.wat | 13 +++ tests/compiler/while.optimized.wat | 5 ++ tests/compiler/while.untouched.wat | 13 +++ 48 files changed, 481 insertions(+), 29 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index cd79f545e4..940e3d8d81 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -3125,28 +3125,46 @@ 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; + } + 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 (fromType.nonNullableType.isAssignableTo(toType)) { + assert(fromType.kind == toType.kind); + if (!this.options.noAssert) { + expr = this.makeNonNullCheck(expr, fromType); + } + this.currentType = toType; + return expr; + } + } else { + // TODO: upcast? + if (fromType.isAssignableTo(toType)) { + assert(fromType.kind == toType.kind); + 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 (fromType.is(TypeFlags.REFERENCE) || toType.is(TypeFlags.REFERENCE)) { + if (!explicit) { this.error( - DiagnosticCode.Type_0_is_not_assignable_to_type_1, + DiagnosticCode.Conversion_from_type_0_to_1_requires_an_explicit_cast, reportNode.range, fromType.toString(), toType.toString() - ); - return module.unreachable(); - } - 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 - } + ); // recoverable } } @@ -3298,6 +3316,23 @@ export class Compiler extends DiagnosticEmitter { : expr; } + /** Makes a runtime non-null check. */ + private makeNonNullCheck(expr: ExpressionRef, type: Type): 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()), + module.unreachable() + ); + flow.freeTempLocal(temp); + return expr; + } + private compileAssertionExpression( expression: AssertionExpression, contextualType: Type, @@ -3326,17 +3361,7 @@ 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.makeNonNullCheck(expr, type); } this.currentType = this.currentType.nonNullableType; return expr; diff --git a/tests/compiler/do.optimized.wat b/tests/compiler/do.optimized.wat index bce1ce0f7d..f691486f07 100644 --- a/tests/compiler/do.optimized.wat +++ b/tests/compiler/do.optimized.wat @@ -1510,6 +1510,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 64 diff --git a/tests/compiler/do.untouched.wat b/tests/compiler/do.untouched.wat index 28466b9fdc..41560b0904 100644 --- a/tests/compiler/do.untouched.wat +++ b/tests/compiler/do.untouched.wat @@ -1965,6 +1965,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 28 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2006,6 +2007,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -2025,6 +2032,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/extends-baseaggregate.optimized.wat b/tests/compiler/extends-baseaggregate.optimized.wat index 3d8858c95a..8c9e36b97a 100644 --- a/tests/compiler/extends-baseaggregate.optimized.wat +++ b/tests/compiler/extends-baseaggregate.optimized.wat @@ -1261,6 +1261,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 128 diff --git a/tests/compiler/extends-baseaggregate.untouched.wat b/tests/compiler/extends-baseaggregate.untouched.wat index fa9cfeaf85..88b227668d 100644 --- a/tests/compiler/extends-baseaggregate.untouched.wat +++ b/tests/compiler/extends-baseaggregate.untouched.wat @@ -1575,6 +1575,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1616,6 +1617,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1635,6 +1642,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/for.optimized.wat b/tests/compiler/for.optimized.wat index 1ed8f49fc3..e8e110f5f8 100644 --- a/tests/compiler/for.optimized.wat +++ b/tests/compiler/for.optimized.wat @@ -1530,6 +1530,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 64 diff --git a/tests/compiler/for.untouched.wat b/tests/compiler/for.untouched.wat index baf9ac0823..9cc3f2e7c3 100644 --- a/tests/compiler/for.untouched.wat +++ b/tests/compiler/for.untouched.wat @@ -1999,6 +1999,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 30 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2040,6 +2041,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -2059,6 +2066,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/global-init.untouched.wat b/tests/compiler/rc/global-init.untouched.wat index e633ed7976..ce6fe3e72c 100644 --- a/tests/compiler/rc/global-init.untouched.wat +++ b/tests/compiler/rc/global-init.untouched.wat @@ -1661,6 +1661,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 23 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1702,6 +1703,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1721,6 +1728,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/local-init.optimized.wat b/tests/compiler/rc/local-init.optimized.wat index 5fdd6c1451..f92a9950d9 100644 --- a/tests/compiler/rc/local-init.optimized.wat +++ b/tests/compiler/rc/local-init.optimized.wat @@ -1280,6 +1280,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 96 diff --git a/tests/compiler/rc/local-init.untouched.wat b/tests/compiler/rc/local-init.untouched.wat index 665e5d02e7..be1656d091 100644 --- a/tests/compiler/rc/local-init.untouched.wat +++ b/tests/compiler/rc/local-init.untouched.wat @@ -1599,6 +1599,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 20 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1640,6 +1641,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1659,6 +1666,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/logical-and-mismatch.optimized.wat b/tests/compiler/rc/logical-and-mismatch.optimized.wat index 028e2b64d8..49abdda31a 100644 --- a/tests/compiler/rc/logical-and-mismatch.optimized.wat +++ b/tests/compiler/rc/logical-and-mismatch.optimized.wat @@ -1260,6 +1260,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/logical-and-mismatch.untouched.wat b/tests/compiler/rc/logical-and-mismatch.untouched.wat index 8298354b0c..5cedb445b1 100644 --- a/tests/compiler/rc/logical-and-mismatch.untouched.wat +++ b/tests/compiler/rc/logical-and-mismatch.untouched.wat @@ -1574,6 +1574,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1615,6 +1616,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1634,6 +1641,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/logical-or-mismatch.optimized.wat b/tests/compiler/rc/logical-or-mismatch.optimized.wat index f1ba740510..4187069152 100644 --- a/tests/compiler/rc/logical-or-mismatch.optimized.wat +++ b/tests/compiler/rc/logical-or-mismatch.optimized.wat @@ -1260,6 +1260,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/logical-or-mismatch.untouched.wat b/tests/compiler/rc/logical-or-mismatch.untouched.wat index 56b270725e..1563c30088 100644 --- a/tests/compiler/rc/logical-or-mismatch.untouched.wat +++ b/tests/compiler/rc/logical-or-mismatch.untouched.wat @@ -1574,6 +1574,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1615,6 +1616,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1634,6 +1641,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/optimize.optimized.wat b/tests/compiler/rc/optimize.optimized.wat index 7bac65c3aa..f0a9e538e1 100644 --- a/tests/compiler/rc/optimize.optimized.wat +++ b/tests/compiler/rc/optimize.optimized.wat @@ -1351,6 +1351,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 80 diff --git a/tests/compiler/rc/optimize.untouched.wat b/tests/compiler/rc/optimize.untouched.wat index ad1efd71fb..129b5b03c7 100644 --- a/tests/compiler/rc/optimize.untouched.wat +++ b/tests/compiler/rc/optimize.untouched.wat @@ -1669,6 +1669,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 25 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1710,6 +1711,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1729,6 +1736,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/rereturn.optimized.wat b/tests/compiler/rc/rereturn.optimized.wat index efa1c3e6cd..e194ee7923 100644 --- a/tests/compiler/rc/rereturn.optimized.wat +++ b/tests/compiler/rc/rereturn.optimized.wat @@ -1258,6 +1258,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/rereturn.untouched.wat b/tests/compiler/rc/rereturn.untouched.wat index 5989bbf377..f949d2511b 100644 --- a/tests/compiler/rc/rereturn.untouched.wat +++ b/tests/compiler/rc/rereturn.untouched.wat @@ -1572,6 +1572,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1613,6 +1614,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1632,6 +1639,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/ternary-mismatch.optimized.wat b/tests/compiler/rc/ternary-mismatch.optimized.wat index 7e8310abf3..2b9c7b0935 100644 --- a/tests/compiler/rc/ternary-mismatch.optimized.wat +++ b/tests/compiler/rc/ternary-mismatch.optimized.wat @@ -1262,6 +1262,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/ternary-mismatch.untouched.wat b/tests/compiler/rc/ternary-mismatch.untouched.wat index ce9ccf2a2c..95cfc0f13b 100644 --- a/tests/compiler/rc/ternary-mismatch.untouched.wat +++ b/tests/compiler/rc/ternary-mismatch.untouched.wat @@ -1576,6 +1576,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1617,6 +1618,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1636,6 +1643,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/resolve-ternary.optimized.wat b/tests/compiler/resolve-ternary.optimized.wat index 0a838332c0..dd87efa42a 100644 --- a/tests/compiler/resolve-ternary.optimized.wat +++ b/tests/compiler/resolve-ternary.optimized.wat @@ -1284,6 +1284,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/resolve-ternary.untouched.wat b/tests/compiler/resolve-ternary.untouched.wat index 02aaa3dcf5..c45c226c2e 100644 --- a/tests/compiler/resolve-ternary.untouched.wat +++ b/tests/compiler/resolve-ternary.untouched.wat @@ -1607,6 +1607,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1648,6 +1649,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1667,6 +1674,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/retain-release-sanity.optimized.wat b/tests/compiler/retain-release-sanity.optimized.wat index 381f7a97fa..3e55ec5d9c 100644 --- a/tests/compiler/retain-release-sanity.optimized.wat +++ b/tests/compiler/retain-release-sanity.optimized.wat @@ -1269,6 +1269,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/retain-release-sanity.untouched.wat b/tests/compiler/retain-release-sanity.untouched.wat index 0ddb8646a5..bc46aaf9b7 100644 --- a/tests/compiler/retain-release-sanity.untouched.wat +++ b/tests/compiler/retain-release-sanity.untouched.wat @@ -1582,6 +1582,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1623,6 +1624,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1642,6 +1649,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/retain-return.optimized.wat b/tests/compiler/retain-return.optimized.wat index 9ebd37b214..533c90d6b5 100644 --- a/tests/compiler/retain-return.optimized.wat +++ b/tests/compiler/retain-return.optimized.wat @@ -1257,6 +1257,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/retain-return.untouched.wat b/tests/compiler/retain-return.untouched.wat index a948bf28ef..f6ae9a315b 100644 --- a/tests/compiler/retain-return.untouched.wat +++ b/tests/compiler/retain-return.untouched.wat @@ -1578,6 +1578,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1619,6 +1620,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1638,6 +1645,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/runtime-full.optimized.wat b/tests/compiler/runtime-full.optimized.wat index a6086eecb0..103b0251ec 100644 --- a/tests/compiler/runtime-full.optimized.wat +++ b/tests/compiler/runtime-full.optimized.wat @@ -1258,6 +1258,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/runtime-full.untouched.wat b/tests/compiler/runtime-full.untouched.wat index ec352a486f..b7b846ab28 100644 --- a/tests/compiler/runtime-full.untouched.wat +++ b/tests/compiler/runtime-full.untouched.wat @@ -1571,6 +1571,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1612,6 +1613,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1631,6 +1638,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/array-literal.optimized.wat b/tests/compiler/std/array-literal.optimized.wat index d9f48e614e..bcedfbf3dd 100644 --- a/tests/compiler/std/array-literal.optimized.wat +++ b/tests/compiler/std/array-literal.optimized.wat @@ -1313,6 +1313,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 384 diff --git a/tests/compiler/std/array-literal.untouched.wat b/tests/compiler/std/array-literal.untouched.wat index 44da5ed355..71a94ee773 100644 --- a/tests/compiler/std/array-literal.untouched.wat +++ b/tests/compiler/std/array-literal.untouched.wat @@ -1656,6 +1656,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 25 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1697,6 +1698,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1716,6 +1723,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/array.optimized.wat b/tests/compiler/std/array.optimized.wat index 35faf25e73..1933b0e403 100644 --- a/tests/compiler/std/array.optimized.wat +++ b/tests/compiler/std/array.optimized.wat @@ -1478,6 +1478,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/std/array.untouched.wat b/tests/compiler/std/array.untouched.wat index 615b652d86..cc5f13eb67 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -1793,6 +1793,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 20 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1834,6 +1835,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1853,6 +1860,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/arraybuffer.optimized.wat b/tests/compiler/std/arraybuffer.optimized.wat index 1a6814a69d..0dd81ec797 100644 --- a/tests/compiler/std/arraybuffer.optimized.wat +++ b/tests/compiler/std/arraybuffer.optimized.wat @@ -1267,6 +1267,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/std/arraybuffer.untouched.wat b/tests/compiler/std/arraybuffer.untouched.wat index 4557a886b9..7d19191121 100644 --- a/tests/compiler/std/arraybuffer.untouched.wat +++ b/tests/compiler/std/arraybuffer.untouched.wat @@ -1581,6 +1581,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1622,6 +1623,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1641,6 +1648,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/dataview.optimized.wat b/tests/compiler/std/dataview.optimized.wat index df21c1f34d..ac7b54985a 100644 --- a/tests/compiler/std/dataview.optimized.wat +++ b/tests/compiler/std/dataview.optimized.wat @@ -1274,6 +1274,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/std/dataview.untouched.wat b/tests/compiler/std/dataview.untouched.wat index aeeab0af52..148920c431 100644 --- a/tests/compiler/std/dataview.untouched.wat +++ b/tests/compiler/std/dataview.untouched.wat @@ -1588,6 +1588,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1629,6 +1630,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1648,6 +1655,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/map.optimized.wat b/tests/compiler/std/map.optimized.wat index b2c80026da..d03538aa62 100644 --- a/tests/compiler/std/map.optimized.wat +++ b/tests/compiler/std/map.optimized.wat @@ -1288,6 +1288,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/std/map.untouched.wat b/tests/compiler/std/map.untouched.wat index 97feb4b9f0..012dc52f78 100644 --- a/tests/compiler/std/map.untouched.wat +++ b/tests/compiler/std/map.untouched.wat @@ -1598,6 +1598,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1639,6 +1640,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1658,6 +1665,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/set.optimized.wat b/tests/compiler/std/set.optimized.wat index 96d3e110e1..fcd7743393 100644 --- a/tests/compiler/std/set.optimized.wat +++ b/tests/compiler/std/set.optimized.wat @@ -1280,6 +1280,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/std/set.untouched.wat b/tests/compiler/std/set.untouched.wat index 9557c96c67..436ac46471 100644 --- a/tests/compiler/std/set.untouched.wat +++ b/tests/compiler/std/set.untouched.wat @@ -1593,6 +1593,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1634,6 +1635,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1653,6 +1660,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/string-encoding.optimized.wat b/tests/compiler/std/string-encoding.optimized.wat index 72bb3817d1..2058a2cf6c 100644 --- a/tests/compiler/std/string-encoding.optimized.wat +++ b/tests/compiler/std/string-encoding.optimized.wat @@ -1346,6 +1346,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 112 diff --git a/tests/compiler/std/string-encoding.untouched.wat b/tests/compiler/std/string-encoding.untouched.wat index 22582ba2e4..5f93500ad6 100644 --- a/tests/compiler/std/string-encoding.untouched.wat +++ b/tests/compiler/std/string-encoding.untouched.wat @@ -1670,6 +1670,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 22 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1711,6 +1712,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1730,6 +1737,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/string.optimized.wat b/tests/compiler/std/string.optimized.wat index 9df5106f8f..0a5925baf3 100644 --- a/tests/compiler/std/string.optimized.wat +++ b/tests/compiler/std/string.optimized.wat @@ -1819,6 +1819,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 208 diff --git a/tests/compiler/std/string.untouched.wat b/tests/compiler/std/string.untouched.wat index 57bfd93372..b9712dd5e0 100644 --- a/tests/compiler/std/string.untouched.wat +++ b/tests/compiler/std/string.untouched.wat @@ -2147,6 +2147,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 25 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2188,6 +2189,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -2207,6 +2214,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/typedarray.optimized.wat b/tests/compiler/std/typedarray.optimized.wat index 7369d651a4..a44e95385a 100644 --- a/tests/compiler/std/typedarray.optimized.wat +++ b/tests/compiler/std/typedarray.optimized.wat @@ -1449,6 +1449,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/std/typedarray.untouched.wat b/tests/compiler/std/typedarray.untouched.wat index 62d39ac3a0..42b75e2c33 100644 --- a/tests/compiler/std/typedarray.untouched.wat +++ b/tests/compiler/std/typedarray.untouched.wat @@ -1774,6 +1774,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 20 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1815,6 +1816,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -1834,6 +1841,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/while.optimized.wat b/tests/compiler/while.optimized.wat index 7298eb4246..fa16abfb66 100644 --- a/tests/compiler/while.optimized.wat +++ b/tests/compiler/while.optimized.wat @@ -1539,6 +1539,11 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz + if + unreachable + end + local.get $2 + i32.eqz if i32.const 0 i32.const 64 diff --git a/tests/compiler/while.untouched.wat b/tests/compiler/while.untouched.wat index 48d5103b3e..31a99328c8 100644 --- a/tests/compiler/while.untouched.wat +++ b/tests/compiler/while.untouched.wat @@ -2003,6 +2003,7 @@ (func $~lib/rt/tlsf/allocateBlock (; 28 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) + (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2044,6 +2045,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz @@ -2063,6 +2070,12 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock + local.tee $4 + if (result i32) + local.get $4 + else + unreachable + end local.set $3 local.get $3 i32.eqz From b281c241680b39af555e4e4754ffb4438faabc51 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 15 Jan 2020 18:08:36 +0100 Subject: [PATCH 3/8] update error check --- tests/compiler/nullable.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From ed135815dc55bab230bfdd68c554894e496fc104 Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 18 Jan 2020 18:29:05 +0100 Subject: [PATCH 4/8] handle upcast --- src/compiler.ts | 69 +- tests/compiler/managed-cast.optimized.wat | 1932 ++++++++++++ tests/compiler/managed-cast.ts | 16 + tests/compiler/managed-cast.untouched.wat | 3512 +++++++++++++++++++++ 4 files changed, 5511 insertions(+), 18 deletions(-) create mode 100644 tests/compiler/managed-cast.optimized.wat create mode 100644 tests/compiler/managed-cast.ts create mode 100644 tests/compiler/managed-cast.untouched.wat diff --git a/src/compiler.ts b/src/compiler.ts index 940e3d8d81..4d219c7753 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -3129,25 +3129,26 @@ export class Compiler extends DiagnosticEmitter { if (fromType.is(TypeFlags.REFERENCE) || toType.is(TypeFlags.REFERENCE)) { if (this.currentFlow.isNonnull(expr, fromType)) { fromType = fromType.nonNullableType; - } - if (explicit && fromType.is(TypeFlags.NULLABLE) && !toType.is(TypeFlags.NULLABLE)) { + } 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 (fromType.nonNullableType.isAssignableTo(toType)) { - assert(fromType.kind == toType.kind); - if (!this.options.noAssert) { - expr = this.makeNonNullCheck(expr, fromType); - } - this.currentType = toType; - return expr; + if (!this.options.noAssert) { + expr = this.makeRuntimeNonNullCheck(expr, fromType); } - } else { - // TODO: upcast? - if (fromType.isAssignableTo(toType)) { - assert(fromType.kind == toType.kind); - this.currentType = toType; - return expr; + fromType = fromType.nonNullableType; + } + if (fromType.isAssignableTo(toType)) { // downcast or same + assert(fromType.kind == toType.kind); + this.currentType = toType; + return expr; + } else if (toType.nonNullableType.isAssignableTo(fromType)) { // upcast + // (animal) + assert(fromType.kind == toType.kind); + if (!this.options.noAssert) { + expr = this.makeRuntimeUpcastCheck(expr, fromType, toType); } + this.currentType = toType; + return expr; } this.error( DiagnosticCode.Type_0_is_not_assignable_to_type_1, @@ -3317,7 +3318,12 @@ export class Compiler extends DiagnosticEmitter { } /** Makes a runtime non-null check. */ - private makeNonNullCheck(expr: ExpressionRef, type: Type): ExpressionRef { + private makeRuntimeNonNullCheck( + /** Expression being checked. */ + expr: ExpressionRef, + /** Type of the expression. */ + type: Type + ): ExpressionRef { assert(type.is(TypeFlags.NULLABLE | TypeFlags.REFERENCE)); var module = this.module; var flow = this.currentFlow; @@ -3327,7 +3333,34 @@ export class Compiler extends DiagnosticEmitter { expr = module.if( module.local_tee(temp.index, expr), module.local_get(temp.index, type.toNativeType()), - module.unreachable() + module.unreachable() // TODO: throw + ); + flow.freeTempLocal(temp); + return expr; + } + + /** Makes a runtime upcast check. */ + private makeRuntimeUpcastCheck( + /** Expression being upcast. */ + expr: ExpressionRef, + /** Type of the expression. */ + type: Type, + /** Type casting to. */ + toType: Type, + ): ExpressionRef { + assert(toType.is(TypeFlags.REFERENCE) && toType.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()), + module.unreachable() // TODO: throw ); flow.freeTempLocal(temp); return expr; @@ -3361,7 +3394,7 @@ export class Compiler extends DiagnosticEmitter { expression.expression.range ); } else if (!this.options.noAssert) { - expr = this.makeNonNullCheck(expr, type); + expr = this.makeRuntimeNonNullCheck(expr, type); } this.currentType = this.currentType.nonNullableType; return expr; diff --git a/tests/compiler/managed-cast.optimized.wat b/tests/compiler/managed-cast.optimized.wat new file mode 100644 index 0000000000..de2008508e --- /dev/null +++ b/tests/compiler/managed-cast.optimized.wat @@ -0,0 +1,1932 @@ +(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_=>_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))) + (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) "\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 $~lib/rt/__rtti_base i32 (i32.const 288)) + (export "memory" (memory $0)) + (export "__alloc" (func $~lib/rt/tlsf/__alloc)) + (export "__retain" (func $~lib/rt/pure/__retain)) + (export "__release" (func $~lib/rt/pure/__release)) + (export "__collect" (func $~lib/rt/pure/__collect)) + (export "__rtti_base" (global $~lib/rt/__rtti_base)) + (start $~start) + (func $~lib/rt/tlsf/removeBlock (; 1 ;) (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 (; 2 ;) (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 (; 3 ;) (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 (; 4 ;) (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 336 + local.tee $0 + i32.const 0 + i32.store + i32.const 1904 + 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 336 + 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 336 + 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 336 + i32.const 1920 + memory.size + i32.const 16 + i32.shl + call $~lib/rt/tlsf/addMemory + i32.const 336 + global.set $~lib/rt/tlsf/ROOT + end + local.get $0 + ) + (func $~lib/rt/tlsf/prepareSize (; 5 ;) (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 (; 6 ;) (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 (; 7 ;) (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 (; 8 ;) (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 + ) + (func $~lib/rt/pure/scanBlack (; 9 ;) (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 (; 10 ;) (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 (; 11 ;) (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 (; 12 ;) + (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 (; 13 ;) (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 (; 14 ;) (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 (; 15 ;) (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 + unreachable + end + local.get $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 + ) + (func $~lib/rt/tlsf/__alloc (; 16 ;) (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 (; 17 ;) (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 + 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 (; 18 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 332 + i32.gt_u + if + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/pure/increment + end + local.get $0 + ) + (func $~lib/rt/__typeinfo (; 19 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 288 + 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 292 + i32.add + i32.load + ) + (func $~lib/memory/memory.copy (; 20 ;) (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 (; 21 ;) (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 (; 22 ;) + (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 + local.get $1 + local.get $2 + call $~lib/memory/memory.copy + local.get $1 + if + 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 (; 23 ;) (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 (; 24 ;) (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 + 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 (; 25 ;) (param $0 i32) + local.get $0 + i32.const 332 + i32.gt_u + if + local.get $0 + i32.const 16 + i32.sub + call $~lib/rt/pure/decrement + end + ) + (func $managed-cast/Cat#constructor (; 26 ;) (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/__instanceof (; 27 ;) (param $0 i32) (result i32) + local.get $0 + i32.const 16 + i32.sub + i32.load offset=8 + local.tee $0 + i32.const 288 + 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 292 + i32.add + i32.load offset=4 + local.tee $0 + br_if $do-continue|0 + end + end + i32.const 0 + ) + (func $~start (; 28 ;) + (local $0 i32) + (local $1 i32) + call $managed-cast/Cat#constructor + call $managed-cast/Cat#constructor + local.tee $1 + call $~lib/rt/__instanceof + i32.eqz + if + unreachable + end + call $~lib/rt/pure/__release + local.get $1 + call $~lib/rt/pure/__release + ) + (func $~lib/rt/pure/__visit (; 29 ;) (param $0 i32) (param $1 i32) + local.get $0 + i32.const 332 + 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 (; 30 ;) (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..41d16531a4 --- /dev/null +++ b/tests/compiler/managed-cast.ts @@ -0,0 +1,16 @@ +class Animal { + tame(): void {} +} +class Cat extends Animal { + meow(): void {} +} + +function testDowncast(cat: Cat): void { + (cat).tame(); +} +testDowncast(new Cat()); + +function testUpcast(animal: Animal): void { + (animal).meow(); +} +testUpcast(new Cat()); diff --git a/tests/compiler/managed-cast.untouched.wat b/tests/compiler/managed-cast.untouched.wat new file mode 100644 index 0000000000..add4111b72 --- /dev/null +++ b/tests/compiler/managed-cast.untouched.wat @@ -0,0 +1,3512 @@ +(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))) + (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) "\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 $~lib/rt/__rtti_base i32 (i32.const 288)) + (global $~lib/heap/__heap_base i32 (i32.const 332)) + (export "memory" (memory $0)) + (export "__alloc" (func $~lib/rt/tlsf/__alloc)) + (export "__retain" (func $~lib/rt/pure/__retain)) + (export "__release" (func $~lib/rt/pure/__release)) + (export "__collect" (func $~lib/rt/pure/__collect)) + (export "__rtti_base" (global $~lib/rt/__rtti_base)) + (start $~start) + (func $~lib/rt/tlsf/removeBlock (; 1 ;) (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 (; 2 ;) (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 (; 3 ;) (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 (; 4 ;) (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 (; 5 ;) (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 (; 6 ;) (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 (; 7 ;) (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 (; 8 ;) (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 + ) + (func $~lib/rt/pure/scanBlack (; 9 ;) (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 (; 10 ;) (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 (; 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 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 (; 12 ;) + (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 (; 13 ;) (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 (; 14 ;) (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 (; 15 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 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.tee $4 + if (result i32) + local.get $4 + else + unreachable + end + 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.tee $4 + if (result i32) + local.get $4 + else + unreachable + end + 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 + ) + (func $~lib/rt/tlsf/__alloc (; 16 ;) (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 (; 17 ;) (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 + 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 (; 18 ;) (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 $~lib/rt/__typeinfo (; 19 ;) (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 (; 20 ;) (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 (; 21 ;) (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 (; 22 ;) (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 (; 23 ;) + (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 + local.get $0 + local.get $1 + call $~lib/memory/memory.copy + local.get $0 + if + 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 (; 24 ;) (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 (; 25 ;) (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 + 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 (; 26 ;) (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/Animal#constructor (; 27 ;) (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 (; 28 ;) (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 (; 29 ;) (param $0 i32) + nop + ) + (func $managed-cast/testDowncast (; 30 ;) (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 $~lib/rt/__instanceof (; 31 ;) (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 (; 32 ;) (param $0 i32) + nop + ) + (func $managed-cast/testUpcast (; 33 ;) (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 + unreachable + end + call $managed-cast/Cat#meow + local.get $0 + call $~lib/rt/pure/__release + ) + (func $start:managed-cast (; 34 ;) + (local $0 i32) + (local $1 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/testUpcast + local.get $0 + call $~lib/rt/pure/__release + local.get $1 + call $~lib/rt/pure/__release + ) + (func $~start (; 35 ;) + call $start:managed-cast + ) + (func $~lib/rt/pure/__visit (; 36 ;) (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 (; 37 ;) (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 + ) +) From 3a2ce078eba413151aae6e87bf1dfe41ede2b562 Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 18 Jan 2020 18:39:12 +0100 Subject: [PATCH 5/8] test nullable cases, fix assert --- src/compiler.ts | 2 +- tests/compiler/managed-cast.optimized.wat | 65 +++++++- tests/compiler/managed-cast.ts | 34 ++++ tests/compiler/managed-cast.untouched.wat | 186 +++++++++++++++++++++- 4 files changed, 275 insertions(+), 12 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 4d219c7753..0e4bc61657 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -3348,7 +3348,7 @@ export class Compiler extends DiagnosticEmitter { /** Type casting to. */ toType: Type, ): ExpressionRef { - assert(toType.is(TypeFlags.REFERENCE) && toType.isAssignableTo(type)); + assert(toType.is(TypeFlags.REFERENCE) && toType.nonNullableType.isAssignableTo(type)); var module = this.module; var flow = this.currentFlow; var temp = flow.getTempLocal(type); diff --git a/tests/compiler/managed-cast.optimized.wat b/tests/compiler/managed-cast.optimized.wat index de2008508e..f1d99d207d 100644 --- a/tests/compiler/managed-cast.optimized.wat +++ b/tests/compiler/managed-cast.optimized.wat @@ -1,8 +1,8 @@ (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 (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))) @@ -1787,22 +1787,79 @@ end i32.const 0 ) - (func $~start (; 28 ;) + (func $managed-cast/testUpcastToNullable (; 28 ;) (param $0 i32) + local.get $0 + call $~lib/rt/__instanceof + i32.eqz + if + unreachable + end + ) + (func $start:managed-cast (; 29 ;) (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 $3 + i32.eqz + if + unreachable + end call $managed-cast/Cat#constructor + local.set $4 + call $managed-cast/Cat#constructor + local.set $5 + call $managed-cast/Cat#constructor + local.tee $6 + call $~lib/rt/__instanceof + i32.eqz + if + unreachable + end call $managed-cast/Cat#constructor local.tee $1 + local.get $1 + i32.eqz + if + unreachable + end call $~lib/rt/__instanceof i32.eqz if unreachable end + call $managed-cast/Cat#constructor + local.tee $0 + call $managed-cast/testUpcastToNullable + call $managed-cast/Cat#constructor + local.tee $7 + call $managed-cast/testUpcastToNullable + 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 $1 call $~lib/rt/pure/__release + local.get $0 + call $~lib/rt/pure/__release + local.get $7 + call $~lib/rt/pure/__release + ) + (func $~start (; 30 ;) + call $start:managed-cast ) - (func $~lib/rt/pure/__visit (; 29 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/pure/__visit (; 31 ;) (param $0 i32) (param $1 i32) local.get $0 i32.const 332 i32.lt_u @@ -1905,7 +1962,7 @@ unreachable end ) - (func $~lib/rt/__visit_members (; 30 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/__visit_members (; 32 ;) (param $0 i32) (param $1 i32) block $switch$1$default block $switch$1$case$4 block $switch$1$case$2 diff --git a/tests/compiler/managed-cast.ts b/tests/compiler/managed-cast.ts index 41d16531a4..d3ea53b229 100644 --- a/tests/compiler/managed-cast.ts +++ b/tests/compiler/managed-cast.ts @@ -10,7 +10,41 @@ function testDowncast(cat: Cat): void { } 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 index add4111b72..c0a2e95421 100644 --- a/tests/compiler/managed-cast.untouched.wat +++ b/tests/compiler/managed-cast.untouched.wat @@ -3274,7 +3274,59 @@ local.get $0 call $~lib/rt/pure/__release ) - (func $~lib/rt/__instanceof (; 31 ;) (param $0 i32) (param $1 i32) (result i32) + (func $managed-cast/testDowncastFromNullable (; 31 ;) (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 + unreachable + end + call $managed-cast/Animal#tame + local.get $0 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testDowncastToNullable (; 32 ;) (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 (; 33 ;) (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 (; 34 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -3314,16 +3366,40 @@ end i32.const 0 ) - (func $managed-cast/Cat#meow (; 32 ;) (param $0 i32) + (func $managed-cast/Cat#meow (; 35 ;) (param $0 i32) nop ) - (func $managed-cast/testUpcast (; 33 ;) (param $0 i32) + (func $managed-cast/testUpcast (; 36 ;) (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 + unreachable + end + call $managed-cast/Cat#meow + local.get $0 + call $~lib/rt/pure/__release + ) + (func $managed-cast/testUpcastFromNullable (; 37 ;) (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 + unreachable + end + local.tee $1 i32.const 3 call $~lib/rt/__instanceof if (result i32) @@ -3335,9 +3411,69 @@ local.get $0 call $~lib/rt/pure/__release ) - (func $start:managed-cast (; 34 ;) + (func $managed-cast/testUpcastToNullable (; 38 ;) (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 + 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 (; 39 ;) (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 + 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 (; 40 ;) (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 @@ -3345,16 +3481,52 @@ 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 (; 35 ;) + (func $~start (; 41 ;) call $start:managed-cast ) - (func $~lib/rt/pure/__visit (; 36 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/pure/__visit (; 42 ;) (param $0 i32) (param $1 i32) (local $2 i32) (local $3 i32) local.get $0 @@ -3484,7 +3656,7 @@ end end ) - (func $~lib/rt/__visit_members (; 37 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/__visit_members (; 43 ;) (param $0 i32) (param $1 i32) (local $2 i32) block $switch$1$default block $switch$1$case$4 From 578deb3b1321ef703de0d0802404e6c1d0cf3523 Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 18 Jan 2020 18:57:56 +0100 Subject: [PATCH 6/8] update tlsf --- src/compiler.ts | 18 +- std/assembly/rt/tlsf.ts | 4 +- tests/compiler/assert-nonnull.optimized.wat | 132 +++++++--- tests/compiler/assert-nonnull.untouched.wat | 85 ++++++- tests/compiler/do.optimized.wat | 5 - tests/compiler/do.untouched.wat | 13 - .../extends-baseaggregate.optimized.wat | 5 - .../extends-baseaggregate.untouched.wat | 13 - tests/compiler/for.optimized.wat | 5 - tests/compiler/for.untouched.wat | 13 - tests/compiler/managed-cast.json | 7 + tests/compiler/managed-cast.optimized.wat | 239 +++++++++++------- tests/compiler/managed-cast.untouched.wat | 225 ++++++++++------- tests/compiler/rc/global-init.untouched.wat | 13 - tests/compiler/rc/local-init.optimized.wat | 5 - tests/compiler/rc/local-init.untouched.wat | 13 - .../rc/logical-and-mismatch.optimized.wat | 5 - .../rc/logical-and-mismatch.untouched.wat | 13 - .../rc/logical-or-mismatch.optimized.wat | 5 - .../rc/logical-or-mismatch.untouched.wat | 13 - tests/compiler/rc/optimize.optimized.wat | 5 - tests/compiler/rc/optimize.untouched.wat | 13 - tests/compiler/rc/rereturn.optimized.wat | 5 - tests/compiler/rc/rereturn.untouched.wat | 13 - .../rc/ternary-mismatch.optimized.wat | 5 - .../rc/ternary-mismatch.untouched.wat | 13 - tests/compiler/resolve-ternary.optimized.wat | 5 - tests/compiler/resolve-ternary.untouched.wat | 13 - .../retain-release-sanity.optimized.wat | 5 - .../retain-release-sanity.untouched.wat | 13 - tests/compiler/retain-return.optimized.wat | 5 - tests/compiler/retain-return.untouched.wat | 13 - tests/compiler/runtime-full.optimized.wat | 5 - tests/compiler/runtime-full.untouched.wat | 13 - .../compiler/std/array-literal.optimized.wat | 5 - .../compiler/std/array-literal.untouched.wat | 13 - tests/compiler/std/array.optimized.wat | 15 +- tests/compiler/std/array.untouched.wat | 23 +- tests/compiler/std/arraybuffer.optimized.wat | 5 - tests/compiler/std/arraybuffer.untouched.wat | 13 - tests/compiler/std/dataview.optimized.wat | 5 - tests/compiler/std/dataview.untouched.wat | 13 - tests/compiler/std/map.optimized.wat | 5 - tests/compiler/std/map.untouched.wat | 13 - tests/compiler/std/set.optimized.wat | 5 - tests/compiler/std/set.untouched.wat | 13 - .../std/string-encoding.optimized.wat | 5 - .../std/string-encoding.untouched.wat | 13 - tests/compiler/std/string.optimized.wat | 5 - tests/compiler/std/string.untouched.wat | 13 - tests/compiler/std/symbol.optimized.wat | 10 + tests/compiler/std/symbol.untouched.wat | 10 + tests/compiler/std/typedarray.optimized.wat | 5 - tests/compiler/std/typedarray.untouched.wat | 13 - tests/compiler/while.optimized.wat | 5 - tests/compiler/while.untouched.wat | 13 - 56 files changed, 515 insertions(+), 662 deletions(-) create mode 100644 tests/compiler/managed-cast.json diff --git a/src/compiler.ts b/src/compiler.ts index 0e4bc61657..87ff6a97b1 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -3133,7 +3133,7 @@ export class Compiler extends DiagnosticEmitter { // 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); + expr = this.makeRuntimeNonNullCheck(expr, fromType, reportNode); } fromType = fromType.nonNullableType; } @@ -3145,7 +3145,7 @@ export class Compiler extends DiagnosticEmitter { // (animal) assert(fromType.kind == toType.kind); if (!this.options.noAssert) { - expr = this.makeRuntimeUpcastCheck(expr, fromType, toType); + expr = this.makeRuntimeUpcastCheck(expr, fromType, toType, reportNode); } this.currentType = toType; return expr; @@ -3322,7 +3322,9 @@ export class Compiler extends DiagnosticEmitter { /** Expression being checked. */ expr: ExpressionRef, /** Type of the expression. */ - type: Type + type: Type, + /** Report node. */ + reportNode: Node ): ExpressionRef { assert(type.is(TypeFlags.NULLABLE | TypeFlags.REFERENCE)); var module = this.module; @@ -3333,7 +3335,7 @@ export class Compiler extends DiagnosticEmitter { expr = module.if( module.local_tee(temp.index, expr), module.local_get(temp.index, type.toNativeType()), - module.unreachable() // TODO: throw + compileAbort(this, null, reportNode) // TODO: throw ); flow.freeTempLocal(temp); return expr; @@ -3347,6 +3349,8 @@ export class Compiler extends DiagnosticEmitter { 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; @@ -3360,7 +3364,7 @@ export class Compiler extends DiagnosticEmitter { module.i32(assert(toType.classReference).id) ], NativeType.I32), module.local_get(temp.index, type.toNativeType()), - module.unreachable() // TODO: throw + compileAbort(this, null, reportNode) // TODO: throw ); flow.freeTempLocal(temp); return expr; @@ -3394,9 +3398,9 @@ export class Compiler extends DiagnosticEmitter { expression.expression.range ); } else if (!this.options.noAssert) { - expr = this.makeRuntimeNonNullCheck(expr, type); + expr = this.makeRuntimeNonNullCheck(expr, type, expression); } - this.currentType = this.currentType.nonNullableType; + this.currentType = type.nonNullableType; return expr; } default: assert(false); 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/do.optimized.wat b/tests/compiler/do.optimized.wat index f691486f07..bce1ce0f7d 100644 --- a/tests/compiler/do.optimized.wat +++ b/tests/compiler/do.optimized.wat @@ -1510,11 +1510,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 64 diff --git a/tests/compiler/do.untouched.wat b/tests/compiler/do.untouched.wat index 41560b0904..28466b9fdc 100644 --- a/tests/compiler/do.untouched.wat +++ b/tests/compiler/do.untouched.wat @@ -1965,7 +1965,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 28 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2007,12 +2006,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -2032,12 +2025,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/extends-baseaggregate.optimized.wat b/tests/compiler/extends-baseaggregate.optimized.wat index 8c9e36b97a..3d8858c95a 100644 --- a/tests/compiler/extends-baseaggregate.optimized.wat +++ b/tests/compiler/extends-baseaggregate.optimized.wat @@ -1261,11 +1261,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 128 diff --git a/tests/compiler/extends-baseaggregate.untouched.wat b/tests/compiler/extends-baseaggregate.untouched.wat index 88b227668d..fa9cfeaf85 100644 --- a/tests/compiler/extends-baseaggregate.untouched.wat +++ b/tests/compiler/extends-baseaggregate.untouched.wat @@ -1575,7 +1575,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1617,12 +1616,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1642,12 +1635,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/for.optimized.wat b/tests/compiler/for.optimized.wat index e8e110f5f8..1ed8f49fc3 100644 --- a/tests/compiler/for.optimized.wat +++ b/tests/compiler/for.optimized.wat @@ -1530,11 +1530,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 64 diff --git a/tests/compiler/for.untouched.wat b/tests/compiler/for.untouched.wat index 9cc3f2e7c3..baf9ac0823 100644 --- a/tests/compiler/for.untouched.wat +++ b/tests/compiler/for.untouched.wat @@ -1999,7 +1999,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 30 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2041,12 +2040,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -2066,12 +2059,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz 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 index f1d99d207d..c0b359a1fc 100644 --- a/tests/compiler/managed-cast.optimized.wat +++ b/tests/compiler/managed-cast.optimized.wat @@ -8,27 +8,27 @@ (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) "\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") + (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 $~lib/rt/__rtti_base i32 (i32.const 288)) + (global $~started (mut i32) (i32.const 0)) + (export "_start" (func $~start)) (export "memory" (memory $0)) - (export "__alloc" (func $~lib/rt/tlsf/__alloc)) - (export "__retain" (func $~lib/rt/pure/__retain)) - (export "__release" (func $~lib/rt/pure/__release)) - (export "__collect" (func $~lib/rt/pure/__collect)) - (export "__rtti_base" (global $~lib/rt/__rtti_base)) - (start $~start) - (func $~lib/rt/tlsf/removeBlock (; 1 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/removeBlock (; 5 ;) (param $0 i32) (param $1 i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -194,7 +194,7 @@ end end ) - (func $~lib/rt/tlsf/insertBlock (; 2 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/insertBlock (; 6 ;) (param $0 i32) (param $1 i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -477,7 +477,7 @@ i32.or i32.store offset=4 ) - (func $~lib/rt/tlsf/addMemory (; 3 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (func $~lib/rt/tlsf/addMemory (; 7 ;) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) local.get $2 @@ -591,7 +591,7 @@ local.get $1 call $~lib/rt/tlsf/insertBlock ) - (func $~lib/rt/tlsf/maybeInitialize (; 4 ;) (result i32) + (func $~lib/rt/tlsf/maybeInitialize (; 8 ;) (result i32) (local $0 i32) (local $1 i32) (local $2 i32) @@ -616,11 +616,11 @@ if unreachable end - i32.const 336 + i32.const 384 local.tee $0 i32.const 0 i32.store - i32.const 1904 + i32.const 1952 i32.const 0 i32.store loop $for-loop|0 @@ -631,7 +631,7 @@ local.get $1 i32.const 2 i32.shl - i32.const 336 + i32.const 384 i32.add i32.const 0 i32.store offset=4 @@ -649,7 +649,7 @@ i32.add i32.const 2 i32.shl - i32.const 336 + i32.const 384 i32.add i32.const 0 i32.store offset=96 @@ -667,18 +667,18 @@ br $for-loop|0 end end - i32.const 336 - i32.const 1920 + i32.const 384 + i32.const 1968 memory.size i32.const 16 i32.shl call $~lib/rt/tlsf/addMemory - i32.const 336 + i32.const 384 global.set $~lib/rt/tlsf/ROOT end local.get $0 ) - (func $~lib/rt/tlsf/prepareSize (; 5 ;) (param $0 i32) (result i32) + (func $~lib/rt/tlsf/prepareSize (; 9 ;) (param $0 i32) (result i32) local.get $0 i32.const 1073741808 i32.ge_u @@ -702,7 +702,7 @@ i32.gt_u select ) - (func $~lib/rt/tlsf/searchBlock (; 6 ;) (param $0 i32) (param $1 i32) (result i32) + (func $~lib/rt/tlsf/searchBlock (; 10 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) local.get $1 i32.const 256 @@ -833,7 +833,7 @@ end end ) - (func $~lib/rt/pure/markGray (; 7 ;) (param $0 i32) + (func $~lib/rt/pure/markGray (; 11 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -857,7 +857,7 @@ call $~lib/rt/__visit_members end ) - (func $~lib/rt/tlsf/freeBlock (; 8 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/freeBlock (; 12 ;) (param $0 i32) (param $1 i32) (local $2 i32) local.get $1 i32.load @@ -880,8 +880,10 @@ local.get $0 local.get $1 call $~lib/rt/tlsf/insertBlock + local.get $1 + call $~lib/rt/rtrace/onfree ) - (func $~lib/rt/pure/scanBlack (; 9 ;) (param $0 i32) + (func $~lib/rt/pure/scanBlack (; 13 ;) (param $0 i32) local.get $0 local.get $0 i32.load offset=4 @@ -894,7 +896,7 @@ i32.const 4 call $~lib/rt/__visit_members ) - (func $~lib/rt/pure/scan (; 10 ;) (param $0 i32) + (func $~lib/rt/pure/scan (; 14 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -928,7 +930,7 @@ end end ) - (func $~lib/rt/pure/collectWhite (; 11 ;) (param $0 i32) + (func $~lib/rt/pure/collectWhite (; 15 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -961,7 +963,7 @@ call $~lib/rt/tlsf/freeBlock end ) - (func $~lib/rt/pure/__collect (; 12 ;) + (func $~lib/rt/pure/__collect (; 16 ;) (local $0 i32) (local $1 i32) (local $2 i32) @@ -1082,7 +1084,7 @@ local.get $5 global.set $~lib/rt/pure/CUR ) - (func $~lib/rt/tlsf/growMemory (; 13 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/growMemory (; 17 ;) (param $0 i32) (param $1 i32) (local $2 i32) memory.size local.tee $2 @@ -1144,7 +1146,7 @@ i32.shl call $~lib/rt/tlsf/addMemory ) - (func $~lib/rt/tlsf/prepareBlock (; 14 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (func $~lib/rt/tlsf/prepareBlock (; 18 ;) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) local.get $1 @@ -1220,7 +1222,7 @@ i32.store end ) - (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) + (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 @@ -1259,11 +1261,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 @@ -1302,8 +1299,10 @@ local.get $3 call $~lib/rt/tlsf/prepareBlock local.get $2 + call $~lib/rt/rtrace/onalloc + local.get $2 ) - (func $~lib/rt/tlsf/__alloc (; 16 ;) (param $0 i32) (param $1 i32) (result i32) + (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 @@ -1314,7 +1313,7 @@ i32.const 16 i32.add ) - (func $~lib/rt/pure/increment (; 17 ;) (param $0 i32) + (func $~lib/rt/pure/increment (; 21 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -1341,6 +1340,8 @@ i32.add i32.store offset=4 local.get $0 + call $~lib/rt/rtrace/onincrement + local.get $0 i32.load i32.const 1 i32.and @@ -1353,9 +1354,9 @@ unreachable end ) - (func $~lib/rt/pure/__retain (; 18 ;) (param $0 i32) (result i32) + (func $~lib/rt/pure/__retain (; 22 ;) (param $0 i32) (result i32) local.get $0 - i32.const 332 + i32.const 380 i32.gt_u if local.get $0 @@ -1365,9 +1366,26 @@ end local.get $0 ) - (func $~lib/rt/__typeinfo (; 19 ;) (param $0 i32) (result i32) + (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 288 + i32.const 336 i32.load i32.gt_u if @@ -1381,11 +1399,11 @@ local.get $0 i32.const 3 i32.shl - i32.const 292 + i32.const 340 i32.add i32.load ) - (func $~lib/memory/memory.copy (; 20 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (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 @@ -1558,7 +1576,7 @@ end end ) - (func $~lib/rt/tlsf/__free (; 21 ;) (param $0 i32) + (func $~lib/rt/tlsf/__free (; 26 ;) (param $0 i32) local.get $0 i32.const 15 i32.and @@ -1581,7 +1599,7 @@ i32.sub call $~lib/rt/tlsf/freeBlock ) - (func $~lib/rt/pure/growRoots (; 22 ;) + (func $~lib/rt/pure/growRoots (; 27 ;) (local $0 i32) (local $1 i32) (local $2 i32) @@ -1603,11 +1621,19 @@ 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 @@ -1622,7 +1648,7 @@ i32.add global.set $~lib/rt/pure/END ) - (func $~lib/rt/pure/appendRoot (; 23 ;) (param $0 i32) + (func $~lib/rt/pure/appendRoot (; 28 ;) (param $0 i32) (local $1 i32) global.get $~lib/rt/pure/CUR local.tee $1 @@ -1641,7 +1667,7 @@ i32.add global.set $~lib/rt/pure/CUR ) - (func $~lib/rt/pure/decrement (; 24 ;) (param $0 i32) + (func $~lib/rt/pure/decrement (; 29 ;) (param $0 i32) (local $1 i32) (local $2 i32) local.get $0 @@ -1651,6 +1677,8 @@ i32.and local.set $1 local.get $0 + call $~lib/rt/rtrace/ondecrement + local.get $0 i32.load i32.const 1 i32.and @@ -1729,9 +1757,9 @@ end end ) - (func $~lib/rt/pure/__release (; 25 ;) (param $0 i32) + (func $~lib/rt/pure/__release (; 30 ;) (param $0 i32) local.get $0 - i32.const 332 + i32.const 380 i32.gt_u if local.get $0 @@ -1740,30 +1768,13 @@ call $~lib/rt/pure/decrement end ) - (func $managed-cast/Cat#constructor (; 26 ;) (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/__instanceof (; 27 ;) (param $0 i32) (result i32) + (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 288 + i32.const 336 i32.load i32.le_u if @@ -1778,7 +1789,7 @@ local.get $0 i32.const 3 i32.shl - i32.const 292 + i32.const 340 i32.add i32.load offset=4 local.tee $0 @@ -1787,15 +1798,25 @@ end i32.const 0 ) - (func $managed-cast/testUpcastToNullable (; 28 ;) (param $0 i32) - local.get $0 - call $~lib/rt/__instanceof - i32.eqz - if - unreachable + (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 (; 29 ;) + (func $start:managed-cast (; 33 ;) (local $0 i32) (local $1 i32) (local $2 i32) @@ -1806,40 +1827,63 @@ (local $7 i32) call $managed-cast/Cat#constructor call $managed-cast/Cat#constructor - local.tee $3 + 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 $4 + local.set $2 call $managed-cast/Cat#constructor - local.set $5 + local.set $3 call $managed-cast/Cat#constructor - local.tee $6 + 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 $1 - local.get $1 + 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 $managed-cast/Cat#constructor - local.tee $0 - call $managed-cast/testUpcastToNullable - call $managed-cast/Cat#constructor - local.tee $7 - call $managed-cast/testUpcastToNullable + 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 @@ -1849,19 +1893,22 @@ call $~lib/rt/pure/__release local.get $6 call $~lib/rt/pure/__release - local.get $1 - call $~lib/rt/pure/__release - local.get $0 - call $~lib/rt/pure/__release local.get $7 call $~lib/rt/pure/__release ) - (func $~start (; 30 ;) + (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 (; 31 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/pure/__visit (; 35 ;) (param $0 i32) (param $1 i32) local.get $0 - i32.const 332 + i32.const 380 i32.lt_u if return @@ -1962,7 +2009,7 @@ unreachable end ) - (func $~lib/rt/__visit_members (; 32 ;) (param $0 i32) (param $1 i32) + (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 diff --git a/tests/compiler/managed-cast.untouched.wat b/tests/compiler/managed-cast.untouched.wat index c0a2e95421..e67dc6eab6 100644 --- a/tests/compiler/managed-cast.untouched.wat +++ b/tests/compiler/managed-cast.untouched.wat @@ -9,13 +9,18 @@ (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) "\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") + (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)) @@ -24,16 +29,12 @@ (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 $~lib/rt/__rtti_base i32 (i32.const 288)) - (global $~lib/heap/__heap_base i32 (i32.const 332)) + (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)) - (export "__alloc" (func $~lib/rt/tlsf/__alloc)) - (export "__retain" (func $~lib/rt/pure/__retain)) - (export "__release" (func $~lib/rt/pure/__release)) - (export "__collect" (func $~lib/rt/pure/__collect)) - (export "__rtti_base" (global $~lib/rt/__rtti_base)) - (start $~start) - (func $~lib/rt/tlsf/removeBlock (; 1 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/removeBlock (; 5 ;) (param $0 i32) (param $1 i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -243,7 +244,7 @@ end end ) - (func $~lib/rt/tlsf/insertBlock (; 2 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/insertBlock (; 6 ;) (param $0 i32) (param $1 i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -593,7 +594,7 @@ local.get $7 i32.store offset=4 ) - (func $~lib/rt/tlsf/addMemory (; 3 ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (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) @@ -741,7 +742,7 @@ call $~lib/rt/tlsf/insertBlock i32.const 1 ) - (func $~lib/rt/tlsf/maybeInitialize (; 4 ;) (result i32) + (func $~lib/rt/tlsf/maybeInitialize (; 8 ;) (result i32) (local $0 i32) (local $1 i32) (local $2 i32) @@ -891,7 +892,7 @@ end local.get $0 ) - (func $~lib/rt/tlsf/prepareSize (; 5 ;) (param $0 i32) (result i32) + (func $~lib/rt/tlsf/prepareSize (; 9 ;) (param $0 i32) (result i32) (local $1 i32) (local $2 i32) local.get $0 @@ -920,7 +921,7 @@ i32.gt_u select ) - (func $~lib/rt/tlsf/searchBlock (; 6 ;) (param $0 i32) (param $1 i32) (result i32) + (func $~lib/rt/tlsf/searchBlock (; 10 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -1103,7 +1104,7 @@ end local.get $7 ) - (func $~lib/rt/pure/markGray (; 7 ;) (param $0 i32) + (func $~lib/rt/pure/markGray (; 11 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -1130,7 +1131,7 @@ call $~lib/rt/__visit_members end ) - (func $~lib/rt/tlsf/freeBlock (; 8 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/freeBlock (; 12 ;) (param $0 i32) (param $1 i32) (local $2 i32) local.get $1 i32.load @@ -1156,8 +1157,10 @@ local.get $0 local.get $1 call $~lib/rt/tlsf/insertBlock + local.get $1 + call $~lib/rt/rtrace/onfree ) - (func $~lib/rt/pure/scanBlack (; 9 ;) (param $0 i32) + (func $~lib/rt/pure/scanBlack (; 13 ;) (param $0 i32) local.get $0 local.get $0 i32.load offset=4 @@ -1174,7 +1177,7 @@ i32.const 4 call $~lib/rt/__visit_members ) - (func $~lib/rt/pure/scan (; 10 ;) (param $0 i32) + (func $~lib/rt/pure/scan (; 14 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -1211,7 +1214,7 @@ end end ) - (func $~lib/rt/pure/collectWhite (; 11 ;) (param $0 i32) + (func $~lib/rt/pure/collectWhite (; 15 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -1249,7 +1252,7 @@ call $~lib/rt/tlsf/freeBlock end ) - (func $~lib/rt/pure/__collect (; 12 ;) + (func $~lib/rt/pure/__collect (; 16 ;) (local $0 i32) (local $1 i32) (local $2 i32) @@ -1390,7 +1393,7 @@ local.get $0 global.set $~lib/rt/pure/CUR ) - (func $~lib/rt/tlsf/growMemory (; 13 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/tlsf/growMemory (; 17 ;) (param $0 i32) (param $1 i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -1474,7 +1477,7 @@ call $~lib/rt/tlsf/addMemory drop ) - (func $~lib/rt/tlsf/prepareBlock (; 14 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (func $~lib/rt/tlsf/prepareBlock (; 18 ;) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) (local $5 i32) @@ -1569,10 +1572,9 @@ i32.store end ) - (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) + (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1614,12 +1616,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1639,12 +1635,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1687,8 +1677,10 @@ local.get $2 call $~lib/rt/tlsf/prepareBlock local.get $3 + call $~lib/rt/rtrace/onalloc + local.get $3 ) - (func $~lib/rt/tlsf/__alloc (; 16 ;) (param $0 i32) (param $1 i32) (result i32) + (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 @@ -1701,7 +1693,7 @@ i32.const 16 i32.add ) - (func $~lib/rt/pure/increment (; 17 ;) (param $0 i32) + (func $~lib/rt/pure/increment (; 21 ;) (param $0 i32) (local $1 i32) local.get $0 i32.load offset=4 @@ -1730,6 +1722,8 @@ i32.add i32.store offset=4 local.get $0 + call $~lib/rt/rtrace/onincrement + local.get $0 i32.load i32.const 1 i32.and @@ -1744,7 +1738,7 @@ unreachable end ) - (func $~lib/rt/pure/__retain (; 18 ;) (param $0 i32) (result i32) + (func $~lib/rt/pure/__retain (; 22 ;) (param $0 i32) (result i32) local.get $0 global.get $~lib/heap/__heap_base i32.gt_u @@ -1756,7 +1750,37 @@ end local.get $0 ) - (func $~lib/rt/__typeinfo (; 19 ;) (param $0 i32) (result i32) + (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 @@ -1781,7 +1805,7 @@ i32.add i32.load ) - (func $~lib/util/memory/memcpy (; 20 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (func $~lib/util/memory/memcpy (; 27 ;) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) (local $5 i32) @@ -2805,7 +2829,7 @@ i32.store8 end ) - (func $~lib/memory/memory.copy (; 21 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (func $~lib/memory/memory.copy (; 28 ;) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) (local $4 i32) (local $5 i32) @@ -3025,7 +3049,7 @@ end end ) - (func $~lib/rt/tlsf/__free (; 22 ;) (param $0 i32) + (func $~lib/rt/tlsf/__free (; 29 ;) (param $0 i32) local.get $0 i32.const 0 i32.ne @@ -3052,7 +3076,7 @@ i32.sub call $~lib/rt/tlsf/freeBlock ) - (func $~lib/rt/pure/growRoots (; 23 ;) + (func $~lib/rt/pure/growRoots (; 30 ;) (local $0 i32) (local $1 i32) (local $2 i32) @@ -3083,11 +3107,19 @@ 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 @@ -3102,7 +3134,7 @@ i32.add global.set $~lib/rt/pure/END ) - (func $~lib/rt/pure/appendRoot (; 24 ;) (param $0 i32) + (func $~lib/rt/pure/appendRoot (; 31 ;) (param $0 i32) (local $1 i32) global.get $~lib/rt/pure/CUR local.set $1 @@ -3122,7 +3154,7 @@ i32.add global.set $~lib/rt/pure/CUR ) - (func $~lib/rt/pure/decrement (; 25 ;) (param $0 i32) + (func $~lib/rt/pure/decrement (; 32 ;) (param $0 i32) (local $1 i32) (local $2 i32) local.get $0 @@ -3133,6 +3165,8 @@ i32.and local.set $2 local.get $0 + call $~lib/rt/rtrace/ondecrement + local.get $0 i32.load i32.const 1 i32.and @@ -3224,7 +3258,7 @@ end end ) - (func $~lib/rt/pure/__release (; 26 ;) (param $0 i32) + (func $~lib/rt/pure/__release (; 33 ;) (param $0 i32) local.get $0 global.get $~lib/heap/__heap_base i32.gt_u @@ -3235,37 +3269,7 @@ call $~lib/rt/pure/decrement end ) - (func $managed-cast/Animal#constructor (; 27 ;) (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 (; 28 ;) (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 (; 29 ;) (param $0 i32) - nop - ) - (func $managed-cast/testDowncast (; 30 ;) (param $0 i32) + (func $managed-cast/testDowncast (; 34 ;) (param $0 i32) local.get $0 call $~lib/rt/pure/__retain local.set $0 @@ -3274,7 +3278,7 @@ local.get $0 call $~lib/rt/pure/__release ) - (func $managed-cast/testDowncastFromNullable (; 31 ;) (param $0 i32) + (func $managed-cast/testDowncastFromNullable (; 35 ;) (param $0 i32) (local $1 i32) local.get $0 call $~lib/rt/pure/__retain @@ -3284,13 +3288,18 @@ 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 (; 32 ;) (param $0 i32) + (func $managed-cast/testDowncastToNullable (; 36 ;) (param $0 i32) (local $1 i32) local.get $0 call $~lib/rt/pure/__retain @@ -3308,7 +3317,7 @@ local.get $1 call $~lib/rt/pure/__release ) - (func $managed-cast/testDowncastFromToNullable (; 33 ;) (param $0 i32) + (func $managed-cast/testDowncastFromToNullable (; 37 ;) (param $0 i32) (local $1 i32) local.get $0 call $~lib/rt/pure/__retain @@ -3326,7 +3335,7 @@ local.get $1 call $~lib/rt/pure/__release ) - (func $~lib/rt/__instanceof (; 34 ;) (param $0 i32) (param $1 i32) (result i32) + (func $~lib/rt/__instanceof (; 38 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) (local $4 i32) @@ -3366,10 +3375,10 @@ end i32.const 0 ) - (func $managed-cast/Cat#meow (; 35 ;) (param $0 i32) + (func $managed-cast/Cat#meow (; 39 ;) (param $0 i32) nop ) - (func $managed-cast/testUpcast (; 36 ;) (param $0 i32) + (func $managed-cast/testUpcast (; 40 ;) (param $0 i32) (local $1 i32) local.get $0 call $~lib/rt/pure/__retain @@ -3381,13 +3390,18 @@ 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 (; 37 ;) (param $0 i32) + (func $managed-cast/testUpcastFromNullable (; 41 ;) (param $0 i32) (local $1 i32) local.get $0 call $~lib/rt/pure/__retain @@ -3397,6 +3411,11 @@ 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 @@ -3405,13 +3424,18 @@ 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 (; 38 ;) (param $0 i32) + (func $managed-cast/testUpcastToNullable (; 42 ;) (param $0 i32) (local $1 i32) (local $2 i32) local.get $0 @@ -3424,6 +3448,11 @@ 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 @@ -3438,7 +3467,7 @@ local.get $2 call $~lib/rt/pure/__release ) - (func $managed-cast/testUpcastFromToNullable (; 39 ;) (param $0 i32) + (func $managed-cast/testUpcastFromToNullable (; 43 ;) (param $0 i32) (local $1 i32) (local $2 i32) local.get $0 @@ -3451,6 +3480,11 @@ 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 @@ -3465,7 +3499,7 @@ local.get $2 call $~lib/rt/pure/__release ) - (func $start:managed-cast (; 40 ;) + (func $start:managed-cast (; 44 ;) (local $0 i32) (local $1 i32) (local $2 i32) @@ -3523,10 +3557,17 @@ local.get $7 call $~lib/rt/pure/__release ) - (func $~start (; 41 ;) + (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 (; 42 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/pure/__visit (; 46 ;) (param $0 i32) (param $1 i32) (local $2 i32) (local $3 i32) local.get $0 @@ -3656,7 +3697,7 @@ end end ) - (func $~lib/rt/__visit_members (; 43 ;) (param $0 i32) (param $1 i32) + (func $~lib/rt/__visit_members (; 47 ;) (param $0 i32) (param $1 i32) (local $2 i32) block $switch$1$default block $switch$1$case$4 diff --git a/tests/compiler/rc/global-init.untouched.wat b/tests/compiler/rc/global-init.untouched.wat index ce6fe3e72c..e633ed7976 100644 --- a/tests/compiler/rc/global-init.untouched.wat +++ b/tests/compiler/rc/global-init.untouched.wat @@ -1661,7 +1661,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 23 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1703,12 +1702,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1728,12 +1721,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/local-init.optimized.wat b/tests/compiler/rc/local-init.optimized.wat index f92a9950d9..5fdd6c1451 100644 --- a/tests/compiler/rc/local-init.optimized.wat +++ b/tests/compiler/rc/local-init.optimized.wat @@ -1280,11 +1280,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 96 diff --git a/tests/compiler/rc/local-init.untouched.wat b/tests/compiler/rc/local-init.untouched.wat index be1656d091..665e5d02e7 100644 --- a/tests/compiler/rc/local-init.untouched.wat +++ b/tests/compiler/rc/local-init.untouched.wat @@ -1599,7 +1599,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 20 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1641,12 +1640,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1666,12 +1659,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/logical-and-mismatch.optimized.wat b/tests/compiler/rc/logical-and-mismatch.optimized.wat index 49abdda31a..028e2b64d8 100644 --- a/tests/compiler/rc/logical-and-mismatch.optimized.wat +++ b/tests/compiler/rc/logical-and-mismatch.optimized.wat @@ -1260,11 +1260,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/logical-and-mismatch.untouched.wat b/tests/compiler/rc/logical-and-mismatch.untouched.wat index 5cedb445b1..8298354b0c 100644 --- a/tests/compiler/rc/logical-and-mismatch.untouched.wat +++ b/tests/compiler/rc/logical-and-mismatch.untouched.wat @@ -1574,7 +1574,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1616,12 +1615,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1641,12 +1634,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/logical-or-mismatch.optimized.wat b/tests/compiler/rc/logical-or-mismatch.optimized.wat index 4187069152..f1ba740510 100644 --- a/tests/compiler/rc/logical-or-mismatch.optimized.wat +++ b/tests/compiler/rc/logical-or-mismatch.optimized.wat @@ -1260,11 +1260,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/logical-or-mismatch.untouched.wat b/tests/compiler/rc/logical-or-mismatch.untouched.wat index 1563c30088..56b270725e 100644 --- a/tests/compiler/rc/logical-or-mismatch.untouched.wat +++ b/tests/compiler/rc/logical-or-mismatch.untouched.wat @@ -1574,7 +1574,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1616,12 +1615,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1641,12 +1634,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/optimize.optimized.wat b/tests/compiler/rc/optimize.optimized.wat index f0a9e538e1..7bac65c3aa 100644 --- a/tests/compiler/rc/optimize.optimized.wat +++ b/tests/compiler/rc/optimize.optimized.wat @@ -1351,11 +1351,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 80 diff --git a/tests/compiler/rc/optimize.untouched.wat b/tests/compiler/rc/optimize.untouched.wat index 129b5b03c7..ad1efd71fb 100644 --- a/tests/compiler/rc/optimize.untouched.wat +++ b/tests/compiler/rc/optimize.untouched.wat @@ -1669,7 +1669,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 25 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1711,12 +1710,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1736,12 +1729,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/rereturn.optimized.wat b/tests/compiler/rc/rereturn.optimized.wat index e194ee7923..efa1c3e6cd 100644 --- a/tests/compiler/rc/rereturn.optimized.wat +++ b/tests/compiler/rc/rereturn.optimized.wat @@ -1258,11 +1258,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/rereturn.untouched.wat b/tests/compiler/rc/rereturn.untouched.wat index f949d2511b..5989bbf377 100644 --- a/tests/compiler/rc/rereturn.untouched.wat +++ b/tests/compiler/rc/rereturn.untouched.wat @@ -1572,7 +1572,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1614,12 +1613,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1639,12 +1632,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/rc/ternary-mismatch.optimized.wat b/tests/compiler/rc/ternary-mismatch.optimized.wat index 2b9c7b0935..7e8310abf3 100644 --- a/tests/compiler/rc/ternary-mismatch.optimized.wat +++ b/tests/compiler/rc/ternary-mismatch.optimized.wat @@ -1262,11 +1262,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/rc/ternary-mismatch.untouched.wat b/tests/compiler/rc/ternary-mismatch.untouched.wat index 95cfc0f13b..ce9ccf2a2c 100644 --- a/tests/compiler/rc/ternary-mismatch.untouched.wat +++ b/tests/compiler/rc/ternary-mismatch.untouched.wat @@ -1576,7 +1576,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1618,12 +1617,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1643,12 +1636,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/resolve-ternary.optimized.wat b/tests/compiler/resolve-ternary.optimized.wat index dd87efa42a..0a838332c0 100644 --- a/tests/compiler/resolve-ternary.optimized.wat +++ b/tests/compiler/resolve-ternary.optimized.wat @@ -1284,11 +1284,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/resolve-ternary.untouched.wat b/tests/compiler/resolve-ternary.untouched.wat index c45c226c2e..02aaa3dcf5 100644 --- a/tests/compiler/resolve-ternary.untouched.wat +++ b/tests/compiler/resolve-ternary.untouched.wat @@ -1607,7 +1607,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1649,12 +1648,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1674,12 +1667,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/retain-release-sanity.optimized.wat b/tests/compiler/retain-release-sanity.optimized.wat index 3e55ec5d9c..381f7a97fa 100644 --- a/tests/compiler/retain-release-sanity.optimized.wat +++ b/tests/compiler/retain-release-sanity.optimized.wat @@ -1269,11 +1269,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/retain-release-sanity.untouched.wat b/tests/compiler/retain-release-sanity.untouched.wat index bc46aaf9b7..0ddb8646a5 100644 --- a/tests/compiler/retain-release-sanity.untouched.wat +++ b/tests/compiler/retain-release-sanity.untouched.wat @@ -1582,7 +1582,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1624,12 +1623,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1649,12 +1642,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/retain-return.optimized.wat b/tests/compiler/retain-return.optimized.wat index 533c90d6b5..9ebd37b214 100644 --- a/tests/compiler/retain-return.optimized.wat +++ b/tests/compiler/retain-return.optimized.wat @@ -1257,11 +1257,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/retain-return.untouched.wat b/tests/compiler/retain-return.untouched.wat index f6ae9a315b..a948bf28ef 100644 --- a/tests/compiler/retain-return.untouched.wat +++ b/tests/compiler/retain-return.untouched.wat @@ -1578,7 +1578,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1620,12 +1619,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1645,12 +1638,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/runtime-full.optimized.wat b/tests/compiler/runtime-full.optimized.wat index 103b0251ec..a6086eecb0 100644 --- a/tests/compiler/runtime-full.optimized.wat +++ b/tests/compiler/runtime-full.optimized.wat @@ -1258,11 +1258,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/runtime-full.untouched.wat b/tests/compiler/runtime-full.untouched.wat index b7b846ab28..ec352a486f 100644 --- a/tests/compiler/runtime-full.untouched.wat +++ b/tests/compiler/runtime-full.untouched.wat @@ -1571,7 +1571,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 15 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1613,12 +1612,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1638,12 +1631,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/array-literal.optimized.wat b/tests/compiler/std/array-literal.optimized.wat index bcedfbf3dd..d9f48e614e 100644 --- a/tests/compiler/std/array-literal.optimized.wat +++ b/tests/compiler/std/array-literal.optimized.wat @@ -1313,11 +1313,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 384 diff --git a/tests/compiler/std/array-literal.untouched.wat b/tests/compiler/std/array-literal.untouched.wat index 71a94ee773..44da5ed355 100644 --- a/tests/compiler/std/array-literal.untouched.wat +++ b/tests/compiler/std/array-literal.untouched.wat @@ -1656,7 +1656,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 25 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1698,12 +1697,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1723,12 +1716,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/array.optimized.wat b/tests/compiler/std/array.optimized.wat index 1933b0e403..5006934d88 100644 --- a/tests/compiler/std/array.optimized.wat +++ b/tests/compiler/std/array.optimized.wat @@ -1478,11 +1478,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 144 @@ -13935,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 @@ -13979,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 cc5f13eb67..cbcf719961 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -1793,7 +1793,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 20 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1835,12 +1834,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1860,12 +1853,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -21757,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 @@ -21807,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/arraybuffer.optimized.wat b/tests/compiler/std/arraybuffer.optimized.wat index 0dd81ec797..1a6814a69d 100644 --- a/tests/compiler/std/arraybuffer.optimized.wat +++ b/tests/compiler/std/arraybuffer.optimized.wat @@ -1267,11 +1267,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/std/arraybuffer.untouched.wat b/tests/compiler/std/arraybuffer.untouched.wat index 7d19191121..4557a886b9 100644 --- a/tests/compiler/std/arraybuffer.untouched.wat +++ b/tests/compiler/std/arraybuffer.untouched.wat @@ -1581,7 +1581,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1623,12 +1622,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1648,12 +1641,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/dataview.optimized.wat b/tests/compiler/std/dataview.optimized.wat index ac7b54985a..df21c1f34d 100644 --- a/tests/compiler/std/dataview.optimized.wat +++ b/tests/compiler/std/dataview.optimized.wat @@ -1274,11 +1274,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/std/dataview.untouched.wat b/tests/compiler/std/dataview.untouched.wat index 148920c431..aeeab0af52 100644 --- a/tests/compiler/std/dataview.untouched.wat +++ b/tests/compiler/std/dataview.untouched.wat @@ -1588,7 +1588,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1630,12 +1629,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1655,12 +1648,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/map.optimized.wat b/tests/compiler/std/map.optimized.wat index d03538aa62..b2c80026da 100644 --- a/tests/compiler/std/map.optimized.wat +++ b/tests/compiler/std/map.optimized.wat @@ -1288,11 +1288,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/std/map.untouched.wat b/tests/compiler/std/map.untouched.wat index 012dc52f78..97feb4b9f0 100644 --- a/tests/compiler/std/map.untouched.wat +++ b/tests/compiler/std/map.untouched.wat @@ -1598,7 +1598,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1640,12 +1639,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1665,12 +1658,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/set.optimized.wat b/tests/compiler/std/set.optimized.wat index fcd7743393..96d3e110e1 100644 --- a/tests/compiler/std/set.optimized.wat +++ b/tests/compiler/std/set.optimized.wat @@ -1280,11 +1280,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 32 diff --git a/tests/compiler/std/set.untouched.wat b/tests/compiler/std/set.untouched.wat index 436ac46471..9557c96c67 100644 --- a/tests/compiler/std/set.untouched.wat +++ b/tests/compiler/std/set.untouched.wat @@ -1593,7 +1593,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 19 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1635,12 +1634,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1660,12 +1653,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/string-encoding.optimized.wat b/tests/compiler/std/string-encoding.optimized.wat index 2058a2cf6c..72bb3817d1 100644 --- a/tests/compiler/std/string-encoding.optimized.wat +++ b/tests/compiler/std/string-encoding.optimized.wat @@ -1346,11 +1346,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 112 diff --git a/tests/compiler/std/string-encoding.untouched.wat b/tests/compiler/std/string-encoding.untouched.wat index 5f93500ad6..22582ba2e4 100644 --- a/tests/compiler/std/string-encoding.untouched.wat +++ b/tests/compiler/std/string-encoding.untouched.wat @@ -1670,7 +1670,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 22 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1712,12 +1711,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1737,12 +1730,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/std/string.optimized.wat b/tests/compiler/std/string.optimized.wat index 0a5925baf3..9df5106f8f 100644 --- a/tests/compiler/std/string.optimized.wat +++ b/tests/compiler/std/string.optimized.wat @@ -1819,11 +1819,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 208 diff --git a/tests/compiler/std/string.untouched.wat b/tests/compiler/std/string.untouched.wat index b9712dd5e0..57bfd93372 100644 --- a/tests/compiler/std/string.untouched.wat +++ b/tests/compiler/std/string.untouched.wat @@ -2147,7 +2147,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 25 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2189,12 +2188,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -2214,12 +2207,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz 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 diff --git a/tests/compiler/std/typedarray.optimized.wat b/tests/compiler/std/typedarray.optimized.wat index a44e95385a..7369d651a4 100644 --- a/tests/compiler/std/typedarray.optimized.wat +++ b/tests/compiler/std/typedarray.optimized.wat @@ -1449,11 +1449,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 144 diff --git a/tests/compiler/std/typedarray.untouched.wat b/tests/compiler/std/typedarray.untouched.wat index 42b75e2c33..62d39ac3a0 100644 --- a/tests/compiler/std/typedarray.untouched.wat +++ b/tests/compiler/std/typedarray.untouched.wat @@ -1774,7 +1774,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 20 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -1816,12 +1815,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -1841,12 +1834,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz diff --git a/tests/compiler/while.optimized.wat b/tests/compiler/while.optimized.wat index fa16abfb66..7298eb4246 100644 --- a/tests/compiler/while.optimized.wat +++ b/tests/compiler/while.optimized.wat @@ -1539,11 +1539,6 @@ call $~lib/rt/tlsf/searchBlock local.tee $2 i32.eqz - if - unreachable - end - local.get $2 - i32.eqz if i32.const 0 i32.const 64 diff --git a/tests/compiler/while.untouched.wat b/tests/compiler/while.untouched.wat index 31a99328c8..48d5103b3e 100644 --- a/tests/compiler/while.untouched.wat +++ b/tests/compiler/while.untouched.wat @@ -2003,7 +2003,6 @@ (func $~lib/rt/tlsf/allocateBlock (; 28 ;) (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (local $4 i32) global.get $~lib/rt/tlsf/collectLock i32.eqz i32.eqz @@ -2045,12 +2044,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz @@ -2070,12 +2063,6 @@ local.get $0 local.get $2 call $~lib/rt/tlsf/searchBlock - local.tee $4 - if (result i32) - local.get $4 - else - unreachable - end local.set $3 local.get $3 i32.eqz From fc6f45492d2282c54b97a26dcebeb1d939cbe20d Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 18 Jan 2020 19:08:03 +0100 Subject: [PATCH 7/8] upcast must be explicit --- src/compiler.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 87ff6a97b1..4922a22d36 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -3141,8 +3141,9 @@ export class Compiler extends DiagnosticEmitter { assert(fromType.kind == toType.kind); this.currentType = toType; return expr; - } else if (toType.nonNullableType.isAssignableTo(fromType)) { // upcast - // (animal) + } + if (explicit && toType.nonNullableType.isAssignableTo(fromType)) { // upcast + // (maybeCat) assert(fromType.kind == toType.kind); if (!this.options.noAssert) { expr = this.makeRuntimeUpcastCheck(expr, fromType, toType, reportNode); From de94c1d76a6f45bba5cc40fc74824a41a4b1bc2b Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 18 Jan 2020 21:48:32 +0100 Subject: [PATCH 8/8] refactor abort generation --- src/builtins.ts | 45 +-------------- src/compiler.ts | 150 ++++++++++++++++++++++++++++++------------------ 2 files changed, 96 insertions(+), 99 deletions(-) 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 4922a22d36..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); } @@ -3318,59 +3319,6 @@ export class Compiler extends DiagnosticEmitter { : expr; } - /** Makes a runtime non-null check. */ - private 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()), - compileAbort(this, null, reportNode) // TODO: throw - ); - flow.freeTempLocal(temp); - return expr; - } - - /** Makes a runtime upcast check. */ - private 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()), - compileAbort(this, null, reportNode) // TODO: throw - ); - flow.freeTempLocal(temp); - return expr; - } - private compileAssertionExpression( expression: AssertionExpression, contextualType: Type, @@ -9446,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