diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt index cb10e4c9218..51c244e0054 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt @@ -16,8 +16,15 @@ package org.jetbrains.kotlin.backend.jvm +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl +import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -object JvmDeclarationOrigins { +interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER") + object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPL") +} + +interface JvmLoweredStatementOrigin : IrStatementOrigin { + object DEFAULT_IMPLS_DELEGATION : IrStatementOrigin.IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION") } \ No newline at end of file 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 68a4af5e6f1..0ae265dc5a3 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,9 +16,7 @@ package org.jetbrains.kotlin.backend.jvm -import org.jetbrains.kotlin.backend.jvm.lower.FileClassLowering -import org.jetbrains.kotlin.backend.jvm.lower.InitializersLowering -import org.jetbrains.kotlin.backend.jvm.lower.PropertiesLowering +import org.jetbrains.kotlin.backend.jvm.lower.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer import org.jetbrains.kotlin.ir.declarations.IrFile @@ -28,6 +26,8 @@ class JvmLower(val context: JvmBackendContext) { FileClassLowering(context.jvmFileClassProvider).lower(irFile) PropertiesLowering().lower(irFile) InitializersLowering().runOnNormalizedFile(irFile) + InterfaceLowering(context.state).runOnNormalizedFile(irFile) + InterfaceDelegationLowering(context.state).runOnNormalizedFile(irFile) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 7537acc6d5d..0a6865985ca 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -19,11 +19,8 @@ package org.jetbrains.kotlin.backend.jvm.codegen import com.intellij.psi.PsiElement import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor -import org.jetbrains.kotlin.codegen.ClassBuilder -import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen +import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor -import org.jetbrains.kotlin.codegen.OwnerKind -import org.jetbrains.kotlin.codegen.SuperClassInfo import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.name.SpecialNames @@ -99,6 +96,9 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac is IrAnonymousInitializer -> { // skip } + is IrClass -> { + ClassCodegen(declaration, context).generate() + } else -> throw RuntimeException("Unsupported declaration $declaration") } } @@ -118,9 +118,8 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac } fun ClassDescriptor.calculateClassFlags(): Int { - return (if (!DescriptorUtils.isInterface(this)) Opcodes.ACC_SUPER else 0). - or(calculateCommonFlags()). - or(if (DescriptorUtils.isInterface(this)) Opcodes.ACC_INTERFACE else 0) + return (if (DescriptorUtils.isInterface(this)) Opcodes.ACC_INTERFACE else Opcodes.ACC_SUPER). + or(calcModalityFlag()).or(AsmUtil.getVisibilityAccessFlagForClass(this)) } fun MemberDescriptor.calculateCommonFlags(): Int { @@ -138,6 +137,11 @@ fun MemberDescriptor.calculateCommonFlags(): Int { throw RuntimeException("Unsupported visibility $visibility for descriptor $this") } + return flags.or(calcModalityFlag()) +} + +private fun MemberDescriptor.calcModalityFlag(): Int { + var flags = 0 when (modality) { Modality.ABSTRACT -> { flags = flags.or(Opcodes.ACC_ABSTRACT) @@ -150,7 +154,7 @@ fun MemberDescriptor.calculateCommonFlags(): Int { Modality.OPEN -> { assert(!Visibilities.isPrivate(visibility)) } - else -> throw RuntimeException("Unsupported modality $modality for descriptor $this") + else -> throw RuntimeException("Unsupported modality $modality for descriptor ${this}") } if (this is CallableMemberDescriptor) { @@ -158,7 +162,6 @@ fun MemberDescriptor.calculateCommonFlags(): Int { flags = flags or Opcodes.ACC_STATIC } } - return flags } 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 57dd619b8e6..66b61272376 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 @@ -156,7 +156,7 @@ class ExpressionCodegen( } else { val receiver = expression.dispatchReceiver receiver?.apply { - gen(receiver, callable.owner, data) + gen(receiver, callable.dispatchReceiverType!!, data) } val args = (listOf(expression.extensionReceiver).filterNotNull() + diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index 955fc686bd4..b4982ed3553 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -16,24 +16,44 @@ package org.jetbrains.kotlin.backend.jvm.codegen +import org.jetbrains.kotlin.backend.jvm.lower.InitializersLowering +import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod import org.jetbrains.kotlin.codegen.FunctionCodegen.createFrameMap +import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.codegen.OwnerKind import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.org.objectweb.asm.Opcodes.ACC_STATIC +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class FunctionCodegen(val irFunction: IrFunction, val classCodegen: ClassCodegen) { - fun generate() { - val signature = classCodegen.typeMapper.mapSignatureWithGeneric(irFunction.descriptor, OwnerKind.IMPLEMENTATION) - val isStatic = isStaticMethod(classCodegen.descriptor.getMemberOwnerKind(), irFunction.descriptor) - val frameMap = createFrameMap(classCodegen.state, irFunction.descriptor, signature, isStatic) + val state = classCodegen.state + + val descriptor = irFunction.descriptor + + fun generate() { + val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION) + val isStatic = isStaticMethod(classCodegen.descriptor.getMemberOwnerKind(), descriptor) || DescriptorUtils.isStaticDeclaration(descriptor) + val frameMap = createFrameMap(classCodegen.state, descriptor, signature, isStatic) + + var flags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, state).or(if (isStatic) Opcodes.ACC_STATIC else 0) + val interfaceClInit = JvmCodegenUtil.isJvmInterface(classCodegen.descriptor) && InitializersLowering.clinitName == descriptor.name + if (interfaceClInit) { + //reset abstract flag + flags = flags.xor(Opcodes.ACC_ABSTRACT) + } val methodVisitor = classCodegen.visitor.newMethod(irFunction.OtherOrigin, - irFunction.descriptor.calculateCommonFlags().or(if (isStatic) ACC_STATIC else 0), + flags, signature.asmMethod.name, signature.asmMethod.descriptor, signature.genericsSignature, null/*TODO support exception*/) + if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0) { + methodVisitor.visitEnd() + return + } + ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen).generate() } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/DefaultImplsClassDescriptor.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/DefaultImplsClassDescriptor.kt new file mode 100644 index 00000000000..4b47b5766f6 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/DefaultImplsClassDescriptor.kt @@ -0,0 +1,80 @@ +/* + * 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.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.* + +interface DefaultImplsClassDescriptor : ClassDescriptor { + val correspondingInterface: ClassDescriptor +} + +class DefaultImplsClassDescriptorImpl( + private val nameImpl: Name, + override val correspondingInterface: ClassDescriptor, + private val sourceElement: SourceElement +) : DefaultImplsClassDescriptor { + override fun getCompanionObjectDescriptor(): ClassDescriptor? = null + override fun getConstructors(): Collection = emptyList() + override fun getContainingDeclaration(): DeclarationDescriptor = correspondingInterface + override fun getDeclaredTypeParameters(): List = emptyList() + override fun getKind(): ClassKind = ClassKind.CLASS + + override fun getMemberScope(typeSubstitution: TypeSubstitution): MemberScope = error("File class has no member scope") + override fun getModality(): Modality = Modality.FINAL + override fun getOriginal(): ClassDescriptor = this + override fun getName(): Name = nameImpl + override fun getStaticScope(): MemberScope = error("File class has no static scope") + override fun getThisAsReceiverParameter(): ReceiverParameterDescriptor = error("File class has no instances") + override fun getUnsubstitutedInnerClassesScope(): MemberScope = error("File class has no inner classes scope") + override fun getUnsubstitutedMemberScope(): MemberScope = error("File class has no member scope") + override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null + override fun getVisibility(): Visibility = Visibilities.PUBLIC + override fun isCompanionObject(): Boolean = false + override fun isData(): Boolean = false + override fun substitute(substitutor: TypeSubstitutor): ClassDescriptor = error("File class can't be substituted") + override fun getSource(): SourceElement = sourceElement + override fun isInner(): Boolean = false + + override val annotations = Annotations.EMPTY + + private val typeConstructor = ClassTypeConstructorImpl(this, annotations, true, emptyList(), listOf(builtIns.anyType)) + private val defaultType = KotlinTypeFactory.simpleNotNullType(annotations, this, emptyList()) + + override fun getTypeConstructor(): TypeConstructor = typeConstructor + + override fun getDefaultType(): SimpleType = defaultType + + override fun getMemberScope(typeArguments: MutableList): MemberScope = + MemberScope.Empty // TODO do we need a more useful MemberScope here? + + override fun accept(visitor: DeclarationDescriptorVisitor, data: D): R { + return visitor.visitClassDescriptor(this, data) + } + + override fun acceptVoid(visitor: DeclarationDescriptorVisitor) { + visitor.visitClassDescriptor(this, null) + } + + override fun toString(): String = + "IrFileClassDescriptor($fqNameUnsafe)" +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt index 6bde59603db..8a9c762ed58 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass -import org.jetbrains.kotlin.backend.jvm.JvmDeclarationOrigins +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.getMemberOwnerKind import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.descriptors.* @@ -127,7 +127,7 @@ class InitializersLowering : ClassLoweringPass { Modality.FINAL, Visibilities.PUBLIC ) irClass.declarations.add( - IrFunctionImpl(irClass.startOffset, irClass.endOffset, JvmDeclarationOrigins.CLASS_STATIC_INITIALIZER, + IrFunctionImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, staticInitializerDescriptor, IrBlockBodyImpl(irClass.startOffset, irClass.endOffset, staticInitializerStatements.map { it.copy() })) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt new file mode 100644 index 00000000000..a27fd7e592e --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt @@ -0,0 +1,90 @@ +/* + * 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.common.CodegenUtil +import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin +import org.jetbrains.kotlin.codegen.JvmCodegenUtil +import org.jetbrains.kotlin.codegen.isDefinitelyNotDefaultImplsMethod +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.resolve.DescriptorUtils + + +class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass { + + override fun lower(irClass: IrClass) { + val descriptor = irClass.descriptor + if (!DescriptorUtils.isClass(descriptor)) { + return + } + + irClass.transformChildrenVoid(this) + generateInterfaceMethods(irClass, descriptor) + } + + + private fun generateInterfaceMethods(irClass: IrClass, descriptor: ClassDescriptor) { + val classDescriptor = if (descriptor is DefaultImplsClassDescriptor) descriptor.correspondingInterface else descriptor + for ((interfaceFun, value) in CodegenUtil.getNonPrivateTraitMethods(classDescriptor)) { + //skip java 8 default methods + if (!interfaceFun.isDefinitelyNotDefaultImplsMethod()) { + val inheritedFun = + if (classDescriptor !== descriptor) { + InterfaceLowering.createDefaultImplFunDescriptor(descriptor as DefaultImplsClassDescriptorImpl, interfaceFun, classDescriptor) + } + else { + value + } + generateDelegationToDefaultImpl(irClass, interfaceFun, inheritedFun) + } + } + } + + private fun generateDelegationToDefaultImpl(irClass: IrClass, interfaceFun: FunctionDescriptor, inheritedFun: FunctionDescriptor) { + val irBody = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET) + val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, inheritedFun, irBody) + irClass.declarations.add(irFunction) + + val interfaceDescriptor = interfaceFun.containingDeclaration as ClassDescriptor + val defaultImpls = InterfaceLowering.createDefaultImplsClassDescriptor(interfaceDescriptor) + val defaultImplFun = InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun, interfaceDescriptor) + val returnType = inheritedFun.returnType!! + val irCallImpl = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, defaultImplFun, null, JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION) + irBody.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, inheritedFun, irCallImpl)) + + var shift = 0 + if (inheritedFun.dispatchReceiverParameter != null) { + irCallImpl.putValueArgument(0, IrThisReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irClass.descriptor.defaultType, irClass.descriptor)) + shift = 1 + } + inheritedFun.valueParameters.mapIndexed { i, valueParameterDescriptor -> + irCallImpl.putValueArgument(i + shift, IrGetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueParameterDescriptor, null)) + } + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt new file mode 100644 index 00000000000..9d9d8517ce7 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt @@ -0,0 +1,111 @@ +/* + * 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.common.CodegenUtil +import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin +import org.jetbrains.kotlin.codegen.JvmCodegenUtil +import org.jetbrains.kotlin.codegen.isDefinitelyNotDefaultImplsMethod +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl +import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.DescriptorUtils + + +class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass { + + override fun lower(irClass: IrClass) { + if (!DescriptorUtils.isInterface(irClass.descriptor)) { + return + } + + + val interfaceDescriptor = irClass.descriptor + val defaultImplsDescriptor = createDefaultImplsClassDescriptor(interfaceDescriptor) + val defaultImplsIrClass = IrClassImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS, defaultImplsDescriptor) + irClass.declarations.add(defaultImplsIrClass) + + val members = defaultImplsIrClass.declarations + + irClass.declarations.filterIsInstance().mapNotNull { + val descriptor = it.descriptor + if (descriptor.modality != Modality.ABSTRACT) { + val functionDescriptorImpl = createDefaultImplFunDescriptor(defaultImplsDescriptor, descriptor, interfaceDescriptor) + + members.add(IrFunctionImpl(it.startOffset, it.endOffset, it.origin, functionDescriptorImpl, it.body)) + it.body = null + } + } + + + irClass.transformChildrenVoid(this) + } + + + companion object { + + fun createDefaultImplsClassDescriptor(interfaceDescriptor: ClassDescriptor): DefaultImplsClassDescriptorImpl { + return DefaultImplsClassDescriptorImpl( + Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME), interfaceDescriptor, interfaceDescriptor.source + ) + } + + fun createDefaultImplFunDescriptor( + defaultImplsDescriptor: DefaultImplsClassDescriptorImpl, + descriptor: FunctionDescriptor, + interfaceDescriptor: ClassDescriptor + ): SimpleFunctionDescriptorImpl { + + val newFunction = SimpleFunctionDescriptorImpl.create( + defaultImplsDescriptor, AnnotationsImpl(emptyList()), descriptor.name, descriptor.kind, descriptor.source + ) + + val valueParameters = + listOf(ValueParameterDescriptorImpl.createWithDestructuringDeclarations( + newFunction, null, 0, AnnotationsImpl(emptyList()), Name.identifier("this"), + interfaceDescriptor.defaultType, false, false, false, false, null, interfaceDescriptor.source, null) + ) + + descriptor.valueParameters.map { it.copy(newFunction, it.name, it.index + 1) } + newFunction.initialize( + null, null, emptyList()/*TODO: type parameters*/, + valueParameters, descriptor.returnType, Modality.FINAL, descriptor.visibility + ) + return newFunction + } + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/LoweredFunction.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/LoweredFunction.kt new file mode 100644 index 00000000000..c4d67cecc29 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/LoweredFunction.kt @@ -0,0 +1,42 @@ +/* + * 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.annotations.NotNull +import org.jetbrains.annotations.Nullable +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl +import org.jetbrains.kotlin.name.Name + +interface LoweredFunction: FunctionDescriptor + +class LoweredFunctionImpl(containingDeclaration: DeclarationDescriptor, + original: FunctionDescriptor, + annotations: Annotations, + name: Name, + kind: CallableMemberDescriptor.Kind, + source: SourceElement) : + FunctionDescriptorImpl(containingDeclaration, original, annotations, name, kind, source), LoweredFunction { + override fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? { + return super.getDispatchReceiverParameter() + } + + override fun createSubstitutedCopy(newOwner: DeclarationDescriptor, original: FunctionDescriptor?, kind: CallableMemberDescriptor.Kind, newName: Name?, annotations: Annotations, source: SourceElement): FunctionDescriptorImpl { + TODO("not implemented") + } +} \ No newline at end of file