Inner classes lowering: remap old constructor parameters.

This commit is contained in:
Dmitry Petrov
2016-10-20 10:56:15 +03:00
parent 2986e7b508
commit 4fc135709e
6 changed files with 69 additions and 16 deletions
@@ -46,7 +46,7 @@ class FunctionCodegen(val irFunction: IrFunction, val classCodegen: ClassCodegen
doGenerate()
}
catch (e: Throwable) {
throw RuntimeException("${e.message} + while generating code for:\n${irFunction.dump()}", e)
throw RuntimeException("${e.message} while generating code for:\n${irFunction.dump()}", e)
}
}
@@ -33,6 +33,7 @@ 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
import java.util.*
class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
@@ -42,13 +43,16 @@ class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
private inner class InnerClassTransformer(val irClass: IrClass) {
val classDescriptor = irClass.descriptor
private lateinit var outerThisFieldDescriptor: PropertyDescriptor
lateinit var outerThisFieldDescriptor: PropertyDescriptor
val oldConstructorParameterToNew = HashMap<ValueDescriptor, ValueDescriptor>()
fun lowerInnerClass() {
if (!irClass.descriptor.isInner) return
createOuterThisField()
lowerConstructors()
lowerConstructorParameterUsages()
lowerOuterThisReferences()
}
@@ -79,6 +83,10 @@ class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
val newDescriptor = context.specialDescriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor)
val outerThisValueParameter = newDescriptor.valueParameters[0]
oldDescriptor.valueParameters.forEach { oldValueParameter ->
oldConstructorParameterToNew[oldValueParameter] = newDescriptor.valueParameters[oldValueParameter.index + 1]
}
val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
val instanceInitializerIndex = blockBody.statements.indexOfFirst { it is IrInstanceInitializerCall }
@@ -111,6 +119,10 @@ class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
)
}
private fun lowerConstructorParameterUsages() {
irClass.transformChildrenVoid(VariableRemapper(oldConstructorParameterToNew))
}
private fun lowerOuterThisReferences() {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
@@ -179,7 +191,7 @@ class InnerClassConstructorCallsLowering(val context: JvmBackendContext) : BodyL
newCall.putValueArgument(0, dispatchReceiver)
for (i in 1 .. newCallee.valueParameters.lastIndex) {
newCall.putValueArgument(i, expression.getValueArgument(i))
newCall.putValueArgument(i, expression.getValueArgument(i - 1))
}
return newCall
@@ -200,7 +212,7 @@ class InnerClassConstructorCallsLowering(val context: JvmBackendContext) : BodyL
newCall.putValueArgument(0, dispatchReceiver)
for (i in 1 .. newCallee.valueParameters.lastIndex) {
newCall.putValueArgument(i, expression.getValueArgument(i))
newCall.putValueArgument(i, expression.getValueArgument(i - 1))
}
return newCall
@@ -31,9 +31,6 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
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.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -66,7 +63,7 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
members.add(newFunction)
it.body = null
val mapping: Map<DeclarationDescriptor, ValueParameterDescriptor> =
val mapping: Map<ValueDescriptor, ValueDescriptor> =
(
listOf(it.descriptor.dispatchReceiverParameter!!, it.descriptor.extensionReceiverParameter).filterNotNull() +
it.descriptor.valueParameters
@@ -133,11 +130,3 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
}
}
class VariableRemapper(val mapping: Map<DeclarationDescriptor, VariableDescriptor>): IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression =
mapping[expression.descriptor]?.let { loweredParameter ->
IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter, expression.origin)
} ?: expression
}
@@ -0,0 +1,39 @@
/*
* 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.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
abstract class AbstractVariableRemapper : IrElementTransformerVoid() {
protected abstract fun remapVariable(value: ValueDescriptor): ValueDescriptor?
override fun visitGetValue(expression: IrGetValue): IrExpression =
remapVariable(expression.descriptor)?.let {
IrGetValueImpl(expression.startOffset, expression.endOffset, it, expression.origin)
} ?: expression
}
class VariableRemapper(val mapping: Map<ValueDescriptor, ValueDescriptor>): AbstractVariableRemapper() {
override fun remapVariable(value: ValueDescriptor): ValueDescriptor? =
mapping[value]
}
@@ -0,0 +1,7 @@
class Outer(val x: String) {
inner class Inner(val y: String) {
val z = x + y
}
}
fun box() = Outer("O").Inner("K").z
@@ -115,6 +115,12 @@ public class IrOnlyBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTest
doTest(fileName);
}
@TestMetadata("innerClass2.kt")
public void testInnerClass2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/innerClass2.kt");
doTest(fileName);
}
@TestMetadata("mutable1.kt")
public void testMutable1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/mutable1.kt");