[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<*>) { override fun visitConst(expression: IrConst<*>): Unit =
when (val kind = expression.kind) { generateConstExpression(expression, body, context)
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 visitGetField(expression: IrGetField) { override fun visitGetField(expression: IrGetField) {
val field: IrField = expression.symbol.owner 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.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody 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.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
@@ -364,13 +367,21 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext) : IrElementVis
val initBody = mutableListOf<WasmInstr>() val initBody = mutableListOf<WasmInstr>()
val wasmExpressionGenerator = WasmIrExpressionBuilder(initBody) 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( val global = WasmGlobal(
name = declaration.fqNameWhenAvailable.toString(), name = declaration.fqNameWhenAvailable.toString(),
type = wasmType, type = wasmType,
isMutable = true, isMutable = true,
// All globals are currently initialized in start function
init = initBody init = initBody
) )
@@ -396,4 +407,25 @@ fun IrFunction.getEffectiveValueParameters(): List<IrValueParameter> {
} }
fun IrFunction.isExported(): Boolean = 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.at
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext 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.IrElement
import org.jetbrains.kotlin.ir.builders.irSetField import org.jetbrains.kotlin.ir.builders.irSetField
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrBlockBody 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.expressions.IrExpression
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -45,6 +48,8 @@ class FieldInitializersLowering(val context: WasmBackendContext) : FileLoweringP
if (!declaration.isStatic) return if (!declaration.isStatic) return
val initValue: IrExpression = declaration.initializer?.expression ?: 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( startFunctionBody.statements.add(
builder.at(initValue).irSetField(null, declaration, initValue) builder.at(initValue).irSetField(null, declaration, initValue)