Closed8

Kotlin/Wasm コードリーディング wasm.ir 編

tanishikingtanishiking

WasmFuction

WasmFunction.Defined

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt#L44-L49

(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

  ...
)

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt#L330-L343

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt#L534-L550

  • 例えば field.nameboxid62 の function は $${sanitizeWatIdentifier(field.name)}___${indexSpaceKind}_$id$box___fun_62 になるのね
  • WasmLocal#isParameter なものについては (param $... type) で書いていって
  • それ以外の WasmLocal は instruction の前に書いて
    • local は WasmFunction.Defined の時点でわかってる必要があるのね
    • instruction はまあそうですね

WasmFunction.Imported

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt#L51-L55

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt#L202-L205

そんなに特筆すべきことは無さそう

tanishikingtanishiking

WasmTypeDeclaration

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt#L146-L148

(type ...) のやつ

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt#L230-L240

WasmFunctionType

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt#L150-L153

例えば visitFunction 内で

https://github.com/JetBrains/kotlin/blob/d935db9e3acffe633a47b2075a9e9f165294814e/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt#L108-L112

これ、primitive type じゃなくて struct などが必要な場合はどうなるのだろう?

type transformer はこちら

https://github.com/JetBrains/kotlin/blob/d935db9e3acffe633a47b2075a9e9f165294814e/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt#L43-L55

type transformer 詳しくは次の投稿(?)で

https://github.com/JetBrains/kotlin/blob/d935db9e3acffe633a47b2075a9e9f165294814e/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt#L18-L126

parameter も result type も WasmType で、 wasm gc の struct とか array type だとどうするんですかというと、そういうのは WasmRef(Null)Type(heapType: WasmHeapType) という形


Ir to text はまあこんなもん。 WasmRefNullType の print については次のやつで

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt#L264-L274

tanishikingtanishiking

一旦 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 (?) の変換、まあそうですね

https://github.com/JetBrains/kotlin/blob/d935db9e3acffe633a47b2075a9e9f165294814e/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt#L94-L113

  • 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 はこう

https://github.com/JetBrains/kotlin/blob/de6a27aeeb184b0b6d1d8cca697dce5f13697509/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt#L74-L85

ir に対して空の WasmSymbol を生成。これはのちのち linkWasmCompiledFragments で bind

https://github.com/JetBrains/kotlin/blob/de6a27aeeb184b0b6d1d8cca697dce5f13697509/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt#L104-L108

WasmHeapType.Type

sealed class WasmHeapType {
    data class Type(val type: WasmSymbolReadOnly<WasmTypeDeclaration>) : WasmHeapType() { ... }
// ...

WasmHeapType には Symbol があるだけ、じゃあ ir to text とかするときどうなるのですか?

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt#L494-L502

https://github.com/JetBrains/kotlin/blob/57eae167cc319954668821d0cb0d6e0277e1a8f7/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt#L471-L481

.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

このスクラップは3ヶ月前にクローズされました