Support default function lowering

This commit is contained in:
Mikhael Bogdanov
2017-06-08 14:09:12 +02:00
parent 83710a8ed6
commit 1f053be289
3 changed files with 105 additions and 40 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.lower.LateinitLowering
import org.jetbrains.kotlin.backend.common.lower.LocalFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.SharedVariablesLowering
import org.jetbrains.kotlin.backend.common.lower.TailrecLowering
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.backend.jvm.lower.*
import org.jetbrains.kotlin.ir.declarations.IrFile
@@ -33,6 +34,11 @@ class JvmLower(val context: JvmBackendContext) {
LateinitLowering(context).lower(irFile)
ConstAndJvmFieldPropertiesLowering().lower(irFile)
PropertiesLowering().lower(irFile)
//Should be before interface lowering
DefaultArgumentStubGenerator(context).runOnFilePostfix(irFile)
StaticDefaultFunctionLowering(context.state).runOnFilePostfix(irFile)
InterfaceLowering(context.state).runOnFilePostfix(irFile)
InterfaceDelegationLowering(context.state).runOnFilePostfix(irFile)
SharedVariablesLowering(context).runOnFilePostfix(irFile)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptorImpl
import org.jetbrains.kotlin.backend.jvm.lower.InitializersLowering.Companion.clinitName
@@ -36,12 +37,11 @@ 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
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Opcodes
class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass {
override fun lower(irClass: IrClass) {
if (!DescriptorUtils.isInterface(irClass.descriptor)) {
return
@@ -58,18 +58,8 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
val descriptor = it.descriptor
if (descriptor.modality != Modality.ABSTRACT) {
val functionDescriptorImpl = createDefaultImplFunDescriptor(defaultImplsDescriptor, descriptor, interfaceDescriptor, state.typeMapper)
val newFunction = IrFunctionImpl(it.startOffset, it.endOffset, it.origin, functionDescriptorImpl, it.body)
members.add(newFunction)
members.add(functionDescriptorImpl.createFunctionAndMapVariables(it))
it.body = null
val mapping: Map<ValueDescriptor, ValueDescriptor> =
(
listOf(it.descriptor.dispatchReceiverParameter!!, it.descriptor.extensionReceiverParameter).filterNotNull() +
it.descriptor.valueParameters
).zip(functionDescriptorImpl.valueParameters).toMap()
newFunction.body?.transform(VariableRemapper(mapping), null)
}
}
@@ -84,7 +74,12 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
}
else null
}
val defaultBodies = irClass.declarations.filterIsInstance<IrFunction>().filter {
it.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
}
irClass.declarations.removeAll(privateToRemove)
irClass.declarations.removeAll(defaultBodies)
}
companion object {
@@ -100,33 +95,49 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
descriptor: FunctionDescriptor,
interfaceDescriptor: ClassDescriptor, typeMapper: KotlinTypeMapper
): SimpleFunctionDescriptorImpl {
val newFunction = SimpleFunctionDescriptorImpl.create(
defaultImplsDescriptor, AnnotationsImpl(emptyList()),
Name.identifier(typeMapper.mapAsmMethod(descriptor).name),
CallableMemberDescriptor.Kind.DECLARATION, descriptor.source
)
val dispatchReceiver =
ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
newFunction, null, 0, AnnotationsImpl(emptyList()), Name.identifier("this"),
interfaceDescriptor.defaultType, false, false, false, null, interfaceDescriptor.source, null)
val oldExtensionReceiver = descriptor.extensionReceiverParameter
val extensionReceiver = if (oldExtensionReceiver != null )
ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
newFunction, null, 1, AnnotationsImpl(emptyList()), Name.identifier("receiver"),
oldExtensionReceiver.value.type, false, false, false, null, oldExtensionReceiver.source, null)
else null
val valueParameters = listOf(dispatchReceiver, extensionReceiver).filterNotNull() +
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
val name = Name.identifier(typeMapper.mapAsmMethod(descriptor).name)
return createStaticFunctionWithReceivers(defaultImplsDescriptor, name, descriptor, interfaceDescriptor.defaultType)
}
}
}
internal fun createStaticFunctionWithReceivers(owner: ClassOrPackageFragmentDescriptor, name: Name, descriptor: FunctionDescriptor, dispatchReceiverType: KotlinType): SimpleFunctionDescriptorImpl {
val newFunction = SimpleFunctionDescriptorImpl.create(
owner,
AnnotationsImpl(emptyList()),
name,
CallableMemberDescriptor.Kind.DECLARATION, descriptor.source
)
val dispatchReceiver =
ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
newFunction, null, 0, AnnotationsImpl(emptyList()), Name.identifier("this"),
dispatchReceiverType, false, false, false, null, descriptor.source, null)
val extensionReceiver =
descriptor.extensionReceiverParameter?.let { extensionReceiver ->
ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
newFunction, null, 1, AnnotationsImpl(emptyList()), Name.identifier("receiver"),
extensionReceiver.value.type, false, false, false, null, extensionReceiver.source, null)
}
val valueParameters = listOf(dispatchReceiver, extensionReceiver).filterNotNull() +
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
}
internal fun FunctionDescriptor.createFunctionAndMapVariables(oldFunction: IrFunction) =
IrFunctionImpl(oldFunction.startOffset, oldFunction.endOffset, oldFunction.origin, this, oldFunction.body).also {
val mapping: Map<ValueDescriptor, ValueDescriptor> =
(
listOf(oldFunction.descriptor.dispatchReceiverParameter!!, oldFunction.descriptor.extensionReceiverParameter).filterNotNull() +
oldFunction.descriptor.valueParameters
).zip(this.valueParameters).toMap()
it.body?.transform(VariableRemapper(mapping), null)
}
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2017 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.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.resolve.DescriptorUtils
class StaticDefaultFunctionLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass {
override fun lower(irClass: IrClass) {
val descriptor = irClass.descriptor
if (DescriptorUtils.isInterface(descriptor) || DescriptorUtils.isAnnotationClass(descriptor)) {
return
}
irClass.accept(this, null)
}
override fun visitFunction(declaration: IrFunction): IrStatement {
if (declaration.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null) {
val newFunction = createStaticFunctionWithReceivers(declaration.descriptor.containingDeclaration as ClassDescriptor, declaration.descriptor.name, declaration.descriptor, declaration.descriptor.dispatchReceiverParameter!!.type)
return newFunction.createFunctionAndMapVariables(declaration)
}
else {
return super.visitFunction(declaration)
}
}
}