Inner classes lowering.
This commit is contained in:
@@ -1261,10 +1261,13 @@ public class KotlinTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeAdditionalConstructorParameters(@NotNull ClassConstructorDescriptor descriptor, @NotNull JvmSignatureWriter sw) {
|
private void writeAdditionalConstructorParameters(@NotNull ClassConstructorDescriptor descriptor, @NotNull JvmSignatureWriter sw) {
|
||||||
|
boolean isSynthesized = descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||||
|
//if (isSynthesized) return;
|
||||||
|
|
||||||
MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
|
MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
|
||||||
|
|
||||||
ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
|
ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
|
||||||
if (captureThis != null) {
|
if (!isSynthesized && captureThis != null) {
|
||||||
writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor);
|
writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1274,12 +1277,16 @@ public class KotlinTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
if (descriptor.getKind() != CallableMemberDescriptor.Kind.SYNTHESIZED &&
|
|
||||||
(containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY)) {
|
if (!isSynthesized) {
|
||||||
writeParameter(
|
if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
|
||||||
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor);
|
writeParameter(
|
||||||
writeParameter(
|
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(),
|
||||||
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType(), descriptor);
|
descriptor);
|
||||||
|
writeParameter(
|
||||||
|
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType(),
|
||||||
|
descriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closure == null) return;
|
if (closure == null) return;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.jvm
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||||
|
|
||||||
interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||||
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
|
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
|
||||||
@@ -26,10 +27,10 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
|||||||
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
||||||
object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES")
|
object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES")
|
||||||
object FIELD_FOR_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
object FIELD_FOR_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
||||||
|
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||||
object SYNTHETIC_ACCESSOR : IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR")
|
object SYNTHETIC_ACCESSOR : IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR")
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||||
object DEFAULT_IMPLS_DELEGATION : IrStatementOrigin.IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
object DEFAULT_IMPLS_DELEGATION : IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -35,6 +35,8 @@ class JvmLower(val context: JvmBackendContext) {
|
|||||||
InterfaceLowering(context.state).runOnFilePostfix(irFile)
|
InterfaceLowering(context.state).runOnFilePostfix(irFile)
|
||||||
InterfaceDelegationLowering(context.state).runOnFilePostfix(irFile)
|
InterfaceDelegationLowering(context.state).runOnFilePostfix(irFile)
|
||||||
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
||||||
|
InnerClassesLowering(context).runOnFilePostfix(irFile)
|
||||||
|
InnerClassConstructorCallsLowering(context).runOnFilePostfix(irFile)
|
||||||
LocalFunctionsLowering(context).runOnFilePostfix(irFile)
|
LocalFunctionsLowering(context).runOnFilePostfix(irFile)
|
||||||
EnumClassLowering(context).runOnFilePostfix(irFile)
|
EnumClassLowering(context).runOnFilePostfix(irFile)
|
||||||
ObjectClassLowering(context).runOnFilePostfix(irFile)
|
ObjectClassLowering(context).runOnFilePostfix(irFile)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
|
|||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -201,6 +202,9 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
|||||||
else if (visibility == Visibilities.PROTECTED) {
|
else if (visibility == Visibilities.PROTECTED) {
|
||||||
flags = flags.or(Opcodes.ACC_PROTECTED)
|
flags = flags.or(Opcodes.ACC_PROTECTED)
|
||||||
}
|
}
|
||||||
|
else if (visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
|
||||||
|
// default visibility
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
|
throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
@@ -41,6 +42,15 @@ class FunctionCodegen(val irFunction: IrFunction, val classCodegen: ClassCodegen
|
|||||||
val descriptor = irFunction.descriptor
|
val descriptor = irFunction.descriptor
|
||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
|
try {
|
||||||
|
doGenerate()
|
||||||
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
throw RuntimeException("${e.message} + while generating code for:\n${irFunction.dump()}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doGenerate() {
|
||||||
val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION)
|
val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION)
|
||||||
val isStatic = isStaticMethod(classCodegen.descriptor.getMemberOwnerKind(), descriptor) || DescriptorUtils.isStaticDeclaration(descriptor)
|
val isStatic = isStaticMethod(classCodegen.descriptor.getMemberOwnerKind(), descriptor) || DescriptorUtils.isStaticDeclaration(descriptor)
|
||||||
val frameMap = createFrameMapWithReceivers(classCodegen.state, descriptor, signature, isStatic)
|
val frameMap = createFrameMapWithReceivers(classCodegen.state, descriptor, signature, isStatic)
|
||||||
|
|||||||
+14
@@ -70,5 +70,19 @@ class JvmPropertyDescriptorImpl(
|
|||||||
containingDeclaration, null, annotations, modality, visibility, extraFlags, false, name,
|
containingDeclaration, null, annotations, modality, visibility, extraFlags, false, name,
|
||||||
CallableMemberDescriptor.Kind.SYNTHESIZED, source, false, false
|
CallableMemberDescriptor.Kind.SYNTHESIZED, source, false, false
|
||||||
).initialize(type)
|
).initialize(type)
|
||||||
|
|
||||||
|
fun createFinalField(
|
||||||
|
name: Name,
|
||||||
|
type: KotlinType,
|
||||||
|
classDescriptor: ClassDescriptor,
|
||||||
|
annotations: Annotations,
|
||||||
|
visibility: Visibility,
|
||||||
|
extraFlags: Int,
|
||||||
|
source: SourceElement
|
||||||
|
): PropertyDescriptorImpl =
|
||||||
|
JvmPropertyDescriptorImpl(
|
||||||
|
classDescriptor, null, annotations, Modality.FINAL, visibility, extraFlags, false, name,
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED, source, false, false
|
||||||
|
).initialize(type, dispatchReceiverParameter = classDescriptor.thisAsReceiverParameter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+46
@@ -19,11 +19,14 @@ package org.jetbrains.kotlin.backend.jvm.descriptors
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.ir.SourceManager
|
import org.jetbrains.kotlin.ir.SourceManager
|
||||||
|
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -33,6 +36,8 @@ class SpecialDescriptorsFactory(
|
|||||||
val builtIns: KotlinBuiltIns
|
val builtIns: KotlinBuiltIns
|
||||||
) {
|
) {
|
||||||
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
|
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
|
||||||
|
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
|
||||||
|
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>()
|
||||||
|
|
||||||
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
|
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
|
||||||
singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
|
singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
|
||||||
@@ -52,6 +57,47 @@ class SpecialDescriptorsFactory(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor =
|
||||||
|
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor")
|
||||||
|
else outerThisDescriptors.getOrPut(innerClassDescriptor) {
|
||||||
|
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) ?:
|
||||||
|
throw AssertionError("No containing class for inner class $innerClassDescriptor")
|
||||||
|
|
||||||
|
JvmPropertyDescriptorImpl.createFinalField(
|
||||||
|
Name.identifier("this$0"), outerClassDescriptor.defaultType, innerClassDescriptor,
|
||||||
|
Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): ClassConstructorDescriptor {
|
||||||
|
val innerClass = innerClassConstructor.containingDeclaration
|
||||||
|
assert(innerClass.isInner) { "Class is not inner: $innerClass" }
|
||||||
|
|
||||||
|
return innerClassConstructors.getOrPut(innerClassConstructor) {
|
||||||
|
createInnerClassConstructorWithOuterThisParameter(innerClassConstructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor {
|
||||||
|
val classDescriptor = oldDescriptor.containingDeclaration
|
||||||
|
val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType
|
||||||
|
|
||||||
|
val newDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
|
||||||
|
classDescriptor, oldDescriptor.annotations, oldDescriptor.isPrimary, oldDescriptor.source
|
||||||
|
)
|
||||||
|
|
||||||
|
val outerThisValueParameter = newDescriptor.createValueParameter(0, "\$outer", outerThisType)
|
||||||
|
|
||||||
|
val newValueParameters =
|
||||||
|
listOf(outerThisValueParameter) +
|
||||||
|
oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) }
|
||||||
|
newDescriptor.initialize(newValueParameters, oldDescriptor.visibility)
|
||||||
|
newDescriptor.returnType = oldDescriptor.returnType
|
||||||
|
return newDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor {
|
private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor {
|
||||||
assert(enumEntryDescriptor.kind == ClassKind.ENUM_ENTRY) { "Should be enum entry: $enumEntryDescriptor" }
|
assert(enumEntryDescriptor.kind == ClassKind.ENUM_ENTRY) { "Should be enum entry: $enumEntryDescriptor" }
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.descriptors
|
package org.jetbrains.kotlin.backend.jvm.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
fun PropertyDescriptorImpl.initialize(
|
fun PropertyDescriptorImpl.initialize(
|
||||||
type: KotlinType,
|
type: KotlinType,
|
||||||
@@ -34,4 +35,14 @@ fun PropertyDescriptorImpl.initialize(
|
|||||||
setType(type, typeParameters, dispatchReceiverParameter, extensionReceiverParameter)
|
setType(type, typeParameters, dispatchReceiverParameter, extensionReceiverParameter)
|
||||||
initialize(getter, setter)
|
initialize(getter, setter)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CallableMemberDescriptor.createValueParameter(index: Int, name: String, type: KotlinType): ValueParameterDescriptor =
|
||||||
|
ValueParameterDescriptorImpl(
|
||||||
|
this, null,
|
||||||
|
index,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
Name.identifier(name),
|
||||||
|
type,
|
||||||
|
false, false, false, false, null, SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
|||||||
+3
-12
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl
|
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||||
@@ -137,8 +138,8 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
|
|
||||||
val valueParameters =
|
val valueParameters =
|
||||||
listOf(
|
listOf(
|
||||||
loweredConstructorDescriptor.createSpecialParameter(0, "name", context.builtIns.stringType),
|
loweredConstructorDescriptor.createValueParameter(0, "name", context.builtIns.stringType),
|
||||||
loweredConstructorDescriptor.createSpecialParameter(1, "ordinal", context.builtIns.intType)
|
loweredConstructorDescriptor.createValueParameter(1, "ordinal", context.builtIns.intType)
|
||||||
) +
|
) +
|
||||||
constructorDescriptor.valueParameters.map {
|
constructorDescriptor.valueParameters.map {
|
||||||
lowerConstructorValueParameter(loweredConstructorDescriptor, it)
|
lowerConstructorValueParameter(loweredConstructorDescriptor, it)
|
||||||
@@ -152,16 +153,6 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
return loweredConstructorDescriptor
|
return loweredConstructorDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ClassConstructorDescriptor.createSpecialParameter(index: Int, name: String, type: KotlinType): ValueParameterDescriptor =
|
|
||||||
ValueParameterDescriptorImpl(
|
|
||||||
this, null,
|
|
||||||
index,
|
|
||||||
Annotations.EMPTY,
|
|
||||||
Name.identifier(name),
|
|
||||||
type,
|
|
||||||
false, false, false, false, null, SourceElement.NO_SOURCE
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun lowerConstructorValueParameter(
|
private fun lowerConstructorValueParameter(
|
||||||
loweredConstructorDescriptor: ClassConstructorDescriptor,
|
loweredConstructorDescriptor: ClassConstructorDescriptor,
|
||||||
valueParameterDescriptor: ValueParameterDescriptor
|
valueParameterDescriptor: ValueParameterDescriptor
|
||||||
|
|||||||
+213
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* 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.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.BodyLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||||
|
|
||||||
|
class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||||
|
override fun lower(irClass: IrClass) {
|
||||||
|
InnerClassTransformer(irClass).lowerInnerClass()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class InnerClassTransformer(val irClass: IrClass) {
|
||||||
|
val classDescriptor = irClass.descriptor
|
||||||
|
|
||||||
|
private lateinit var outerThisFieldDescriptor: PropertyDescriptor
|
||||||
|
|
||||||
|
fun lowerInnerClass() {
|
||||||
|
if (!irClass.descriptor.isInner) return
|
||||||
|
|
||||||
|
createOuterThisField()
|
||||||
|
lowerConstructors()
|
||||||
|
lowerOuterThisReferences()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createOuterThisField() {
|
||||||
|
outerThisFieldDescriptor = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(irClass.descriptor)
|
||||||
|
|
||||||
|
irClass.declarations.add(IrFieldImpl(
|
||||||
|
irClass.startOffset, irClass.endOffset,
|
||||||
|
JvmLoweredDeclarationOrigin.FIELD_FOR_OUTER_THIS,
|
||||||
|
outerThisFieldDescriptor
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lowerConstructors() {
|
||||||
|
irClass.declarations.transformFlat { irMember ->
|
||||||
|
if (irMember is IrConstructor)
|
||||||
|
lowerConstructor(irMember).singletonList()
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lowerConstructor(irConstructor: IrConstructor): IrConstructor {
|
||||||
|
val oldDescriptor = irConstructor.descriptor
|
||||||
|
val startOffset = irConstructor.startOffset
|
||||||
|
val endOffset = irConstructor.endOffset
|
||||||
|
|
||||||
|
val newDescriptor = context.specialDescriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor)
|
||||||
|
val outerThisValueParameter = newDescriptor.valueParameters[0]
|
||||||
|
|
||||||
|
val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
|
||||||
|
|
||||||
|
val instanceInitializerIndex = blockBody.statements.indexOfFirst { it is IrInstanceInitializerCall }
|
||||||
|
if (instanceInitializerIndex >= 0) {
|
||||||
|
// Initializing constructor: initialize 'this.this$0' with '$outer'
|
||||||
|
blockBody.statements.add(
|
||||||
|
instanceInitializerIndex,
|
||||||
|
IrSetFieldImpl(
|
||||||
|
startOffset, endOffset, outerThisFieldDescriptor,
|
||||||
|
IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter),
|
||||||
|
IrGetValueImpl(startOffset, endOffset, outerThisValueParameter)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Delegating constructor: invoke old constructor with dispatch receiver '$outer'
|
||||||
|
val delegatingConstructorCall = (blockBody.statements.find { it is IrDelegatingConstructorCall } ?:
|
||||||
|
throw AssertionError("Delegating constructor call expected: ${irConstructor.dump()}")
|
||||||
|
) as IrDelegatingConstructorCall
|
||||||
|
delegatingConstructorCall.dispatchReceiver = IrGetValueImpl(
|
||||||
|
delegatingConstructorCall.startOffset, delegatingConstructorCall.endOffset, outerThisValueParameter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return IrConstructorImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
irConstructor.origin, // TODO special origin for lowered inner class constructors?
|
||||||
|
newDescriptor,
|
||||||
|
blockBody
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lowerOuterThisReferences() {
|
||||||
|
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
val implicitThisClass = expression.descriptor.getClassDescriptorForImplicitThis() ?:
|
||||||
|
return expression
|
||||||
|
|
||||||
|
if (implicitThisClass == classDescriptor) return expression
|
||||||
|
|
||||||
|
val startOffset = expression.startOffset
|
||||||
|
val endOffset = expression.endOffset
|
||||||
|
val origin = expression.origin
|
||||||
|
|
||||||
|
var irThis: IrExpression = IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter, origin)
|
||||||
|
var innerClass = classDescriptor
|
||||||
|
|
||||||
|
while (innerClass != implicitThisClass) {
|
||||||
|
if (!innerClass.isInner) {
|
||||||
|
// Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is -
|
||||||
|
// should be transformed by closures conversion.
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
val outerThisField = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(innerClass)
|
||||||
|
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin)
|
||||||
|
|
||||||
|
val outer = classDescriptor.containingDeclaration
|
||||||
|
innerClass = outer as? ClassDescriptor ?:
|
||||||
|
throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer")
|
||||||
|
}
|
||||||
|
|
||||||
|
return irThis
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ValueDescriptor.getClassDescriptorForImplicitThis(): ClassDescriptor? {
|
||||||
|
if (this is ReceiverParameterDescriptor) {
|
||||||
|
val receiverValue = value
|
||||||
|
if (receiverValue is ImplicitClassReceiver) {
|
||||||
|
return receiverValue.classDescriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InnerClassConstructorCallsLowering(val context: JvmBackendContext) : BodyLoweringPass {
|
||||||
|
override fun lower(irBody: IrBody) {
|
||||||
|
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
val dispatchReceiver = expression.dispatchReceiver ?: return expression
|
||||||
|
val callee = expression.descriptor as? ClassConstructorDescriptor ?: return expression
|
||||||
|
if (!callee.constructedClass.isInner) return expression
|
||||||
|
|
||||||
|
val newCallee = context.specialDescriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee)
|
||||||
|
val newCall = IrCallImpl(
|
||||||
|
expression.startOffset, expression.endOffset, newCallee,
|
||||||
|
null, // TODO type arguments map
|
||||||
|
expression.origin
|
||||||
|
)
|
||||||
|
|
||||||
|
newCall.putValueArgument(0, dispatchReceiver)
|
||||||
|
for (i in 1 .. newCallee.valueParameters.lastIndex) {
|
||||||
|
newCall.putValueArgument(i, expression.getValueArgument(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
return newCall
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
val dispatchReceiver = expression.dispatchReceiver ?: return expression
|
||||||
|
val callee = expression.descriptor
|
||||||
|
if (!callee.constructedClass.isInner) return expression
|
||||||
|
|
||||||
|
val newCallee = context.specialDescriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee)
|
||||||
|
val newCall = IrDelegatingConstructorCallImpl(
|
||||||
|
expression.startOffset, expression.endOffset, newCallee,
|
||||||
|
null // TODO type arguments map
|
||||||
|
)
|
||||||
|
|
||||||
|
newCall.putValueArgument(0, dispatchReceiver)
|
||||||
|
for (i in 1 .. newCallee.valueParameters.lastIndex) {
|
||||||
|
newCall.putValueArgument(i, expression.getValueArgument(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
return newCall
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO callable references?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -16,11 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.expressions
|
package org.jetbrains.kotlin.ir.expressions
|
||||||
|
|
||||||
interface IrStatementOrigin {
|
abstract class IrStatementOriginImpl(val debugName: String): IrStatementOrigin {
|
||||||
abstract class IrStatementOriginImpl(val debugName: String): IrStatementOrigin {
|
override fun toString(): String = debugName
|
||||||
override fun toString(): String = debugName
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
interface IrStatementOrigin {
|
||||||
object SAFE_CALL : IrStatementOriginImpl("SAFE_CALL")
|
object SAFE_CALL : IrStatementOriginImpl("SAFE_CALL")
|
||||||
|
|
||||||
object UMINUS : IrStatementOriginImpl("UMINUS")
|
object UMINUS : IrStatementOriginImpl("UMINUS")
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class Outer {
|
||||||
|
val x = "O"
|
||||||
|
inner class Inner {
|
||||||
|
val y = x + "K"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = Outer().Inner().y
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class Outer {
|
||||||
|
inner class Inner(val x: Int) {
|
||||||
|
constructor() : this(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
FILE /innerClassWithDelegatingConstructor.kt
|
||||||
|
CLASS CLASS Outer
|
||||||
|
CONSTRUCTOR public constructor Outer()
|
||||||
|
BLOCK_BODY
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
|
||||||
|
INSTANCE_INITIALIZER_CALL classDescriptor='Outer'
|
||||||
|
CLASS CLASS Inner
|
||||||
|
CONSTRUCTOR public constructor Inner(x: kotlin.Int)
|
||||||
|
BLOCK_BODY
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
|
||||||
|
INSTANCE_INITIALIZER_CALL classDescriptor='Inner'
|
||||||
|
PROPERTY public final val x: kotlin.Int
|
||||||
|
FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
FUN DEFAULT_PROPERTY_ACCESSOR public final fun <get-x>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='<get-x>(): Int'
|
||||||
|
GET_FIELD 'x: Int' type=kotlin.Int origin=null
|
||||||
|
receiver: GET_VAR '<receiver: Inner>' type=Outer.Inner origin=null
|
||||||
|
CONSTRUCTOR public constructor Inner()
|
||||||
|
BLOCK_BODY
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL 'constructor Inner(Int)'
|
||||||
|
$this: GET_VAR '<receiver: Outer>' type=Outer origin=null
|
||||||
|
x: CONST Int type=kotlin.Int value='0'
|
||||||
@@ -109,6 +109,12 @@ public class IrOnlyBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTest
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClass1.kt")
|
||||||
|
public void testInnerClass1() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/innerClass1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("mutable1.kt")
|
@TestMetadata("mutable1.kt")
|
||||||
public void testMutable1() throws Exception {
|
public void testMutable1() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/mutable1.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/mutable1.kt");
|
||||||
|
|||||||
@@ -127,6 +127,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClassWithDelegatingConstructor.kt")
|
||||||
|
public void testInnerClassWithDelegatingConstructor() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/innerClassWithDelegatingConstructor.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localClasses.kt")
|
@TestMetadata("localClasses.kt")
|
||||||
public void testLocalClasses() throws Exception {
|
public void testLocalClasses() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/localClasses.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/localClasses.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user