[Wasm] Support Wasm GC milestone 5
This commit is contained in:
@@ -9,6 +9,7 @@ package org.jetbrains.kotlin.wasm.ir
|
||||
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 WasmNamedModuleField {
|
||||
|
||||
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 @@ sealed class WasmTypeDeclaration(
|
||||
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(
|
||||
|
||||
@@ -343,6 +343,8 @@ enum class WasmOp(
|
||||
// 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 @@ enum class WasmOp(
|
||||
|
||||
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 @@ enum class WasmOp(
|
||||
|
||||
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)),
|
||||
|
||||
|
||||
@@ -26,18 +26,18 @@ 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 +46,7 @@ sealed class WasmHeapType {
|
||||
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 +71,8 @@ fun WasmType.getHeapType(): WasmHeapType =
|
||||
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
|
||||
is WasmExternRef -> WasmHeapType.Simple.Extern
|
||||
else -> error("Unknown heap type for type $this")
|
||||
}
|
||||
|
||||
@@ -142,12 +142,12 @@ abstract class WasmExpressionBuilder {
|
||||
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>) {
|
||||
|
||||
@@ -97,7 +97,7 @@ class WasmBinaryToIR(val b: MyByteReader) {
|
||||
val type = functionTypes[b.readVarUInt32AsInt()]
|
||||
importedFunctions += WasmFunction.Imported(
|
||||
name = "",
|
||||
type = type,
|
||||
type = WasmSymbol(type),
|
||||
importPair = importPair,
|
||||
).also { importsInOrder.add(it) }
|
||||
}
|
||||
@@ -141,7 +141,7 @@ class WasmBinaryToIR(val b: MyByteReader) {
|
||||
definedFunctions.add(
|
||||
WasmFunction.Defined(
|
||||
"",
|
||||
functionType,
|
||||
WasmSymbol(functionType),
|
||||
locals = functionType.parameterTypes.mapIndexed { index, wasmType ->
|
||||
WasmLocal(index, "", wasmType, true)
|
||||
}.toMutableList()
|
||||
@@ -330,6 +330,7 @@ class WasmBinaryToIR(val b: MyByteReader) {
|
||||
return WasmModule(
|
||||
functionTypes = functionTypes,
|
||||
gcTypes = gcTypes,
|
||||
gcTypesInRecursiveGroup = false,
|
||||
importsInOrder = importsInOrder,
|
||||
importedFunctions = importedFunctions,
|
||||
importedMemories = importedMemories,
|
||||
@@ -450,7 +451,7 @@ class WasmBinaryToIR(val b: MyByteReader) {
|
||||
(-0x20).toByte() -> {
|
||||
val types = mapVector { readValueType() }
|
||||
val returnTypes = mapVector { readValueType() }
|
||||
return WasmFunctionType("", types, returnTypes)
|
||||
return WasmFunctionType(types, returnTypes)
|
||||
}
|
||||
|
||||
else -> TODO()
|
||||
@@ -466,8 +467,8 @@ class WasmBinaryToIR(val b: MyByteReader) {
|
||||
WasmI8,
|
||||
WasmI16,
|
||||
WasmFuncRef,
|
||||
WasmExternRef,
|
||||
WasmAnyRef,
|
||||
WasmExternRef,
|
||||
WasmEqRef
|
||||
).associateBy { it.code }
|
||||
|
||||
|
||||
@@ -21,13 +21,17 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule, val mod
|
||||
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 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule, val mod
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -290,7 +300,7 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule, val mod
|
||||
}
|
||||
|
||||
val WasmFunctionType.index: Int
|
||||
get() = module.functionTypes.indexOf(this)
|
||||
get() = id!!
|
||||
|
||||
private fun appendLimits(limits: WasmLimits) {
|
||||
b.writeVarUInt1(limits.maxSize != null)
|
||||
@@ -303,11 +313,11 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule, val mod
|
||||
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 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule, val mod
|
||||
appendHeapType(type.heapType)
|
||||
}
|
||||
if (type is WasmRtt) {
|
||||
b.writeVarUInt32(type.depth)
|
||||
appendModuleFieldReference(type.type.owner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,12 +246,26 @@ class WasmIrToText : SExpressionBuilder() {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ class WasmIrToText : SExpressionBuilder() {
|
||||
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,6 +452,7 @@ class WasmIrToText : SExpressionBuilder() {
|
||||
fun appendReferencedType(type: WasmType) {
|
||||
when (type) {
|
||||
is WasmFuncRef -> appendElement("func")
|
||||
is WasmAnyRef -> appendElement("any")
|
||||
is WasmExternRef -> appendElement("extern")
|
||||
else -> TODO()
|
||||
}
|
||||
@@ -457,7 +472,6 @@ class WasmIrToText : SExpressionBuilder() {
|
||||
|
||||
is WasmRtt ->
|
||||
sameLineList("rtt") {
|
||||
appendElement(type.depth.toString())
|
||||
appendModuleFieldReference(type.type.owner)
|
||||
}
|
||||
|
||||
@@ -489,6 +503,10 @@ class WasmIrToText : SExpressionBuilder() {
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user