[Native] Support evaluation of const intrinsics for K2
#KT-56023 #KT-55469 Fixed
This commit is contained in:
+4
-5
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.wrap
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isArray
|
||||
import org.jetbrains.kotlin.ir.types.isUnsignedType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -91,7 +88,9 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
verify(handleIntrinsicMethods(irConstructor)) { "Unsupported intrinsic constructor: ${irConstructor.render()}" }
|
||||
}
|
||||
irClass.defaultType.isUnsignedType() -> {
|
||||
val propertySymbol = irClass.declarations.single { it is IrProperty }.symbol
|
||||
// Check for type is a hack needed for Native;
|
||||
// in UInt, for example, we may have (after lowerings, I guess) additional property "$companion".
|
||||
val propertySymbol = irClass.declarations.single { it is IrProperty && it.getter?.returnType?.isPrimitiveType() == true }.symbol
|
||||
callStack.pushState(receiver.apply { this.setField(propertySymbol, args.single()) })
|
||||
}
|
||||
else -> defaultAction()
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val bodyMap: Map<IdSignature, IrBody>) {
|
||||
class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val bodyMap: Map<IdSignature, IrBody> = emptyMap()) {
|
||||
val irBuiltIns: IrBuiltIns
|
||||
get() = environment.irBuiltIns
|
||||
private val callStack: CallStack
|
||||
@@ -239,7 +239,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
constructor.valueParameters.forEachIndexed { i, param -> callStack.storeState(param.symbol, valueArguments[i]) }
|
||||
callStack.storeState(constructor.symbol, KTypeState(returnType, environment.kTypeClass.owner))
|
||||
|
||||
val superReceiver = when (val irStatement = constructor.body?.statements?.get(0)) {
|
||||
val superReceiver = when (val irStatement = constructor.body?.statements?.getOrNull(0)) {
|
||||
null -> null // for jvm
|
||||
is IrTypeOperatorCall -> (irStatement.argument as IrFunctionAccessExpression).getThisReceiver() // for enums
|
||||
is IrFunctionAccessExpression -> irStatement.getThisReceiver()
|
||||
|
||||
+32
-8
@@ -255,14 +255,38 @@ internal fun interpretBinaryFunction(name: String, typeA: String, typeB: String,
|
||||
"Comparable" -> if (typeB == "T") return (a as Comparable<Any?>).compareTo(b)
|
||||
}
|
||||
"equals" -> when (typeA) {
|
||||
"Boolean" -> if (typeB == "Any?") return (a as Boolean).equals(b)
|
||||
"Char" -> if (typeB == "Any?") return (a as Char).equals(b)
|
||||
"Byte" -> if (typeB == "Any?") return (a as Byte).equals(b)
|
||||
"Short" -> if (typeB == "Any?") return (a as Short).equals(b)
|
||||
"Int" -> if (typeB == "Any?") return (a as Int).equals(b)
|
||||
"Float" -> if (typeB == "Any?") return (a as Float).equals(b)
|
||||
"Long" -> if (typeB == "Any?") return (a as Long).equals(b)
|
||||
"Double" -> if (typeB == "Any?") return (a as Double).equals(b)
|
||||
"Boolean" -> when (typeB) {
|
||||
"Any?" -> return (a as Boolean).equals(b)
|
||||
"Boolean" -> return (a as Boolean).equals(b as Boolean)
|
||||
}
|
||||
"Char" -> when (typeB) {
|
||||
"Any?" -> return (a as Char).equals(b)
|
||||
"Char" -> return (a as Char).equals(b as Char)
|
||||
}
|
||||
"Byte" -> when (typeB) {
|
||||
"Any?" -> return (a as Byte).equals(b)
|
||||
"Byte" -> return (a as Byte).equals(b as Byte)
|
||||
}
|
||||
"Short" -> when (typeB) {
|
||||
"Any?" -> return (a as Short).equals(b)
|
||||
"Short" -> return (a as Short).equals(b as Short)
|
||||
}
|
||||
"Int" -> when (typeB) {
|
||||
"Any?" -> return (a as Int).equals(b)
|
||||
"Int" -> return (a as Int).equals(b as Int)
|
||||
}
|
||||
"Float" -> when (typeB) {
|
||||
"Any?" -> return (a as Float).equals(b)
|
||||
"Float" -> return (a as Float).equals(b as Float)
|
||||
}
|
||||
"Long" -> when (typeB) {
|
||||
"Any?" -> return (a as Long).equals(b)
|
||||
"Long" -> return (a as Long).equals(b as Long)
|
||||
}
|
||||
"Double" -> when (typeB) {
|
||||
"Any?" -> return (a as Double).equals(b)
|
||||
"Double" -> return (a as Double).equals(b as Double)
|
||||
}
|
||||
"String" -> if (typeB == "Any?") return (a as String).equals(b)
|
||||
"Any" -> if (typeB == "Any?") return (a as Any).equals(b)
|
||||
}
|
||||
|
||||
+4
-1
@@ -50,7 +50,10 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
||||
ONLY_BUILTINS(mustCheckBody = false) {
|
||||
private val forbiddenMethodsOnPrimitives = setOf("inc", "dec", "rangeTo", "rangeUntil", "hashCode")
|
||||
private val forbiddenMethodsOnStrings = setOf("subSequence", "hashCode", "<init>")
|
||||
private val allowedExtensionFunctions = setOf("kotlin.floorDiv", "kotlin.mod", "kotlin.NumbersKt.floorDiv", "kotlin.NumbersKt.mod")
|
||||
private val allowedExtensionFunctions = setOf(
|
||||
"kotlin.floorDiv", "kotlin.mod", "kotlin.NumbersKt.floorDiv", "kotlin.NumbersKt.mod", "kotlin.<get-code>",
|
||||
"kotlin.internal.ir.EQEQ",
|
||||
)
|
||||
|
||||
override fun canEvaluateFunction(function: IrFunction, context: IrCall?): Boolean {
|
||||
if ((function as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.isConst == true) return true
|
||||
|
||||
+7
@@ -99,6 +99,13 @@ class IrCompileTimeChecker(
|
||||
if (mode == EvaluationMode.ONLY_INTRINSIC_CONST && expression.origin == IrStatementOrigin.WHEN) {
|
||||
return expression.statements.all { it.accept(this, null) }
|
||||
}
|
||||
|
||||
// `IrReturnableBlock` will be created from IrCall after inline. We should do basically the same check as for IrCall.
|
||||
if (expression is IrReturnableBlock) {
|
||||
// TODO after JVM inline MR 8122 will be pushed check original IrCall.
|
||||
TODO("Interpretation of `IrReturnableBlock` is not implemented")
|
||||
}
|
||||
|
||||
return visitStatements(expression.statements)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user