IR: add getPrimitiveType, optimize some usages of isInt/isByte/...

This commit is contained in:
Alexander Udalov
2021-02-21 12:12:57 +01:00
parent 17ee10a0d8
commit 0ebdf7c3c4
6 changed files with 114 additions and 119 deletions
@@ -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.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase 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.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
@@ -52,18 +53,18 @@ class FoldConstantLowering(
) )
@Suppress("unused") @Suppress("unused")
private data class PrimitiveType<T>(val name: String) private data class PrimitiveTypeName<T>(val name: String)
companion object { companion object {
private val INT = PrimitiveType<Int>("Int") private val INT = PrimitiveTypeName<Int>("Int")
private val LONG = PrimitiveType<Long>("Long") private val LONG = PrimitiveTypeName<Long>("Long")
private val DOUBLE = PrimitiveType<Double>("Double") private val DOUBLE = PrimitiveTypeName<Double>("Double")
private val FLOAT = PrimitiveType<Float>("Float") private val FLOAT = PrimitiveTypeName<Float>("Float")
private val BINARY_OP_TO_EVALUATOR = HashMap<BinaryOp, Function2<Any?, Any?, Any>>() private val BINARY_OP_TO_EVALUATOR = HashMap<BinaryOp, Function2<Any?, Any?, Any>>()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun <T> registerBuiltinBinaryOp(operandType: PrimitiveType<T>, operatorName: String, f: (T, T) -> Any) { private fun <T> registerBuiltinBinaryOp(operandType: PrimitiveTypeName<T>, operatorName: String, f: (T, T) -> Any) {
BINARY_OP_TO_EVALUATOR[BinaryOp(operandType.name, operandType.name, operatorName)] = f as Function2<Any?, Any?, Any> BINARY_OP_TO_EVALUATOR[BinaryOp(operandType.name, operandType.name, operatorName)] = f as Function2<Any?, Any?, Any>
} }
@@ -105,17 +106,19 @@ class FoldConstantLowering(
private fun buildIrConstant(startOffset: Int, endOffset: Int, type: IrType, v: Any?): IrConst<*> { private fun buildIrConstant(startOffset: Int, endOffset: Int, type: IrType, v: Any?): IrConst<*> {
val constType = type.makeNotNull() val constType = type.makeNotNull()
return when { return when (type.getPrimitiveType()) {
constType.isInt() -> IrConstImpl.int(startOffset, endOffset, constType, (v as Number).toInt()) PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, constType, v as Boolean)
constType.isChar() -> IrConstImpl.char(startOffset, endOffset, constType, v as Char) PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, constType, v as Char)
constType.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, constType, v as Boolean) PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (v as Number).toByte())
constType.isByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (v as Number).toByte()) PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, constType, (v as Number).toShort())
constType.isShort() -> IrConstImpl.short(startOffset, endOffset, constType, (v as Number).toShort()) PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, constType, (v as Number).toInt())
constType.isLong() -> IrConstImpl.long(startOffset, endOffset, constType, (v as Number).toLong()) PrimitiveType.FLOAT -> fromFloatConstSafe(startOffset, endOffset, type, v)
constType.isDouble() -> IrConstImpl.double(startOffset, endOffset, constType, (v as Number).toDouble()) PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, constType, (v as Number).toLong())
constType.isFloat() -> fromFloatConstSafe(startOffset, endOffset, type, v) PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, constType, (v as Number).toDouble())
constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, v as String) else -> when {
else -> throw IllegalArgumentException("Unexpected IrCall return type") constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, v as String)
else -> throw IllegalArgumentException("Unexpected IrCall return type")
}
} }
} }
@@ -251,7 +251,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
null -> true null -> true
TypeAdaptationConstraint.FORCE_BOXING -> irType.isNullable() TypeAdaptationConstraint.FORCE_BOXING -> irType.isNullable()
TypeAdaptationConstraint.KEEP_UNBOXED -> !irType.isNullable() TypeAdaptationConstraint.KEEP_UNBOXED -> !irType.isNullable()
TypeAdaptationConstraint.BOX_PRIMITIVE -> irType.isJvmPrimitiveOrNullable() TypeAdaptationConstraint.BOX_PRIMITIVE -> irType.getPrimitiveType() != null
TypeAdaptationConstraint.CONFLICT -> false TypeAdaptationConstraint.CONFLICT -> false
} }
@@ -414,9 +414,9 @@ internal class LambdaMetafactoryArgumentsBuilder(
// ** JVM primitives ** // ** JVM primitives **
// All Kotlin types mapped to JVM primitive are final, // All Kotlin types mapped to JVM primitive are final,
// and their supertypes are trivially mapped reference types. // and their supertypes are trivially mapped reference types.
if (adapteeType.isJvmPrimitiveType()) { if (adapteeType.isPrimitiveType()) {
return if ( return if (
expectedType.isJvmPrimitiveType() && expectedType.isPrimitiveType() &&
!expectedType.hasAnnotation(context.ir.symbols.enhancedNullabilityAnnotationFqName) !expectedType.hasAnnotation(context.ir.symbols.enhancedNullabilityAnnotationFqName)
) )
TypeAdaptationConstraint.KEEP_UNBOXED 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. // 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 val underlyingAdapteeType = getInlineClassUnderlyingType(erasedAdapteeClass) as? IrSimpleType
?: throw AssertionError("Underlying type for inline class should be a simple type: ${erasedAdapteeClass.render()}") ?: 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 return TypeAdaptationConstraint.CONFLICT
} }
@@ -522,14 +522,6 @@ internal class LambdaMetafactoryArgumentsBuilder(
private fun IrDeclarationParent.isCrossinlineLambda(): Boolean = private fun IrDeclarationParent.isCrossinlineLambda(): Boolean =
this is IrSimpleFunction && this in crossinlineLambdas 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( fun collectValueParameters(
irFun: IrFunction, irFun: IrFunction,
withDispatchReceiver: Boolean = false, withDispatchReceiver: Boolean = false,
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.interpreter package org.jetbrains.kotlin.ir.interpreter
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET 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<*> { 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() val constType = irType.makeNotNull()
return when { return when (irType.getPrimitiveType()) {
this == null -> IrConstImpl.constNull(startOffset, endOffset, irType) PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, constType, this as Boolean)
constType.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, constType, this as Boolean) PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, constType, this as Char)
constType.isChar() -> IrConstImpl.char(startOffset, endOffset, constType, this as Char) PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
constType.isByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte()) PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
constType.isShort() -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort()) PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
constType.isInt() -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt()) PrimitiveType.FLOAT -> IrConstImpl.float(startOffset, endOffset, constType, (this as Number).toFloat())
constType.isLong() -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong()) PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String) PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, constType, (this as Number).toDouble())
constType.isFloat() -> IrConstImpl.float(startOffset, endOffset, constType, (this as Number).toFloat()) else -> when {
constType.isDouble() -> IrConstImpl.double(startOffset, endOffset, constType, (this as Number).toDouble()) constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, this as String)
constType.isUByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte()) constType.isUByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (this as Number).toByte())
constType.isUShort() -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort()) constType.isUShort() -> IrConstImpl.short(startOffset, endOffset, constType, (this as Number).toShort())
constType.isUInt() -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt()) constType.isUInt() -> IrConstImpl.int(startOffset, endOffset, constType, (this as Number).toInt())
constType.isULong() -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong()) constType.isULong() -> IrConstImpl.long(startOffset, endOffset, constType, (this as Number).toLong())
else -> throw UnsupportedOperationException("Unsupported const element type ${constType.render()}") 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() return (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString()
} }
internal fun getPrimitiveClass(irType: IrType, asObject: Boolean = false): Class<*>? { internal fun getPrimitiveClass(irType: IrType, asObject: Boolean = false): Class<*>? =
return when { when (irType.getPrimitiveType()) {
irType.isBoolean() -> if (asObject) Boolean::class.javaObjectType else Boolean::class.java PrimitiveType.BOOLEAN -> if (asObject) Boolean::class.javaObjectType else Boolean::class.java
irType.isChar() -> if (asObject) Char::class.javaObjectType else Char::class.java PrimitiveType.CHAR -> if (asObject) Char::class.javaObjectType else Char::class.java
irType.isByte() -> if (asObject) Byte::class.javaObjectType else Byte::class.java PrimitiveType.BYTE -> if (asObject) Byte::class.javaObjectType else Byte::class.java
irType.isShort() -> if (asObject) Short::class.javaObjectType else Short::class.java PrimitiveType.SHORT -> if (asObject) Short::class.javaObjectType else Short::class.java
irType.isInt() -> if (asObject) Int::class.javaObjectType else Int::class.java PrimitiveType.INT -> if (asObject) Int::class.javaObjectType else Int::class.java
irType.isLong() -> if (asObject) Long::class.javaObjectType else Long::class.java PrimitiveType.FLOAT -> if (asObject) Float::class.javaObjectType else Float::class.java
irType.isString() -> if (asObject) String::class.javaObjectType else String::class.java PrimitiveType.LONG -> if (asObject) Long::class.javaObjectType else Long::class.java
irType.isFloat() -> if (asObject) Float::class.javaObjectType else Float::class.java PrimitiveType.DOUBLE -> if (asObject) Double::class.javaObjectType else Double::class.java
irType.isDouble() -> if (asObject) Double::class.javaObjectType else Double::class.java else -> when {
else -> null irType.isString() -> String::class.java
else -> null
}
} }
}
internal fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> { internal fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> {
val argsValues = args.map { val argsValues = args.map {
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.ir.expressions.impl 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.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
@@ -74,16 +75,19 @@ class IrConstImpl<T>(
fun short(startOffset: Int, endOffset: Int, type: IrType, value: Short): IrConstImpl<Short> = fun short(startOffset: Int, endOffset: Int, type: IrType, value: Short): IrConstImpl<Short> =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Short, value) IrConstImpl(startOffset, endOffset, type, IrConstKind.Short, value)
fun defaultValueForType(startOffset: Int, endOffset: Int, type: IrType) = when { fun defaultValueForType(startOffset: Int, endOffset: Int, type: IrType): IrConstImpl<*> {
type.isFloat() -> float(startOffset, endOffset, type, 0.0F) if (type.isMarkedNullable()) return constNull(startOffset, endOffset, type)
type.isDouble() -> double(startOffset, endOffset, type, 0.0) return when (type.getPrimitiveType()) {
type.isBoolean() -> boolean(startOffset, endOffset, type, false) PrimitiveType.BOOLEAN -> boolean(startOffset, endOffset, type, false)
type.isByte() -> byte(startOffset, endOffset, type, 0) PrimitiveType.CHAR -> char(startOffset, endOffset, type, 0.toChar())
type.isChar() -> char(startOffset, endOffset, type, 0.toChar()) PrimitiveType.BYTE -> byte(startOffset, endOffset, type, 0)
type.isShort() -> short(startOffset, endOffset, type, 0) PrimitiveType.SHORT -> short(startOffset, endOffset, type, 0)
type.isInt() -> int(startOffset, endOffset, type, 0) PrimitiveType.INT -> int(startOffset, endOffset, type, 0)
type.isLong() -> long(startOffset, endOffset, type, 0) PrimitiveType.FLOAT -> float(startOffset, endOffset, type, 0.0F)
else -> constNull(startOffset, endOffset, type) PrimitiveType.LONG -> long(startOffset, endOffset, type, 0)
PrimitiveType.DOUBLE -> double(startOffset, endOffset, type, 0.0)
else -> constNull(startOffset, endOffset, type)
}
} }
} }
} }
@@ -11,39 +11,36 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.util.IdSignature 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.ir.util.hasEqualFqName
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
@Suppress("ObjectPropertyName") @Suppress("ObjectPropertyName")
object IdSignatureValues { object IdSignatureValues {
@JvmField val any = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Any") @JvmField val any = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Any")
@JvmField val nothing = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Nothing") @JvmField val nothing = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Nothing")
@JvmField val unit = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Unit") @JvmField val unit = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Unit")
@JvmField val _boolean = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Boolean") @JvmField val _boolean = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Boolean")
@JvmField val _char = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Char") @JvmField val _char = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Char")
@JvmField val _byte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Byte") @JvmField val _byte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Byte")
@JvmField val _short = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Short") @JvmField val _short = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Short")
@JvmField val _int = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Int") @JvmField val _int = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Int")
@JvmField val _long = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Long") @JvmField val _long = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Long")
@JvmField val _float = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Float") @JvmField val _float = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Float")
@JvmField val _double = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Double") @JvmField val _double = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Double")
@JvmField val number = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Number") @JvmField val number = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Number")
@JvmField val uByte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UByte") @JvmField val uByte = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "UByte")
@JvmField val uShort = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UShort") @JvmField val uShort = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "UShort")
@JvmField val uInt = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"UInt") @JvmField val uInt = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "UInt")
@JvmField val uLong = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"ULong") @JvmField val uLong = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "ULong")
@JvmField val string = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"String") @JvmField val string = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "String")
@JvmField val array = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Array") @JvmField val array = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Array")
@JvmField val collection = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Collection") @JvmField val collection = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Collection")
@JvmField val kClass = getPublicSignature(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KClass") @JvmField val kClass = getPublicSignature(StandardNames.KOTLIN_REFLECT_FQ_NAME, "KClass")
@JvmField val comparable = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"Comparable") @JvmField val comparable = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Comparable")
@JvmField val charSequence = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME,"CharSequence") @JvmField val charSequence = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "CharSequence")
@JvmField val iterable = getPublicSignature(StandardNames.COLLECTIONS_PACKAGE_FQ_NAME, "Iterable") @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 result = getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "Result")
@JvmField val sequence = IdSignature.PublicSignature("kotlin.sequences", "Sequence", null, 0) @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<IdSignature.PublicSignature, PrimitiveType> = private val idSignatureToPrimitiveType: Map<IdSignature.PublicSignature, PrimitiveType> =
newHashMapWithExpectedSize<IdSignature.PublicSignature, PrimitiveType>(PrimitiveType.values().size).apply { PrimitiveType.values().associateBy {
for (primitiveType in PrimitiveType.values()) { getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, it.typeName.asString())
this[getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, primitiveType.typeName.asString())] = primitiveType
}
} }
val primitiveArrayTypesSignatures: Map<PrimitiveType, IdSignature.PublicSignature> = val primitiveArrayTypesSignatures: Map<PrimitiveType, IdSignature.PublicSignature> =
newHashMapWithExpectedSize<PrimitiveType, IdSignature.PublicSignature>(PrimitiveType.values().size).apply { PrimitiveType.values().associateWith {
for (primitiveType in PrimitiveType.values()) { getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "${it.typeName.asString()}Array")
this[primitiveType] =
getPublicSignature(StandardNames.BUILT_INS_PACKAGE_FQ_NAME, "${primitiveType.typeName.asString()}Array")
}
} }
private fun classFqNameEquals(declaration: IrClass, fqName: FqNameUnsafe): Boolean = 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.isNullableNothing(): Boolean = isNullableClassType(IdSignatureValues.nothing)
fun IrType.isPrimitiveType(hasQuestionMark: Boolean = false): Boolean = fun IrType.isPrimitiveType(hasQuestionMark: Boolean = false): Boolean =
(this is IrSimpleType && hasQuestionMark == this.hasQuestionMark) && this is IrSimpleType && hasQuestionMark == this.hasQuestionMark && getPrimitiveType() != null
classOrNull?.signature in idSignatureToPrimitiveType
fun IrType.isNullablePrimitiveType(): Boolean = isPrimitiveType(true) 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.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false
fun IrType.isUnit() = isNotNullClassType(IdSignatureValues.unit) fun IrType.isUnit() = isNotNullClassType(IdSignatureValues.unit)
fun IrType.isBoolean(): Boolean = isNotNullClassType(IdSignatureValues._boolean) fun IrType.isBoolean(): Boolean = isNotNullClassType(IdSignatureValues._boolean)
fun IrType.isBooleanOrNullable(): Boolean = isClassType(IdSignatureValues._boolean)
fun IrType.isChar(): Boolean = isNotNullClassType(IdSignatureValues._char) fun IrType.isChar(): Boolean = isNotNullClassType(IdSignatureValues._char)
fun IrType.isCharOrNullable(): Boolean = isClassType(IdSignatureValues._char)
fun IrType.isByte(): Boolean = isNotNullClassType(IdSignatureValues._byte) fun IrType.isByte(): Boolean = isNotNullClassType(IdSignatureValues._byte)
fun IrType.isByteOrNullable(): Boolean = isClassType(IdSignatureValues._byte)
fun IrType.isShort(): Boolean = isNotNullClassType(IdSignatureValues._short) fun IrType.isShort(): Boolean = isNotNullClassType(IdSignatureValues._short)
fun IrType.isShortOrNullable(): Boolean = isClassType(IdSignatureValues._short)
fun IrType.isInt(): Boolean = isNotNullClassType(IdSignatureValues._int) fun IrType.isInt(): Boolean = isNotNullClassType(IdSignatureValues._int)
fun IrType.isIntOrNullable(): Boolean = isClassType(IdSignatureValues._int)
fun IrType.isLong(): Boolean = isNotNullClassType(IdSignatureValues._long) fun IrType.isLong(): Boolean = isNotNullClassType(IdSignatureValues._long)
fun IrType.isLongOrNullable(): Boolean = isClassType(IdSignatureValues._long)
fun IrType.isUByte(): Boolean = isNotNullClassType(IdSignatureValues.uByte) fun IrType.isUByte(): Boolean = isNotNullClassType(IdSignatureValues.uByte)
fun IrType.isUShort(): Boolean = isNotNullClassType(IdSignatureValues.uShort) fun IrType.isUShort(): Boolean = isNotNullClassType(IdSignatureValues.uShort)
fun IrType.isUInt(): Boolean = isNotNullClassType(IdSignatureValues.uInt) fun IrType.isUInt(): Boolean = isNotNullClassType(IdSignatureValues.uInt)
fun IrType.isULong(): Boolean = isNotNullClassType(IdSignatureValues.uLong) fun IrType.isULong(): Boolean = isNotNullClassType(IdSignatureValues.uLong)
fun IrType.isFloat(): Boolean = isNotNullClassType(IdSignatureValues._float) fun IrType.isFloat(): Boolean = isNotNullClassType(IdSignatureValues._float)
fun IrType.isFloatOrNullable(): Boolean = isClassType(IdSignatureValues._float)
fun IrType.isDouble(): Boolean = isNotNullClassType(IdSignatureValues._double) fun IrType.isDouble(): Boolean = isNotNullClassType(IdSignatureValues._double)
fun IrType.isDoubleOrNullable(): Boolean = isClassType(IdSignatureValues._double)
fun IrType.isNumber(): Boolean = isNotNullClassType(IdSignatureValues.number) fun IrType.isNumber(): Boolean = isNotNullClassType(IdSignatureValues.number)
fun IrType.isComparable(): Boolean = isNotNullClassType(IdSignatureValues.comparable) fun IrType.isComparable(): Boolean = isNotNullClassType(IdSignatureValues.comparable)
@@ -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.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -358,17 +359,19 @@ open class SerializerIrGenerator(
private fun IrBuilderWithScope.defaultValueAndType(descriptor: PropertyDescriptor): Pair<IrExpression, IrType> { private fun IrBuilderWithScope.defaultValueAndType(descriptor: PropertyDescriptor): Pair<IrExpression, IrType> {
val kType = descriptor.returnType!! val kType = descriptor.returnType!!
val T = kType.toIrType() val T = kType.toIrType()
val defaultPrimitive: IrExpression? = when { val defaultPrimitive: IrExpression? =
T.isInt() -> IrConstImpl.int(startOffset, endOffset, T, 0) if (T.isMarkedNullable()) null
T.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, T, false) else when (T.getPrimitiveType()) {
T.isLong() -> IrConstImpl.long(startOffset, endOffset, T, 0) PrimitiveType.BOOLEAN -> IrConstImpl.boolean(startOffset, endOffset, T, false)
T.isDouble() -> IrConstImpl.double(startOffset, endOffset, T, 0.0) PrimitiveType.CHAR -> IrConstImpl.char(startOffset, endOffset, T, 0.toChar())
T.isFloat() -> IrConstImpl.float(startOffset, endOffset, T, 0.0f) PrimitiveType.BYTE -> IrConstImpl.byte(startOffset, endOffset, T, 0)
T.isChar() -> IrConstImpl.char(startOffset, endOffset, T, 0.toChar()) PrimitiveType.SHORT -> IrConstImpl.short(startOffset, endOffset, T, 0)
T.isByte() -> IrConstImpl.byte(startOffset, endOffset, T, 0) PrimitiveType.INT -> IrConstImpl.int(startOffset, endOffset, T, 0)
T.isShort() -> IrConstImpl.short(startOffset, endOffset, T, 0) PrimitiveType.FLOAT -> IrConstImpl.float(startOffset, endOffset, T, 0.0f)
else -> null PrimitiveType.LONG -> IrConstImpl.long(startOffset, endOffset, T, 0)
} PrimitiveType.DOUBLE -> IrConstImpl.double(startOffset, endOffset, T, 0.0)
else -> null
}
return if (defaultPrimitive == null) return if (defaultPrimitive == null)
irNull(compilerContext.irBuiltIns.anyNType) to (compilerContext.irBuiltIns.anyNType) irNull(compilerContext.irBuiltIns.anyNType) to (compilerContext.irBuiltIns.anyNType)
else else