Support default impls
This commit is contained in:
committed by
Dmitry Petrov
parent
7950235df3
commit
011ed60eee
@@ -16,8 +16,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm
|
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.declarations.IrDeclarationOriginImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
|
|
||||||
object JvmDeclarationOrigins {
|
interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||||
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
|
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")
|
||||||
}
|
}
|
||||||
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm
|
package org.jetbrains.kotlin.backend.jvm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.FileClassLowering
|
import org.jetbrains.kotlin.backend.jvm.lower.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.InitializersLowering
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.PropertiesLowering
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
@@ -28,6 +26,8 @@ class JvmLower(val context: JvmBackendContext) {
|
|||||||
FileClassLowering(context.jvmFileClassProvider).lower(irFile)
|
FileClassLowering(context.jvmFileClassProvider).lower(irFile)
|
||||||
PropertiesLowering().lower(irFile)
|
PropertiesLowering().lower(irFile)
|
||||||
InitializersLowering().runOnNormalizedFile(irFile)
|
InitializersLowering().runOnNormalizedFile(irFile)
|
||||||
|
InterfaceLowering(context.state).runOnNormalizedFile(irFile)
|
||||||
|
InterfaceDelegationLowering(context.state).runOnNormalizedFile(irFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-9
@@ -19,11 +19,8 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
|
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
|
||||||
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
@@ -99,6 +96,9 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
|
|||||||
is IrAnonymousInitializer -> {
|
is IrAnonymousInitializer -> {
|
||||||
// skip
|
// skip
|
||||||
}
|
}
|
||||||
|
is IrClass -> {
|
||||||
|
ClassCodegen(declaration, context).generate()
|
||||||
|
}
|
||||||
else -> throw RuntimeException("Unsupported declaration $declaration")
|
else -> throw RuntimeException("Unsupported declaration $declaration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,9 +118,8 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun ClassDescriptor.calculateClassFlags(): Int {
|
fun ClassDescriptor.calculateClassFlags(): Int {
|
||||||
return (if (!DescriptorUtils.isInterface(this)) Opcodes.ACC_SUPER else 0).
|
return (if (DescriptorUtils.isInterface(this)) Opcodes.ACC_INTERFACE else Opcodes.ACC_SUPER).
|
||||||
or(calculateCommonFlags()).
|
or(calcModalityFlag()).or(AsmUtil.getVisibilityAccessFlagForClass(this))
|
||||||
or(if (DescriptorUtils.isInterface(this)) Opcodes.ACC_INTERFACE else 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MemberDescriptor.calculateCommonFlags(): Int {
|
fun MemberDescriptor.calculateCommonFlags(): Int {
|
||||||
@@ -138,6 +137,11 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
|||||||
throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
|
throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return flags.or(calcModalityFlag())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MemberDescriptor.calcModalityFlag(): Int {
|
||||||
|
var flags = 0
|
||||||
when (modality) {
|
when (modality) {
|
||||||
Modality.ABSTRACT -> {
|
Modality.ABSTRACT -> {
|
||||||
flags = flags.or(Opcodes.ACC_ABSTRACT)
|
flags = flags.or(Opcodes.ACC_ABSTRACT)
|
||||||
@@ -150,7 +154,7 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
|||||||
Modality.OPEN -> {
|
Modality.OPEN -> {
|
||||||
assert(!Visibilities.isPrivate(visibility))
|
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) {
|
if (this is CallableMemberDescriptor) {
|
||||||
@@ -158,7 +162,6 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
|||||||
flags = flags or Opcodes.ACC_STATIC
|
flags = flags or Opcodes.ACC_STATIC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -156,7 +156,7 @@ class ExpressionCodegen(
|
|||||||
} else {
|
} else {
|
||||||
val receiver = expression.dispatchReceiver
|
val receiver = expression.dispatchReceiver
|
||||||
receiver?.apply {
|
receiver?.apply {
|
||||||
gen(receiver, callable.owner, data)
|
gen(receiver, callable.dispatchReceiverType!!, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
val args = (listOf(expression.extensionReceiver).filterNotNull() +
|
val args = (listOf(expression.extensionReceiver).filterNotNull() +
|
||||||
|
|||||||
+26
-6
@@ -16,24 +16,44 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
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.AsmUtil.isStaticMethod
|
||||||
import org.jetbrains.kotlin.codegen.FunctionCodegen.createFrameMap
|
import org.jetbrains.kotlin.codegen.FunctionCodegen.createFrameMap
|
||||||
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
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
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
class FunctionCodegen(val irFunction: IrFunction, val classCodegen: ClassCodegen) {
|
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,
|
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.asmMethod.name, signature.asmMethod.descriptor,
|
||||||
signature.genericsSignature, null/*TODO support exception*/)
|
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()
|
ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen).generate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+80
@@ -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<ClassConstructorDescriptor> = emptyList()
|
||||||
|
override fun getContainingDeclaration(): DeclarationDescriptor = correspondingInterface
|
||||||
|
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = 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<out TypeProjection>): MemberScope =
|
||||||
|
MemberScope.Empty // TODO do we need a more useful MemberScope here?
|
||||||
|
|
||||||
|
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitClassDescriptor(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>) {
|
||||||
|
visitor.visitClassDescriptor(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String =
|
||||||
|
"IrFileClassDescriptor($fqNameUnsafe)"
|
||||||
|
}
|
||||||
+2
-2
@@ -17,7 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
|
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.backend.jvm.codegen.getMemberOwnerKind
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -127,7 +127,7 @@ class InitializersLowering : ClassLoweringPass {
|
|||||||
Modality.FINAL, Visibilities.PUBLIC
|
Modality.FINAL, Visibilities.PUBLIC
|
||||||
)
|
)
|
||||||
irClass.declarations.add(
|
irClass.declarations.add(
|
||||||
IrFunctionImpl(irClass.startOffset, irClass.endOffset, JvmDeclarationOrigins.CLASS_STATIC_INITIALIZER,
|
IrFunctionImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER,
|
||||||
staticInitializerDescriptor,
|
staticInitializerDescriptor,
|
||||||
IrBlockBodyImpl(irClass.startOffset, irClass.endOffset,
|
IrBlockBodyImpl(irClass.startOffset, irClass.endOffset,
|
||||||
staticInitializerStatements.map { it.copy() }))
|
staticInitializerStatements.map { it.copy() }))
|
||||||
|
|||||||
+90
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+111
@@ -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<IrFunction>().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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user