summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler/core/codegen.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-08-01 20:32:10 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-08-01 20:33:41 +0900
commit1315e8751e70937e4cf43ba9225ea0cfaa67689d (patch)
tree92c7523efa77f7d879df9fcb6c9abb1a0d924e25 /mrbgems/mruby-compiler/core/codegen.c
parent9dc801a79810760b6911b2856e20b27e04e64986 (diff)
downloadmruby-1315e8751e70937e4cf43ba9225ea0cfaa67689d.tar.gz
mruby-1315e8751e70937e4cf43ba9225ea0cfaa67689d.zip
codegen.c: eliminate loop if condition is constant.
For example, `while false; ...; end` should be removed.
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 8cc3bad7a..7d0b51740 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -2096,33 +2096,40 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_WHILE:
- {
- struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
- uint32_t pos;
-
- if (!val) lp->acc = -1;
- lp->pc0 = new_label(s);
- codegen(s, tree->car, VAL);
- pop();
- pos = genjmp2_0(s, OP_JMPNOT, cursp(), NOVAL);
- lp->pc1 = new_label(s);
- codegen(s, tree->cdr, NOVAL);
- genjmp(s, OP_JMP, lp->pc0);
- dispatch(s, pos);
- loop_pop(s, val);
- }
- break;
-
case NODE_UNTIL:
{
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
- uint32_t pos;
+ uint32_t pos = JMPLINK_START;
if (!val) lp->acc = -1;
lp->pc0 = new_label(s);
- codegen(s, tree->car, VAL);
- pop();
- pos = genjmp2_0(s, OP_JMPIF, cursp(), NOVAL);
+ switch (nint(tree->car->car)) {
+ case NODE_TRUE:
+ case NODE_INT:
+ case NODE_STR:
+ if (nt == NODE_UNTIL) {
+ if (val) genop_1(s, OP_LOADNIL, cursp());
+ goto exit;
+ }
+ break;
+ case NODE_FALSE:
+ case NODE_NIL:
+ if (nt == NODE_WHILE) {
+ if (val) genop_1(s, OP_LOADNIL, cursp());
+ goto exit;
+ }
+ break;
+ default:
+ codegen(s, tree->car, VAL);
+ pop();
+ if (nt == NODE_WHILE) {
+ pos = genjmp2_0(s, OP_JMPNOT, cursp(), NOVAL);
+ }
+ else {
+ pos = genjmp2_0(s, OP_JMPIF, cursp(), NOVAL);
+ }
+ break;
+ }
lp->pc1 = new_label(s);
codegen(s, tree->cdr, NOVAL);
genjmp(s, OP_JMP, lp->pc0);