[Wasm] Switch to iso-recursive types
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..7bf26bb 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.
@@ -323,7 +328,7 @@
call: IrFunctionAccessExpression,
function: IrFunction
): Boolean {
- if (tryToGenerateWasmOpIntrinsicCall(call, function)) {
+ if (tryToGenerateWasmOpIntrinsicCall(function)) {
return true
}
@@ -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)!!
@@ -544,7 +555,7 @@
}
// Return true if function is recognized as intrinsic.
- fun tryToGenerateWasmOpIntrinsicCall(call: IrFunctionAccessExpression, function: IrFunction): Boolean {
+ fun tryToGenerateWasmOpIntrinsicCall(function: IrFunction): Boolean {
if (function.hasWasmNoOpCastAnnotation()) {
return true
}
@@ -554,17 +565,7 @@
val op = WasmOp.valueOf(opString)
var immediates = emptyArray<WasmImmediate>()
when (op.immediates.size) {
- 0 -> {
- when (op) {
- WasmOp.REF_TEST -> {
- val toIrType = call.getTypeArgument(0)!!
- // ref.test takes RTT as a second operand
- generateTypeRTT(toIrType)
- }
- else -> {
- }
- }
- }
+ 0 -> {}
1 -> {
immediates = arrayOf(
when (val imm = op.immediates[0]) {
@@ -572,6 +573,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..0462420 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.Any)
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/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 8ed125b..55a0633 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.0.132"
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/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt
index decb962..cc94bb4 100644
--- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt
+++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt
@@ -285,7 +285,6 @@
@WasmOp(WasmOp.REF_EQ)
public external fun wasm_ref_eq(a: Any?, b: Any?): Boolean
-@WasmOp(WasmOp.REF_TEST)
public external fun <T> wasm_ref_test(a: Any?): Boolean
// ---
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..48106e7 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"
}
@@ -45,7 +44,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 +69,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..dc3f3f2 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
@@ -11,7 +11,12 @@
import java.io.ByteArrayOutputStream
import java.io.OutputStream
-class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule, val moduleName: String, val emitNameSection: Boolean) {
+class WasmIrToBinary(
+ outputStream: OutputStream,
+ val module: WasmModule,
+ val moduleName: String,
+ val emitNameSection: Boolean,
+) {
var b: ByteWriter = ByteWriter.OutputStream(outputStream)
fun appendWasmModule() {
@@ -21,13 +26,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 +286,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 +318,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 +498,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")