summaryrefslogtreecommitdiffstats
path: root/generic/tclCompCmds.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2013-06-05 08:11:06 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2013-06-05 08:11:06 (GMT)
commit4265e044139d2dd3217a93741524cd31d7d4fa84 (patch)
tree1c78cdffefc59b1c8cffdea512f701b5eaffa9be /generic/tclCompCmds.c
parent6f640f9e5701a60ac0fbde981742fd3a80f59d18 (diff)
parent984c4923d6abb322e755dcde5b14bc19747eb8b8 (diff)
downloadtcl-4265e044139d2dd3217a93741524cd31d7d4fa84.zip
tcl-4265e044139d2dd3217a93741524cd31d7d4fa84.tar.gz
tcl-4265e044139d2dd3217a93741524cd31d7d4fa84.tar.bz2
[Bugs 2835313, 3614226]: Complete the construction of break/continue compilers
that get the stack cleanup right, even when there's expansion going on.
Diffstat (limited to 'generic/tclCompCmds.c')
-rw-r--r--generic/tclCompCmds.c70
1 files changed, 22 insertions, 48 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index 3046841..365e647 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -493,37 +493,24 @@ TclCompileBreakCmd(
rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxPtr);
if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
- int toPop = envPtr->currStackDepth - auxPtr->stackDepth;
-
/*
- * Pop off the extra stack frames.
+ * Found the target! No need for a nasty INST_BREAK here.
*/
- while (toPop > 0) {
- TclEmitOpcode(INST_POP, envPtr);
- TclAdjustStackDepth(1, envPtr);
- toPop--;
- }
-
- if (envPtr->expandCount == auxPtr->expandTarget) {
- /*
- * Found the target! Also, no built-up expansion stack. No need
- * for a nasty INST_BREAK here.
- */
+ TclCleanupStackForBreakContinue(envPtr, auxPtr);
+ TclAddLoopBreakFixup(envPtr, auxPtr);
+ } else {
+ /*
+ * Emit a real break.
+ */
- TclAddLoopBreakFixup(envPtr, auxPtr);
- goto done;
- }
+ PushStringLiteral(envPtr, "");
+ TclEmitOpcode(INST_DUP, envPtr);
+ TclEmitInstInt4(INST_RETURN_IMM, TCL_BREAK, envPtr);
+ TclEmitInt4(0, envPtr);
}
/*
- * Emit a break instruction.
- */
-
- TclEmitOpcode(INST_BREAK, envPtr);
-
- done:
- /*
* Instructions that raise exceptions don't really have to follow the
* usual stack management rules, but the cleanup code does.
*/
@@ -840,37 +827,24 @@ TclCompileContinueCmd(
rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxPtr);
if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
- int toPop = envPtr->currStackDepth - auxPtr->stackDepth;
-
/*
- * Pop off the extra stack frames.
+ * Found the target! No need for a nasty INST_CONTINUE here.
*/
- while (toPop > 0) {
- TclEmitOpcode(INST_POP, envPtr);
- TclAdjustStackDepth(1, envPtr);
- toPop--;
- }
-
- if (envPtr->expandCount == auxPtr->expandTarget) {
- /*
- * Found the target! Also, no built-up expansion stack. No need
- * for a nasty INST_CONTINUE here.
- */
+ TclCleanupStackForBreakContinue(envPtr, auxPtr);
+ TclAddLoopContinueFixup(envPtr, auxPtr);
+ } else {
+ /*
+ * Emit a real continue.
+ */
- TclAddLoopContinueFixup(envPtr, auxPtr);
- goto done;
- }
+ PushStringLiteral(envPtr, "");
+ TclEmitOpcode(INST_DUP, envPtr);
+ TclEmitInstInt4(INST_RETURN_IMM, TCL_CONTINUE, envPtr);
+ TclEmitInt4(0, envPtr);
}
/*
- * Emit a continue instruction.
- */
-
- TclEmitOpcode(INST_CONTINUE, envPtr);
-
- done:
- /*
* Instructions that raise exceptions don't really have to follow the
* usual stack management rules, but the cleanup code does.
*/