diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 4d0e56c7d20..f76b530caf9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -7,9 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.common.descriptors.propertyIfAccessor import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicFunction import org.jetbrains.kotlin.backend.jvm.lower.CrIrType -import org.jetbrains.kotlin.backend.jvm.lower.JvmBuiltinOptimizationLowering.Companion.isNegation import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.AsmUtil.* @@ -115,6 +113,8 @@ class ExpressionCodegen( val typeMapper = classCodegen.typeMapper + val context = classCodegen.context + private val state = classCodegen.state private val fileEntry = classCodegen.context.psiSourceManager.getFileEntry(irFunction.fileParent) @@ -307,7 +307,7 @@ class ExpressionCodegen( return visitStatementContainer(expression, data).coerce(expression.type) } - override fun visitMemberAccess(expression: IrMemberAccessExpression, data: BlockInfo): StackValue { + override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: BlockInfo): StackValue { expression.markLineNumber(startOffset = true) return generateCall(expression, null, data) } @@ -346,14 +346,12 @@ class ExpressionCodegen( return generateCall(expression, expression.superQualifier, data) } - private fun generateCall(expression: IrMemberAccessExpression, superQualifier: ClassDescriptor?, data: BlockInfo): StackValue { + private fun generateCall(expression: IrFunctionAccessExpression, superQualifier: ClassDescriptor?, data: BlockInfo): StackValue { + classCodegen.context.irIntrinsics.getIntrinsic(expression.descriptor.original as CallableMemberDescriptor) + ?.invoke(expression, this, data)?.let { return it } val isSuperCall = superQualifier != null val callable = resolveToCallable(expression, isSuperCall) - return if (callable is IrIntrinsicFunction) { - callable.invoke(mv, this, data) - } else { - generateCall(expression, callable, data, isSuperCall) - } + return generateCall(expression, callable, data, isSuperCall) } fun generateCall(expression: IrMemberAccessExpression, callable: Callable, data: BlockInfo, isSuperCall: Boolean = false): StackValue { @@ -1085,15 +1083,6 @@ class ExpressionCodegen( } private fun resolveToCallable(irCall: IrMemberAccessExpression, isSuper: Boolean): Callable { - val intrinsic = classCodegen.context.irIntrinsics.getIntrinsic(irCall.descriptor.original as CallableMemberDescriptor) - if (intrinsic != null) { - return intrinsic.toCallable( - irCall, - typeMapper.mapSignatureSkipGeneric(irCall.descriptor as FunctionDescriptor), - classCodegen.context - ) - } - var descriptor = irCall.descriptor if (descriptor is TypeAliasConstructorDescriptor) { //TODO where is best to unwrap? diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt index 3b44122eddf..fa6b5385b3f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.AsmUtil.comparisonOperandType import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -66,24 +67,14 @@ class PrimitiveComparison( private val primitiveNumberType: KotlinType, private val operatorToken: KtSingleValueToken ) : IntrinsicMethod() { - - override fun toCallable( - expression: IrMemberAccessExpression, - signature: JvmMethodSignature, - context: JvmBackendContext - ): IrIntrinsicFunction { - val parameterType = context.state.typeMapper.mapType(primitiveNumberType) - - return object : IrIntrinsicFunction(expression, signature, context, listOf(parameterType, parameterType)) { - override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue { - loadArguments(codegen, data) - return StackValue.cmp( - operatorToken, - parameterType, - StackValue.onStack(parameterType, primitiveNumberType), - StackValue.onStack(parameterType, primitiveNumberType) - ) - } - } + override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): StackValue? { + val parameterType = codegen.typeMapper.mapType(primitiveNumberType) + val (left, right) = expression.receiverAndArgs() + return StackValue.cmp( + operatorToken, + parameterType, + codegen.gen(left, parameterType, data), + codegen.gen(right, parameterType, data) + ) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt index 092dc7fd899..4ca3abb2db7 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil.* import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.types.toKotlinType @@ -27,40 +28,27 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class Equals(val operator: IElementType) : IntrinsicMethod() { - - override fun toCallable( - expression: IrMemberAccessExpression, - signature: JvmMethodSignature, - context: JvmBackendContext - ): IrIntrinsicFunction { - val receiverAndArgs = expression.receiverAndArgs().apply { - assert(size == 2) { "Equals expects 2 arguments, but ${joinToString()}" } - } - - val (leftArg, rightArg) = receiverAndArgs - var leftType = context.state.typeMapper.mapType(leftArg.type.toKotlinType()) - var rightType = context.state.typeMapper.mapType(rightArg.type.toKotlinType()) + override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): StackValue? { + val (leftArg, rightArg) = expression.receiverAndArgs() + var leftType = codegen.typeMapper.mapType(leftArg.type.toKotlinType()) + var rightType = codegen.typeMapper.mapType(rightArg.type.toKotlinType()) if (isPrimitive(leftType) != isPrimitive(rightType)) { leftType = boxType(leftType) rightType = boxType(rightType) } - return object : IrIntrinsicFunction(expression, signature, context, listOf(leftType, rightType)) { - override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue { - val opToken = expression.origin - return if (leftArg.isNullConst() || rightArg.isNullConst()) { - val other = if (leftArg.isNullConst()) rightArg else leftArg - StackValue.compareWithNull(other.accept(codegen, data), Opcodes.IFNONNULL) - } else if (leftType.isFloatingPoint && rightType.isFloatingPoint) { - genEqualsBoxedOnStack(operator) - } else if (opToken === IrStatementOrigin.EQEQEQ || opToken === IrStatementOrigin.EXCLEQEQ) { - // TODO: always casting to the type of the left operand in case of primitives looks wrong - val operandType = if (isPrimitive(leftType)) leftType else OBJECT_TYPE - StackValue.cmp(operator, operandType, codegen.gen(leftArg, operandType, data), codegen.gen(rightArg, operandType, data)) - } else { - genEqualsForExpressionsOnStack(operator, codegen.gen(leftArg, leftType, data), codegen.gen(rightArg, rightType, data)) - } - } + val opToken = expression.origin + return if (leftArg.isNullConst() || rightArg.isNullConst()) { + val other = if (leftArg.isNullConst()) rightArg else leftArg + return StackValue.compareWithNull(other.accept(codegen, data), Opcodes.IFNONNULL) + } else if (leftType.isFloatingPoint && rightType.isFloatingPoint) { + genEqualsBoxedOnStack(operator) + } else if (opToken === IrStatementOrigin.EQEQEQ || opToken === IrStatementOrigin.EXCLEQEQ) { + // TODO: always casting to the type of the left operand in case of primitives looks wrong + val operandType = if (isPrimitive(leftType)) leftType else OBJECT_TYPE + StackValue.cmp(operator, operandType, codegen.gen(leftArg, operandType, data), codegen.gen(rightArg, operandType, data)) + } else { + genEqualsForExpressionsOnStack(operator, codegen.gen(leftArg, leftType, data), codegen.gen(rightArg, rightType, data)) } } @@ -122,3 +110,4 @@ class Ieee754Equals(val operandType: Type) : IntrinsicMethod() { } } } + diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt index ec1fcbf6d64..de7ccd6b741 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt @@ -6,7 +6,12 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo +import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -14,11 +19,18 @@ import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.Method abstract class IntrinsicMethod { - abstract fun toCallable( + open fun toCallable( expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext - ): IrIntrinsicFunction + ): IrIntrinsicFunction = TODO("implement toCallable() or invoke() of $this") + + open fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): StackValue? = + toCallable( + expression, + codegen.typeMapper.mapSignatureSkipGeneric(expression.descriptor), + codegen.context + ).invoke(codegen.mv, codegen, data) companion object { fun calcReceiverType(call: IrMemberAccessExpression, context: JvmBackendContext): Type { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt index bf545c06fb4..d70ede93a40 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt @@ -16,31 +16,20 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics -import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo +import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.expressions.IrClassReference +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrGetClass -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class KClassJavaProperty : IntrinsicMethod() { - override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { - return object: IrIntrinsicFunction(expression, signature, context) { - override fun invoke(v: InstructionAdapter, codegen: org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen, data: BlockInfo): StackValue { - val extensionReceiver = expression.extensionReceiver - if (extensionReceiver is IrClassReference || extensionReceiver is IrGetClass) { - codegen.generateClassLiteralReference(extensionReceiver, false, data) - } - else { - codegen.gen(extensionReceiver!!, data) - val mapToCallableMethod = context.state.typeMapper.mapToCallableMethod(expression.descriptor as FunctionDescriptor, false) - mapToCallableMethod.genInvokeInstruction(codegen.mv) - } - return StackValue.onStack(signature.returnType) - } + override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): StackValue? { + val extensionReceiver = expression.extensionReceiver + if (extensionReceiver !is IrClassReference && extensionReceiver !is IrGetClass) { + return null } + codegen.generateClassLiteralReference(extensionReceiver, false, data) + return with(codegen) { expression.onStack } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt index e4072a704a1..a739b2abd40 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt @@ -16,26 +16,12 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics -import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression class Not : IntrinsicMethod() { - override fun toCallable( - expression: IrMemberAccessExpression, - signature: JvmMethodSignature, - context: JvmBackendContext - ): IrIntrinsicFunction { - return object : IrIntrinsicFunction(expression, signature, context, expression.argTypes(context)) { - override fun invoke( - v: InstructionAdapter, - codegen: ExpressionCodegen, - data: BlockInfo - ) = StackValue.not(expression.dispatchReceiver!!.accept(codegen, data)) - } - } + override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo) = + StackValue.not(expression.dispatchReceiver!!.accept(codegen, data)) }