JVM IR: remove CrIrType, use class container in callable reference lowerings
This is possible now because after3a9b94235f,0423d0f41eand5341de253f, all top level functions/properties in sources and in binaries have a corresponding containing facade class
This commit is contained in:
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.KClassJavaProperty
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
@@ -18,6 +19,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.defaultType
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
@@ -50,6 +52,7 @@ class JvmSymbols(
|
|||||||
private fun createPackage(fqName: FqName): IrPackageFragment =
|
private fun createPackage(fqName: FqName): IrPackageFragment =
|
||||||
IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(EmptyPackageFragmentDescriptor(context.state.module, fqName)))
|
IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(EmptyPackageFragmentDescriptor(context.state.module, fqName)))
|
||||||
|
|
||||||
|
private val kotlinJvmPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm"))
|
||||||
private val kotlinJvmInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.internal"))
|
private val kotlinJvmInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.internal"))
|
||||||
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
||||||
private val javaLangPackage: IrPackageFragment = createPackage(FqName("java.lang"))
|
private val javaLangPackage: IrPackageFragment = createPackage(FqName("java.lang"))
|
||||||
@@ -307,4 +310,15 @@ class JvmSymbols(
|
|||||||
|
|
||||||
val genericToArray: IrSimpleFunctionSymbol =
|
val genericToArray: IrSimpleFunctionSymbol =
|
||||||
collectionToArrayClass.functions.single { it.owner.name.asString() == "toArray" && it.owner.valueParameters.size == 2 }
|
collectionToArrayClass.functions.single { it.owner.name.asString() == "toArray" && it.owner.valueParameters.size == 2 }
|
||||||
|
|
||||||
|
val kClassJava: IrPropertySymbol =
|
||||||
|
buildProperty {
|
||||||
|
name = Name.identifier("java")
|
||||||
|
}.apply {
|
||||||
|
parent = kotlinJvmPackage
|
||||||
|
addGetter().apply {
|
||||||
|
addExtensionReceiver(irBuiltIns.kClassClass.typeWith())
|
||||||
|
returnType = javaLangClass.typeWith()
|
||||||
|
}
|
||||||
|
}.symbol
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-11
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
|||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty
|
||||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.Not
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.Not
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.CrIrType
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
@@ -1080,18 +1079,15 @@ class ExpressionCodegen(
|
|||||||
JavaClassProperty.invokeWith(classReference.argument.accept(this, data))
|
JavaClassProperty.invokeWith(classReference.argument.accept(this, data))
|
||||||
} else if (classReference is IrClassReference) {
|
} else if (classReference is IrClassReference) {
|
||||||
val classType = classReference.classType
|
val classType = classReference.classType
|
||||||
if (classType is CrIrType) {
|
val classifier = classType.classifierOrNull
|
||||||
putJavaLangClassInstance(mv, classType.type, null, typeMapper.kotlinTypeMapper)
|
if (classifier is IrTypeParameterSymbol) {
|
||||||
return classReference.onStack
|
assert(classifier.owner.isReified) {
|
||||||
} else {
|
"Non-reified type parameter under ::class should be rejected by type checker: ${classifier.owner.dump()}"
|
||||||
val classifier = classType.classifierOrNull
|
|
||||||
if (classifier is IrTypeParameterSymbol) {
|
|
||||||
assert(classifier.owner.isReified) { "Non-reified type parameter under ::class should be rejected by type checker: ${classifier.owner.dump()}" }
|
|
||||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(classType, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
|
||||||
}
|
}
|
||||||
|
putReifiedOperationMarkerIfTypeIsReifiedParameter(classType, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
||||||
putJavaLangClassInstance(mv, typeMapper.mapType(classType), classType.toKotlinType(), typeMapper.kotlinTypeMapper)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
putJavaLangClassInstance(mv, typeMapper.mapType(classType), classType.toKotlinType(), typeMapper.kotlinTypeMapper)
|
||||||
} else {
|
} else {
|
||||||
throw AssertionError("not an IrGetClass or IrClassReference: ${classReference.dump()}")
|
throw AssertionError("not an IrGetClass or IrClassReference: ${classReference.dump()}")
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-40
@@ -51,18 +51,6 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
|
||||||
|
|
||||||
//Hack implementation to support CR java types in lower
|
|
||||||
class CrIrType(val type: Type) : IrType {
|
|
||||||
override val annotations: List<IrConstructorCall> = emptyList()
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean =
|
|
||||||
other is CrIrType && type == other.type
|
|
||||||
|
|
||||||
override fun hashCode(): Int =
|
|
||||||
type.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val callableReferencePhase = makeIrFilePhase(
|
internal val callableReferencePhase = makeIrFilePhase(
|
||||||
::CallableReferenceLowering,
|
::CallableReferenceLowering,
|
||||||
@@ -410,42 +398,40 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createGetOwnerMethod(superFunction: IrSimpleFunction): IrSimpleFunction = buildOverride(superFunction).apply {
|
private fun createGetOwnerMethod(superFunction: IrSimpleFunction): IrSimpleFunction = buildOverride(superFunction).apply {
|
||||||
val globalContext = context
|
body = context.createIrBuilder(symbol, startOffset, endOffset).run {
|
||||||
val state = globalContext.state
|
irExprBody(calculateOwner(callee.parent, this@CallableReferenceLowering.context))
|
||||||
val irContainer = callee.parent
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun IrBuilderWithScope.calculateOwner(irContainer: IrDeclarationParent, context: JvmBackendContext): IrExpression {
|
||||||
|
val symbols = context.ir.symbols
|
||||||
|
|
||||||
val isContainerPackage =
|
val isContainerPackage =
|
||||||
((irContainer as? IrClass)?.origin == IrDeclarationOrigin.FILE_CLASS) || irContainer is IrPackageFragment
|
(irContainer as? IrClass)?.origin == IrDeclarationOrigin.FILE_CLASS || irContainer is IrPackageFragment
|
||||||
|
|
||||||
val type = when (irContainer) {
|
|
||||||
// TODO: getDefaultType() here is wrong and won't work for arrays
|
|
||||||
is IrClass -> state.typeMapper.mapType(irContainer.defaultType.toKotlinType())
|
|
||||||
else -> state.typeMapper.mapOwner(callee.descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
val clazz = globalContext.ir.symbols.javaLangClass
|
|
||||||
val clazzRef = IrClassReferenceImpl(
|
val clazzRef = IrClassReferenceImpl(
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET,
|
||||||
clazz.typeWith(),
|
symbols.javaLangClass.typeWith(),
|
||||||
clazz,
|
symbols.javaLangClass,
|
||||||
CrIrType(type)
|
// For built-in members (i.e. top level `toString`) we don't know any meaningful container, so we're generating Any.
|
||||||
|
// The non-IR backend generates equally meaningless "kotlin/KotlinPackage" in this case (see KT-17151).
|
||||||
|
(irContainer as? IrClass)?.defaultType ?: context.irBuiltIns.anyNType
|
||||||
)
|
)
|
||||||
|
|
||||||
body = context.createIrBuilder(symbol, startOffset, endOffset).run {
|
if (!isContainerPackage) return clazzRef
|
||||||
irExprBody(if (isContainerPackage) {
|
|
||||||
irCall(globalContext.ir.symbols.getOrCreateKotlinPackage).apply {
|
val jClass = irGet(symbols.javaLangClass.typeWith(), null, symbols.kClassJava.owner.getter!!.symbol).apply {
|
||||||
putValueArgument(0, clazzRef)
|
extensionReceiver = clazzRef
|
||||||
// Note that this name is not used in reflection. There should be the name of the referenced declaration's
|
}
|
||||||
// module instead, but there's no nice API to obtain that name here yet
|
return irCall(symbols.getOrCreateKotlinPackage).apply {
|
||||||
// TODO: write the referenced declaration's module name and use it in reflection
|
putValueArgument(0, jClass)
|
||||||
putValueArgument(1, irString(state.moduleName))
|
// Note that this name is not used in reflection. There should be the name of the referenced declaration's
|
||||||
}
|
// module instead, but there's no nice API to obtain that name here yet
|
||||||
} else {
|
// TODO: write the referenced declaration's module name and use it in reflection
|
||||||
irCall(globalContext.ir.symbols.getOrCreateKotlinClass).apply {
|
putValueArgument(1, irString(context.state.moduleName))
|
||||||
putValueArgument(0, clazzRef)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-39
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
|||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||||
@@ -30,7 +29,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
|||||||
import org.jetbrains.kotlin.ir.types.createType
|
import org.jetbrains.kotlin.ir.types.createType
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.types.typeWith
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
@@ -85,48 +83,18 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
|||||||
private val kPropertiesFieldType =
|
private val kPropertiesFieldType =
|
||||||
context.ir.symbols.array.createType(false, listOf(makeTypeProjection(kPropertyStarType, Variance.OUT_VARIANCE)))
|
context.ir.symbols.array.createType(false, listOf(makeTypeProjection(kPropertyStarType, Variance.OUT_VARIANCE)))
|
||||||
|
|
||||||
// Return some declaration the parent of which is the containing class/package for the referenced property. This is
|
private val IrMemberAccessExpression.propertyContainer: IrDeclarationParent
|
||||||
// a bit of a hack, as the reason for not returning the container itself is the `mapImplementationOwner` call below.
|
|
||||||
// TODO: move after LocalDeclarationsLowering and always use the getter/field? Can't move below ConstLowering
|
|
||||||
// right now -- get() would not be optimized.
|
|
||||||
private val IrMemberAccessExpression.propertyContainerChild: IrDeclaration?
|
|
||||||
get() {
|
get() {
|
||||||
var current: IrDeclaration? = getter?.owner ?: field?.owner
|
var current: IrDeclaration = getter?.owner ?: field?.owner ?: error("Property without getter or field: ${dump()}")
|
||||||
while (current?.parent is IrFunction)
|
while (current.parent is IrFunction)
|
||||||
current = current.parent as IrFunction // Local delegated property.
|
current = current.parent as IrFunction // Local delegated property.
|
||||||
return current
|
return current.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove code duplication with CallableReferenceLowering
|
private fun IrBuilderWithScope.buildReflectedContainerReference(expression: IrMemberAccessExpression): IrExpression =
|
||||||
private val IrMemberAccessExpression.parentJavaClassReference
|
with(CallableReferenceLowering) {
|
||||||
get() = IrClassReferenceImpl(
|
calculateOwner(expression.propertyContainer, this@PropertyReferenceLowering.context)
|
||||||
startOffset, endOffset,
|
|
||||||
context.ir.symbols.javaLangClass.typeWith(),
|
|
||||||
context.ir.symbols.javaLangClass,
|
|
||||||
// TODO: when the parent is an interface, this should map to DefaultImpls. However, that requires
|
|
||||||
// moving this lowering below InterfaceLowering; see comment about the ordering above, though.
|
|
||||||
CrIrType(context.state.typeMapper.mapImplementationOwner(propertyContainerChild!!.descriptor))
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.buildReflectedContainerReference(expression: IrMemberAccessExpression): IrExpression {
|
|
||||||
val parent = expression.propertyContainerChild?.parent
|
|
||||||
val context = this@PropertyReferenceLowering.context
|
|
||||||
return when {
|
|
||||||
// FileClassLowering creates a class to which all package-level declarations are moved. However, there
|
|
||||||
// can still be external declarations at the package level, which is why we check for both a file class
|
|
||||||
// and a package fragment.
|
|
||||||
parent is IrPackageFragment || (parent is IrClass && parent.origin == IrDeclarationOrigin.FILE_CLASS) ->
|
|
||||||
irCall(context.ir.symbols.getOrCreateKotlinPackage).apply {
|
|
||||||
putValueArgument(0, expression.parentJavaClassReference)
|
|
||||||
putValueArgument(1, irString(context.state.moduleName))
|
|
||||||
}
|
|
||||||
parent is IrClass ->
|
|
||||||
irCall(context.ir.symbols.getOrCreateKotlinClass).apply {
|
|
||||||
putValueArgument(0, expression.parentJavaClassReference)
|
|
||||||
}
|
|
||||||
else -> throw AssertionError("referenced property not inside a class/package fragment")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrClass.addOverride(method: IrSimpleFunction, buildBody: IrBuilderWithScope.(List<IrValueParameter>) -> IrExpression) =
|
private fun IrClass.addOverride(method: IrSimpleFunction, buildBody: IrBuilderWithScope.(List<IrValueParameter>) -> IrExpression) =
|
||||||
addFunction {
|
addFunction {
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
|
// IGNORE_BACKEND: JS_IR, JS, NATIVE
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|
||||||
import kotlin.reflect.KCallable
|
import kotlin.reflect.KCallable
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user