[Wasm] Revert ref cast and test instructions to be compatible with Binaryen

This commit is contained in:
Zalim Bashorov
2022-11-17 19:19:41 +01:00
parent 5f140dac21
commit 7f8f7aa050
7 changed files with 41 additions and 26 deletions
@@ -179,8 +179,8 @@ class WasmSymbols(
val refEq = getInternalFunction("wasm_ref_eq")
val refIsNull = getInternalFunction("wasm_ref_is_null")
val externRefIsNull = getInternalFunction("wasm_externref_is_null")
val refTest = getInternalFunction("wasm_ref_test")
val refCastNull = getInternalFunction("wasm_ref_cast_null")
val refTest = getInternalFunction("wasm_ref_test_deprecated")
val refCastNull = getInternalFunction("wasm_ref_cast_deprecated")
val wasmArrayCopy = getInternalFunction("wasm_array_copy")
val wasmArrayNewData0 = getInternalFunction("array_new_data0")
@@ -492,7 +492,7 @@ class BodyGenerator(
body.buildBlock("isInterface", WasmRefNullType(WasmHeapType.Simple.Data)) { innerLabel ->
body.buildGetLocal(parameterLocal)
body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1))
body.buildBrInstr(WasmOp.BR_ON_CAST_FAIL, innerLabel, classITable)
body.buildBrInstr(WasmOp.BR_ON_CAST_FAIL_DEPRECATED, innerLabel, classITable)
body.buildStructGet(classITable, context.referenceClassITableInterfaceSlot(irInterface.symbol))
body.buildInstr(WasmOp.REF_IS_NULL)
body.buildInstr(WasmOp.I32_EQZ)
@@ -146,8 +146,11 @@ internal fun externRefToAny(ref: ExternalInterfaceType): Any? {
// }
// If ref is an instance of kotlin class -- return it casted to Any
val refAsAnyref = ref.externAsWasmAnyref()
if (wasm_ref_test_null<Any>(refAsAnyref)) {
return wasm_ref_cast_null<Any>(refAsAnyref)
if (wasm_ref_is_data_deprecated(refAsAnyref)) {
val refAsDataRef = wasm_ref_as_data_deprecated(refAsAnyref)
if (wasm_ref_test_deprecated<Any>(refAsDataRef)) {
return wasm_ref_cast_deprecated<Any>(refAsDataRef)
}
}
// If we have Null in notNullRef -- return null
@@ -20,16 +20,11 @@ internal fun wasm_unreachable(): Nothing =
implementedAsIntrinsic
@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE")
internal fun <reified To> wasm_ref_cast_null(a: Any?): To =
internal fun <reified To> wasm_ref_cast_deprecated(a: Any?): To =
implementedAsIntrinsic
@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE")
internal fun <reified To> wasm_ref_test(a: Any?): Boolean =
implementedAsIntrinsic
@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE")
@WasmOp(WasmOp.REF_TEST_NULL)
internal fun <reified To> wasm_ref_test_null(a: Any?): Boolean =
internal fun <reified To> wasm_ref_test_deprecated(a: Any?): Boolean =
implementedAsIntrinsic
internal fun <T> wasm_array_copy(destination: T, destinationIndex: Int, source: T, sourceIndex: Int, length: Int): Unit =
@@ -392,3 +387,9 @@ internal external fun wasm_i64_ctz(a: Long): Long
@WasmOp(WasmOp.REF_IS_NULL)
internal external fun wasm_externref_is_null(a: ExternalInterfaceType?): Boolean
@WasmOp(WasmOp.REF_AS_DATA_DEPRECATED)
internal external fun wasm_ref_as_data_deprecated(x: anyref): dataref
@WasmOp(WasmOp.REF_IS_DATA_DEPRECATED)
internal external fun wasm_ref_is_data_deprecated(x: anyref): Boolean
@@ -259,13 +259,13 @@ internal annotation class WasmOp(val name: String) {
const val I31_GET_S = "I31_GET_S"
const val I31_GET_U = "I31_GET_U"
const val REF_EQ = "REF_EQ"
const val REF_TEST = "REF_TEST"
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_FAIL = "BR_ON_CAST_FAIL"
const val EXTERN_INTERNALIZE = "EXTERN_INTERNALIZE"
const val EXTERN_EXTERNALIZE = "EXTERN_EXTERNALIZE"
const val REF_TEST_DEPRECATED = "REF_TEST_DEPRECATED"
const val REF_CAST_DEPRECATED = "REF_CAST_DEPRECATED"
const val REF_IS_DATA_DEPRECATED = "REF_IS_DATA_DEPRECATED"
const val REF_AS_DATA_DEPRECATED = "REF_AS_DATA_DEPRECATED"
const val BR_ON_CAST_FAIL_DEPRECATED = "BR_ON_CAST_FAIL_DEPRECATED"
const val GET_UNIT = "GET_UNIT"
}
}
@@ -372,13 +372,11 @@ enum class WasmOp(
I31_GET_U("i31.get_u", 0xFB_22),
REF_EQ("ref.eq", 0xD5),
REF_TEST("ref.test", 0xFB_40, HEAP_TYPE),
REF_TEST_NULL("ref.test null", 0xFB_48, HEAP_TYPE),
REF_CAST("ref.cast", 0xFB_41, HEAP_TYPE),
REF_CAST_NULL("ref.cast null", 0xFB_49, HEAP_TYPE),
// TODO remove as soon as V8 support new instructions, see below
BR_ON_CAST_FAIL("br_on_cast_fail", 0xfb47, listOf(LABEL_IDX, STRUCT_TYPE_IDX)),
// Not yet supported by Binaryen
// REF_TEST("ref.test", 0xFB_40, HEAP_TYPE),
// REF_TEST_NULL("ref.test null", 0xFB_48, HEAP_TYPE),
// REF_CAST("ref.cast", 0xFB_41, HEAP_TYPE),
// REF_CAST_NULL("ref.cast null", 0xFB_49, HEAP_TYPE),
// Not yet supported by V8
// BR_ON_CAST("br_on_cast", 0xFB42, listOf(LABEL_IDX, HEAP_TYPE)),
@@ -389,6 +387,19 @@ enum class WasmOp(
EXTERN_INTERNALIZE("extern.internalize", 0xfb70), // externref -> anyref
EXTERN_EXTERNALIZE("extern.externalize", 0xfb71), // anyref -> externref
// ------------------------
// Deprecated instructions
// TODO Remove as soon as V8 & Binaryen support new instructions.
// Revert ________.
REF_TEST_DEPRECATED("ref.test", 0xFB_44, STRUCT_TYPE_IDX),
REF_CAST_DEPRECATED("ref.cast", 0xFB_45, STRUCT_TYPE_IDX),
REF_IS_DATA_DEPRECATED("ref.is_data", 0xFB_51),
REF_AS_DATA_DEPRECATED("ref.as_data", 0xFB_59),
BR_ON_CAST_FAIL_DEPRECATED("br_on_cast_fail", 0xFB_47, listOf(LABEL_IDX, STRUCT_TYPE_IDX)),
// ============================================================
// Pseudo-instruction, just alias for a normal call. It's used to easily spot get_unit on the wasm level.
GET_UNIT("call", 0x10, FUNC_IDX)
@@ -157,11 +157,11 @@ abstract class WasmExpressionBuilder {
}
fun buildRefCastNullStatic(toType: WasmSymbolReadOnly<WasmTypeDeclaration>) {
buildInstr(WasmOp.REF_CAST_NULL, WasmImmediate.HeapType(WasmHeapType.Type(toType)))
buildInstr(WasmOp.REF_CAST_DEPRECATED, WasmImmediate.TypeIdx(toType))
}
fun buildRefTestStatic(toType: WasmSymbolReadOnly<WasmTypeDeclaration>) {
buildInstr(WasmOp.REF_TEST, WasmImmediate.HeapType(WasmHeapType.Type(toType)))
buildInstr(WasmOp.REF_TEST_DEPRECATED, WasmImmediate.TypeIdx(toType))
}
fun buildRefNull(type: WasmHeapType) {