Merge generateBreakOrContinueExpression and doFinallyOnReturn
This commit is contained in:
+22
-47
@@ -75,8 +75,6 @@ class BlockInfo private constructor(val parent: BlockInfo?) {
|
|||||||
this@apply.infos.addAll(this@BlockInfo.infos)
|
this@apply.infos.addAll(this@BlockInfo.infos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isEmpty(): Boolean = infos.isEmpty()
|
|
||||||
|
|
||||||
fun hasFinallyBlocks(): Boolean = infos.firstIsInstanceOrNull<TryInfo>() != null
|
fun hasFinallyBlocks(): Boolean = infos.firstIsInstanceOrNull<TryInfo>() != null
|
||||||
|
|
||||||
inline fun <R> withBlock(info: ExpressionInfo, f: (ExpressionInfo) -> R): R {
|
inline fun <R> withBlock(info: ExpressionInfo, f: (ExpressionInfo) -> R): R {
|
||||||
@@ -88,7 +86,10 @@ class BlockInfo private constructor(val parent: BlockInfo?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <R> handleBlock(f: (ExpressionInfo) -> R): R {
|
inline fun <R> handleBlock(f: (ExpressionInfo) -> R): R? {
|
||||||
|
if (infos.isEmpty()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
val top = infos.pop()
|
val top = infos.pop()
|
||||||
try {
|
try {
|
||||||
return f(top)
|
return f(top)
|
||||||
@@ -955,37 +956,24 @@ class ExpressionCodegen(
|
|||||||
return StackValue.none()
|
return StackValue.none()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBreakContinue(jump: IrBreakContinue, data: BlockInfo): StackValue {
|
private fun unwindBlockStack(endLabel: Label, data: BlockInfo, loop: IrLoop? = null): LoopInfo? {
|
||||||
jump.markLineNumber(startOffset = true)
|
return data.handleBlock {
|
||||||
generateBreakOrContinueExpression(jump, Label(), data)
|
when {
|
||||||
return none()
|
it is TryInfo -> genFinallyBlock(it, null, endLabel, data)
|
||||||
|
it is LoopInfo && it.loop == loop -> return it
|
||||||
|
}
|
||||||
|
unwindBlockStack(endLabel, data, loop)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateBreakOrContinueExpression(
|
override fun visitBreakContinue(jump: IrBreakContinue, data: BlockInfo): StackValue {
|
||||||
expression: IrBreakContinue,
|
jump.markLineNumber(startOffset = true)
|
||||||
afterBreakContinueLabel: Label,
|
val endLabel = Label()
|
||||||
data: BlockInfo
|
val stackElement = unwindBlockStack(endLabel, data, jump.loop)
|
||||||
) {
|
?: throw AssertionError("Target label for break/continue not found")
|
||||||
if (data.isEmpty()) {
|
mv.fixStackAndJump(if (jump is IrBreak) stackElement.breakLabel else stackElement.continueLabel)
|
||||||
throw UnsupportedOperationException("Target label for break/continue not found")
|
mv.mark(endLabel)
|
||||||
}
|
return none()
|
||||||
|
|
||||||
data.handleBlock { stackElement ->
|
|
||||||
when (stackElement) {
|
|
||||||
is TryInfo -> genFinallyBlock(stackElement, null, afterBreakContinueLabel, data)
|
|
||||||
is LoopInfo -> {
|
|
||||||
val loop = expression.loop
|
|
||||||
if (loop == stackElement.loop) {
|
|
||||||
val label = if (expression is IrBreak) stackElement.breakLabel else stackElement.continueLabel
|
|
||||||
mv.fixStackAndJump(label)
|
|
||||||
mv.mark(afterBreakContinueLabel)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
|
|
||||||
}
|
|
||||||
generateBreakOrContinueExpression(expression, afterBreakContinueLabel, data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: BlockInfo): StackValue {
|
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: BlockInfo): StackValue {
|
||||||
@@ -1126,24 +1114,11 @@ class ExpressionCodegen(
|
|||||||
val returnValIndex = frame.enterTemp(returnType)
|
val returnValIndex = frame.enterTemp(returnType)
|
||||||
val localForReturnValue = StackValue.local(returnValIndex, returnType)
|
val localForReturnValue = StackValue.local(returnValIndex, returnType)
|
||||||
localForReturnValue.store(StackValue.onStack(returnType), mv)
|
localForReturnValue.store(StackValue.onStack(returnType), mv)
|
||||||
doFinallyOnReturn(afterReturnLabel, data)
|
unwindBlockStack(afterReturnLabel, data, null)
|
||||||
localForReturnValue.put(returnType, mv)
|
localForReturnValue.put(returnType, mv)
|
||||||
frame.leaveTemp(returnType)
|
frame.leaveTemp(returnType)
|
||||||
} else {
|
} else {
|
||||||
doFinallyOnReturn(afterReturnLabel, data)
|
unwindBlockStack(afterReturnLabel, data, null)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doFinallyOnReturn(afterReturnLabel: Label, data: BlockInfo) {
|
|
||||||
if (!data.isEmpty()) {
|
|
||||||
data.handleBlock { stackElement ->
|
|
||||||
when (stackElement) {
|
|
||||||
is TryInfo -> genFinallyBlock(stackElement, null, afterReturnLabel, data)
|
|
||||||
is LoopInfo -> {}
|
|
||||||
else -> throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
|
|
||||||
}
|
|
||||||
doFinallyOnReturn(afterReturnLabel, data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user