~ Progress
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt index 01dd4071..3251bef 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/dce/WasmUsefulDeclarationProcessor.kt
@@ -46,7 +46,8 @@ } context.wasmSymbols.wasmClassId, context.wasmSymbols.wasmInterfaceId, - context.wasmSymbols.wasmRefCast -> { + context.wasmSymbols.wasmRefCast, + context.wasmSymbols.refTest -> { call.getTypeArgument(0)?.getClass()?.enqueue(from, "generic intrinsic ${call.symbol.owner.name}") true }
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 b269e75..211f0be 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
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.getInlineClassBackingField @@ -217,7 +218,7 @@ generateDefaultInitializerForType(context.transformType(field.type), body) } - body.buildGetGlobal(context.referenceClassRTT(klass.symbol)) + generateClassRTT(klass.symbol) body.buildStructNew(wasmGcType) generateCall(expression) } @@ -247,7 +248,7 @@ body.buildConstI32Symbol(klassId) body.buildConstI32(0) // Any::_hashCode generateExpression(call.getValueArgument(0)!!) - body.buildGetGlobal(context.referenceClassRTT(klass.symbol)) + generateClassRTT(klass.symbol) body.buildStructNew(structTypeName) return } @@ -313,8 +314,12 @@ } private fun generateTypeRTT(type: IrType) { - val rtClass = type.getRuntimeClass?.symbol ?: context.backendContext.irBuiltIns.anyClass - body.buildGetGlobal(context.referenceClassRTT(rtClass)) + val klass = type.getRuntimeClass?.symbol ?: context.backendContext.irBuiltIns.anyClass + generateClassRTT(klass) + } + + private fun generateClassRTT(klass: IrClassSymbol) { + body.buildRttCanon(context.referenceGcType(klass)) } // Return true if generated. @@ -348,6 +353,12 @@ body.buildRefCast() } + wasmSymbols.refTest -> { + val toType = call.getTypeArgument(0)!! + generateTypeRTT(toType) + body.buildInstr(WasmOp.REF_TEST) + } + wasmSymbols.unboxIntrinsic -> { val fromType = call.getTypeArgument(0)!! @@ -572,6 +583,9 @@ WasmImmediate.MemArg(0u, 0u) WasmImmediateKind.STRUCT_TYPE_IDX -> WasmImmediate.GcType(context.referenceGcType(function.dispatchReceiverParameter!!.type.classOrNull!!)) + WasmImmediateKind.TYPE_IDX -> + WasmImmediate.TypeIdx(context.referenceGcType(function.dispatchReceiverParameter!!.type.classOrNull!!)) + else -> error("Immediate $imm is unsupported") }
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt index d117414..bdd51df 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt
@@ -86,7 +86,6 @@ val wasmFunctionType = WasmFunctionType( - name = watName, parameterTypes = irParameters.map { context.transformValueParameterType(it) }, resultTypes = listOfNotNull(resultType) ) @@ -105,17 +104,19 @@ "Sanity check that $declaration is a real function that can be used in calls" } + val functionTypeSymbol = context.referenceFunctionType(declaration.symbol) + if (importedName != null) { // Imported functions don't have bodies. Declaring the signature: context.defineFunction( declaration.symbol, - WasmFunction.Imported(watName, wasmFunctionType, importedName) + WasmFunction.Imported(watName, functionTypeSymbol, importedName) ) // TODO: Support re-export of imported functions. return } - val function = WasmFunction.Defined(watName, wasmFunctionType) + val function = WasmFunction.Defined(watName, functionTypeSymbol) val functionCodegenContext = WasmFunctionCodegenContextImpl( declaration, function, @@ -201,6 +202,8 @@ context.registerInterface(symbol) } else { val nameStr = declaration.fqNameWhenAvailable.toString() + val metadata = context.getClassMetadata(symbol) + val superClass = metadata.superClass val structType = WasmStructDeclaration( name = nameStr, fields = declaration.allFields(irBuiltIns).map { @@ -209,40 +212,11 @@ type = context.transformFieldType(it.type), isMutable = true ) - } + }, + superClass?.let { context.referenceGcType(superClass.klass.symbol) } ) context.defineGcType(symbol, structType) - - var depth = 0 - val metadata = context.getClassMetadata(symbol) - var subMetadata = metadata - while (true) { - subMetadata = subMetadata.superClass ?: break - depth++ - } - - val initBody = mutableListOf<WasmInstr>() - val wasmExpressionGenerator = WasmIrExpressionBuilder(initBody) - - val wasmGcType = context.referenceGcType(symbol) - val superClass = metadata.superClass - if (superClass != null) { - val superRTT = context.referenceClassRTT(superClass.klass.symbol) - wasmExpressionGenerator.buildGetGlobal(superRTT) - wasmExpressionGenerator.buildRttSub(wasmGcType) - } else { - wasmExpressionGenerator.buildRttCanon(wasmGcType) - } - - val rtt = WasmGlobal( - name = "rtt_of_$nameStr", - isMutable = false, - type = WasmRtt(depth, WasmSymbol(structType)), - init = initBody - ) - - context.defineRTT(symbol, rtt) context.registerClass(symbol) context.generateTypeInfo(symbol, binaryDataStruct(metadata)) @@ -395,7 +369,7 @@ WasmF32 -> g.buildConstF32(0f) WasmF64 -> g.buildConstF64(0.0) is WasmRefNullType -> g.buildRefNull(type.heapType) - is WasmExternRef, is WasmAnyRef -> g.buildRefNull(WasmHeapType.Simple.Extern) + is WasmAnyRef -> g.buildRefNull(WasmHeapType.Simple.Extern) WasmUnreachableType -> error("Unreachable type can't be initialized") else -> error("Unknown value type ${type.name}") }
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt index f787b57..b3bb08f 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt
@@ -82,11 +82,11 @@ WasmF64 builtIns.nothingNType -> - WasmExternRef + WasmAnyRef // Value will not be created. Just using a random Wasm type. builtIns.nothingType -> - WasmExternRef + WasmAnyRef symbols.voidType -> error("Void type can't be used as a value")
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt index 7c1678b..97e78c5 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt
@@ -29,7 +29,6 @@ fun referenceClassId(irClass: IrClassSymbol): WasmSymbol<Int> fun referenceInterfaceId(irInterface: IrClassSymbol): WasmSymbol<Int> fun referenceVirtualFunctionId(irFunction: IrSimpleFunctionSymbol): WasmSymbol<Int> - fun referenceClassRTT(irClass: IrClassSymbol): WasmSymbol<WasmGlobal> fun referenceSignatureId(signature: WasmSignature): WasmSymbol<Int>
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt index 35b3077..84c4975 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt
@@ -5,7 +5,6 @@ package org.jetbrains.kotlin.backend.wasm.ir2wasm -import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName @@ -35,11 +34,7 @@ val stringLiteralId = ReferencableElements<String, Int>() - val runtimeTypes = - ReferencableAndDefinable<IrClassSymbol, WasmGlobal>() - val tagFuncType = WasmFunctionType( - "ex_handling_tag", listOf( WasmRefNullType(WasmHeapType.Type(gcTypes.reference(irBuiltIns.throwableClass))) ), @@ -124,9 +119,18 @@ fun linkWasmCompiledFragments(): WasmModule { bind(functions.unbound, functions.defined) bind(globals.unbound, globals.defined) - bind(functionTypes.unbound, functionTypes.defined) + bind(gcTypes.unbound, gcTypes.defined) - bind(runtimeTypes.unbound, runtimeTypes.defined) + + // Associate function types to a single canonical function type + val canonicalFunctionTypes = + functionTypes.elements.associateWithTo(LinkedHashMap()) { it } + + functionTypes.unbound.forEach { (irSymbol, wasmSymbol) -> + if (irSymbol !in functionTypes.defined) + error("Can't link symbol ${irSymbolDebugDump(irSymbol)}") + wasmSymbol.bind(canonicalFunctionTypes.getValue(functionTypes.defined.getValue(irSymbol))) + } val klassIds = mutableMapOf<IrClassSymbol, Int>() var currentDataSectionAddress = 0 @@ -261,8 +265,8 @@ ) } - val masterInitFunctionType = WasmFunctionType("__init_t", emptyList(), emptyList()) - val masterInitFunction = WasmFunction.Defined("__init", masterInitFunctionType) + val masterInitFunctionType = WasmFunctionType(emptyList(), emptyList()) + val masterInitFunction = WasmFunction.Defined("__init", WasmSymbol(masterInitFunctionType)) with(WasmIrExpressionBuilder(masterInitFunction.instructions)) { initFunctions.sortedBy { it.priority }.forEach { buildCall(WasmSymbol(it.function)) @@ -284,18 +288,28 @@ val importedFunctions = functions.elements.filterIsInstance<WasmFunction.Imported>() - // Sorting by depth for a valid init order - val sortedRttGlobals = runtimeTypes.elements.sortedBy { (it.type as WasmRtt).depth } + fun wasmTypeDeclarationOrderKey(declaration: WasmTypeDeclaration): Int { + return when (declaration) { + is WasmArrayDeclaration -> 0 + is WasmFunctionType -> 0 + is WasmStructDeclaration -> + // Subtype depth + declaration.superType?.let { wasmTypeDeclarationOrderKey(it.owner) + 1 } ?: 0 + } + } + + val sortedGcTypes = gcTypes.elements.sortedBy(::wasmTypeDeclarationOrderKey) val module = WasmModule( - functionTypes = functionTypes.elements + tagFuncType + masterInitFunctionType, - gcTypes = gcTypes.elements, + functionTypes = canonicalFunctionTypes.values.toList() + tagFuncType + masterInitFunctionType, + gcTypes = sortedGcTypes, + gcTypesInRecursiveGroup = true, importsInOrder = importedFunctions, importedFunctions = importedFunctions, definedFunctions = functions.elements.filterIsInstance<WasmFunction.Defined>() + masterInitFunction, tables = listOf(table) + interfaceMethodTables.elements, memories = listOf(memory), - globals = globals.elements + sortedRttGlobals, + globals = globals.elements, exports = exports, startFunction = null, // Module is initialized via export call elements = listOf(elements) + interfaceTableElements,
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt index 8048b95..a3803c3 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt
@@ -18,7 +18,6 @@ fun defineFunction(irFunction: IrFunctionSymbol, wasmFunction: WasmFunction) fun defineGlobal(irField: IrFieldSymbol, wasmGlobal: WasmGlobal) fun defineGcType(irClass: IrClassSymbol, wasmType: WasmTypeDeclaration) - fun defineRTT(irClass: IrClassSymbol, wasmGlobal: WasmGlobal) fun defineFunctionType(irFunction: IrFunctionSymbol, wasmFunctionType: WasmFunctionType) fun defineInterfaceMethodTable(irFunction: IrFunctionSymbol, wasmTable: WasmTable) fun addJsFun(importName: String, jsCode: String)
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt index 2d62e5f..7c32ae9 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt
@@ -106,10 +106,6 @@ wasmFragment.gcTypes.define(irClass, wasmType) } - override fun defineRTT(irClass: IrClassSymbol, wasmGlobal: WasmGlobal) { - wasmFragment.runtimeTypes.define(irClass, wasmGlobal) - } - override fun defineFunctionType(irFunction: IrFunctionSymbol, wasmFunctionType: WasmFunctionType) { wasmFragment.functionTypes.define(irFunction, wasmFunctionType) } @@ -157,9 +153,6 @@ return wasmFragment.gcTypes.reference(irClass) } - override fun referenceClassRTT(irClass: IrClassSymbol): WasmSymbol<WasmGlobal> = - wasmFragment.runtimeTypes.reference(irClass) - override fun referenceFunctionType(irFunction: IrFunctionSymbol): WasmSymbol<WasmFunctionType> = wasmFragment.functionTypes.reference(irFunction)
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt index c8f8993..b384b05 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt
@@ -51,9 +51,6 @@ val function: IrSimpleFunction = call.symbol.owner as? IrSimpleFunction ?: return call - if (!function.realOverrideTarget.returnType.isTypeParameter()) - return call - val erasedReturnType: IrType = function.realOverrideTarget.returnType.eraseUpperBoundType() @@ -72,11 +69,6 @@ ) context.createIrBuilder(scopeOwnerSymbol).apply { - if (call.type.isUnit()) { - return irComposite(call) { - +newCall - } - } return irImplicitCast(newCall, call.type) } }
diff --git a/compiler/testData/codegen/box/controlStructures/kt513.kt b/compiler/testData/codegen/box/controlStructures/kt513.kt index 3859af0..e0beb88 100644 --- a/compiler/testData/codegen/box/controlStructures/kt513.kt +++ b/compiler/testData/codegen/box/controlStructures/kt513.kt
@@ -1,3 +1,6 @@ +// V8 Crash https://bugs.chromium.org/p/v8/issues/detail?id=12640 +// IGNORE_BACKEND: WASM + // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 // WITH_STDLIB
diff --git a/compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt b/compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt index e8e18c6..7c0213f 100644 --- a/compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt +++ b/compiler/testData/codegen/box/coroutines/varSpilling/lvtWithInlineOnly.kt
@@ -2,6 +2,9 @@ // FULL_JDK // IGNORE_BACKEND: JS_IR +// V8 Crash https://bugs.chromium.org/p/v8/issues/detail?id=12640 +// IGNORE_BACKEND: WASM + import kotlin.coroutines.* fun ticker(
diff --git a/compiler/testData/codegen/box/defaultArguments/function/covariantOverride.kt b/compiler/testData/codegen/box/defaultArguments/function/covariantOverride.kt index 5bd56f1..fddf101 100644 --- a/compiler/testData/codegen/box/defaultArguments/function/covariantOverride.kt +++ b/compiler/testData/codegen/box/defaultArguments/function/covariantOverride.kt
@@ -1,7 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: FAKE_OVERRIDE_ISSUES -// On wasm this will produce conflicting return types, foo will return Any but we will try to interpret it as String. -// Before wasm native strings this worked by chance because we added unbox intrinsic for strings. open class Foo { open fun foo(x: CharSequence = "O"): CharSequence = x
diff --git a/compiler/testData/codegen/box/defaultArguments/function/covariantOverrideGeneric.kt b/compiler/testData/codegen/box/defaultArguments/function/covariantOverrideGeneric.kt index f04dcc9..c982d8a 100644 --- a/compiler/testData/codegen/box/defaultArguments/function/covariantOverrideGeneric.kt +++ b/compiler/testData/codegen/box/defaultArguments/function/covariantOverrideGeneric.kt
@@ -1,7 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: FAKE_OVERRIDE_ISSUES -// On wasm this will produce conflicting return types, foo will return Any but we will try to interpret it as String. -// Before wasm native strings this worked by chance because we added unbox intrinsic for strings. open class Foo { open fun foo(x: CharSequence = "O"): CharSequence = x
diff --git a/compiler/testData/codegen/box/lazyCodegen/safeCallAndArray.kt b/compiler/testData/codegen/box/lazyCodegen/safeCallAndArray.kt index 90b61d6..029374d 100644 --- a/compiler/testData/codegen/box/lazyCodegen/safeCallAndArray.kt +++ b/compiler/testData/codegen/box/lazyCodegen/safeCallAndArray.kt
@@ -1,3 +1,6 @@ +// V8 Crash https://bugs.chromium.org/p/v8/issues/detail?id=12640 +// IGNORE_BACKEND: WASM + class C { fun calc() : String { return "OK"
diff --git a/compiler/testData/codegen/box/regressions/resolvedCallForGetOperator.kt b/compiler/testData/codegen/box/regressions/resolvedCallForGetOperator.kt index bf8abb3..1e1e5f8 100644 --- a/compiler/testData/codegen/box/regressions/resolvedCallForGetOperator.kt +++ b/compiler/testData/codegen/box/regressions/resolvedCallForGetOperator.kt
@@ -1,3 +1,6 @@ +// V8 Crash https://bugs.chromium.org/p/v8/issues/detail?id=12640 +// IGNORE_BACKEND: WASM + // WITH_STDLIB val targetNameLists: Map<String, String> = mapOf("1" to "OK")
diff --git a/js/js.tests/build.gradle.kts b/js/js.tests/build.gradle.kts index f459018..dd71401 100644 --- a/js/js.tests/build.gradle.kts +++ b/js/js.tests/build.gradle.kts
@@ -153,7 +153,7 @@ } val v8edition = "rel" // rel or dbg -val v8version = "9.2.212" +val v8version = "10.2.9" val v8fileName = "v8-${v8osString}-${v8edition}-${v8version}" val v8url = "https://storage.googleapis.com/chromium-v8/official/canary/$v8fileName.zip"
diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt index 010bf48..9f0a21e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt
@@ -179,7 +179,6 @@ File(dir, "test.js").writeText(testJs) ExternalTool(System.getProperty("javascript.engine.path.V8")) .run( - "--experimental-wasm-typed-funcref", "--experimental-wasm-gc", "--experimental-wasm-eh", *jsFilesBefore.map { File(it).absolutePath }.toTypedArray(),
diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt index c0492de..706b532 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt
@@ -9,6 +9,7 @@ class WasmModule( val functionTypes: List<WasmFunctionType> = emptyList(), val gcTypes: List<WasmTypeDeclaration> = emptyList(), + val gcTypesInRecursiveGroup: Boolean, val importsInOrder: List<WasmNamedModuleField> = emptyList(), val importedFunctions: List<WasmFunction.Imported> = emptyList(), @@ -38,18 +39,18 @@ sealed class WasmFunction( override val name: String, - val type: WasmFunctionType + val type: WasmSymbolReadOnly<WasmFunctionType> ) : WasmNamedModuleField() { class Defined( name: String, - type: WasmFunctionType, + type: WasmSymbolReadOnly<WasmFunctionType>, val locals: MutableList<WasmLocal> = mutableListOf(), val instructions: MutableList<WasmInstr> = mutableListOf() ) : WasmFunction(name, type) class Imported( name: String, - type: WasmFunctionType, + type: WasmSymbolReadOnly<WasmFunctionType>, val importPair: WasmImportPair ) : WasmFunction(name, type) } @@ -146,15 +147,15 @@ override val name: String ) : WasmNamedModuleField() -class WasmFunctionType( - name: String, +data class WasmFunctionType( val parameterTypes: List<WasmType>, val resultTypes: List<WasmType> -) : WasmTypeDeclaration(name) +) : WasmTypeDeclaration("") class WasmStructDeclaration( name: String, - val fields: List<WasmStructFieldDeclaration> + val fields: List<WasmStructFieldDeclaration>, + val superType: WasmSymbolReadOnly<WasmTypeDeclaration>? ) : WasmTypeDeclaration(name) class WasmArrayDeclaration(
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 1896595..1e549e4 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
@@ -343,6 +343,8 @@ // GC STRUCT_NEW_WITH_RTT("struct.new_with_rtt", 0xFB_01, STRUCT_TYPE_IDX), STRUCT_NEW_DEFAULT_WITH_RTT("struct.new_default_with_rtt", 0xFB_02, STRUCT_TYPE_IDX), + STRUCT_NEW("struct.new", 0xFB_07, STRUCT_TYPE_IDX), + STRUCT_NEW_DEFAULT("struct.new_default", 0xFB_08, STRUCT_TYPE_IDX), STRUCT_GET("struct.get", 0xFB_03, listOf(STRUCT_TYPE_IDX, STRUCT_FIELD_IDX)), STRUCT_GET_S("struct.get_s", 0xFB_04, listOf(STRUCT_TYPE_IDX, STRUCT_FIELD_IDX)), STRUCT_GET_U("struct.get_u", 0xFB_05, listOf(STRUCT_TYPE_IDX, STRUCT_FIELD_IDX)), @@ -350,6 +352,8 @@ ARRAY_NEW_WITH_RTT("array.new_with_rtt", 0xFB_11, STRUCT_TYPE_IDX), ARRAY_NEW_DEFAULT_WITH_RTT("array.new_default_with_rtt", 0xFB_12, STRUCT_TYPE_IDX), + ARRAY_NEW("array.new", 0xFB_1B, STRUCT_TYPE_IDX), + ARRAY_NEW_DEFAULT("array.new_default", 0xFB_1C, STRUCT_TYPE_IDX), ARRAY_GET("array.get", 0xFB_13, listOf(STRUCT_TYPE_IDX)), ARRAY_GET_S("array.get_s", 0xFB_14, listOf(STRUCT_TYPE_IDX)), ARRAY_GET_U("array.get_u", 0xFB_15, listOf(STRUCT_TYPE_IDX)), @@ -362,9 +366,10 @@ RTT_CANON("rtt.canon", 0xFB_30, TYPE_IDX), - RTT_SUB("rtt.sub", 0xFB_31, TYPE_IDX), REF_TEST("ref.test", 0xFB_40), + REF_TEST_STATIC("ref.test_static", 0xFB_44, STRUCT_TYPE_IDX), REF_CAST("ref.cast", 0xFB_41), + REF_CAST_STATIC("ref.cast_static", 0xFB_45, STRUCT_TYPE_IDX), BR_ON_CAST("br_on_cast", 0xFB_42, listOf(LABEL_IDX)),
diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt index b719cc0..e32c338 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt
@@ -22,22 +22,21 @@ object WasmI8 : WasmType("i8", -0x6) object WasmI16 : WasmType("i16", -0x7) object WasmFuncRef : WasmType("funcref", -0x10) -object WasmExternRef : WasmType("externref", -0x11) object WasmAnyRef : WasmType("anyref", -0x12) object WasmEqRef : WasmType("eqref", -0x13) -class WasmRefNullType(val heapType: WasmHeapType) : WasmType("ref null", -0x14) -class WasmRefType(val heapType: WasmHeapType) : WasmType("ref", -0x15) +data class WasmRefNullType(val heapType: WasmHeapType) : WasmType("ref null", -0x14) +data class WasmRefType(val heapType: WasmHeapType) : WasmType("ref", -0x15) @Suppress("unused") object WasmI31Ref : WasmType("i31ref", -0x16) -class WasmRtt(val depth: Int, val type: WasmSymbolReadOnly<WasmTypeDeclaration>) : WasmType("rtt", -0x17) +data class WasmRtt(val type: WasmSymbolReadOnly<WasmTypeDeclaration>) : WasmType("rtt", -0x18) @Suppress("unused") object WasmDataRef : WasmType("dataref", -0x19) sealed class WasmHeapType { - class Type(val type: WasmSymbolReadOnly<WasmTypeDeclaration>) : WasmHeapType() { + data class Type(val type: WasmSymbolReadOnly<WasmTypeDeclaration>) : WasmHeapType() { override fun toString(): String { return "Type:$type" } @@ -46,6 +45,7 @@ sealed class Simple(val name: String, val code: Byte) : WasmHeapType() { object Func : Simple("func", -0x10) object Extern : Simple("extern", -0x11) + object Any : Simple("any", -0x12) object Eq : Simple("eq", -0x13) @Suppress("unused") @@ -70,7 +70,7 @@ is WasmRefType -> heapType is WasmRefNullType -> heapType is WasmEqRef -> WasmHeapType.Simple.Eq - is WasmExternRef -> WasmHeapType.Simple.Extern + is WasmAnyRef -> WasmHeapType.Simple.Any is WasmFuncRef -> WasmHeapType.Simple.Func else -> error("Unknown heap type for type $this") }
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 14b5695..6eacbfe 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
@@ -142,12 +142,12 @@ buildInstr(WasmOp.REF_CAST) } - fun buildRefNull(type: WasmHeapType) { - buildInstr(WasmOp.REF_NULL, WasmImmediate.HeapType(WasmRefType(type))) + fun buildRefCastStatic(type: WasmSymbolReadOnly<WasmTypeDeclaration>) { + buildInstr(WasmOp.REF_CAST_STATIC, WasmImmediate.TypeIdx(type)) } - fun buildRttSub(decl: WasmSymbol<WasmTypeDeclaration>) { - buildInstr(WasmOp.RTT_SUB, WasmImmediate.TypeIdx(decl)) + fun buildRefNull(type: WasmHeapType) { + buildInstr(WasmOp.REF_NULL, WasmImmediate.HeapType(WasmRefType(type))) } fun buildRttCanon(decl: WasmSymbol<WasmTypeDeclaration>) {
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 e0346e7..c30a150 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
@@ -97,7 +97,7 @@ val type = functionTypes[b.readVarUInt32AsInt()] importedFunctions += WasmFunction.Imported( name = "", - type = type, + type = WasmSymbol(type), importPair = importPair, ).also { importsInOrder.add(it) } } @@ -141,7 +141,7 @@ definedFunctions.add( WasmFunction.Defined( "", - functionType, + WasmSymbol(functionType), locals = functionType.parameterTypes.mapIndexed { index, wasmType -> WasmLocal(index, "", wasmType, true) }.toMutableList() @@ -330,6 +330,7 @@ return WasmModule( functionTypes = functionTypes, gcTypes = gcTypes, + gcTypesInRecursiveGroup = false, importsInOrder = importsInOrder, importedFunctions = importedFunctions, importedMemories = importedMemories, @@ -450,7 +451,7 @@ (-0x20).toByte() -> { val types = mapVector { readValueType() } val returnTypes = mapVector { readValueType() } - return WasmFunctionType("", types, returnTypes) + return WasmFunctionType(types, returnTypes) } else -> TODO() @@ -466,7 +467,6 @@ WasmI8, WasmI16, WasmFuncRef, - WasmExternRef, WasmAnyRef, WasmEqRef ).associateBy { it.code } @@ -490,7 +490,7 @@ return when (code.toInt()) { 0x70 -> WasmFuncRef - 0x6F -> WasmExternRef + 0x6F -> WasmAnyRef else -> error("Unsupported heap type ${code.toString(16)}") } }
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 057f198..3794e93 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
@@ -21,13 +21,17 @@ with(module) { // type section appendSection(1u) { + if (module.gcTypesInRecursiveGroup) { + appendVectorSize(1) + b.writeByte(0x4f) + } appendVectorSize(functionTypes.size + gcTypes.size) functionTypes.forEach { appendFunctionTypeDeclaration(it) } gcTypes.forEach { when (it) { is WasmStructDeclaration -> appendStructTypeDeclaration(it) is WasmArrayDeclaration -> appendArrayTypeDeclaration(it) - is WasmFunctionType -> {} + is WasmFunctionType -> error("Function type in GC types") } } } @@ -277,6 +281,12 @@ } private fun appendStructTypeDeclaration(type: WasmStructDeclaration) { + val superType = type.superType + if (superType != null) { + b.writeVarInt7(-0x30) + appendVectorSize(1) + appendModuleFieldReference(superType.owner) + } b.writeVarInt7(-0x21) b.writeVarUInt32(type.fields.size) type.fields.forEach { @@ -303,11 +313,11 @@ b.writeString(function.importPair.moduleName) b.writeString(function.importPair.declarationName) b.writeByte(0) // Function external kind. - b.writeVarUInt32(function.type.index) + b.writeVarUInt32(function.type.owner.index) } private fun appendDefinedFunction(function: WasmFunction.Defined) { - b.writeVarUInt32(function.type.index) + b.writeVarUInt32(function.type.owner.index) } private fun appendTable(table: WasmTable) { @@ -483,7 +493,6 @@ appendHeapType(type.heapType) } if (type is WasmRtt) { - b.writeVarUInt32(type.depth) appendModuleFieldReference(type.type.owner) } }
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 3e80118..c900836 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
@@ -246,12 +246,26 @@ } } + private inline fun maybeSubType(superType: WasmTypeDeclaration?, body: () -> Unit) { + if (superType != null) { + sameLineList("sub") { + appendModuleFieldReference(superType) + body() + } + } else { + body() + } + } + + private fun appendStructTypeDeclaration(type: WasmStructDeclaration) { newLineList("type") { appendModuleFieldReference(type) - sameLineList("struct") { - type.fields.forEach { - appendStructField(it) + maybeSubType(type.superType?.owner) { + sameLineList("struct") { + type.fields.forEach { + appendStructField(it) + } } } } @@ -287,9 +301,9 @@ appendModuleFieldReference(function) sameLineList("type") { appendModuleFieldReference(function.type) } function.locals.forEach { if (it.isParameter) appendLocal(it) } - if (function.type.resultTypes.isNotEmpty()) { + if (function.type.owner.resultTypes.isNotEmpty()) { sameLineList("result") { - function.type.resultTypes.forEach { appendType(it) } + function.type.owner.resultTypes.forEach { appendType(it) } } } function.locals.forEach { if (!it.isParameter) appendLocal(it) } @@ -438,7 +452,7 @@ fun appendReferencedType(type: WasmType) { when (type) { is WasmFuncRef -> appendElement("func") - is WasmExternRef -> appendElement("extern") + is WasmAnyRef -> appendElement("any") else -> TODO() } } @@ -457,7 +471,6 @@ is WasmRtt -> sameLineList("rtt") { - appendElement(type.depth.toString()) appendModuleFieldReference(type.type.owner) } @@ -489,6 +502,10 @@ if (id != 0) appendElement(id.toString()) } + fun appendModuleFieldReference(field: WasmSymbolReadOnly<WasmNamedModuleField>) { + appendModuleFieldReference(field.owner) + } + fun appendModuleFieldReference(field: WasmNamedModuleField) { val id = field.id ?: error("${field::class} ${field.name} ID is unlinked")