[WASM] Initialize constant fields by wasm-initializers

This commit is contained in:
Igor Yakovlev
2022-01-14 17:06:14 +01:00
committed by teamcity
parent f40a0ca704
commit b22190ccc1
3 changed files with 42 additions and 22 deletions
@@ -105,25 +105,8 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
}
}
override fun visitConst(expression: IrConst<*>) {
when (val kind = expression.kind) {
is IrConstKind.Null -> generateDefaultInitializerForType(context.transformType(expression.type), body)
is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0)
is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt())
is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt())
is IrConstKind.Int -> body.buildConstI32(kind.valueOf(expression))
is IrConstKind.Long -> body.buildConstI64(kind.valueOf(expression))
is IrConstKind.Char -> body.buildConstI32(kind.valueOf(expression).code)
is IrConstKind.Float -> body.buildConstF32(kind.valueOf(expression))
is IrConstKind.Double -> body.buildConstF64(kind.valueOf(expression))
is IrConstKind.String -> {
body.buildConstI32Symbol(context.referenceStringLiteral(kind.valueOf(expression)))
body.buildConstI32(kind.valueOf(expression).length)
body.buildCall(context.referenceFunction(wasmSymbols.stringGetLiteral))
}
else -> error("Unknown constant kind")
}
}
override fun visitConst(expression: IrConst<*>): Unit =
generateConstExpression(expression, body, context)
override fun visitGetField(expression: IrGetField) {
val field: IrField = expression.symbol.owner
@@ -20,6 +20,9 @@ import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
@@ -364,13 +367,21 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext) : IrElementVis
val initBody = mutableListOf<WasmInstr>()
val wasmExpressionGenerator = WasmIrExpressionBuilder(initBody)
generateDefaultInitializerForType(wasmType, wasmExpressionGenerator)
val initValue: IrExpression? = declaration.initializer?.expression
if (initValue != null) {
check(initValue is IrConst<*> && initValue.kind !is IrConstKind.String && initValue.kind !is IrConstKind.Null) {
"Static field initializer should be non-string const or null"
}
generateConstExpression(initValue, wasmExpressionGenerator, context)
} else {
generateDefaultInitializerForType(wasmType, wasmExpressionGenerator)
}
val global = WasmGlobal(
name = declaration.fqNameWhenAvailable.toString(),
type = wasmType,
isMutable = true,
// All globals are currently initialized in start function
init = initBody
)
@@ -396,4 +407,25 @@ fun IrFunction.getEffectiveValueParameters(): List<IrValueParameter> {
}
fun IrFunction.isExported(): Boolean =
isJsExport()
isJsExport()
fun generateConstExpression(expression: IrConst<*>, body: WasmExpressionBuilder, context: WasmBaseCodegenContext) {
when (val kind = expression.kind) {
is IrConstKind.Null -> generateDefaultInitializerForType(context.transformType(expression.type), body)
is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0)
is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt())
is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt())
is IrConstKind.Int -> body.buildConstI32(kind.valueOf(expression))
is IrConstKind.Long -> body.buildConstI64(kind.valueOf(expression))
is IrConstKind.Char -> body.buildConstI32(kind.valueOf(expression).code)
is IrConstKind.Float -> body.buildConstF32(kind.valueOf(expression))
is IrConstKind.Double -> body.buildConstF64(kind.valueOf(expression))
is IrConstKind.String -> {
body.buildConstI32Symbol(context.referenceStringLiteral(kind.valueOf(expression)))
body.buildConstI32(kind.valueOf(expression).length)
body.buildCall(context.referenceFunction(context.backendContext.wasmSymbols.stringGetLiteral))
}
else -> error("Unknown constant kind")
}
}
@@ -9,11 +9,14 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.ir2wasm.getRuntimeClass
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.irSetField
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -45,6 +48,8 @@ class FieldInitializersLowering(val context: WasmBackendContext) : FileLoweringP
if (!declaration.isStatic) return
val initValue: IrExpression = declaration.initializer?.expression ?: return
// Constant primitive initializers without implicit casting can be processed by native wasm initializers
if (initValue.type == declaration.type && initValue is IrConst<*> && initValue.kind !is IrConstKind.String && initValue.kind !is IrConstKind.Null) return
startFunctionBody.statements.add(
builder.at(initValue).irSetField(null, declaration, initValue)