Implement interpretation for unsigned numbers

This commit is contained in:
Ivan Kylchik
2020-02-28 18:06:23 +03:00
parent b175f46315
commit 5c845da18a
2 changed files with 36 additions and 4 deletions
@@ -9,6 +9,7 @@ import kotlinx.coroutines.*
import org.jetbrains.kotlin.backend.common.interpreter.builtins.*
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
@@ -540,8 +541,27 @@ class IrInterpreter(irModule: IrModuleFragment) {
}
private suspend fun interpretConst(expression: IrConst<*>, data: Frame): Code {
data.pushReturnValue(expression.toPrimitive())
return Code.NEXT
fun getSignedType(unsignedClassName: String): IrType {
return when (unsignedClassName) {
"UByte" -> irBuiltIns.byteType
"UShort" -> irBuiltIns.shortType
"UInt" -> irBuiltIns.intType
"ULong" -> irBuiltIns.longType
else -> throw AssertionError("")
}
}
return if (UnsignedTypes.isUnsignedType(expression.type.toKotlinType())) {
val unsignedClass = expression.type.classOrNull!!
val constructor = unsignedClass.constructors.single().owner
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
constructorCall.putValueArgument(0, expression.value.toIrConst(getSignedType(unsignedClass.owner.name.asString())))
constructorCall.interpret(data)
} else {
data.pushReturnValue(expression.toPrimitive())
Code.NEXT
}
}
private suspend fun interpretStatements(statements: List<IrStatement>, data: Frame): Code {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.common.interpreter
import org.jetbrains.kotlin.backend.common.interpreter.builtins.evaluateIntrinsicAnnotation
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.isFakeOverride
import org.jetbrains.kotlin.name.FqName
@@ -81,15 +83,25 @@ fun IrFunction.isFakeOverridden(): Boolean {
}
fun State.toIrExpression(expression: IrExpression): IrExpression {
val start = expression.startOffset
val end = expression.endOffset
return when (this) {
is Primitive<*> ->
when (this.value) {
// toIrConst call is necessary to replace ir offsets
is Boolean, is Char, is Byte, is Short, is Int, is Long, is String, is Float, is Double ->
this.value.toIrConst(this.type, expression.startOffset, expression.endOffset)
null -> this.value.toIrConst(this.type, expression.startOffset, expression.endOffset)
this.value.toIrConst(this.type, start, end)
null -> this.value.toIrConst(this.type, start, end)
else -> expression // TODO support for arrays
}
is Complex -> {
val type = this.irClass.defaultType.toKotlinType()
when {
UnsignedTypes.isUnsignedType(type) ->
(this.fields.single().state as Primitive<*>).value.toIrConst(this.irClass.defaultType, start, end)
else -> expression
}
}
else -> expression // TODO support
}
}