Inner classes lowering: remap old constructor parameters.
This commit is contained in:
+1
-1
@@ -46,7 +46,7 @@ class FunctionCodegen(val irFunction: IrFunction, val classCodegen: ClassCodegen
|
|||||||
doGenerate()
|
doGenerate()
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-3
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
@@ -42,13 +43,16 @@ class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
private inner class InnerClassTransformer(val irClass: IrClass) {
|
private inner class InnerClassTransformer(val irClass: IrClass) {
|
||||||
val classDescriptor = irClass.descriptor
|
val classDescriptor = irClass.descriptor
|
||||||
|
|
||||||
private lateinit var outerThisFieldDescriptor: PropertyDescriptor
|
lateinit var outerThisFieldDescriptor: PropertyDescriptor
|
||||||
|
|
||||||
|
val oldConstructorParameterToNew = HashMap<ValueDescriptor, ValueDescriptor>()
|
||||||
|
|
||||||
fun lowerInnerClass() {
|
fun lowerInnerClass() {
|
||||||
if (!irClass.descriptor.isInner) return
|
if (!irClass.descriptor.isInner) return
|
||||||
|
|
||||||
createOuterThisField()
|
createOuterThisField()
|
||||||
lowerConstructors()
|
lowerConstructors()
|
||||||
|
lowerConstructorParameterUsages()
|
||||||
lowerOuterThisReferences()
|
lowerOuterThisReferences()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +83,10 @@ class InnerClassesLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
val newDescriptor = context.specialDescriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor)
|
val newDescriptor = context.specialDescriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor)
|
||||||
val outerThisValueParameter = newDescriptor.valueParameters[0]
|
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 blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
|
||||||
|
|
||||||
val instanceInitializerIndex = blockBody.statements.indexOfFirst { it is IrInstanceInitializerCall }
|
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() {
|
private fun lowerOuterThisReferences() {
|
||||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
@@ -179,7 +191,7 @@ class InnerClassConstructorCallsLowering(val context: JvmBackendContext) : BodyL
|
|||||||
|
|
||||||
newCall.putValueArgument(0, dispatchReceiver)
|
newCall.putValueArgument(0, dispatchReceiver)
|
||||||
for (i in 1 .. newCallee.valueParameters.lastIndex) {
|
for (i in 1 .. newCallee.valueParameters.lastIndex) {
|
||||||
newCall.putValueArgument(i, expression.getValueArgument(i))
|
newCall.putValueArgument(i, expression.getValueArgument(i - 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
return newCall
|
return newCall
|
||||||
@@ -200,7 +212,7 @@ class InnerClassConstructorCallsLowering(val context: JvmBackendContext) : BodyL
|
|||||||
|
|
||||||
newCall.putValueArgument(0, dispatchReceiver)
|
newCall.putValueArgument(0, dispatchReceiver)
|
||||||
for (i in 1 .. newCallee.valueParameters.lastIndex) {
|
for (i in 1 .. newCallee.valueParameters.lastIndex) {
|
||||||
newCall.putValueArgument(i, expression.getValueArgument(i))
|
newCall.putValueArgument(i, expression.getValueArgument(i - 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
return newCall
|
return newCall
|
||||||
|
|||||||
+1
-12
@@ -31,9 +31,6 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
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.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
@@ -66,7 +63,7 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid()
|
|||||||
members.add(newFunction)
|
members.add(newFunction)
|
||||||
it.body = null
|
it.body = null
|
||||||
|
|
||||||
val mapping: Map<DeclarationDescriptor, ValueParameterDescriptor> =
|
val mapping: Map<ValueDescriptor, ValueDescriptor> =
|
||||||
(
|
(
|
||||||
listOf(it.descriptor.dispatchReceiverParameter!!, it.descriptor.extensionReceiverParameter).filterNotNull() +
|
listOf(it.descriptor.dispatchReceiverParameter!!, it.descriptor.extensionReceiverParameter).filterNotNull() +
|
||||||
it.descriptor.valueParameters
|
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
|
|
||||||
}
|
|
||||||
+39
@@ -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);
|
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")
|
@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");
|
||||||
|
|||||||
Reference in New Issue
Block a user