[Psi2Ir, Fir2Ir] Generate toString, hashCode, equals methods for MF VC

This commit is contained in:
Evgeniy.Zhelenskiy
2021-12-31 02:27:17 +03:00
committed by Space
parent c7edc353d3
commit e97ca2ada4
91 changed files with 465 additions and 426 deletions
@@ -21,7 +21,9 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.isSuspend
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Type
@@ -125,7 +127,7 @@ private fun IrSimpleFunction.overridesReturningDifferentType(returnType: IrType)
val owner = overridden.owner
val overriddenReturnType = owner.returnType
if (!overriddenReturnType.erasedUpperBound.isInline) return true
if (!overriddenReturnType.erasedUpperBound.isSingleFieldValueClass) return true
if (overriddenReturnType.isNullable() &&
overriddenReturnType.makeNotNull().unboxInlineClass().isNullable()
@@ -1473,7 +1473,7 @@ class ExpressionCodegen(
companion object {
internal fun generateClassInstance(v: InstructionAdapter, classType: IrType, typeMapper: IrTypeMapper) {
val asmType = typeMapper.mapType(classType)
if (classType.getClass()?.isInline == true || !isPrimitive(asmType)) {
if (classType.getClass()?.isSingleFieldValueClass == true || !isPrimitive(asmType)) {
v.aconst(typeMapper.boxType(classType))
} else {
v.getstatic(boxType(asmType).internalName, "TYPE", "Ljava/lang/Class;")
@@ -318,7 +318,7 @@ class FunctionCodegen(private val irFunction: IrFunction, private val classCodeg
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
IrDeclarationOrigin.GENERATED_INLINE_CLASS_MEMBER,
IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER,
IrDeclarationOrigin.BRIDGE,
IrDeclarationOrigin.BRIDGE_SPECIAL,
JvmLoweredDeclarationOrigin.ABSTRACT_BRIDGE_STUB,
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.isSingleFieldValueClass
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.isTypeParameter
@@ -42,7 +43,7 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
if (!isFromTypeUnboxed && isToTypeUnboxed) {
val boxed = typeMapper.mapType(erasedTargetType, TypeMappingMode.CLASS_DECLARATION)
val irClass = codegen.irFunction.parentAsClass
if (irClass.isInline && irClass.symbol == irType.classifierOrNull && !irType.isNullable()) {
if (irClass.isSingleFieldValueClass && irClass.symbol == irType.classifierOrNull && !irType.isNullable()) {
// Use getfield instead of unbox-impl inside inline classes
codegen.mv.getfield(boxed.internalName, irClass.inlineClassFieldName.asString(), target.descriptor)
} else {
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.backend.jvm.codegen
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.ir.allOverridden
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
@@ -27,14 +26,11 @@ import org.jetbrains.kotlin.codegen.SourceInfo
import org.jetbrains.kotlin.codegen.inline.SourceMapper
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
@@ -45,7 +41,6 @@ import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -166,7 +161,7 @@ private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?):
return Opcodes.ACC_PUBLIC
}
if (this is IrConstructor && parentAsClass.isInline && kind === OwnerKind.IMPLEMENTATION) {
if (this is IrConstructor && parentAsClass.isSingleFieldValueClass && kind === OwnerKind.IMPLEMENTATION) {
return Opcodes.ACC_PRIVATE
}
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.genAreEqualCall
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.ir.declarations.isSingleFieldValueClass
import org.jetbrains.kotlin.ir.descriptors.toIrBasedKotlinType
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
@@ -70,7 +71,7 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
if (a.isNullConst() || b.isNullConst()) {
val irValue = if (a.isNullConst()) b else a
val value = irValue.accept(codegen, data)
return if (!isPrimitive(value.type) && (irValue.type.classOrNull?.owner?.isInline != true || irValue.type.isNullable()))
return if (!isPrimitive(value.type) && (irValue.type.classOrNull?.owner?.isSingleFieldValueClass != true || irValue.type.isNullable()))
BooleanNullCheck(value)
else {
value.discard()
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.PromisedValue
import org.jetbrains.kotlin.backend.jvm.codegen.materialize
import org.jetbrains.kotlin.backend.jvm.mapping.mapTypeAsDeclaration
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.ir.declarations.isSingleFieldValueClass
import org.jetbrains.kotlin.ir.expressions.IrClassReference
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrGetClass
@@ -76,7 +77,7 @@ object GetJavaPrimitiveType : IntrinsicMethod() {
}
private fun IrType.isInlineClassType(): Boolean {
return (classOrNull ?: return false).owner.isInline
return (classOrNull ?: return false).owner.isSingleFieldValueClass
}
private fun Type.isVoidOrPrimitiveWrapper(): Boolean =
@@ -37,7 +37,8 @@ object HashCode : IntrinsicMethod() {
val target = context.state.target
when {
irFunction.origin == JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD ||
irFunction.origin == IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER -> {
irFunction.origin == IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER ||
irFunction.origin == IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER -> {
// TODO generate or lower IR for data class / inline class 'hashCode'?
DescriptorAsmUtil.genHashCode(mv, mv, receiverType, target)
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.boxType
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.ir.declarations.isSingleFieldValueClass
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
@@ -33,7 +34,7 @@ object JavaClassProperty : IntrinsicMethod() {
when {
value.type == Type.VOID_TYPE ->
invokeGetClass(value.materializedAt(AsmTypes.UNIT_TYPE, value.codegen.context.irBuiltIns.unitType))
value.irType.classOrNull?.owner?.isInline == true ->
value.irType.classOrNull?.owner?.isSingleFieldValueClass == true ->
invokeGetClass(value.materializedAtBoxed(value.irType))
isPrimitive(value.type) -> {
value.discard()