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 c470ec74c16..7ea30eed0c2 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 @@ -466,12 +466,6 @@ 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", @@ -715,6 +709,5 @@ 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 90444f18cf7..d7844985bd2 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.Type(wasmGcType), location) // this = null + body.buildRefNull(WasmHeapType.Simple.NullNone, location) // this = null generateCall(expression) } @@ -747,8 +747,14 @@ class BodyGenerator( // NOTHING -> TYPE -> TRUE if (actualType.isNothing()) return - // NOTHING? -> TYPE? -> TRUE - if (actualType.isNullableNothing() && expectedType.isNullable()) 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 + } 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 eee8d4ab67a..fa75cb16c6b 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,6 +22,7 @@ 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 @@ -488,6 +489,8 @@ 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,7 +514,10 @@ fun generateConstExpression( location: SourceLocation ) = when (val kind = expression.kind) { - is IrConstKind.Null -> generateDefaultInitializerForType(context.transformType(expression.type), body) + 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.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 f30417a75b2..69dcf0009b4 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 -> - WasmAnyRef + WasmRefNullNoneType // 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 deleted file mode 100644 index 9a33cfe2630..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2010-2023 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.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.lower.AbstractValueUsageLowering -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.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) - if (this is IrConst<*> && this.kind == IrConstKind.Null) - IrConstImpl(this.startOffset, this.endOffset, expectedType, IrConstKind.Null, null) - else - 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 963617653a8..bdeb999a94b 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,6 +25,8 @@ 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) @@ -47,8 +49,9 @@ 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)})" @@ -66,6 +69,8 @@ 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