[IR] Refactored GET_FIELD, SET_FIELD for inline classes + test

This commit is contained in:
Igor Chevdar
2020-06-30 15:14:22 +05:00
parent 26defca5c3
commit 5373f1c708
3 changed files with 43 additions and 10 deletions
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.target
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -243,26 +242,32 @@ private class InlineClassTransformer(private val context: Context) : IrBuildingT
return declaration
}
private fun IrField.isInlinedClassField(): Boolean {
val parentClass = this.parent as? IrClass
return parentClass != null && parentClass.isInlined()
}
override fun visitGetField(expression: IrGetField): IrExpression {
super.visitGetField(expression)
return if (expression.symbol.owner.isInlinedClassField()) {
expression.receiver!!
} else {
val field = expression.symbol.owner
val parentClass = field.parentClassOrNull
return if (parentClass == null || !parentClass.isInlined())
expression
else {
builder.at(expression)
.irCall(symbols.reinterpret, field.type,
listOf(parentClass.defaultType, field.type)
).apply {
extensionReceiver = expression.receiver!!
}
}
}
override fun visitSetField(expression: IrSetField): IrExpression {
super.visitSetField(expression)
return if (expression.symbol.owner.isInlinedClassField()) {
return if (expression.symbol.owner.parentClassOrNull?.isInlined() == true) {
// TODO: it is better to get rid of functions setting such fields.
// Here we're trying to maintain all IR nodes as is, albeit the transformed IR isn't equivalent to the original.
// By far SET_FIELD can only be in the constructor which won't be codegened.
// Box functions use createUninitializedInstance instead of constructor calls
// and are placed separately so they won't be processed here.
val startOffset = expression.startOffset
val endOffset = expression.endOffset
IrBlockImpl(startOffset, endOffset, irBuiltIns.unitType).apply {
+4
View File
@@ -3110,6 +3110,10 @@ task inlineClass_customEquals(type: KonanLocalTest) {
source = "codegen/inlineClass/customEquals.kt"
}
task inlineClass_defaultEquals(type: KonanLocalTest) {
source = "codegen/inlineClass/defaultEquals.kt"
}
task deserialized_inline0(type: KonanLocalTest) {
source = "serialization/deserialized_inline0.kt"
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package codegen.inlineClass.defaultEquals
import kotlin.test.*
inline class A(val x: Int)
inline class B(val a: A)
inline class C(val s: String)
inline class D(val c: C)
@Test fun runTest() {
val a = A(42)
val b = B(a)
val c = C("zzz")
val d = D(c)
assertTrue(a.equals(a))
assertTrue(b.equals(b))
assertTrue(c.equals(c))
assertTrue(d.equals(d))
}