[WASM] Use wasm bottom types for Nothing?

This commit is contained in:
Igor Yakovlev
2022-09-10 16:06:54 +02:00
committed by teamcity
parent 3e6f153fe5
commit a7ed496a04
6 changed files with 22 additions and 48 deletions
@@ -427,12 +427,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",
@@ -661,6 +655,5 @@ val wasmPhases = NamedCompilerPhase(
virtualDispatchReceiverExtractionPhase then
staticMembersLoweringPhase then
wasmNullSpecializationLowering then
validateIrAfterLowering
)
@@ -589,8 +589,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()
body.buildRefNull(WasmHeapType.Simple.NullNoExtern)
}
return
}
val expectedClassErased = expectedType.getRuntimeClass(irBuiltIns)
@@ -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
@@ -442,13 +443,14 @@ class DeclarationGenerator(
}
}
fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder) = when (type) {
WasmI32 -> g.buildConstI32(0)
WasmI64 -> g.buildConstI64(0)
WasmF32 -> g.buildConstF32(0f)
WasmF64 -> g.buildConstF64(0.0)
is WasmRefNullType -> g.buildRefNull(type.heapType)
is WasmRefNullNoneType -> g.buildRefNull(WasmHeapType.Simple.NullNone)
is WasmRefNullExternrefType -> g.buildRefNull(WasmHeapType.Simple.NullNoExtern)
is WasmAnyRef -> g.buildRefNull(WasmHeapType.Simple.Any)
is WasmExternRef -> g.buildRefNull(WasmHeapType.Simple.Extern)
WasmUnreachableType -> error("Unreachable type can't be initialized")
@@ -466,7 +468,10 @@ fun IrFunction.isExported(): Boolean =
fun generateConstExpression(expression: IrConst<*>, body: WasmExpressionBuilder, context: WasmBaseCodegenContext) {
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, WasmImmediate.HeapType(bottomType))
}
is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0)
is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt())
is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt())
@@ -82,7 +82,7 @@ class WasmTypeTransformer(
WasmF64
builtIns.nothingNType ->
WasmAnyRef
WasmRefNullNoneType
// Value will not be created. Just using a random Wasm type.
builtIns.nothingType ->
@@ -1,35 +0,0 @@
/*
* 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
/**
* 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
}
@@ -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