diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt new file mode 100644 index 00000000000..3783afde462 --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.common.lower + +import org.jetbrains.kotlin.backend.common.BackendContext +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.builtins.getFunctionalClassKind +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrCallableReference +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.types.KotlinType + +class KCallableNamePropertyLowering(val context: BackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(KCallableNamePropertyTransformer(this)) + } +} + +private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyLowering) : IrElementTransformerVoid() { + + override fun visitCall(expression: IrCall): IrExpression { + val callableReference = expression.dispatchReceiver as? IrCallableReference ?: return expression + + //TODO rewrite checking + val directMember = DescriptorUtils.getDirectMember(expression.descriptor) + if (!((directMember.containingDeclaration as? ClassDescriptor)?.defaultType?.isKFunctionType ?: false)) return expression + if (directMember.name.asString() != "name") return expression + + val receiver = callableReference.dispatchReceiver ?: callableReference.extensionReceiver + + return lower.context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).run { + + IrCompositeImpl(startOffset, endOffset, context.builtIns.stringType).apply { + receiver?.let { + //put receiver for bound callable reference + statements.add(it) + } + + statements.add( + IrConstImpl.string( + expression.startOffset, + expression.endOffset, + context.builtIns.stringType, + callableReference.descriptor.name.asString() + ) + ) + } + + } + + } +} + +//TODO move to utils +val KotlinType.isKFunctionType: Boolean + get() { + val kind = constructor.declarationDescriptor?.getFunctionalClassKind() + return kind == FunctionClassDescriptor.Kind.KFunction + } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index b398fecae99..0d9bef58f69 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.backend.jvm +import org.jetbrains.kotlin.backend.common.lower.KCallableNamePropertyLowering import org.jetbrains.kotlin.backend.common.lower.LocalFunctionsLowering import org.jetbrains.kotlin.backend.common.lower.SharedVariablesLowering import org.jetbrains.kotlin.backend.common.runOnFilePostfix @@ -26,6 +27,7 @@ class JvmLower(val context: JvmBackendContext) { fun lower(irFile: IrFile) { // TODO run lowering passes as callbacks in bottom-up visitor FileClassLowering(context).lower(irFile) + KCallableNamePropertyLowering(context).lower(irFile) ConstAndJvmFieldPropertiesLowering().lower(irFile) PropertiesLowering().lower(irFile) InterfaceLowering(context.state).runOnFilePostfix(irFile) 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 6fbc2f34691..4ef752c3c0e 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 @@ -898,6 +898,9 @@ class ExpressionCodegen( //TODO where is best to unwrap? descriptor = descriptor.underlyingConstructorDescriptor } + if (descriptor is PropertyDescriptor) { + descriptor = descriptor.getter!! + } if (descriptor is CallableMemberDescriptor && JvmCodegenUtil.getDirectMember(descriptor) is SyntheticJavaPropertyDescriptor) { val propertyDescriptor = JvmCodegenUtil.getDirectMember(descriptor) as SyntheticJavaPropertyDescriptor if (descriptor is PropertyGetterDescriptor) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java index f7ca2f9aa96..3723820edf3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java @@ -63,7 +63,6 @@ public class IntrinsicMethods { public IntrinsicMethods() { intrinsicsMap.registerIntrinsic(KOTLIN_JVM, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, JavaClassProperty.INSTANCE); intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.kClass, "java", -1, new KClassJavaProperty()); - intrinsicsMap.registerIntrinsic(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe(), null, "name", -1, new KCallableNameProperty()); intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorEnter", 1, MonitorInstruction.MONITOR_ENTER); intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorExit", 1, MonitorInstruction.MONITOR_EXIT); intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.array, "isArrayOf", 0, new IsArrayOf()); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KCallableNameProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KCallableNameProperty.kt deleted file mode 100644 index 1fbb7c6ff25..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KCallableNameProperty.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -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.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.ir.expressions.IrCallableReference -import org.jetbrains.kotlin.ir.expressions.IrClassReference -import org.jetbrains.kotlin.ir.expressions.IrGetClass -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.psi.KtCallableReferenceExpression -import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE -import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature -import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver -import org.jetbrains.kotlin.types.expressions.DoubleColonLHS -import org.jetbrains.org.objectweb.asm.Type -import org.jetbrains.org.objectweb.asm.Type.VOID_TYPE -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter - -class KCallableNameProperty : 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 callableReference = expression.dispatchReceiver as IrCallableReference - /*TODO optimize generation*/ - - codegen.gen(callableReference.dispatchReceiver ?: callableReference.extensionReceiver!!, VOID_TYPE, data) - codegen.mv.aconst(callableReference.descriptor.name.asString()) - StackValue.coerce(JAVA_STRING_TYPE, returnType, codegen.mv) - return StackValue.onStack(signature.returnType) - } - } - } - - fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? { - val expressionReceiver = resolvedCall!!.dispatchReceiver as? ExpressionReceiver ?: return null - val expression = expressionReceiver.expression as? KtCallableReferenceExpression ?: return null - - val receiverExpression = expression.receiverExpression - val lhs = receiverExpression?.let { codegen.bindingContext.get(DOUBLE_COLON_LHS, it) } - - val callableReference = expression.callableReference - val descriptor = callableReference.getResolvedCall(codegen.bindingContext)?.resultingDescriptor ?: return null - - return StackValue.operation(returnType) { iv -> - // Generate the left-hand side of a bound callable reference expression - if (lhs is DoubleColonLHS.Expression) { - codegen.gen(receiverExpression, VOID_TYPE) - } - iv.aconst(descriptor.name.asString()) - StackValue.coerce(JAVA_STRING_TYPE, returnType, iv) - } - } -}