[Wasm] Support Wasm GC milestone 5
This commit is contained in:
+2
-1
@@ -45,7 +45,8 @@ internal class WasmUsefulDeclarationProcessor(
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
+18
-4
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver
|
||||
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.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
@@ -213,7 +214,7 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
||||
generateDefaultInitializerForType(context.transformType(field.type), body)
|
||||
}
|
||||
|
||||
body.buildGetGlobal(context.referenceClassRTT(klass.symbol))
|
||||
generateClassRTT(klass.symbol)
|
||||
body.buildStructNew(wasmGcType)
|
||||
generateCall(expression)
|
||||
}
|
||||
@@ -243,7 +244,7 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
||||
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
|
||||
}
|
||||
@@ -322,8 +323,12 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -357,6 +362,12 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
||||
body.buildRefCast()
|
||||
}
|
||||
|
||||
wasmSymbols.refTest -> {
|
||||
val toType = call.getTypeArgument(0)!!
|
||||
generateTypeRTT(toType)
|
||||
body.buildInstr(WasmOp.REF_TEST)
|
||||
}
|
||||
|
||||
wasmSymbols.unboxIntrinsic -> {
|
||||
val fromType = call.getTypeArgument(0)!!
|
||||
|
||||
@@ -581,6 +592,9 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
||||
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")
|
||||
}
|
||||
|
||||
+9
-35
@@ -85,7 +85,6 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext, private val al
|
||||
|
||||
val wasmFunctionType =
|
||||
WasmFunctionType(
|
||||
name = watName,
|
||||
parameterTypes = irParameters.map { context.transformValueParameterType(it) },
|
||||
resultTypes = listOfNotNull(resultType)
|
||||
)
|
||||
@@ -104,17 +103,19 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext, private val al
|
||||
"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,
|
||||
@@ -200,6 +201,8 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext, private val al
|
||||
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 {
|
||||
@@ -208,40 +211,11 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext, private val al
|
||||
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))
|
||||
|
||||
@@ -394,7 +368,7 @@ fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder)
|
||||
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}")
|
||||
}
|
||||
|
||||
+2
-2
@@ -82,11 +82,11 @@ class WasmTypeTransformer(
|
||||
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")
|
||||
|
||||
-1
@@ -29,7 +29,6 @@ interface WasmBaseCodegenContext {
|
||||
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>
|
||||
|
||||
|
||||
+28
-14
@@ -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 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) {
|
||||
val stringLiteralId =
|
||||
ReferencableElements<String, Int>()
|
||||
|
||||
val runtimeTypes =
|
||||
ReferencableAndDefinable<IrClassSymbol, WasmGlobal>()
|
||||
|
||||
val tagFuncType = WasmFunctionType(
|
||||
"ex_handling_tag",
|
||||
listOf(
|
||||
WasmRefNullType(WasmHeapType.Type(gcTypes.reference(irBuiltIns.throwableClass)))
|
||||
),
|
||||
@@ -123,9 +118,18 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) {
|
||||
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
|
||||
@@ -260,8 +264,8 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) {
|
||||
)
|
||||
}
|
||||
|
||||
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))
|
||||
@@ -283,18 +287,28 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) {
|
||||
|
||||
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,
|
||||
|
||||
-1
@@ -18,7 +18,6 @@ interface WasmModuleCodegenContext : WasmBaseCodegenContext {
|
||||
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)
|
||||
|
||||
-7
@@ -106,10 +106,6 @@ class WasmModuleCodegenContextImpl(
|
||||
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 @@ class WasmModuleCodegenContextImpl(
|
||||
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)
|
||||
|
||||
|
||||
-8
@@ -51,9 +51,6 @@ class GenericReturnTypeLowering(val context: WasmBackendContext) : FileLoweringP
|
||||
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 @@ class GenericReturnTypeLowering(val context: WasmBackendContext) : FileLoweringP
|
||||
)
|
||||
|
||||
context.createIrBuilder(scopeOwnerSymbol).apply {
|
||||
if (call.type.isUnit()) {
|
||||
return irComposite(call) {
|
||||
+newCall
|
||||
}
|
||||
}
|
||||
return irImplicitCast(newCall, call.type)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user