[Wasm] Fix result of statically-know type operators
- Use subclass with erased types to match runtime behavior - Handle casting to Nothing
This commit is contained in:
+20
-14
@@ -13,16 +13,15 @@ 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.common.lower.irNot
|
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound
|
||||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.getRuntimeClass
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.getRuntimeClass
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -98,8 +97,11 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
|
|||||||
private fun IrType.isInlined(): Boolean =
|
private fun IrType.isInlined(): Boolean =
|
||||||
context.inlineClassesUtils.isTypeInlined(this)
|
context.inlineClassesUtils.isTypeInlined(this)
|
||||||
|
|
||||||
private val IrType.erasedType: IrType
|
private val IrType.eraseToClassOrInterface: IrClass
|
||||||
get() = this.getRuntimeClass?.defaultType ?: builtIns.anyType
|
get() = this.erasedUpperBound ?: builtIns.anyClass.owner
|
||||||
|
|
||||||
|
private val IrType.eraseToClass: IrClass
|
||||||
|
get() = this.getRuntimeClass ?: builtIns.anyClass.owner
|
||||||
|
|
||||||
private fun generateTypeCheck(
|
private fun generateTypeCheck(
|
||||||
valueProvider: () -> IrExpression,
|
valueProvider: () -> IrExpression,
|
||||||
@@ -112,7 +114,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
|
|||||||
// Inlined values have no type information on runtime.
|
// Inlined values have no type information on runtime.
|
||||||
// But since they are final we can compute type checks on compile time.
|
// But since they are final we can compute type checks on compile time.
|
||||||
if (fromType.isInlined()) {
|
if (fromType.isInlined()) {
|
||||||
val result = fromType.erasedType.isSubtypeOf(toType.erasedType, context.typeSystem)
|
val result = fromType.eraseToClassOrInterface.isSubclassOf(toType.eraseToClassOrInterface)
|
||||||
return builder.irBoolean(result)
|
return builder.irBoolean(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,11 +190,15 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromType.erasedType.isSubtypeOf(toType.erasedType, context.typeSystem)) {
|
if (fromType.eraseToClassOrInterface.isSubclassOf(toType.eraseToClassOrInterface)) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
if (toType.isNothing()) {
|
if (toType.isNothing()) {
|
||||||
return value
|
// Casting to nothing is unreachable...
|
||||||
|
return builder.irComposite(resultType = context.irBuiltIns.nothingType) {
|
||||||
|
+value // ... but we have to evaluate an argument
|
||||||
|
+irCall(symbols.wasmUnreachable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.irCall(symbols.wasmRefCast, type = toType).apply {
|
return builder.irCall(symbols.wasmRefCast, type = toType).apply {
|
||||||
@@ -208,7 +214,7 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
|
|||||||
val toType = expression.typeOperand
|
val toType = expression.typeOperand
|
||||||
val fromType = expression.argument.type
|
val fromType = expression.argument.type
|
||||||
|
|
||||||
if (fromType.erasedType.isSubtypeOf(expression.type.erasedType, context.typeSystem)) {
|
if (fromType.eraseToClassOrInterface.isSubclassOf(expression.type.eraseToClassOrInterface)) {
|
||||||
return narrowType(fromType, expression.type, expression.argument)
|
return narrowType(fromType, expression.type, expression.argument)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,12 +278,12 @@ class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrEleme
|
|||||||
|
|
||||||
private fun generateIsSubClass(argument: IrExpression, toType: IrType): IrExpression {
|
private fun generateIsSubClass(argument: IrExpression, toType: IrType): IrExpression {
|
||||||
val fromType = argument.type
|
val fromType = argument.type
|
||||||
val fromTypeErased = fromType.erasedType
|
val fromTypeErased = fromType.eraseToClass
|
||||||
val toTypeErased = toType.erasedType
|
val toTypeErased = toType.eraseToClass
|
||||||
if (fromTypeErased.isSubtypeOfClass(toTypeErased.classOrNull!!)) {
|
if (fromTypeErased.isSubclassOf(toTypeErased)) {
|
||||||
return builder.irTrue()
|
return builder.irTrue()
|
||||||
}
|
}
|
||||||
if (!toTypeErased.isSubtypeOfClass(fromTypeErased.classOrNull!!)) {
|
if (!toTypeErased.isSubclassOf(fromTypeErased)) {
|
||||||
return builder.irFalse()
|
return builder.irFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user