diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForInProgressionLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForInProgressionLoopGenerator.kt new file mode 100644 index 00000000000..4c63fafee72 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForInProgressionLoopGenerator.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2010-2017 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.codegen.forLoop + +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtForExpression +import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.Type + +abstract class AbstractForInProgressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) + : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) +{ + protected var incrementVar: Int = -1 + protected val asmLoopRangeType: Type + protected val incrementType: Type + + init { + val loopRangeType = bindingContext.getType(forExpression.loopRange!!)!! + asmLoopRangeType = codegen.asmType(loopRangeType) + + val incrementProp = loopRangeType.memberScope.getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND) + assert(incrementProp.size == 1) { loopRangeType.toString() + " " + incrementProp.size } + incrementType = codegen.asmType(incrementProp.iterator().next().type) + } + + override fun beforeLoop() { + super.beforeLoop() + + incrementVar = createLoopTempVariable(asmElementType) + + storeProgressionParametersToLocalVars() + } + + protected abstract fun storeProgressionParametersToLocalVars() + + override fun checkEmptyLoop(loopExit: Label) { + loopParameter().put(asmElementType, v) + v.load(endVar, asmElementType) + v.load(incrementVar, incrementType) + + val negativeIncrement = Label() + val afterIf = Label() + + if (asmElementType.sort == Type.LONG) { + v.lconst(0L) + v.lcmp() + v.ifle(negativeIncrement) // if increment < 0, jump + + // increment > 0 + v.lcmp() + v.ifgt(loopExit) + v.goTo(afterIf) + + // increment < 0 + v.mark(negativeIncrement) + v.lcmp() + v.iflt(loopExit) + v.mark(afterIf) + } + else { + v.ifle(negativeIncrement) // if increment < 0, jump + + // increment > 0 + v.ificmpgt(loopExit) + v.goTo(afterIf) + + // increment < 0 + v.mark(negativeIncrement) + v.ificmplt(loopExit) + v.mark(afterIf) + } + } + + override fun assignToLoopParameter() {} + + override fun checkPostConditionAndIncrement(loopExit: Label) { + checkPostCondition(loopExit) + + val loopParameter = loopParameter() + loopParameter.put(asmElementType, v) + v.load(incrementVar, asmElementType) + v.add(asmElementType) + + if (asmElementType === Type.BYTE_TYPE || asmElementType === Type.SHORT_TYPE || asmElementType === Type.CHAR_TYPE) { + StackValue.coerce(Type.INT_TYPE, asmElementType, v) + } + + loopParameter.store(StackValue.onStack(asmElementType), v) + } +} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt index 12396a8a334..3235b9ec475 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForInProgressionOrRangeLoopGenerator.kt @@ -25,7 +25,7 @@ import org.jetbrains.org.objectweb.asm.Type abstract class AbstractForInProgressionOrRangeLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) : AbstractForLoopGenerator(codegen, forExpression) { - protected var endVar: Int = 0 + protected var endVar: Int = -1 private var loopParameter: StackValue? = null diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForLoopGenerator.kt index 00c0970dfd7..eee21d5d097 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/AbstractForLoopGenerator.kt @@ -42,7 +42,7 @@ abstract class AbstractForLoopGenerator( protected val elementType: KotlinType = bindingContext.getElementType(forExpression) protected val asmElementType: Type = codegen.asmType(elementType) - protected var loopParameterVar: Int = 0 + protected var loopParameterVar: Int = -1 protected lateinit var loopParameterType: Type private fun BindingContext.getElementType(forExpression: KtForExpression): KotlinType { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/ForInProgressionExpressionLoopGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/ForInProgressionExpressionLoopGenerator.kt index bd2acc1c30e..f4cfaad2f70 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/ForInProgressionExpressionLoopGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/forLoop/ForInProgressionExpressionLoopGenerator.kt @@ -17,32 +17,12 @@ package org.jetbrains.kotlin.codegen.forLoop import org.jetbrains.kotlin.codegen.ExpressionCodegen -import org.jetbrains.kotlin.codegen.StackValue -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtForExpression -import org.jetbrains.org.objectweb.asm.Label -import org.jetbrains.org.objectweb.asm.Type class ForInProgressionExpressionLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) - : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) + : AbstractForInProgressionLoopGenerator(codegen, forExpression) { - private val loopRangeType = bindingContext.getType(forExpression.loopRange!!)!! - private val asmLoopRangeType = codegen.asmType(loopRangeType) - private var incrementVar: Int = -1 - private val incrementType: Type - - init { - val incrementProp = loopRangeType.memberScope.getContributedVariables(Name.identifier("step"), NoLookupLocation.FROM_BACKEND) - assert(incrementProp.size == 1) { loopRangeType.toString() + " " + incrementProp.size } - incrementType = codegen.asmType(incrementProp.iterator().next().type) - } - - override fun beforeLoop() { - super.beforeLoop() - - incrementVar = createLoopTempVariable(asmElementType) - + override fun storeProgressionParametersToLocalVars() { codegen.gen(forExpression.loopRange, asmLoopRangeType) v.dup() v.dup() @@ -51,59 +31,4 @@ class ForInProgressionExpressionLoopGenerator(codegen: ExpressionCodegen, forExp generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar) generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar) } - - override fun checkEmptyLoop(loopExit: Label) { - loopParameter().put(asmElementType, v) - v.load(endVar, asmElementType) - v.load(incrementVar, incrementType) - - val negativeIncrement = Label() - val afterIf = Label() - - if (asmElementType.sort == Type.LONG) { - v.lconst(0L) - v.lcmp() - v.ifle(negativeIncrement) // if increment < 0, jump - - // increment > 0 - v.lcmp() - v.ifgt(loopExit) - v.goTo(afterIf) - - // increment < 0 - v.mark(negativeIncrement) - v.lcmp() - v.iflt(loopExit) - v.mark(afterIf) - } - else { - v.ifle(negativeIncrement) // if increment < 0, jump - - // increment > 0 - v.ificmpgt(loopExit) - v.goTo(afterIf) - - // increment < 0 - v.mark(negativeIncrement) - v.ificmplt(loopExit) - v.mark(afterIf) - } - } - - override fun assignToLoopParameter() {} - - override fun checkPostConditionAndIncrement(loopExit: Label) { - checkPostCondition(loopExit) - - val loopParameter = loopParameter() - loopParameter.put(asmElementType, v) - v.load(incrementVar, asmElementType) - v.add(asmElementType) - - if (asmElementType === Type.BYTE_TYPE || asmElementType === Type.SHORT_TYPE || asmElementType === Type.CHAR_TYPE) { - StackValue.coerce(Type.INT_TYPE, asmElementType, v) - } - - loopParameter.store(StackValue.onStack(asmElementType), v) - } }