KClassJavaProperty support

This commit is contained in:
Michael Bogdanov
2016-10-06 12:36:37 +03:00
committed by Dmitry Petrov
parent 5ee2f87c4a
commit b72d7557d1
7 changed files with 103 additions and 40 deletions
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.*
import org.jetbrains.kotlin.codegen.StackValue.*
import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
@@ -819,6 +820,34 @@ class ExpressionCodegen(
return expression.onStack
}
override fun visitClassReference(expression: IrClassReference, data: BlockInfo): StackValue {
generateClassLiteralReference(expression, true, data)
return expression.onStack
}
fun generateClassLiteralReference(
receiverExpression: IrExpression,
wrapIntoKClass: Boolean,
data: BlockInfo
) {
if (receiverExpression !is IrClassReference /* && DescriptorUtils.isObject(receiverExpression.descriptor)*/) {
JavaClassProperty.generateImpl(mv, gen(receiverExpression, data))
}
else {
// if (TypeUtils.isTypeParameter(type)) {
// assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
// putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
// }
putJavaLangClassInstance(mv, typeMapper.mapType(receiverExpression.descriptor.defaultType))
}
if (wrapIntoKClass) {
wrapJavaClassIntoKClass(mv)
}
}
private fun coerceNotToUnit(fromType: Type, toType: Type) {
if (toType != AsmTypes.UNIT_TYPE) {
coerce(fromType, toType, mv)
@@ -18,57 +18,29 @@ 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.AsmUtil.putJavaLangClassInstance
import org.jetbrains.kotlin.codegen.AsmUtil.wrapJavaClassIntoKClass
import org.jetbrains.kotlin.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.IrGetClass
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.org.objectweb.asm.Type
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 {
putJavaLangClassInstance(v, signature.returnType)
wrapJavaClassIntoKClass(v)
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)
}
}
// val type = lhs.type
// if (lhs is DoubleColonLHS.Expression && !(lhs as DoubleColonLHS.Expression).isObject) {
// JavaClassProperty.generateImpl(v, gen(receiverExpression))
// }
// else {
// if (TypeUtils.isTypeParameter(type)) {
// assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
// putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
// }
// putJavaLangClassInstance(v, typeMapper.mapType(type))
// }
// if (wrapIntoKClass) {
// wrapJavaClassIntoKClass(v)
// }
// return Unit
}
fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
val receiverValue = resolvedCall!!.extensionReceiver as? ExpressionReceiver ?: return null
val classLiteralExpression = receiverValue.expression as? KtClassLiteralExpression ?: return null
val receiverExpression = classLiteralExpression.receiverExpression ?: return null
val lhs = codegen.bindingContext.get(DOUBLE_COLON_LHS, receiverExpression) ?: return null
val value = codegen.generateClassLiteralReference(lhs, receiverExpression, /* wrapIntoKClass = */ false)
return StackValue.coercion(value, returnType)
}
}