Kotlin/Wasm コードリーディング wasm.ir 編
Kotlin IR -> wasm.ir -> Wasm binary/text
WasmFuction
WasmFunction.Defined
(func $name___kind_id (type $____type_0)
(param $0_a i32) (param $1_b i32) (result i32)
// locals
(local $0_foo (ref null $Foo___type_36)) // など
// instrs
...
)
- 例えば
field.name
がbox
でid
が62
の function は$${sanitizeWatIdentifier(field.name)}___${indexSpaceKind}_$id
で$box___fun_62
になるのね -
WasmLocal#isParameter
なものについては(param $... type)
で書いていって - それ以外の
WasmLocal
は instruction の前に書いて- local は
WasmFunction.Defined
の時点でわかってる必要があるのね - instruction はまあそうですね
- local は
WasmFunction.Imported
そんなに特筆すべきことは無さそう
WasmLocal
ローカル変数
local.get
とか local.set
で使われたりする
WasmGlobal
example
(global $Base.vtable___g_24 (ref $Base.vtable___type_26)
ref.func $Base.foo___fun_62
struct.new $Base.vtable___type_26)
- imported global の可能性もあるのか
- どんなときに生成される?
- static field? https://github.com/JetBrains/kotlin/blob/b0367d93991b5cf93d266e395c312eaeca774d36/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt#L456-L488
- vtable https://github.com/JetBrains/kotlin/blob/b0367d93991b5cf93d266e395c312eaeca774d36/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt#L249-L285
- itable https://github.com/JetBrains/kotlin/blob/b0367d93991b5cf93d266e395c312eaeca774d36/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt#L287-L336
WasmTypeDeclaration
(type ...)
のやつ
WasmFunctionType
例えば visitFunction
内で
これ、primitive type じゃなくて struct などが必要な場合はどうなるのだろう?
type transformer はこちら
type transformer 詳しくは次の投稿(?)で
parameter も result type も WasmType
で、 wasm gc の struct とか array type だとどうするんですかというと、そういうのは WasmRef(Null)Type(heapType: WasmHeapType)
という形
Ir to text はまあこんなもん。 WasmRefNullType
の print については次のやつで
一旦 TypeTransformer を見ていく
https://github.com/JetBrains/kotlin/blob/d935db9e3acffe633a47b2075a9e9f165294814e/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt#L67-L92 ここは primitive type (?) の変換、まあそうですね
-
klass.isExternal
は分かる -
isBuiltInWasmRefType(this)
ああ、こういうのもできるのね -
inline classes (opaque type 的なやつだ!?) を向いて underlying class に対して再帰的に
toWasmValueType
- それ以外の場合は
toWasmGcRefType()
なんですか?
toWasmGcRefType
WasmRefNullType(WasmHeapType.Type(
context.referenceGcType(getRuntimeClass(context.backendContext.irBuiltIns).symbol)))
val gcTypes =
ReferencableAndDefinable<IrClassSymbol, WasmTypeDeclaration>()
fun referenceGcType(irClass: IrClassSymbol): WasmSymbol<WasmTypeDeclaration> =
referenceNonNothingType(irClass, wasmFragment.gcTypes)
private fun referenceNonNothingType(
irClass: IrClassSymbol,
from: WasmCompiledModuleFragment.ReferencableAndDefinable<IrClassSymbol, WasmTypeDeclaration>
): WasmSymbol<WasmTypeDeclaration> {
val type = irClass.defaultType
require(!type.isNothing()) {
"Can't reference Nothing type"
}
return from.reference(irClass)
}
data class WasmRefNullType(val heapType: WasmHeapType) : WasmType("ref null", -0x1D)
reference
はこう
ir
に対して空の WasmSymbol
を生成。これはのちのち linkWasmCompiledFragments
で bind
WasmHeapType.Type
sealed class WasmHeapType {
data class Type(val type: WasmSymbolReadOnly<WasmTypeDeclaration>) : WasmHeapType() { ... }
// ...
WasmHeapType
には Symbol があるだけ、じゃあ ir to text とかするときどうなるのですか?
.owner
はその WasmSymbol
を bind している Kotlin IR の symbol ??? と思ったら
sealed class WasmNamedModuleField {
var id: Int? = null
open val name: String = ""
}
らしい。この name
が使われるのね
appendFieldModuleReference はこれね https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt#L534
WasmStruct/ArrayDeclaration
supertype
も WasmStructDeclaration
でよくない? struct の supertype は常に struct では?
class WasmStructFieldDeclaration(
val name: String,
val type: WasmType,
val isMutable: Boolean
)
WasmInstr
WasmOp
WasmInstr
で operand の型指定してるけど難しくない?
こういう感じで追加する、難しい
operand じゃなくて immediate だわ