Support break/continue
This commit is contained in:
committed by
Dmitry Petrov
parent
e5bccf0963
commit
4bcd3d1bdb
+55
-11
@@ -42,12 +42,36 @@ import org.jetbrains.org.objectweb.asm.Label
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
class BlockInfo {
|
class LoopInfo(val irLoop: IrLoop, val continueLabel: Label, val breakLabel: Label)
|
||||||
|
|
||||||
|
class BlockInfo private constructor(val parent: BlockInfo?) {
|
||||||
val variables: MutableList<VariableInfo> = mutableListOf()
|
val variables: MutableList<VariableInfo> = mutableListOf()
|
||||||
|
|
||||||
|
private val loops = mutableListOf<LoopInfo>()
|
||||||
|
|
||||||
|
fun create() = BlockInfo(this)
|
||||||
|
|
||||||
|
fun addLoop(loop: LoopInfo) {
|
||||||
|
loops.add(loop)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeLoop(loop: LoopInfo) {
|
||||||
|
assert (loops.last() == loop)
|
||||||
|
loops.dropLast(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findLoop(loop: IrLoop): LoopInfo? {
|
||||||
|
return loops.firstOrNull { it.irLoop == loop } ?: parent?.findLoop(loop)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create() = BlockInfo(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VariableInfo(val name: String, val index: Int, val type: Type, val startLabel: Label)
|
class VariableInfo(val name: String, val index: Int, val type: Type, val startLabel: Label)
|
||||||
|
|
||||||
|
@Suppress("IMPLICIT_CAST_TO_ANY")
|
||||||
class ExpressionCodegen(
|
class ExpressionCodegen(
|
||||||
val irFunction: IrFunction,
|
val irFunction: IrFunction,
|
||||||
val frame: FrameMap,
|
val frame: FrameMap,
|
||||||
@@ -64,7 +88,7 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
mv.visitCode()
|
mv.visitCode()
|
||||||
val info = BlockInfo()
|
val info = BlockInfo.create()
|
||||||
val result = irFunction.body?.accept(this, info)
|
val result = irFunction.body?.accept(this, info)
|
||||||
// result?.apply {
|
// result?.apply {
|
||||||
// coerce(this.type, irFunction.body!!.as)
|
// coerce(this.type, irFunction.body!!.as)
|
||||||
@@ -86,7 +110,7 @@ class ExpressionCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock, data: BlockInfo): StackValue {
|
override fun visitBlock(expression: IrBlock, data: BlockInfo): StackValue {
|
||||||
val info = BlockInfo()
|
val info = data.create()
|
||||||
return super.visitBlock(expression, info).apply {
|
return super.visitBlock(expression, info).apply {
|
||||||
if (!expression.isTransparentScope) {
|
if (!expression.isTransparentScope) {
|
||||||
writeLocalVariablesInTable(info)
|
writeLocalVariablesInTable(info)
|
||||||
@@ -443,34 +467,54 @@ class ExpressionCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWhileLoop(loop: IrWhileLoop, data: BlockInfo): StackValue {
|
override fun visitWhileLoop(loop: IrWhileLoop, data: BlockInfo): StackValue {
|
||||||
val entry = Label()
|
val continueLabel = Label()
|
||||||
mv.visitLabel(entry)
|
mv.mark(continueLabel)
|
||||||
|
|
||||||
|
val endLabel = Label()
|
||||||
val condition = loop.condition
|
val condition = loop.condition
|
||||||
gen(condition, data)
|
gen(condition, data)
|
||||||
val endLabel = Label()
|
|
||||||
BranchedValue.condJump(StackValue.onStack(condition.asmType), endLabel, true, mv)
|
BranchedValue.condJump(StackValue.onStack(condition.asmType), endLabel, true, mv)
|
||||||
|
|
||||||
loop.body?.apply {
|
with(LoopInfo(loop, continueLabel, endLabel)) {
|
||||||
gen(this, data)
|
data.addLoop(this)
|
||||||
|
loop.body?.apply {
|
||||||
|
gen(this, data)
|
||||||
|
}
|
||||||
|
data.removeLoop(this)
|
||||||
}
|
}
|
||||||
mv.goTo(entry)
|
mv.goTo(continueLabel)
|
||||||
mv.mark(endLabel)
|
mv.mark(endLabel)
|
||||||
|
|
||||||
|
|
||||||
return loop.onStack
|
return loop.onStack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitBreakContinue(jump: IrBreakContinue, data: BlockInfo): StackValue {
|
||||||
|
val loop = data.findLoop(jump.loop)!!
|
||||||
|
val label = if (jump is IrBreak) loop.breakLabel else loop.continueLabel
|
||||||
|
mv.goTo(label)
|
||||||
|
return none()
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: BlockInfo): StackValue {
|
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: BlockInfo): StackValue {
|
||||||
val entry = Label()
|
val entry = Label()
|
||||||
mv.visitLabel(entry)
|
mv.visitLabel(entry)
|
||||||
|
val endLabel = Label()
|
||||||
|
val continueLabel = Label()
|
||||||
|
|
||||||
loop.body?.apply {
|
with(LoopInfo(loop, continueLabel, endLabel)) {
|
||||||
gen(this, data)
|
data.addLoop(this)
|
||||||
|
loop.body?.apply {
|
||||||
|
gen(this, data)
|
||||||
|
}
|
||||||
|
data.removeLoop(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mv.visitLabel(continueLabel)
|
||||||
val condition = loop.condition
|
val condition = loop.condition
|
||||||
gen(condition, data)
|
gen(condition, data)
|
||||||
BranchedValue.condJump(StackValue.onStack(condition.asmType), entry, false, mv)
|
BranchedValue.condJump(StackValue.onStack(condition.asmType), entry, false, mv)
|
||||||
|
mv.mark(endLabel)
|
||||||
|
|
||||||
return loop.onStack
|
return loop.onStack
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user