From 73a86fffe5eac6d64b9887deedcdd2b58e35847d Mon Sep 17 00:00:00 2001 From: Igor Yakovlev Date: Fri, 22 Apr 2022 16:44:05 +0200 Subject: [PATCH] [WASM] Bootstrap std compatibility fix --- .../kotlin/backend/wasm/WasmSymbols.kt | 2 +- .../backend/wasm/ir2wasm/BodyGenerator.kt | 2 +- .../wasm/lower/WasmTypeOperatorLowering.kt | 2 +- .../internal/kotlin/wasm/internal/TypeInfo.kt | 50 ++++++++++++++++++- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt index a7ca8cc596c..36417c8b7b3 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt @@ -173,7 +173,7 @@ class WasmSymbols( val wasmClassId = getInternalFunction("wasmClassId") val wasmInterfaceId = getInternalFunction("wasmInterfaceId") - val isInterface = getInternalFunction("isInterface") + val wasmIsInterface = getInternalFunction("wasmIsInterface") val nullableEquals = getInternalFunction("nullableEquals") val ensureNotNull = getInternalFunction("ensureNotNull") 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 53614c0b91a..7af7a2494a6 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 @@ -402,7 +402,7 @@ class BodyGenerator( body.buildConstI32Symbol(context.referenceInterfaceId(irInterface.symbol)) } - wasmSymbols.isInterface -> { + wasmSymbols.wasmIsInterface -> { val irInterface = call.getTypeArgument(0)!!.getClass() ?: error("No interface given for wasmInterfaceId intrinsic") assert(irInterface.isInterface) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt index 81320f363bf..7ecece22efe 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt @@ -300,7 +300,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme } private fun generateIsInterface(argument: IrExpression, toType: IrType): IrExpression { - return builder.irCall(symbols.isInterface).apply { + return builder.irCall(symbols.wasmIsInterface).apply { putValueArgument(0, argument) putTypeArgument(0, toType) } diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt index b4005e2b4a3..ff01f74195b 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt @@ -48,7 +48,7 @@ internal fun isInterfaceById(obj: Any, interfaceId: Int): Boolean { } @ExcludedFromCodegen -internal fun isInterface(obj: Any): Boolean = +internal fun wasmIsInterface(obj: Any): Boolean = implementedAsIntrinsic @ExcludedFromCodegen @@ -61,4 +61,50 @@ internal fun wasmInterfaceId(): Int = @ExcludedFromCodegen internal fun wasmGetTypeInfoData(): TypeInfoData = - implementedAsIntrinsic \ No newline at end of file + implementedAsIntrinsic + + +//REMOVE AFTER COMPILER BOOTSTRAP +internal const val TYPE_INFO_ITABLE_PTR_OFFSET = TYPE_INFO_SUPER_TYPE_OFFSET + TYPE_INFO_ELEMENT_SIZE +internal const val TYPE_INFO_VTABLE_LENGTH_OFFSET = TYPE_INFO_ITABLE_PTR_OFFSET + TYPE_INFO_ELEMENT_SIZE +internal const val TYPE_INFO_VTABLE_OFFSET = TYPE_INFO_VTABLE_LENGTH_OFFSET + TYPE_INFO_ELEMENT_SIZE + +internal fun getVtablePtr(obj: Any): Int = + obj.typeInfo + TYPE_INFO_VTABLE_OFFSET + +internal fun getVtableLength(obj: Any): Int = + wasm_i32_load(obj.typeInfo + TYPE_INFO_VTABLE_LENGTH_OFFSET) + +internal fun getItablePtr(obj: Any): Int = + wasm_i32_load(obj.typeInfo + TYPE_INFO_ITABLE_PTR_OFFSET) + +internal fun getInterfaceListLength(itablePtr: Int): Int = + wasm_i32_load(itablePtr + TYPE_INFO_VTABLE_LENGTH_OFFSET) + +internal fun getVirtualMethodId(obj: Any, virtualFunctionSlot: Int): Int { + val vtablePtr = getVtablePtr(obj) + val methodIdPtr = vtablePtr + virtualFunctionSlot * TYPE_INFO_ELEMENT_SIZE + return wasm_i32_load(methodIdPtr) +} + +// Returns -1 if obj does not implement interface +internal fun getInterfaceImplId(obj: Any, interfaceId: Int): Int { + val interfaceListSizePtr = getItablePtr(obj) + val interfaceListPtr = interfaceListSizePtr + TYPE_INFO_ELEMENT_SIZE + val interfaceListSize = wasm_i32_load(interfaceListSizePtr) + + var interfaceSlot = 0 + while (interfaceSlot < interfaceListSize) { + val supportedInterface = wasm_i32_load(interfaceListPtr + interfaceSlot * TYPE_INFO_ELEMENT_SIZE) + if (supportedInterface == interfaceId) { + return wasm_i32_load(interfaceListPtr + interfaceListSize * TYPE_INFO_ELEMENT_SIZE + interfaceSlot * TYPE_INFO_ELEMENT_SIZE) + } + interfaceSlot++ + } + + return -1 +} + +internal fun isInterface(obj: Any, interfaceId: Int): Boolean { + return getInterfaceImplId(obj, interfaceId) != -1 +} \ No newline at end of file