From 1d793f7bec82ed3ca1cba760c92acead1b31f20b Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Thu, 26 Jan 2023 18:22:23 +0100 Subject: [PATCH] [Wasm] Revert a7ed496a and few fixes to make Kotlin/Wasm compatible with Firefox Revert changes as soon as the bug is fixed https://bugzilla.mozilla.org/show_bug.cgi?id=1811932 a7ed496a "[WASM] Use wasm bottom types for Nothing?" #KT-56166 In-Progress --- .../kotlin/backend/wasm/WasmLoweringPhases.kt | 7 ++++ .../backend/wasm/ir2wasm/BodyGenerator.kt | 12 ++----- .../wasm/ir2wasm/DeclarationGenerator.kt | 8 +---- .../backend/wasm/ir2wasm/TypeTransformer.kt | 2 +- .../wasm/lower/WasmNullCoercionLowering.kt | 36 +++++++++++++++++++ .../src/org/jetbrains/kotlin/wasm/ir/Types.kt | 7 +--- 6 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt index 797d70595e9..537d4d75933 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt @@ -427,6 +427,12 @@ private val autoboxingTransformerPhase = makeWasmModulePhase( description = "Insert box/unbox intrinsics" ) +private val wasmNullSpecializationLowering = makeWasmModulePhase( + { context -> WasmNullCoercingLowering(context) }, + name = "WasmNullCoercingLowering", + description = "Specialize assigning Nothing? values to other types." +) + private val staticMembersLoweringPhase = makeWasmModulePhase( ::StaticMembersLowering, name = "StaticMembersLowering", @@ -655,5 +661,6 @@ val wasmPhases = SameTypeNamedCompilerPhase( virtualDispatchReceiverExtractionPhase then staticMembersLoweringPhase then + wasmNullSpecializationLowering then validateIrAfterLowering ) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt index 7f7e9f20914..5da097f4801 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt @@ -303,7 +303,7 @@ class BodyGenerator( return } - body.buildRefNull(WasmHeapType.Simple.NullNone, location) // this = null + body.buildRefNull(WasmHeapType.Type(wasmGcType), location) // this = null generateCall(expression) } @@ -725,14 +725,8 @@ class BodyGenerator( // NOTHING -> TYPE -> TRUE if (actualType.isNothing()) return - // NOTHING? -> TYPE? -> (NOTHING?)NULL - if (actualType.isNullableNothing() && expectedType.isNullable()) { - if (expectedType.getClass()?.isExternal == true) { - body.buildDrop(location) - body.buildRefNull(WasmHeapType.Simple.NullNoExtern, location) - } - return - } + // NOTHING? -> TYPE? -> TRUE + if (actualType.isNullableNothing() && expectedType.isNullable()) return val expectedClassErased = expectedType.getRuntimeClass(irBuiltIns) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt index 5083bf93596..af7902c53f1 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrClassSymbol -import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -486,8 +485,6 @@ fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder) WasmF32 -> g.buildConstF32(0f, location) WasmF64 -> g.buildConstF64(0.0, location) is WasmRefNullType -> g.buildRefNull(type.heapType, location) - is WasmRefNullNoneType -> g.buildRefNull(WasmHeapType.Simple.NullNone, location) - is WasmRefNullExternrefType -> g.buildRefNull(WasmHeapType.Simple.NullNoExtern, location) is WasmAnyRef -> g.buildRefNull(WasmHeapType.Simple.Any, location) is WasmExternRef -> g.buildRefNull(WasmHeapType.Simple.Extern, location) WasmUnreachableType -> error("Unreachable type can't be initialized") @@ -511,10 +508,7 @@ fun generateConstExpression( location: SourceLocation ) = when (val kind = expression.kind) { - is IrConstKind.Null -> { - val bottomType = if (expression.type.getClass()?.isExternal == true) WasmRefNullExternrefType else WasmRefNullNoneType - body.buildInstr(WasmOp.REF_NULL, location, WasmImmediate.HeapType(bottomType)) - } + is IrConstKind.Null -> generateDefaultInitializerForType(context.transformType(expression.type), body) is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0, location) is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt(), location) is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt(), location) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt index 69dcf0009b4..f30417a75b2 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt @@ -82,7 +82,7 @@ class WasmTypeTransformer( WasmF64 builtIns.nothingNType -> - WasmRefNullNoneType + WasmAnyRef // Value will not be created. Just using a random Wasm type. builtIns.nothingType -> diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt new file mode 100644 index 00000000000..82d550e0e14 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.lower + +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.backend.js.lower.AbstractValueUsageLowering +import org.jetbrains.kotlin.ir.expressions.IrConstKind +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.types.isNullable +import org.jetbrains.kotlin.ir.types.makeNotNull + +// TODO revert the commit where this was reintroduced as soon the bug in the Firefox is fixed https://bugzilla.mozilla.org/show_bug.cgi?id=1811932 +/** + * Replace null constants of type Nothing? with null constants of a concrete class types. + * + * Wasm GC doesn't have a nullref type anymore. + */ +class WasmNullCoercingLowering(private val contextx: WasmBackendContext) : AbstractValueUsageLowering(contextx) { + override fun IrExpression.useExpressionAsType(actualType: IrType, expectedType: IrType): IrExpression = + if (actualType.makeNotNull().isNothing() && actualType.isNullable() && !expectedType.makeNotNull().isNothing() && expectedType != contextx.wasmSymbols.voidType) + JsIrBuilder.buildComposite( + expectedType, + listOf(this, IrConstImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expectedType, IrConstKind.Null, null)) + ) + else + this +} \ No newline at end of file diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt index bdeb999a94b..963617653a8 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt @@ -25,8 +25,6 @@ object WasmFuncRef : WasmType("funcref", -0x10) object WasmExternRef : WasmType("externref", -0x11) object WasmAnyRef : WasmType("anyref", -0x12) object WasmEqRef : WasmType("eqref", -0x13) -object WasmRefNullNoneType : WasmType("nullnone", -0x1b) -object WasmRefNullExternrefType : WasmType("nullexternref", -0x17) data class WasmRefNullType(val heapType: WasmHeapType) : WasmType("ref null", -0x14) data class WasmRefType(val heapType: WasmHeapType) : WasmType("ref", -0x15) @@ -49,9 +47,8 @@ sealed class WasmHeapType { object Extern : Simple("extern", -0x11) object Any : Simple("any", -0x12) object Eq : Simple("eq", -0x13) + object Data : Simple("data", -0x19) - object NullNone : Simple("nullref", -0x1b) - object NullNoExtern : Simple("nullexternref", -0x17) override fun toString(): String { return "Simple:$name(${code.toString(16)})" @@ -69,8 +66,6 @@ fun WasmType.getHeapType(): WasmHeapType = when (this) { is WasmRefType -> heapType is WasmRefNullType -> heapType - is WasmRefNullNoneType -> WasmHeapType.Simple.NullNone - is WasmRefNullExternrefType -> WasmHeapType.Simple.NullNoExtern is WasmEqRef -> WasmHeapType.Simple.Eq is WasmAnyRef -> WasmHeapType.Simple.Any is WasmFuncRef -> WasmHeapType.Simple.Func