Use getPropertyGetter() in ForLoopsLowering to retrieve property

getters instead of directly retrieving the property first.

When the IR backend is used to compile the standard library, the
progression classes (in sources) are lowered, and therefore do not have
properties anymore (only fields and functions).
This commit is contained in:
Mark Punzalan
2019-09-30 12:48:39 -07:00
committed by max-kammerer
parent a19c5f944e
commit a01c53fb74
2 changed files with 33 additions and 34 deletions
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher
import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
@@ -143,11 +142,11 @@ internal class UntilHandler(private val context: CommonBackendContext, private v
val last = untilArgExpression.decrement() val last = untilArgExpression.decrement()
val (minValueAsLong, minValueIrConst) = val (minValueAsLong, minValueIrConst) =
when (data) { when (data) {
ProgressionType.INT_PROGRESSION -> Pair(Int.MIN_VALUE.toLong(), irInt(Int.MIN_VALUE)) ProgressionType.INT_PROGRESSION -> Pair(Int.MIN_VALUE.toLong(), irInt(Int.MIN_VALUE))
ProgressionType.CHAR_PROGRESSION -> Pair(Char.MIN_VALUE.toLong(), irChar(Char.MIN_VALUE)) ProgressionType.CHAR_PROGRESSION -> Pair(Char.MIN_VALUE.toLong(), irChar(Char.MIN_VALUE))
ProgressionType.LONG_PROGRESSION -> Pair(Long.MIN_VALUE, irLong(Long.MIN_VALUE)) ProgressionType.LONG_PROGRESSION -> Pair(Long.MIN_VALUE, irLong(Long.MIN_VALUE))
} }
val additionalNotEmptyCondition = untilArg.constLongValue.let { val additionalNotEmptyCondition = untilArg.constLongValue.let {
when { when {
it == null && isAdditionalNotEmptyConditionNeeded(receiverValue.type, untilArg.type) -> it == null && isAdditionalNotEmptyConditionNeeded(receiverValue.type, untilArg.type) ->
@@ -251,13 +250,13 @@ internal class CollectionIndicesHandler(context: CommonBackendContext) : Indices
} }
override val IrType.sizePropertyGetter override val IrType.sizePropertyGetter
get() = getClass()!!.properties.first { it.name.asString() == "size" }.getter!! get() = getClass()!!.getPropertyGetter("size")!!.owner
} }
internal class CharSequenceIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) { internal class CharSequenceIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) {
override val matcher = SimpleCalleeMatcher { override val matcher = SimpleCalleeMatcher {
extensionReceiver { it != null && it.type.run { isSubtypeOfClass(context.ir.symbols.charSequence)} } extensionReceiver { it != null && it.type.run { isSubtypeOfClass(context.ir.symbols.charSequence) } }
fqName { it == FqName("kotlin.text.<get-indices>") } fqName { it == FqName("kotlin.text.<get-indices>") }
parameterCount { it == 0 } parameterCount { it == 0 }
} }
@@ -266,9 +265,7 @@ internal class CharSequenceIndicesHandler(context: CommonBackendContext) : Indic
// a type parameter bounded by CharSequence. When that is the case, we cannot get // a type parameter bounded by CharSequence. When that is the case, we cannot get
// the class from the type and instead uses the CharSequence getter. // the class from the type and instead uses the CharSequence getter.
override val IrType.sizePropertyGetter override val IrType.sizePropertyGetter
get() = getClass()?.properties?.first { it.name.asString() == "length" }?.let { get() = getClass()?.getPropertyGetter("length")?.owner ?: context.ir.symbols.charSequence.getPropertyGetter("length")!!.owner
it.getter!!
} ?: context.ir.symbols.charSequence.getPropertyGetter("length")!!.owner
} }
/** Builds a [HeaderInfo] for calls to reverse an iterable. */ /** Builds a [HeaderInfo] for calls to reverse an iterable. */
@@ -306,16 +303,13 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
// Directly use the `first/last/step` properties of the progression. // Directly use the `first/last/step` properties of the progression.
val progression = scope.createTemporaryVariable(expression, nameHint = "progression") val progression = scope.createTemporaryVariable(expression, nameHint = "progression")
val progressionClass = progression.type.getClass()!! val progressionClass = progression.type.getClass()!!
val firstProperty = progressionClass.properties.first { it.name.asString() == "first" } val first = irCall(progressionClass.symbol.getPropertyGetter("first")!!).apply {
val first = irCall(firstProperty.getter!!).apply {
dispatchReceiver = irGet(progression) dispatchReceiver = irGet(progression)
} }
val lastProperty = progressionClass.properties.first { it.name.asString() == "last" } val last = irCall(progressionClass.symbol.getPropertyGetter("last")!!).apply {
val last = irCall(lastProperty.getter!!).apply {
dispatchReceiver = irGet(progression) dispatchReceiver = irGet(progression)
} }
val stepProperty = progressionClass.properties.first { it.name.asString() == "step" } val step = irCall(progressionClass.symbol.getPropertyGetter("step")!!).apply {
val step = irCall(stepProperty.getter!!).apply {
dispatchReceiver = irGet(progression) dispatchReceiver = irGet(progression)
} }
@@ -380,7 +374,7 @@ internal class ArrayIterationHandler(context: CommonBackendContext) : IndexedGet
override fun match(expression: IrExpression) = expression.type.run { isArray() || isPrimitiveArray() } override fun match(expression: IrExpression) = expression.type.run { isArray() || isPrimitiveArray() }
override val IrType.sizePropertyGetter override val IrType.sizePropertyGetter
get() = getClass()!!.properties.first { it.name.asString() == "size" }.getter!! get() = getClass()!!.getPropertyGetter("size")!!.owner
override val IrType.getFunction override val IrType.getFunction
get() = getClass()!!.functions.first { it.name.asString() == "get" } get() = getClass()!!.functions.first { it.name.asString() == "get" }
@@ -391,7 +385,7 @@ internal class StringIterationHandler(context: CommonBackendContext) : IndexedGe
override fun match(expression: IrExpression) = expression.type.isString() override fun match(expression: IrExpression) = expression.type.isString()
override val IrType.sizePropertyGetter override val IrType.sizePropertyGetter
get() = getClass()!!.properties.first { it.name.asString() == "length" }.getter!! get() = getClass()!!.getPropertyGetter("length")!!.owner
override val IrType.getFunction override val IrType.getFunction
get() = getClass()!!.functions.first { it.name.asString() == "get" } get() = getClass()!!.functions.first { it.name.asString() == "get" }
@@ -410,9 +404,7 @@ internal class CharSequenceIterationHandler(context: CommonBackendContext) : Ind
// a type parameter bounded by CharSequence. When that is the case, we cannot get // a type parameter bounded by CharSequence. When that is the case, we cannot get
// the class from the type and instead uses the CharSequence getter and function. // the class from the type and instead uses the CharSequence getter and function.
override val IrType.sizePropertyGetter override val IrType.sizePropertyGetter
get() = getClass()?.properties?.first { it.name.asString() == "length" }?.let { get() = getClass()?.getPropertyGetter("length")?.owner ?: context.ir.symbols.charSequence.getPropertyGetter("length")!!.owner
it.getter!!
} ?: context.ir.symbols.charSequence.getPropertyGetter("length")!!.owner
override val IrType.getFunction override val IrType.getFunction
get() = getClass()?.functions?.first { it.name.asString() == "get" } get() = getClass()?.functions?.first { it.name.asString() == "get" }
@@ -17,25 +17,32 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.name.Name
fun IrClassSymbol.getPropertyDeclaration(name: String) = fun IrClass.getPropertyDeclaration(name: String) =
this.owner.declarations.filterIsInstance<IrProperty>() declarations.filterIsInstance<IrProperty>().atMostOne { it.name.asString() == name }
.atMostOne { it.descriptor.name == Name.identifier(name) }
fun IrClassSymbol.getSimpleFunction(name: String): IrSimpleFunctionSymbol? = fun IrClass.getSimpleFunction(name: String): IrSimpleFunctionSymbol? =
owner.findDeclaration<IrSimpleFunction> { it.name.asString() == name }?.symbol findDeclaration<IrSimpleFunction> { it.name.asString() == name }?.symbol
fun IrClassSymbol.getPropertyGetter(name: String): IrSimpleFunctionSymbol? = fun IrClass.getPropertyGetter(name: String): IrSimpleFunctionSymbol? =
this.getPropertyDeclaration(name)?.getter?.symbol ?: this.getSimpleFunction("<get-$name>") getPropertyDeclaration(name)?.getter?.symbol
?: getSimpleFunction("<get-$name>").also { assert(it?.owner?.correspondingPropertySymbol?.owner?.name?.asString() == name) }
fun IrClassSymbol.getPropertySetter(name: String): IrSimpleFunctionSymbol? = fun IrClass.getPropertySetter(name: String): IrSimpleFunctionSymbol? =
this.getPropertyDeclaration(name)?.setter?.symbol ?: this.getSimpleFunction("<set-$name>") getPropertyDeclaration(name)?.setter?.symbol
?: getSimpleFunction("<set-$name>").also { assert(it?.owner?.correspondingPropertySymbol?.owner?.name?.asString() == name) }
fun IrClassSymbol.getPropertyField(name: String): IrFieldSymbol? = fun IrClass.getPropertyField(name: String): IrFieldSymbol? =
this.getPropertyDeclaration(name)?.backingField?.symbol getPropertyDeclaration(name)?.backingField?.symbol
fun IrClassSymbol.getPropertyDeclaration(name: String) = owner.getPropertyDeclaration(name)
fun IrClassSymbol.getSimpleFunction(name: String): IrSimpleFunctionSymbol? = owner.getSimpleFunction(name)
fun IrClassSymbol.getPropertyGetter(name: String): IrSimpleFunctionSymbol? = owner.getPropertyGetter(name)
fun IrClassSymbol.getPropertySetter(name: String): IrSimpleFunctionSymbol? = owner.getPropertySetter(name)
fun IrClassSymbol.getPropertyField(name: String): IrFieldSymbol? = owner.getPropertyField(name)