diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt index 307bbb79845..6da69340c90 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrCompileTimeChecker.kt @@ -5,13 +5,13 @@ package org.jetbrains.kotlin.ir.interpreter -import org.jetbrains.kotlin.ir.interpreter.builtins.compileTimeAnnotation -import org.jetbrains.kotlin.ir.interpreter.builtins.contractsDslAnnotation -import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.interpreter.builtins.compileTimeAnnotation +import org.jetbrains.kotlin.ir.interpreter.builtins.contractsDslAnnotation +import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -45,7 +45,7 @@ class IrCompileTimeChecker( parentType?.isPrimitiveType() == true -> (this as IrFunction).name.asString() !in setOf("inc", "dec", "rangeTo", "hashCode") parentType?.isString() == true -> (this as IrDeclarationWithName).name.asString() !in setOf("subSequence", "hashCode") parentType?.isAny() == true -> (this as IrFunction).name.asString() == "toString" && expression?.dispatchReceiver !is IrGetObjectValue - parent?.isObject == true -> parent.parentClassOrNull?.defaultType?.let { it.isPrimitiveType() || it.isUnsigned() } == true + parent?.isObject == true -> parent.parentClassOrNull?.defaultType?.let { it.isPrimitiveType() || it.isUnsignedType() } == true else -> false } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index d3525bdff6e..0a916700091 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.interpreter +import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* @@ -417,21 +418,20 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map } private fun interpretConst(expression: IrConst<*>): ExecutionResult { - fun getSignedType(unsignedType: IrType): IrType { - return when { - unsignedType.isUByte() -> irBuiltIns.byteType - unsignedType.isUShort() -> irBuiltIns.shortType - unsignedType.isUInt() -> irBuiltIns.intType - unsignedType.isULong() -> irBuiltIns.longType - else -> throw InterpreterException("Unsupported unsigned class ${unsignedType.render()}") - } + fun getSignedType(unsignedType: IrType): IrType? = when (unsignedType.getUnsignedType()) { + UnsignedType.UBYTE -> irBuiltIns.byteType + UnsignedType.USHORT -> irBuiltIns.shortType + UnsignedType.UINT -> irBuiltIns.intType + UnsignedType.ULONG -> irBuiltIns.longType + else -> null } - return if (expression.type.isUnsigned()) { + val signedType = getSignedType(expression.type) + return if (signedType != null) { 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(expression.type))) + constructorCall.putValueArgument(0, expression.value.toIrConst(signedType)) constructorCall.interpret() } else { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt index 4975c55acde..9a0a78f69fc 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.interpreter import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* @@ -48,7 +49,7 @@ internal fun State.toIrExpression(expression: IrExpression): IrExpression { is Complex -> { val stateType = this.irClass.defaultType when { - stateType.isUnsigned() -> (this.fields.single().state as Primitive<*>).value.toIrConst(type, start, end) + stateType.isUnsignedType() -> (this.fields.single().state as Primitive<*>).value.toIrConst(type, start, end) else -> expression } } @@ -79,13 +80,15 @@ fun Any?.toIrConst(irType: IrType, startOffset: Int = UNDEFINED_OFFSET, endOffse PrimitiveType.FLOAT -> IrConstImpl.float(startOffset, endOffset, constType, (this as Number).toFloat()) PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong()) PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, constType, (this as Number).toDouble()) - else -> when { - constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String) - constType.isUByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte()) - constType.isUShort() -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort()) - constType.isUInt() -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt()) - constType.isULong() -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong()) - else -> throw UnsupportedOperationException("Unsupported const element type ${constType.render()}") + null -> when (constType.getUnsignedType()) { + UnsignedType.UBYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte()) + UnsignedType.USHORT -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort()) + UnsignedType.UINT -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt()) + UnsignedType.ULONG -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong()) + null -> when { + constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String) + else -> throw UnsupportedOperationException("Unsupported const element type ${constType.render()}") + } } } } @@ -213,8 +216,6 @@ internal fun State?.getCorrectReceiverByFunction(irFunction: IrFunction): State? internal fun IrFunction.getCapitalizedFileName() = this.file.name.replace(".kt", "Kt").capitalizeAsciiOnly() -internal fun IrType.isUnsigned() = this.isUByte() || this.isUShort() || this.isUInt() || this.isULong() - internal fun IrType.isPrimitiveArray(): Boolean { return this.getClass()?.fqNameWhenAvailable?.toUnsafe()?.let { StandardNames.isPrimitiveArray(it) } ?: false } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt index 11939a61a4e..5a05ecfed29 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.types import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol @@ -100,6 +101,20 @@ fun IrType.getPrimitiveType(): PrimitiveType? = idSignatureToPrimitiveType[classifier.signature] else null +fun IrType.isUnsignedType(hasQuestionMark: Boolean = false): Boolean = + this is IrSimpleType && hasQuestionMark == this.hasQuestionMark && getUnsignedType() != null + +fun IrType.getUnsignedType(): UnsignedType? = + if (this is IrSimpleType && classifier is IrClassSymbol) + when (classifier.signature) { + IdSignatureValues.uByte -> UnsignedType.UBYTE + IdSignatureValues.uShort -> UnsignedType.USHORT + IdSignatureValues.uInt -> UnsignedType.UINT + IdSignatureValues.uLong -> UnsignedType.ULONG + else -> null + } + else null + fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false fun IrType.isUnit() = isNotNullClassType(IdSignatureValues.unit)