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 d1a1df52c65..1eaaa3d77db 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 @@ -536,10 +536,13 @@ class BodyGenerator( body.buildGetLocal(parameterLocal, location) body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1), location) - body.buildBrInstr( + body.buildBrOnCastInstr( WasmOp.BR_ON_CAST_FAIL, innerLabel, - classITable, + fromIsNullable = true, + toIsNullable = false, + from = WasmHeapType.Simple.Struct, + to = WasmHeapType.Type(classITable), location, ) @@ -599,10 +602,13 @@ class BodyGenerator( body.buildGetLocal(functionContext.referenceLocal(0), location) body.buildInstr(WasmOp.EXTERN_INTERNALIZE, location) - body.buildBrInstr( + body.buildBrOnCastInstr( WasmOp.BR_ON_CAST_FAIL, innerLabel, - context.referenceGcType(backendContext.irBuiltIns.anyClass), + fromIsNullable = true, + toIsNullable = true, + from = WasmHeapType.Simple.Any, + to = WasmHeapType.Type(context.referenceGcType(backendContext.irBuiltIns.anyClass)), location, ) diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt index 808cfd479df..afc5eb0a0e7 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt @@ -153,8 +153,7 @@ internal fun isNullish(ref: ExternalInterfaceType?): Boolean = * block (result anyref) { * local.get 0 * extern.internalize -* br_on_non_data_fail 0 -* br_on_cast_fail 0 (type $kotlin.Any) +* br_on_cast_fail 0000_0011b 0 (type any) (type $kotlin.Any) * return * } * ``` diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Operators.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Operators.kt index 14202728066..1ba6dbeb9f2 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Operators.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Operators.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.wasm.ir import org.jetbrains.kotlin.wasm.ir.WasmImmediateKind.* enum class WasmImmediateKind { + CONST_U8, CONST_I32, CONST_I64, CONST_F32, @@ -38,6 +39,7 @@ enum class WasmImmediateKind { } sealed class WasmImmediate { + class ConstU8(val value: UByte) : WasmImmediate() class ConstI32(val value: Int) : WasmImmediate() class ConstI64(val value: Long) : WasmImmediate() class ConstF32(val rawBits: UInt) : WasmImmediate() @@ -379,8 +381,8 @@ enum class WasmOp( REF_CAST("ref.cast", 0xFB_41, HEAP_TYPE), REF_CAST_NULL("ref.cast null", 0xFB_49, HEAP_TYPE), - BR_ON_CAST("br_on_cast", 0xFB_42, listOf(LABEL_IDX, HEAP_TYPE)), - BR_ON_CAST_FAIL("br_on_cast_fail", 0xFB_43, listOf(LABEL_IDX, HEAP_TYPE)), + BR_ON_CAST("br_on_cast", 0xFB_4E, listOf(CONST_U8, LABEL_IDX, HEAP_TYPE, HEAP_TYPE)), + BR_ON_CAST_FAIL("br_on_cast_fail", 0xFB_4F, listOf(CONST_U8, LABEL_IDX, HEAP_TYPE, HEAP_TYPE)), EXTERN_INTERNALIZE("extern.internalize", 0xfb70), // externref -> anyref EXTERN_EXTERNALIZE("extern.externalize", 0xfb71), // anyref -> externref diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt index 1de080746ce..67e3a1ee9cc 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt @@ -95,10 +95,30 @@ abstract class WasmExpressionBuilder { buildInstr(brOp, location, WasmImmediate.LabelIdx(relativeLevel)) } - fun buildBrInstr(brOp: WasmOp, absoluteBlockLevel: Int, symbol: WasmSymbolReadOnly, location: SourceLocation) { + fun buildBrOnCastInstr( + brOp: WasmOp, + absoluteBlockLevel: Int, + fromIsNullable: Boolean, + toIsNullable: Boolean, + from: WasmHeapType, + to: WasmHeapType, + location: SourceLocation, + ) { val relativeLevel = numberOfNestedBlocks - absoluteBlockLevel assert(relativeLevel >= 0) { "Negative relative block index" } - buildInstr(brOp, location, WasmImmediate.LabelIdx(relativeLevel), WasmImmediate.HeapType(WasmHeapType.Type(symbol))) + + val fromTypeFlag = if (fromIsNullable) 0b01 else 0 + val toTypeFlag = if (toIsNullable) 0b10 else 0 + val flags = fromTypeFlag or toTypeFlag + + buildInstr( + brOp, + location, + WasmImmediate.ConstU8(flags.toUByte()), + WasmImmediate.LabelIdx(relativeLevel), + WasmImmediate.HeapType(from), + WasmImmediate.HeapType(to) + ) } fun buildBr(absoluteBlockLevel: Int, location: SourceLocation) { diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmBinaryToIR.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmBinaryToIR.kt index cbb29e9a0f4..c17afe6831a 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmBinaryToIR.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmBinaryToIR.kt @@ -409,6 +409,7 @@ class WasmBinaryToIR(val b: MyByteReader) { val immediates = op.immediates.map { when (it) { + WasmImmediateKind.CONST_U8 -> WasmImmediate.ConstU8(b.readUByte()) WasmImmediateKind.CONST_I32 -> WasmImmediate.ConstI32(b.readVarInt32()) WasmImmediateKind.CONST_I64 -> WasmImmediate.ConstI64(b.readVarInt64()) WasmImmediateKind.CONST_F32 -> WasmImmediate.ConstF32(b.readUInt32()) diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt index f4b114113c0..f63daeda78f 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt @@ -267,6 +267,7 @@ class WasmIrToBinary( private fun appendImmediate(x: WasmImmediate) { when (x) { + is WasmImmediate.ConstU8 -> b.writeUByte(x.value) is WasmImmediate.ConstI32 -> b.writeVarInt32(x.value) is WasmImmediate.ConstI64 -> b.writeVarInt64(x.value) is WasmImmediate.ConstF32 -> b.writeUInt32(x.rawBits) @@ -603,6 +604,10 @@ abstract class ByteWriter { abstract fun writeBytes(v: ByteArray) abstract fun createTemp(): ByteWriter + fun writeUByte(v: UByte) { + writeByte(v.toByte()) + } + fun writeUInt32(v: UInt) { writeByte(v.toByte()) writeByte((v shr 8).toByte()) diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt index 1f5b0ebd92d..eb2cd1fe92a 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt @@ -110,6 +110,7 @@ class WasmIrToText : SExpressionBuilder() { private fun appendImmediate(x: WasmImmediate) { when (x) { + is WasmImmediate.ConstU8 -> appendElement(x.value.toString().lowercase()) is WasmImmediate.ConstI32 -> appendElement(x.value.toString().lowercase()) is WasmImmediate.ConstI64 -> appendElement(x.value.toString().lowercase()) is WasmImmediate.ConstF32 -> appendElement(f32Str(x).lowercase())