[Wasm] Use more specific types in generateExpression and generateStatement

Also, rename: `generateStatement` -> `generateAsStatement`
This commit is contained in:
Zalim Bashorov
2022-12-09 19:07:50 +01:00
parent ce265c049a
commit e5e786c265
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.wasm.utils.*
import org.jetbrains.kotlin.backend.wasm.utils.isCanonical import org.jetbrains.kotlin.backend.wasm.utils.isCanonical
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.lower.PrimaryConstructorLowering import org.jetbrains.kotlin.ir.backend.js.lower.PrimaryConstructorLowering
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction
@@ -53,27 +54,31 @@ class BodyGenerator(
} }
// Generates code for the given IR element. Leaves something on the stack unless expression was of the type Void. // Generates code for the given IR element. Leaves something on the stack unless expression was of the type Void.
internal fun generateExpression(elem: IrElement) { internal fun generateExpression(expression: IrExpression) {
assert(elem is IrExpression || elem is IrVariable) { "Unsupported statement kind" } expression.acceptVoid(this)
elem.acceptVoid(this) if (expression.type.isNothing()) {
if (elem is IrExpression && elem.type.isNothing()) {
// TODO Ideally, we should generate unreachable only for specific cases and preferable on declaration site. // TODO Ideally, we should generate unreachable only for specific cases and preferable on declaration site.
body.buildUnreachableAfterNothingType() body.buildUnreachableAfterNothingType()
} }
} }
// Generates code for the given IR element but *never* leaves anything on the stack. // Generates code for the given IR element but *never* leaves anything on the stack.
private fun generateStatement(statement: IrElement) { private fun generateAsStatement(statement: IrExpression) {
assert(statement is IrExpression || statement is IrVariable) { "Unsupported statement kind" }
generateExpression(statement) generateExpression(statement)
if (statement is IrExpression && statement.type != wasmSymbols.voidType) { if (statement.type != wasmSymbols.voidType) {
body.buildDrop() body.buildDrop()
} }
} }
private fun generateStatement(statement: IrStatement) {
when(statement) {
is IrExpression -> generateAsStatement(statement)
is IrVariable -> statement.acceptVoid(this)
else -> error("Unsupported node type: ${statement::class.simpleName}")
}
}
override fun visitElement(element: IrElement) { override fun visitElement(element: IrElement) {
error("Unexpected element of type ${element::class}") error("Unexpected element of type ${element::class}")
} }
@@ -161,7 +166,7 @@ class BodyGenerator(
when (expression.operator) { when (expression.operator) {
IrTypeOperator.REINTERPRET_CAST -> generateExpression(expression.argument) IrTypeOperator.REINTERPRET_CAST -> generateExpression(expression.argument)
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> { IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> {
generateStatement(expression.argument) generateAsStatement(expression.argument)
body.buildGetUnit() body.buildGetUnit()
} }
else -> assert(false) { "Other types of casts must be lowered" } else -> assert(false) { "Other types of casts must be lowered" }
@@ -654,7 +659,7 @@ class BodyGenerator(
private fun visitFunctionReturn(expression: IrReturn) { private fun visitFunctionReturn(expression: IrReturn) {
val returnType = expression.returnTargetSymbol.owner.returnType(backendContext) val returnType = expression.returnTargetSymbol.owner.returnType(backendContext)
if (returnType == irBuiltIns.unitType && expression.returnTargetSymbol.owner != unitGetInstance) { if (returnType == irBuiltIns.unitType && expression.returnTargetSymbol.owner != unitGetInstance) {
generateStatement(expression.value) generateAsStatement(expression.value)
} else { } else {
if (isGetUnitFunction) { if (isGetUnitFunction) {
generateExpression(expression.value) generateExpression(expression.value)
@@ -674,12 +679,12 @@ class BodyGenerator(
val actualType = expression.type val actualType = expression.type
if (expectedType == wasmSymbols.voidType) { if (expectedType == wasmSymbols.voidType) {
generateStatement(expression) generateAsStatement(expression)
return return
} }
if (expectedType.isUnit() && !actualType.isUnit()) { if (expectedType.isUnit() && !actualType.isUnit()) {
generateStatement(expression) generateAsStatement(expression)
body.buildGetUnit() body.buildGetUnit()
return return
} }
@@ -817,7 +822,7 @@ class BodyGenerator(
body.buildBlock("CONTINUE_$label") { wasmContinueBlock -> body.buildBlock("CONTINUE_$label") { wasmContinueBlock ->
functionContext.defineLoopLevel(loop, LoopLabelType.BREAK, wasmBreakBlock) functionContext.defineLoopLevel(loop, LoopLabelType.BREAK, wasmBreakBlock)
functionContext.defineLoopLevel(loop, LoopLabelType.CONTINUE, wasmContinueBlock) functionContext.defineLoopLevel(loop, LoopLabelType.CONTINUE, wasmContinueBlock)
loop.body?.let { generateStatement(it) } loop.body?.let { generateAsStatement(it) }
} }
generateExpression(loop.condition) generateExpression(loop.condition)
body.buildBrIf(wasmLoop) body.buildBrIf(wasmLoop)
@@ -845,7 +850,7 @@ class BodyGenerator(
body.buildInstr(WasmOp.I32_EQZ) body.buildInstr(WasmOp.I32_EQZ)
body.buildBrIf(wasmBreakBlock) body.buildBrIf(wasmBreakBlock)
loop.body?.let { loop.body?.let {
generateStatement(it) generateAsStatement(it)
} }
body.buildBr(wasmLoop) body.buildBr(wasmLoop)
} }