diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt index a64d9fdd33e..e60fbaeab0a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds.primitiveArrayTypeByElementType import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.StandardClassIds.unsignedArrayTypeByElementType object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() { override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { @@ -84,6 +85,9 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() { classId in primitiveArrayTypeByElementType.values -> { // DO NOTHING: primitive arrays are allowed } + classId in unsignedArrayTypeByElementType.values -> { + // DO NOTHING: arrays of unsigned types are allowed + } classId == StandardClassIds.Array -> { if (!isAllowedArray(typeRef, context.session)) reporter.reportOn(typeRef.source, FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER, context) 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 f4099518313..507dd77b162 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 @@ -46,6 +46,7 @@ class IrCompileTimeChecker( 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.isUnsignedType() } == true + parentType?.isUnsignedType() == true && (this is IrConstructor) -> 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 0a916700091..6211cfe302f 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 @@ -379,6 +379,10 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map .apply { stack.peekReturnValue().addTypeArguments(typeArguments) } } + if (irClass.defaultType.isUnsignedType()) { + return stack.newFrame(initPool = valueArguments) { handleIntrinsicMethods(owner) } + } + val state = Common(irClass).apply { this.addTypeArguments(typeArguments) } if (irClass.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations if (irClass.isInner) { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt index 7254b8c718e..edbb569f496 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt @@ -23,6 +23,7 @@ internal class IntrinsicEvaluator { EnumHashCode.equalTo(irFunction) -> EnumHashCode.evaluate(irFunction, stack, interpret) JsPrimitives.equalTo(irFunction) -> JsPrimitives.evaluate(irFunction, stack, interpret) ArrayConstructor.equalTo(irFunction) -> ArrayConstructor.evaluate(irFunction, stack, interpret) + UnsignedConstructor.equalTo(irFunction) -> UnsignedConstructor.evaluate(irFunction, stack, interpret) else -> throw InterpreterMethodNotFoundException("Method ${irFunction.name} hasn't implemented") } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt index ff37fac91da..d3258f42709 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt @@ -5,15 +5,20 @@ package org.jetbrains.kotlin.ir.interpreter.intrinsics +import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.ir.interpreter.* import org.jetbrains.kotlin.ir.interpreter.stack.Stack import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrEnumEntry import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.getUnsignedType +import org.jetbrains.kotlin.ir.types.isUnsignedType import org.jetbrains.kotlin.ir.util.* internal sealed class IntrinsicBase { @@ -189,4 +194,22 @@ internal object ArrayConstructor : IntrinsicBase() { stack.pushReturnValue(arrayValue.toPrimitiveStateArray(irFunction.parentAsClass.defaultType)) return Next } +} + +internal object UnsignedConstructor : IntrinsicBase() { + override fun equalTo(irFunction: IrFunction): Boolean { + val constructorCall = irFunction as? IrConstructor ?: return false + val irClass = constructorCall.parent as IrClass + return irClass.defaultType.isUnsignedType() && irFunction.valueParameters.size == 1 + } + + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { + val parameter = irFunction.valueParameters.single() + val argument = stack.getVariable(parameter.symbol).state.asNumber() + val irClass = irFunction.parent as IrClass + val result = Common(irClass) + result.fields.add(Variable(parameter.symbol, argument.toState(parameter.type))) + stack.pushReturnValue(result) + return Next + } } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt index 4b4cc3ec2d2..6d3d62045c0 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt @@ -38,6 +38,7 @@ internal interface State { internal fun State.isNull() = this is Primitive<*> && this.value == null +internal fun State.asNumber() = (this as Primitive<*>).value as Number internal fun State.asInt() = (this as Primitive<*>).value as Int internal fun State.asBoolean() = (this as Primitive<*>).value as Boolean internal fun State.asString() = (this as Primitive<*>).value.toString() diff --git a/compiler/testData/codegen/box/compileKotlinAgainstKotlin/unsignedTypesInAnnotations.kt b/compiler/testData/codegen/box/compileKotlinAgainstKotlin/unsignedTypesInAnnotations.kt index 017f51009de..4c134559a11 100644 --- a/compiler/testData/codegen/box/compileKotlinAgainstKotlin/unsignedTypesInAnnotations.kt +++ b/compiler/testData/codegen/box/compileKotlinAgainstKotlin/unsignedTypesInAnnotations.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: NATIVE // WITH_RUNTIME // WITH_STDLIB diff --git a/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt b/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt index 257877a592f..885faf92093 100644 --- a/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt +++ b/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedArrayType.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // WITH_REFLECT // TARGET_BACKEND: JVM @@ -7,21 +6,21 @@ annotation class AnnoUS(val us: UShortArray) annotation class AnnoUI(val ui: UIntArray) annotation class AnnoUL(val ul: ULongArray) -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") const val ub0 = UByte(1) -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") const val us0 = UShort(2) -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") const val ul0 = ULong(3) -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") const val ui0 = UInt(-1) -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") const val ui1 = UInt(0) -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") const val ui2 = UInt(40 + 2) -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") object Foo { @AnnoUB([UByte(1), ub0]) fun f0() {} @@ -41,7 +40,7 @@ fun check(ann: Annotation, f: T.() -> Boolean) { if (!result) throw RuntimeException("fail for $ann") } -@Suppress("INVISIBLE_MEMBER") +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") fun box(): String { if (ub0.toByte() != 1.toByte()) return "fail" if (us0.toShort() != 2.toShort()) return "fail" diff --git a/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt b/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt index f1f2f09fc7e..55d578105c9 100644 --- a/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt +++ b/compiler/testData/codegen/box/unsignedTypes/evaluateConstructorOfUnsignedType.kt @@ -1,11 +1,10 @@ -// IGNORE_BACKEND_FIR: JVM_IR // WITH_REFLECT // TARGET_BACKEND: JVM // TODO: it's not clear why compilation fails for Android // IGNORE_BACKEND: ANDROID -@file:Suppress("INVISIBLE_MEMBER") +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") annotation class AnnoUB(val ub0: UByte, val ub1: UByte) annotation class AnnoUS(val us0: UShort, val us1: UShort)