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 1eaaa3d77db..79b3f0307ba 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 @@ -532,26 +532,24 @@ class BodyGenerator( val parameterLocal = functionContext.referenceLocal(SyntheticLocalType.IS_INTERFACE_PARAMETER) body.buildSetLocal(parameterLocal, location) body.buildBlock("isInterface", WasmI32) { outerLabel -> - body.buildBlock("isInterface", WasmRefNullType(WasmHeapType.Simple.Struct)) { innerLabel -> + body.buildBlock("isInterface") { innerLabel -> body.buildGetLocal(parameterLocal, location) body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1), location) - body.buildBrOnCastInstr( - WasmOp.BR_ON_CAST_FAIL, - innerLabel, - fromIsNullable = true, - toIsNullable = false, - from = WasmHeapType.Simple.Struct, - to = WasmHeapType.Type(classITable), - location, - ) + val tmpLocal = functionContext.referenceLocal(SyntheticLocalType.TMP_FOR_BR_ON_CAST_EMULATION) + body.buildInstr(WasmOp.LOCAL_TEE, location, WasmImmediate.LocalIdx(tmpLocal)) + body.buildRefTestStatic(classITable, location) + body.buildInstr(WasmOp.I32_EQZ, location) + body.buildBrIf(innerLabel, location) + + body.buildGetLocal(tmpLocal, location) + body.buildRefCastStatic(classITable, location) body.buildStructGet(classITable, context.referenceClassITableInterfaceSlot(irInterface.symbol), location) body.buildInstr(WasmOp.REF_IS_NULL, location) body.buildInstr(WasmOp.I32_EQZ, location) body.buildBr(outerLabel, location) } - body.buildDrop(location) body.buildConstI32(0, location) } } else { @@ -598,23 +596,23 @@ class BodyGenerator( } wasmSymbols.returnArgumentIfItIsKotlinAny -> { - body.buildBlock("returnIfAny", WasmAnyRef) { innerLabel -> + body.buildBlock("returnIfAny") { innerLabel -> body.buildGetLocal(functionContext.referenceLocal(0), location) body.buildInstr(WasmOp.EXTERN_INTERNALIZE, location) - body.buildBrOnCastInstr( - WasmOp.BR_ON_CAST_FAIL, - innerLabel, - fromIsNullable = true, - toIsNullable = true, - from = WasmHeapType.Simple.Any, - to = WasmHeapType.Type(context.referenceGcType(backendContext.irBuiltIns.anyClass)), - location, - ) + val tmpLocal = functionContext.referenceLocal(SyntheticLocalType.TMP_FOR_BR_ON_CAST_EMULATION) + body.buildInstr(WasmOp.LOCAL_TEE, location, WasmImmediate.LocalIdx(tmpLocal)) + + val toType = context.referenceGcType(backendContext.irBuiltIns.anyClass) + body.buildRefTestStatic(toType, location) + body.buildInstr(WasmOp.I32_EQZ, location) + body.buildBrIf(innerLabel, location) + + body.buildGetLocal(tmpLocal, location) + body.buildRefCastStatic(toType, location) body.buildInstr(WasmOp.RETURN, location) } - body.buildDrop(location) } wasmSymbols.wasmArrayCopy -> { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt index e38936b6873..86277994bdf 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.wasm.ir.* enum class LoopLabelType { BREAK, CONTINUE } -enum class SyntheticLocalType { IS_INTERFACE_PARAMETER, TABLE_SWITCH_SELECTOR } +enum class SyntheticLocalType { IS_INTERFACE_PARAMETER, TABLE_SWITCH_SELECTOR, TMP_FOR_BR_ON_CAST_EMULATION } class WasmFunctionCodegenContext( val irFunction: IrFunction, @@ -61,6 +61,8 @@ class WasmFunctionCodegenContext( get() = when (this) { SyntheticLocalType.IS_INTERFACE_PARAMETER -> WasmRefNullType(WasmHeapType.Type(context.referenceGcType(backendContext.irBuiltIns.anyClass))) + SyntheticLocalType.TMP_FOR_BR_ON_CAST_EMULATION -> + WasmRefNullType(WasmHeapType.Simple.Any) SyntheticLocalType.TABLE_SWITCH_SELECTOR -> WasmI32 } diff --git a/libraries/stdlib/wasm/src/generated/wasm/internal/_WasmOp.kt b/libraries/stdlib/wasm/src/generated/wasm/internal/_WasmOp.kt index 7c208c521a4..50797946ad8 100644 --- a/libraries/stdlib/wasm/src/generated/wasm/internal/_WasmOp.kt +++ b/libraries/stdlib/wasm/src/generated/wasm/internal/_WasmOp.kt @@ -251,8 +251,6 @@ internal annotation class WasmOp(val name: String) { const val REF_TEST_NULL = "REF_TEST_NULL" const val REF_CAST = "REF_CAST" const val REF_CAST_NULL = "REF_CAST_NULL" - const val BR_ON_CAST = "BR_ON_CAST" - const val BR_ON_CAST_FAIL = "BR_ON_CAST_FAIL" const val EXTERN_INTERNALIZE = "EXTERN_INTERNALIZE" const val EXTERN_EXTERNALIZE = "EXTERN_EXTERNALIZE" const val PSEUDO_COMMENT_PREVIOUS_INSTR = "PSEUDO_COMMENT_PREVIOUS_INSTR" 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 1ba6dbeb9f2..cdfb9474469 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 @@ -381,8 +381,9 @@ 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_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)), +// TODO: KT-60828 Return br_on_cast_fail usages when it's possible +// 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