[IR] For loop lowering for CharacterSequence.indices.

This commit is contained in:
Mads Ager
2019-08-30 11:12:36 +02:00
committed by max-kammerer
parent 63f43d9b2e
commit 85b1e0165b
4 changed files with 53 additions and 17 deletions
@@ -212,7 +212,8 @@ internal class HeaderInfoBuilder(context: CommonBackendContext, private val scop
)
private val progressionHandlers = listOf(
IndicesHandler(context),
ArrayIndicesHandler(context),
CharSequenceIndicesHandler(context),
UntilHandler(context, progressionElementTypes),
DownToHandler(context, progressionElementTypes),
RangeToHandler(context, progressionElementTypes)
@@ -219,22 +219,17 @@ internal class UntilHandler(private val context: CommonBackendContext, private v
}
/** Builds a [HeaderInfo] for progressions built using the `indices` extension property. */
internal class IndicesHandler(private val context: CommonBackendContext) : ProgressionHandler {
internal abstract class IndicesHandler(private val context: CommonBackendContext) : ProgressionHandler {
override val matcher = SimpleCalleeMatcher {
// TODO: Handle Collection<*>.indices
// TODO: Handle CharSequence.indices
extensionReceiver { it != null && it.type.run { isArray() || isPrimitiveArray() } }
fqName { it == FqName("kotlin.collections.<get-indices>") }
parameterCount { it == 0 }
}
// TODO: Handle Collection<*>.indices
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// `last = array.size - 1` (last is inclusive) for the loop `for (i in array.indices)`.
val arraySizeProperty = expression.extensionReceiver!!.type.getClass()!!.properties.first { it.name.asString() == "size" }
val last = irCall(arraySizeProperty.getter!!).apply {
dispatchReceiver = expression.extensionReceiver
val receiver = expression.extensionReceiver!!
val sizeProperty = receiver.type.getClass()!!.properties.first { it.name.asString() == sizePropertyName() }
val last = irCall(sizeProperty.getter!!).apply {
dispatchReceiver = receiver
}.decrement()
ProgressionHeaderInfo(
@@ -246,6 +241,29 @@ internal class IndicesHandler(private val context: CommonBackendContext) : Progr
direction = ProgressionDirection.INCREASING
)
}
internal abstract fun sizePropertyName() : String
}
internal class ArrayIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) {
override val matcher = SimpleCalleeMatcher {
extensionReceiver { it != null && it.type.run { isArray() || isPrimitiveArray() } }
fqName { it == FqName("kotlin.collections.<get-indices>") }
parameterCount { it == 0 }
}
override fun sizePropertyName(): String = "size"
}
internal class CharSequenceIndicesHandler(context: CommonBackendContext) : IndicesHandler(context) {
override val matcher = SimpleCalleeMatcher {
extensionReceiver { it != null && it.type.run { isSubtypeOfClass(context.ir.symbols.charSequence)} }
fqName { it == FqName("kotlin.text.<get-indices>") }
parameterCount { it == 0 }
}
override fun sizePropertyName(): String = "length"
}
/** Builds a [HeaderInfo] for calls to reverse an iterable. */
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
fun test(s: CharSequence): Int {
var result = 0
for (i in s.indices) {
@@ -7,12 +6,22 @@ fun test(s: CharSequence): Int {
return result
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// JVM_TEMPLATES
// 0 IF_ICMPGT
// 0 IF_ICMPEQ
// 1 IF_ICMPGE
// 1 IF
// JVM_IR_TEMPLATES
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// NOTE: Enable once CharSequence.indices is handled
import kotlin.test.*
fun box(): String {
@@ -13,6 +11,9 @@ fun box(): String {
return "OK"
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 reversed
// 0 iterator
// 0 getStart
@@ -20,5 +21,12 @@ fun box(): String {
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF(_ICMPG|L)T
// 1 IF
// JVM_TEMPLATES
// 1 IFLT
// 1 IF
// JVM_IR_TEMPLATES
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF