From 5c845da18a061409b8694108cff0028a0e3e7dd6 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 28 Feb 2020 18:06:23 +0300 Subject: [PATCH] Implement interpretation for unsigned numbers --- .../common/interpreter/IrInterpreter.kt | 24 +++++++++++++++++-- .../backend/common/interpreter/Utils.kt | 16 +++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt index 198209a9ff9..799cddba5e0 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt @@ -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, data: Frame): Code { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt index 85a474bd2e1..2d88aa2bb5a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt @@ -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 } }