IR: simplify for-loop lowering internals a bit

Remove ExpressionHandler, HeaderInfoFromCallHandler, ProgressionHandler.
This commit is contained in:
Alexander Udalov
2022-12-09 15:53:59 +01:00
parent 812e257d54
commit 18950b448c
13 changed files with 74 additions and 87 deletions
@@ -411,15 +411,16 @@ internal open class RangeHeaderInfoBuilder(context: CommonBackendContext, scopeO
} }
/** Builds a [HeaderInfo] for closed floating-point ranges built using the `rangeTo` function. */ /** Builds a [HeaderInfo] for closed floating-point ranges built using the `rangeTo` function. */
internal object FloatingPointRangeToHandler : HeaderInfoFromCallHandler<Nothing?> { internal object FloatingPointRangeToHandler : HeaderInfoHandler<IrCall, Nothing?> {
private val matcher = SimpleCalleeMatcher {
override val matcher = SimpleCalleeMatcher {
fqName { it == FqName("kotlin.ranges.${OperatorNameConventions.RANGE_TO}") } fqName { it == FqName("kotlin.ranges.${OperatorNameConventions.RANGE_TO}") }
extensionReceiver { it != null && it.type.run { isFloat() || isDouble() } } extensionReceiver { it != null && it.type.run { isFloat() || isDouble() } }
parameterCount { it == 1 } parameterCount { it == 1 }
parameter(0) { it.type.run { isFloat() || isDouble() } } parameter(0) { it.type.run { isFloat() || isDouble() } }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol) = override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol) =
FloatingPointRangeHeaderInfo( FloatingPointRangeHeaderInfo(
start = expression.extensionReceiver!!, start = expression.extensionReceiver!!,
@@ -428,14 +429,15 @@ internal object FloatingPointRangeToHandler : HeaderInfoFromCallHandler<Nothing?
} }
/** Builds a [HeaderInfo] for ranges of Comparables built using the `rangeTo` extension function. */ /** Builds a [HeaderInfo] for ranges of Comparables built using the `rangeTo` extension function. */
internal class ComparableRangeToHandler(context: CommonBackendContext) : HeaderInfoFromCallHandler<Nothing?> { internal class ComparableRangeToHandler(context: CommonBackendContext) : HeaderInfoHandler<IrCall, Nothing?> {
private val matcher = SimpleCalleeMatcher {
override val matcher = SimpleCalleeMatcher {
fqName { it == FqName("kotlin.ranges.${OperatorNameConventions.RANGE_TO}") } fqName { it == FqName("kotlin.ranges.${OperatorNameConventions.RANGE_TO}") }
extensionReceiver { it != null && it.type.isSubtypeOfClass(context.ir.symbols.comparable) } extensionReceiver { it != null && it.type.isSubtypeOfClass(context.ir.symbols.comparable) }
parameterCount { it == 1 } parameterCount { it == 1 }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol) = override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol) =
ComparableRangeInfo( ComparableRangeInfo(
start = expression.extensionReceiver!!, start = expression.extensionReceiver!!,
@@ -3,8 +3,6 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:OptIn(ExperimentalUnsignedTypes::class)
package org.jetbrains.kotlin.backend.common.lower.loops package org.jetbrains.kotlin.backend.common.lower.loops
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
@@ -258,27 +256,11 @@ internal interface HeaderInfoHandler<E : IrExpression, D> {
} }
} }
internal interface ExpressionHandler : HeaderInfoHandler<IrExpression, Nothing?> {
fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo?
override fun build(expression: IrExpression, data: Nothing?, scopeOwner: IrSymbol) = build(expression, scopeOwner)
}
/** Matches a call to build an iterable and builds a [HeaderInfo] from the call's context. */
internal interface HeaderInfoFromCallHandler<D> : HeaderInfoHandler<IrCall, D> {
val matcher: IrCallMatcher
override fun matchIterable(expression: IrCall) = matcher(expression)
}
internal typealias ProgressionHandler = HeaderInfoFromCallHandler<ProgressionType>
internal abstract class HeaderInfoBuilder( internal abstract class HeaderInfoBuilder(
context: CommonBackendContext, context: CommonBackendContext,
private val scopeOwnerSymbol: () -> IrSymbol, private val scopeOwnerSymbol: () -> IrSymbol,
private val allowUnsignedBounds: Boolean = false private val allowUnsignedBounds: Boolean = false
) : ) : IrElementVisitor<HeaderInfo?, IrCall?> {
IrElementVisitor<HeaderInfo?, IrCall?> {
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
protected open val progressionHandlers = listOf( protected open val progressionHandlers = listOf(
@@ -291,8 +273,8 @@ internal abstract class HeaderInfoBuilder(
StepHandler(context, this) StepHandler(context, this)
) )
protected abstract val callHandlers: List<HeaderInfoFromCallHandler<Nothing?>> protected abstract val callHandlers: List<HeaderInfoHandler<IrCall, Nothing?>>
protected abstract val expressionHandlers: List<ExpressionHandler> protected abstract val expressionHandlers: List<HeaderInfoHandler<IrExpression, Nothing?>>
override fun visitElement(element: IrElement, data: IrCall?): HeaderInfo? = null override fun visitElement(element: IrElement, data: IrCall?): HeaderInfo? = null
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.backend.common.lower.loops.handlers
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.loops.ExpressionHandler
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoHandler
import org.jetbrains.kotlin.backend.common.lower.loops.IterableHeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.IterableHeaderInfo
import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.createTmpVariable
import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.irCall
@@ -19,13 +19,12 @@ import org.jetbrains.kotlin.ir.util.getSimpleFunction
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
/** Builds a [HeaderInfo] for Iterables not handled by more specialized handlers. */ /** Builds a [HeaderInfo] for Iterables not handled by more specialized handlers. */
internal class DefaultIterableHandler(private val context: CommonBackendContext) : ExpressionHandler { internal class DefaultIterableHandler(private val context: CommonBackendContext) : HeaderInfoHandler<IrExpression, Nothing?> {
private val iterableClassSymbol = context.ir.symbols.iterable private val iterableClassSymbol = context.ir.symbols.iterable
override fun matchIterable(expression: IrExpression) = expression.type.isSubtypeOfClass(iterableClassSymbol) override fun matchIterable(expression: IrExpression) = expression.type.isSubtypeOfClass(iterableClassSymbol)
override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrExpression, data: Nothing?, scopeOwner: IrSymbol): HeaderInfo =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
val iteratorFun = val iteratorFun =
iterableClassSymbol.getSimpleFunction(OperatorNameConventions.ITERATOR.asString())!!.owner iterableClassSymbol.getSimpleFunction(OperatorNameConventions.ITERATOR.asString())!!.owner
@@ -33,4 +32,4 @@ internal class DefaultIterableHandler(private val context: CommonBackendContext)
scope.createTmpVariable(irCall(iteratorFun).apply { dispatchReceiver = expression }, nameHint = "iterator") scope.createTmpVariable(irCall(iteratorFun).apply { dispatchReceiver = expression }, nameHint = "iterator")
) )
} }
} }
@@ -18,9 +18,9 @@ import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.ir.util.shallowCopy import org.jetbrains.kotlin.ir.util.shallowCopy
/** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */ /** Builds a [HeaderInfo] for progressions not handled by more specialized handlers. */
internal class DefaultProgressionHandler(private val context: CommonBackendContext, private val allowUnsignedBounds: Boolean = false) : internal class DefaultProgressionHandler(
ExpressionHandler { private val context: CommonBackendContext, private val allowUnsignedBounds: Boolean = false
) : HeaderInfoHandler<IrExpression, Nothing?> {
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
private val rangeClassesTypes = symbols.rangeClasses.map { it.defaultType }.toSet() private val rangeClassesTypes = symbols.rangeClasses.map { it.defaultType }.toSet()
@@ -30,7 +30,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
allowUnsignedBounds allowUnsignedBounds
) != null ) != null
override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrExpression, data: Nothing?, scopeOwner: IrSymbol): HeaderInfo =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// Directly use the `first/last/step` properties of the progression. // Directly use the `first/last/step` properties of the progression.
val (progressionVar, progressionExpression) = createTemporaryVariableIfNecessary(expression, nameHint = "progression") val (progressionVar, progressionExpression) = createTemporaryVariableIfNecessary(expression, nameHint = "progression")
@@ -62,4 +62,4 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
direction = direction direction = direction
) )
} }
} }
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.backend.common.lower.loops.handlers
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.loops.ExpressionHandler
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoHandler
import org.jetbrains.kotlin.backend.common.lower.loops.IterableHeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.IterableHeaderInfo
import org.jetbrains.kotlin.ir.builders.createTmpVariable import org.jetbrains.kotlin.ir.builders.createTmpVariable
import org.jetbrains.kotlin.ir.builders.irCall import org.jetbrains.kotlin.ir.builders.irCall
@@ -19,14 +19,13 @@ import org.jetbrains.kotlin.ir.util.getSimpleFunction
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
/** Builds a [HeaderInfo] for Sequences not handled by more specialized handlers. */ /** Builds a [HeaderInfo] for Sequences not handled by more specialized handlers. */
internal class DefaultSequenceHandler(private val context: CommonBackendContext) : ExpressionHandler { internal class DefaultSequenceHandler(private val context: CommonBackendContext) : HeaderInfoHandler<IrExpression, Nothing?> {
private val sequenceClassSymbol = context.ir.symbols.sequence private val sequenceClassSymbol = context.ir.symbols.sequence
override fun matchIterable(expression: IrExpression) = override fun matchIterable(expression: IrExpression) =
sequenceClassSymbol != null && expression.type.isSubtypeOfClass(sequenceClassSymbol) sequenceClassSymbol != null && expression.type.isSubtypeOfClass(sequenceClassSymbol)
override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrExpression, data: Nothing?, scopeOwner: IrSymbol): HeaderInfo =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
val iteratorFun = val iteratorFun =
sequenceClassSymbol!!.getSimpleFunction(OperatorNameConventions.ITERATOR.asString())!!.owner sequenceClassSymbol!!.getSimpleFunction(OperatorNameConventions.ITERATOR.asString())!!.owner
@@ -34,4 +33,4 @@ internal class DefaultSequenceHandler(private val context: CommonBackendContext)
scope.createTmpVariable(irCall(iteratorFun).apply { dispatchReceiver = expression }, nameHint = "iterator") scope.createTmpVariable(irCall(iteratorFun).apply { dispatchReceiver = expression }, nameHint = "iterator")
) )
} }
} }
@@ -20,19 +20,19 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
/** Builds a [HeaderInfo] for progressions built using the `downTo` extension function. */ /** Builds a [HeaderInfo] for progressions built using the `downTo` extension function. */
internal class DownToHandler(private val context: CommonBackendContext) : internal class DownToHandler(private val context: CommonBackendContext) : HeaderInfoHandler<IrCall, ProgressionType> {
ProgressionHandler {
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
private val progressionElementTypes = context.ir.symbols.progressionElementTypes private val progressionElementTypes = context.ir.symbols.progressionElementTypes
override val matcher = SimpleCalleeMatcher { private val matcher = SimpleCalleeMatcher {
singleArgumentExtension(FqName("kotlin.ranges.downTo"), progressionElementTypes) singleArgumentExtension(FqName("kotlin.ranges.downTo"), progressionElementTypes)
parameterCount { it == 1 } parameterCount { it == 1 }
parameter(0) { it.type in progressionElementTypes } parameter(0) { it.type in progressionElementTypes }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
val first = expression.extensionReceiver!! val first = expression.extensionReceiver!!
@@ -108,4 +108,4 @@ internal class DownToHandler(private val context: CommonBackendContext) :
null null
} }
} }
} }
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.backend.common.lower.loops.handlers
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.loops.ExpressionHandler
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoHandler
import org.jetbrains.kotlin.backend.common.lower.loops.IndexedGetHeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.IndexedGetHeaderInfo
import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
@@ -31,8 +31,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
abstract class IndexedGetIterationHandler( abstract class IndexedGetIterationHandler(
protected val context: CommonBackendContext, protected val context: CommonBackendContext,
private val canCacheLast: Boolean private val canCacheLast: Boolean
) : ExpressionHandler { ) : HeaderInfoHandler<IrExpression, Nothing?> {
override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrExpression, data: Nothing?, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// Consider the case like: // Consider the case like:
// //
@@ -156,4 +156,4 @@ internal class StringIterationHandler(context: CommonBackendContext) : CharSeque
override val IrType.getFunction: IrSimpleFunction override val IrType.getFunction: IrSimpleFunction
get() = context.ir.symbols.string.getSimpleFunction(OperatorNameConventions.GET.asString())!!.owner get() = context.ir.symbols.string.getSimpleFunction(OperatorNameConventions.GET.asString())!!.owner
} }
@@ -22,9 +22,7 @@ import org.jetbrains.kotlin.ir.util.isUnsignedArray
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
/** Builds a [HeaderInfo] for progressions built using the `indices` extension property. */ /** Builds a [HeaderInfo] for progressions built using the `indices` extension property. */
internal abstract class IndicesHandler(protected val context: CommonBackendContext) : internal abstract class IndicesHandler(protected val context: CommonBackendContext) : HeaderInfoHandler<IrCall, ProgressionType> {
ProgressionHandler {
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
@@ -64,13 +62,14 @@ internal abstract class IndicesHandler(protected val context: CommonBackendConte
} }
internal class CollectionIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) { internal class CollectionIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) {
private val matcher = SimpleCalleeMatcher {
override val matcher = SimpleCalleeMatcher {
extensionReceiver { it?.type?.isCollection() == true } extensionReceiver { it?.type?.isCollection() == true }
fqName { it == FqName("kotlin.collections.<get-indices>") } fqName { it == FqName("kotlin.collections.<get-indices>") }
parameterCount { it == 0 } parameterCount { it == 0 }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override val IrType.sizePropertyGetter: IrSimpleFunction override val IrType.sizePropertyGetter: IrSimpleFunction
get() = context.ir.symbols.collection.getPropertyGetter("size")!!.owner get() = context.ir.symbols.collection.getPropertyGetter("size")!!.owner
} }
@@ -78,7 +77,7 @@ internal class CollectionIndicesHandler(context: CommonBackendContext) : Indices
internal class ArrayIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) { internal class ArrayIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) {
private val supportsUnsignedArrays = context.optimizeLoopsOverUnsignedArrays private val supportsUnsignedArrays = context.optimizeLoopsOverUnsignedArrays
override val matcher = SimpleCalleeMatcher { private val matcher = SimpleCalleeMatcher {
extensionReceiver { extensionReceiver {
it != null && it.type.run { it != null && it.type.run {
isArray() || isPrimitiveArray() || (supportsUnsignedArrays && isUnsignedArray()) isArray() || isPrimitiveArray() || (supportsUnsignedArrays && isUnsignedArray())
@@ -88,18 +87,21 @@ internal class ArrayIndicesHandler(context: CommonBackendContext) : IndicesHandl
parameterCount { it == 0 } parameterCount { it == 0 }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override val IrType.sizePropertyGetter: IrSimpleFunction override val IrType.sizePropertyGetter: IrSimpleFunction
get() = getClass()!!.getPropertyGetter("size")!!.owner get() = getClass()!!.getPropertyGetter("size")!!.owner
} }
internal class CharSequenceIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) { internal class CharSequenceIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) {
private val matcher = SimpleCalleeMatcher {
override val matcher = SimpleCalleeMatcher {
extensionReceiver { it != null && it.type.run { isCharSequence() } } extensionReceiver { it != null && it.type.run { isCharSequence() } }
fqName { it == FqName("kotlin.text.<get-indices>") } fqName { it == FqName("kotlin.text.<get-indices>") }
parameterCount { it == 0 } parameterCount { it == 0 }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override val IrType.sizePropertyGetter: IrSimpleFunction override val IrType.sizePropertyGetter: IrSimpleFunction
get() = context.ir.symbols.charSequence.getPropertyGetter("length")!!.owner get() = context.ir.symbols.charSequence.getPropertyGetter("length")!!.owner
} }
@@ -17,20 +17,20 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
/** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */ /** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */
internal class RangeToHandler(private val context: CommonBackendContext) : internal class RangeToHandler(private val context: CommonBackendContext) : HeaderInfoHandler<IrCall, ProgressionType> {
ProgressionHandler {
private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop
private val progressionElementTypes = context.ir.symbols.progressionElementTypes private val progressionElementTypes = context.ir.symbols.progressionElementTypes
override val matcher = SimpleCalleeMatcher { private val matcher = SimpleCalleeMatcher {
dispatchReceiver { it != null && it.type in progressionElementTypes } dispatchReceiver { it != null && it.type in progressionElementTypes }
fqName { it.pathSegments().last() == OperatorNameConventions.RANGE_TO } fqName { it.pathSegments().last() == OperatorNameConventions.RANGE_TO }
parameterCount { it == 1 } parameterCount { it == 1 }
parameter(0) { it.type in progressionElementTypes } parameter(0) { it.type in progressionElementTypes }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
val first = expression.dispatchReceiver!! val first = expression.dispatchReceiver!!
@@ -145,4 +145,4 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
null null
} }
} }
} }
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.common.lower.loops.handlers
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoBuilder import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoBuilder
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoFromCallHandler import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoHandler
import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier
import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
@@ -17,12 +17,11 @@ import org.jetbrains.kotlin.name.FqName
/** Builds a [HeaderInfo] for calls to reverse an iterable. */ /** Builds a [HeaderInfo] for calls to reverse an iterable. */
internal class ReversedHandler(context: CommonBackendContext, private val visitor: HeaderInfoBuilder) : internal class ReversedHandler(context: CommonBackendContext, private val visitor: HeaderInfoBuilder) :
HeaderInfoFromCallHandler<Nothing?> { HeaderInfoHandler<IrCall, Nothing?> {
private val progressionClassesTypes = context.ir.symbols.progressionClasses.map { it.defaultType }.toSet() private val progressionClassesTypes = context.ir.symbols.progressionClasses.map { it.defaultType }.toSet()
// Use Quantifier.ANY so we can handle all reversed iterables in the same manner. // Use Quantifier.ANY so we can handle all reversed iterables in the same manner.
override val matcher = private val matcher =
createIrCallMatcher(Quantifier.ANY) { createIrCallMatcher(Quantifier.ANY) {
// Matcher for reversed progression. // Matcher for reversed progression.
callee { callee {
@@ -34,7 +33,9 @@ internal class ReversedHandler(context: CommonBackendContext, private val visito
// TODO: Handle reversed String, Progression.withIndex(), etc. // TODO: Handle reversed String, Progression.withIndex(), etc.
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
// Reverse the HeaderInfo from the underlying progression or array (if any). // Reverse the HeaderInfo from the underlying progression or array (if any).
override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol) = override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol) =
expression.extensionReceiver!!.accept(visitor, null)?.asReversed() expression.extensionReceiver!!.accept(visitor, null)?.asReversed()
} }
@@ -28,19 +28,19 @@ import kotlin.math.absoluteValue
/** Builds a [HeaderInfo] for progressions built using the `step` extension function. */ /** Builds a [HeaderInfo] for progressions built using the `step` extension function. */
internal class StepHandler( internal class StepHandler(
private val context: CommonBackendContext, private val context: CommonBackendContext, private val visitor: HeaderInfoBuilder
private val visitor: HeaderInfoBuilder ) : HeaderInfoHandler<IrCall, ProgressionType> {
) : ProgressionHandler {
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
override val matcher = SimpleCalleeMatcher { private val matcher = SimpleCalleeMatcher {
singleArgumentExtension( singleArgumentExtension(
FqName("kotlin.ranges.step"), FqName("kotlin.ranges.step"),
symbols.progressionClasses.map { it.defaultType }) symbols.progressionClasses.map { it.defaultType })
parameter(0) { it.type.isInt() || it.type.isLong() } parameter(0) { it.type.isInt() || it.type.isLong() }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// Retrieve the HeaderInfo from the underlying progression (if any). // Retrieve the HeaderInfo from the underlying progression (if any).
@@ -321,4 +321,4 @@ internal class StepHandler(
} }
} }
} }
} }
@@ -16,18 +16,18 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
/** Builds a [HeaderInfo] for progressions built using the `until` extension function. */ /** Builds a [HeaderInfo] for progressions built using the `until` extension function. */
internal class UntilHandler(private val context: CommonBackendContext) : internal class UntilHandler(private val context: CommonBackendContext) : HeaderInfoHandler<IrCall, ProgressionType> {
ProgressionHandler {
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
private val progressionElementTypes = symbols.progressionElementTypes private val progressionElementTypes = symbols.progressionElementTypes
override val matcher = SimpleCalleeMatcher { private val matcher = SimpleCalleeMatcher {
singleArgumentExtension(FqName("kotlin.ranges.until"), progressionElementTypes) singleArgumentExtension(FqName("kotlin.ranges.until"), progressionElementTypes)
parameterCount { it == 1 } parameterCount { it == 1 }
parameter(0) { it.type in progressionElementTypes } parameter(0) { it.type in progressionElementTypes }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
ProgressionHeaderInfo( ProgressionHeaderInfo(
@@ -40,4 +40,4 @@ internal class UntilHandler(private val context: CommonBackendContext) :
direction = ProgressionDirection.INCREASING direction = ProgressionDirection.INCREASING
) )
} }
} }
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.common.lower.loops.handlers
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfo
import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoFromCallHandler import org.jetbrains.kotlin.backend.common.lower.loops.HeaderInfoHandler
import org.jetbrains.kotlin.backend.common.lower.loops.NestedHeaderInfoBuilderForWithIndex import org.jetbrains.kotlin.backend.common.lower.loops.NestedHeaderInfoBuilderForWithIndex
import org.jetbrains.kotlin.backend.common.lower.loops.WithIndexHeaderInfo import org.jetbrains.kotlin.backend.common.lower.loops.WithIndexHeaderInfo
import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier
@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.ir.util.isUnsignedArray
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
/** Builds a [HeaderInfo] for calls to `withIndex()`. */ /** Builds a [HeaderInfo] for calls to `withIndex()`. */
internal class WithIndexHandler(context: CommonBackendContext, private val visitor: NestedHeaderInfoBuilderForWithIndex) : internal class WithIndexHandler(
HeaderInfoFromCallHandler<Nothing?> { context: CommonBackendContext, private val visitor: NestedHeaderInfoBuilderForWithIndex
) : HeaderInfoHandler<IrCall, Nothing?> {
private val supportsUnsignedArrays = context.optimizeLoopsOverUnsignedArrays private val supportsUnsignedArrays = context.optimizeLoopsOverUnsignedArrays
// Use Quantifier.ANY so we can handle all `withIndex()` calls in the same manner. // Use Quantifier.ANY so we can handle all `withIndex()` calls in the same manner.
override val matcher = private val matcher =
createIrCallMatcher(Quantifier.ANY) { createIrCallMatcher(Quantifier.ANY) {
callee { callee {
fqName { it == FqName("kotlin.collections.withIndex") } fqName { it == FqName("kotlin.collections.withIndex") }
@@ -53,6 +53,8 @@ internal class WithIndexHandler(context: CommonBackendContext, private val visit
} }
} }
override fun matchIterable(expression: IrCall): Boolean = matcher(expression)
override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol): HeaderInfo? { override fun build(expression: IrCall, data: Nothing?, scopeOwner: IrSymbol): HeaderInfo? {
// WithIndexHeaderInfo is a composite that contains the HeaderInfo for the underlying iterable (if any). // WithIndexHeaderInfo is a composite that contains the HeaderInfo for the underlying iterable (if any).
val nestedInfo = expression.extensionReceiver!!.accept(visitor, null) ?: return null val nestedInfo = expression.extensionReceiver!!.accept(visitor, null) ?: return null
@@ -63,4 +65,4 @@ internal class WithIndexHandler(context: CommonBackendContext, private val visit
return WithIndexHeaderInfo(nestedInfo) return WithIndexHeaderInfo(nestedInfo)
} }
} }