From 0ebdf7c3c49c87dc674775d93950f3fdfe21f1a6 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Sun, 21 Feb 2021 12:12:57 +0100 Subject: [PATCH] IR: add getPrimitiveType, optimize some usages of isInt/isByte/... --- .../optimizations/FoldConstantLowering.kt | 37 +++++----- .../lower/indy/LambdaMetafactoryArguments.kt | 16 ++--- .../jetbrains/kotlin/ir/interpreter/Utils.kt | 63 +++++++++-------- .../kotlin/ir/expressions/impl/IrConstImpl.kt | 24 ++++--- .../kotlin/ir/types/irTypePredicates.kt | 68 ++++++++----------- .../backend/ir/SerializerIrGenerator.kt | 25 ++++--- 6 files changed, 114 insertions(+), 119 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/FoldConstantLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/FoldConstantLowering.kt index 1014850784d..b2bb459d844 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/FoldConstantLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/FoldConstantLowering.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.common.lower.optimizations import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.* @@ -52,18 +53,18 @@ class FoldConstantLowering( ) @Suppress("unused") - private data class PrimitiveType(val name: String) + private data class PrimitiveTypeName(val name: String) companion object { - private val INT = PrimitiveType("Int") - private val LONG = PrimitiveType("Long") - private val DOUBLE = PrimitiveType("Double") - private val FLOAT = PrimitiveType("Float") + private val INT = PrimitiveTypeName("Int") + private val LONG = PrimitiveTypeName("Long") + private val DOUBLE = PrimitiveTypeName("Double") + private val FLOAT = PrimitiveTypeName("Float") private val BINARY_OP_TO_EVALUATOR = HashMap>() @Suppress("UNCHECKED_CAST") - private fun registerBuiltinBinaryOp(operandType: PrimitiveType, operatorName: String, f: (T, T) -> Any) { + private fun registerBuiltinBinaryOp(operandType: PrimitiveTypeName, operatorName: String, f: (T, T) -> Any) { BINARY_OP_TO_EVALUATOR[BinaryOp(operandType.name, operandType.name, operatorName)] = f as Function2 } @@ -105,17 +106,19 @@ class FoldConstantLowering( private fun buildIrConstant(startOffset: Int, endOffset: Int, type: IrType, v: Any?): IrConst<*> { val constType = type.makeNotNull() - return when { - constType.isInt() -> IrConstImpl.int(startOffset, endOffset, constType, (v as Number).toInt()) - constType.isChar() -> IrConstImpl.char(startOffset, endOffset, constType, v as Char) - constType.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, constType, v as Boolean) - constType.isByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (v as Number).toByte()) - constType.isShort() -> IrConstImpl.short(startOffset, endOffset, constType, (v as Number).toShort()) - constType.isLong() -> IrConstImpl.long(startOffset, endOffset, constType, (v as Number).toLong()) - constType.isDouble() -> IrConstImpl.double(startOffset, endOffset, constType, (v as Number).toDouble()) - constType.isFloat() -> fromFloatConstSafe(startOffset, endOffset, type, v) - constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, v as String) - else -> throw IllegalArgumentException("Unexpected IrCall return type") + return when (type.getPrimitiveType()) { + PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, constType, v as Boolean) + PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, constType, v as Char) + PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (v as Number).toByte()) + PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, constType, (v as Number).toShort()) + PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, constType, (v as Number).toInt()) + PrimitiveType.FLOAT -> fromFloatConstSafe(startOffset, endOffset, type, v) + PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, constType, (v as Number).toLong()) + PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, constType, (v as Number).toDouble()) + else -> when { + constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, v as String) + else -> throw IllegalArgumentException("Unexpected IrCall return type") + } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt index cf3433b9e14..7c0130dddc1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt @@ -251,7 +251,7 @@ internal class LambdaMetafactoryArgumentsBuilder( null -> true TypeAdaptationConstraint.FORCE_BOXING -> irType.isNullable() TypeAdaptationConstraint.KEEP_UNBOXED -> !irType.isNullable() - TypeAdaptationConstraint.BOX_PRIMITIVE -> irType.isJvmPrimitiveOrNullable() + TypeAdaptationConstraint.BOX_PRIMITIVE -> irType.getPrimitiveType() != null TypeAdaptationConstraint.CONFLICT -> false } @@ -414,9 +414,9 @@ internal class LambdaMetafactoryArgumentsBuilder( // ** JVM primitives ** // All Kotlin types mapped to JVM primitive are final, // and their supertypes are trivially mapped reference types. - if (adapteeType.isJvmPrimitiveType()) { + if (adapteeType.isPrimitiveType()) { return if ( - expectedType.isJvmPrimitiveType() && + expectedType.isPrimitiveType() && !expectedType.hasAnnotation(context.ir.symbols.enhancedNullabilityAnnotationFqName) ) TypeAdaptationConstraint.KEEP_UNBOXED @@ -433,7 +433,7 @@ internal class LambdaMetafactoryArgumentsBuilder( // TODO consider adding a special type annotation to force boxing on an inline class type regardless of its underlying type. val underlyingAdapteeType = getInlineClassUnderlyingType(erasedAdapteeClass) as? IrSimpleType ?: throw AssertionError("Underlying type for inline class should be a simple type: ${erasedAdapteeClass.render()}") - if (!underlyingAdapteeType.hasQuestionMark && !underlyingAdapteeType.isJvmPrimitiveType()) { + if (!underlyingAdapteeType.hasQuestionMark && !underlyingAdapteeType.isPrimitiveType()) { return TypeAdaptationConstraint.CONFLICT } @@ -522,14 +522,6 @@ internal class LambdaMetafactoryArgumentsBuilder( private fun IrDeclarationParent.isCrossinlineLambda(): Boolean = this is IrSimpleFunction && this in crossinlineLambdas - private fun IrType.isJvmPrimitiveType() = - isBoolean() || isChar() || isByte() || isShort() || isInt() || isLong() || isFloat() || isDouble() - - private fun IrType.isJvmPrimitiveOrNullable() = - isBooleanOrNullable() || isCharOrNullable() || - isByteOrNullable() || isShortOrNullable() || isIntOrNullable() || isLongOrNullable() || - isFloatOrNullable() || isDoubleOrNullable() - fun collectValueParameters( irFun: IrFunction, withDispatchReceiver: Boolean = false, 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 452fdd9bd55..4975c55acde 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.interpreter +import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET @@ -66,23 +67,26 @@ internal fun Any?.toState(irType: IrType): State { } fun Any?.toIrConst(irType: IrType, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET): IrConst<*> { + if (this == null) return IrConstImpl.constNull(startOffset, endOffset, irType) + val constType = irType.makeNotNull() - return when { - this == null -> IrConstImpl.constNull(startOffset, endOffset, irType) - constType.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, constType, this as Boolean) - constType.isChar() -> IrConstImpl.char(startOffset, endOffset, constType, this as Char) - constType.isByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte()) - constType.isShort() -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort()) - constType.isInt() -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt()) - constType.isLong() -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong()) - constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String) - constType.isFloat() -> IrConstImpl.float(startOffset, endOffset, constType, (this as Number).toFloat()) - constType.isDouble() -> IrConstImpl.double(startOffset, endOffset, constType, (this as Number).toDouble()) - 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()}") + return when (irType.getPrimitiveType()) { + PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, constType, this as Boolean) + PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, constType, this as Char) + PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte()) + PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort()) + PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt()) + 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()}") + } } } @@ -109,20 +113,21 @@ internal fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? { return (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString() } -internal fun getPrimitiveClass(irType: IrType, asObject: Boolean = false): Class<*>? { - return when { - irType.isBoolean() -> if (asObject) Boolean::class.javaObjectType else Boolean::class.java - irType.isChar() -> if (asObject) Char::class.javaObjectType else Char::class.java - irType.isByte() -> if (asObject) Byte::class.javaObjectType else Byte::class.java - irType.isShort() -> if (asObject) Short::class.javaObjectType else Short::class.java - irType.isInt() -> if (asObject) Int::class.javaObjectType else Int::class.java - irType.isLong() -> if (asObject) Long::class.javaObjectType else Long::class.java - irType.isString() -> if (asObject) String::class.javaObjectType else String::class.java - irType.isFloat() -> if (asObject) Float::class.javaObjectType else Float::class.java - irType.isDouble() -> if (asObject) Double::class.javaObjectType else Double::class.java - else -> null +internal fun getPrimitiveClass(irType: IrType, asObject: Boolean = false): Class<*>? = + when (irType.getPrimitiveType()) { + PrimitiveType.BOOLEAN -> if (asObject) Boolean::class.javaObjectType else Boolean::class.java + PrimitiveType.CHAR -> if (asObject) Char::class.javaObjectType else Char::class.java + PrimitiveType.BYTE -> if (asObject) Byte::class.javaObjectType else Byte::class.java + PrimitiveType.SHORT -> if (asObject) Short::class.javaObjectType else Short::class.java + PrimitiveType.INT -> if (asObject) Int::class.javaObjectType else Int::class.java + PrimitiveType.FLOAT -> if (asObject) Float::class.javaObjectType else Float::class.java + PrimitiveType.LONG -> if (asObject) Long::class.javaObjectType else Long::class.java + PrimitiveType.DOUBLE -> if (asObject) Double::class.javaObjectType else Double::class.java + else -> when { + irType.isString() -> String::class.java + else -> null + } } -} internal fun IrFunction.getArgsForMethodInvocation(args: List): List { val argsValues = args.map { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt index 019443e5623..d5e49c4c706 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstImpl.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.ir.expressions.impl +import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.types.* @@ -74,16 +75,19 @@ class IrConstImpl( fun short(startOffset: Int, endOffset: Int, type: IrType, value: Short): IrConstImpl = IrConstImpl(startOffset, endOffset, type, IrConstKind.Short, value) - fun defaultValueForType(startOffset: Int, endOffset: Int, type: IrType) = when { - type.isFloat() -> float(startOffset, endOffset, type, 0.0F) - type.isDouble() -> double(startOffset, endOffset, type, 0.0) - type.isBoolean() -> boolean(startOffset, endOffset, type, false) - type.isByte() -> byte(startOffset, endOffset, type, 0) - type.isChar() -> char(startOffset, endOffset, type, 0.toChar()) - type.isShort() -> short(startOffset, endOffset, type, 0) - type.isInt() -> int(startOffset, endOffset, type, 0) - type.isLong() -> long(startOffset, endOffset, type, 0) - else -> constNull(startOffset, endOffset, type) + fun defaultValueForType(startOffset: Int, endOffset: Int, type: IrType): IrConstImpl<*> { + if (type.isMarkedNullable()) return constNull(startOffset, endOffset, type) + return when (type.getPrimitiveType()) { + PrimitiveType.BOOLEAN -> boolean(startOffset, endOffset, type, false) + PrimitiveType.CHAR -> char(startOffset, endOffset, type, 0.toChar()) + PrimitiveType.BYTE -> byte(startOffset, endOffset, type, 0) + PrimitiveType.SHORT -> short(startOffset, endOffset, type, 0) + PrimitiveType.INT -> int(startOffset, endOffset, type, 0) + PrimitiveType.FLOAT -> float(startOffset, endOffset, type, 0.0F) + PrimitiveType.LONG -> long(startOffset, endOffset, type, 0) + PrimitiveType.DOUBLE -> double(startOffset, endOffset, type, 0.0) + else -> constNull(startOffset, endOffset, type) + } } } } 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 f023b5dfdfa..11939a61a4e 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 @@ -11,39 +11,36 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.util.IdSignature -import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.hasEqualFqName import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize @Suppress("ObjectPropertyName") object IdSignatureValues { @JvmField val any = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Any") - @JvmField val nothing = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Nothing") - @JvmField val unit = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Unit") + @JvmField val nothing = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Nothing") + @JvmField val unit = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Unit") @JvmField val _boolean = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Boolean") @JvmField val _char = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Char") - @JvmField val _byte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Byte") - @JvmField val _short = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Short") - @JvmField val _int = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Int") - @JvmField val _long = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Long") - @JvmField val _float = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Float") - @JvmField val _double = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Double") - @JvmField val number = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Number") - @JvmField val uByte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UByte") - @JvmField val uShort = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UShort") - @JvmField val uInt = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UInt") - @JvmField val uLong = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"ULong") - @JvmField val string = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"String") - @JvmField val array = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Array") + @JvmField val _byte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Byte") + @JvmField val _short = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Short") + @JvmField val _int = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Int") + @JvmField val _long = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Long") + @JvmField val _float = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Float") + @JvmField val _double = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Double") + @JvmField val number = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Number") + @JvmField val uByte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "UByte") + @JvmField val uShort = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "UShort") + @JvmField val uInt = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "UInt") + @JvmField val uLong = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "ULong") + @JvmField val string = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "String") + @JvmField val array = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Array") @JvmField val collection = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Collection") @JvmField val kClass = getPublicSignature(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KClass") - @JvmField val comparable = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Comparable") - @JvmField val charSequence = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"CharSequence") + @JvmField val comparable = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Comparable") + @JvmField val charSequence = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "CharSequence") @JvmField val iterable = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Iterable") - @JvmField val continuation = getPublicSignature(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE,"Continuation") + @JvmField val continuation = getPublicSignature(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, "Continuation") @JvmField val result = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Result") @JvmField val sequence = IdSignature.PublicSignature("kotlin.sequences", "Sequence", null, 0) } @@ -69,18 +66,13 @@ private fun classFqNameEquals(symbol: IrClassSymbol, fqName: FqNameUnsafe): Bool } private val idSignatureToPrimitiveType: Map = - newHashMapWithExpectedSize(PrimitiveType.values().size).apply { - for (primitiveType in PrimitiveType.values()) { - this[getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, primitiveType.typeName.asString())] = primitiveType - } + PrimitiveType.values().associateBy { + getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, it.typeName.asString()) } val primitiveArrayTypesSignatures: Map = - newHashMapWithExpectedSize(PrimitiveType.values().size).apply { - for (primitiveType in PrimitiveType.values()) { - this[primitiveType] = - getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "${primitiveType.typeName.asString()}Array") - } + PrimitiveType.values().associateWith { + getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "${it.typeName.asString()}Array") } private fun classFqNameEquals(declaration: IrClass, fqName: FqNameUnsafe): Boolean = @@ -99,35 +91,31 @@ fun IrType.isNothing(): Boolean = isNotNullClassType(IdSignatureValues.nothing) fun IrType.isNullableNothing(): Boolean = isNullableClassType(IdSignatureValues.nothing) fun IrType.isPrimitiveType(hasQuestionMark: Boolean = false): Boolean = - (this is IrSimpleType && hasQuestionMark == this.hasQuestionMark) && - classOrNull?.signature in idSignatureToPrimitiveType + this is IrSimpleType && hasQuestionMark == this.hasQuestionMark && getPrimitiveType() != null fun IrType.isNullablePrimitiveType(): Boolean = isPrimitiveType(true) +fun IrType.getPrimitiveType(): PrimitiveType? = + if (this is IrSimpleType && classifier is IrClassSymbol) + idSignatureToPrimitiveType[classifier.signature] + else null + fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false fun IrType.isUnit() = isNotNullClassType(IdSignatureValues.unit) fun IrType.isBoolean(): Boolean = isNotNullClassType(IdSignatureValues._boolean) -fun IrType.isBooleanOrNullable(): Boolean = isClassType(IdSignatureValues._boolean) fun IrType.isChar(): Boolean = isNotNullClassType(IdSignatureValues._char) -fun IrType.isCharOrNullable(): Boolean = isClassType(IdSignatureValues._char) fun IrType.isByte(): Boolean = isNotNullClassType(IdSignatureValues._byte) -fun IrType.isByteOrNullable(): Boolean = isClassType(IdSignatureValues._byte) fun IrType.isShort(): Boolean = isNotNullClassType(IdSignatureValues._short) -fun IrType.isShortOrNullable(): Boolean = isClassType(IdSignatureValues._short) fun IrType.isInt(): Boolean = isNotNullClassType(IdSignatureValues._int) -fun IrType.isIntOrNullable(): Boolean = isClassType(IdSignatureValues._int) fun IrType.isLong(): Boolean = isNotNullClassType(IdSignatureValues._long) -fun IrType.isLongOrNullable(): Boolean = isClassType(IdSignatureValues._long) fun IrType.isUByte(): Boolean = isNotNullClassType(IdSignatureValues.uByte) fun IrType.isUShort(): Boolean = isNotNullClassType(IdSignatureValues.uShort) fun IrType.isUInt(): Boolean = isNotNullClassType(IdSignatureValues.uInt) fun IrType.isULong(): Boolean = isNotNullClassType(IdSignatureValues.uLong) fun IrType.isFloat(): Boolean = isNotNullClassType(IdSignatureValues._float) -fun IrType.isFloatOrNullable(): Boolean = isClassType(IdSignatureValues._float) fun IrType.isDouble(): Boolean = isNotNullClassType(IdSignatureValues._double) -fun IrType.isDoubleOrNullable(): Boolean = isClassType(IdSignatureValues._double) fun IrType.isNumber(): Boolean = isNotNullClassType(IdSignatureValues.number) fun IrType.isComparable(): Boolean = isNotNullClassType(IdSignatureValues.comparable) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt index f91c9a8cddb..f1d8342e60d 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irThrow +import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.* @@ -358,17 +359,19 @@ open class SerializerIrGenerator( private fun IrBuilderWithScope.defaultValueAndType(descriptor: PropertyDescriptor): Pair { val kType = descriptor.returnType!! val T = kType.toIrType() - val defaultPrimitive: IrExpression? = when { - T.isInt() -> IrConstImpl.int(startOffset, endOffset, T, 0) - T.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, T, false) - T.isLong() -> IrConstImpl.long(startOffset, endOffset, T, 0) - T.isDouble() -> IrConstImpl.double(startOffset, endOffset, T, 0.0) - T.isFloat() -> IrConstImpl.float(startOffset, endOffset, T, 0.0f) - T.isChar() -> IrConstImpl.char(startOffset, endOffset, T, 0.toChar()) - T.isByte() -> IrConstImpl.byte(startOffset, endOffset, T, 0) - T.isShort() -> IrConstImpl.short(startOffset, endOffset, T, 0) - else -> null - } + val defaultPrimitive: IrExpression? = + if (T.isMarkedNullable()) null + else when (T.getPrimitiveType()) { + PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, T, false) + PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, T, 0.toChar()) + PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, T, 0) + PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, T, 0) + PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, T, 0) + PrimitiveType.FLOAT -> IrConstImpl.float(startOffset, endOffset, T, 0.0f) + PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, T, 0) + PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, T, 0.0) + else -> null + } return if (defaultPrimitive == null) irNull(compilerContext.irBuiltIns.anyNType) to (compilerContext.irBuiltIns.anyNType) else