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()
|
||||
}
|
||||
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.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
|
||||
|
||||
+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.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
|
||||
}
|
||||
+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);
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
Reference in New Issue
Block a user