fix: for() loop without cond expr, such as 'for( ; ; )' master
authoryu.dongliang <18588496441@163.com>
Tue, 18 Nov 2025 13:35:37 +0000 (21:35 +0800)
committeryu.dongliang <18588496441@163.com>
Tue, 18 Nov 2025 13:35:37 +0000 (21:35 +0800)
core/scf_operator_handler_3ac.c
examples/for2.c [new file with mode: 0644]
parse/scf_operator_handler_semantic.c

index 3d31a07f70c08584a4b29dfe689a14f7b0292752..33d276cc52003225a2509d4ec050c49750aecd6f 100644 (file)
@@ -796,85 +796,98 @@ static int _scf_op_end_loop(scf_list_t* start_prev, scf_list_t* continue_prev, s
        scf_list_t*        l2;
        scf_list_t*        cond_prev = scf_list_tail(d->_3ac_list_head);
 
-       for (l = scf_list_next(start_prev); l != &jmp_end->list; l = scf_list_next(l)) {
-               c  = scf_list_data(l, scf_3ac_code_t, list);
+       int jmp_op = -1;
+       if (jmp_end) {
+               for (l = scf_list_next(start_prev); l != &jmp_end->list; l = scf_list_next(l)) {
+                       c  = scf_list_data(l, scf_3ac_code_t, list);
 
-               c2 = scf_3ac_code_clone(c);
-               if (!c2)
-                       return -ENOMEM;
+                       c2 = scf_3ac_code_clone(c);
+                       if (!c2)
+                               return -ENOMEM;
 
-               scf_list_add_tail(d->_3ac_list_head, &c2->list);
-       }
+                       scf_list_add_tail(d->_3ac_list_head, &c2->list);
+               }
 
-       for (l = scf_list_next(cond_prev); l != scf_list_sentinel(d->_3ac_list_head); l = scf_list_next(l)) {
-               c  = scf_list_data(l, scf_3ac_code_t, list);
+               for (l = scf_list_next(cond_prev); l != scf_list_sentinel(d->_3ac_list_head); l = scf_list_next(l)) {
+                       c  = scf_list_data(l, scf_3ac_code_t, list);
 
-               if (!scf_type_is_jmp(c->op->type))
-                       continue;
+                       if (!scf_type_is_jmp(c->op->type))
+                               continue;
 
-               for (l2 = scf_list_next(cond_prev); l2 != scf_list_sentinel(d->_3ac_list_head); l2 = scf_list_next(l2)) {
-                       c2  = scf_list_data(l2, scf_3ac_code_t, list);
+                       for (l2 = scf_list_next(cond_prev); l2 != scf_list_sentinel(d->_3ac_list_head); l2 = scf_list_next(l2)) {
+                               c2  = scf_list_data(l2, scf_3ac_code_t, list);
 
-                       dst = c->dsts->data[0];
+                               dst = c->dsts->data[0];
 
-                       if (dst->code == c2->origin) {
-                               dst->code =  c2;
-                               break;
+                               if (dst->code == c2->origin) {
+                                       dst->code =  c2;
+                                       break;
+                               }
                        }
+                       assert(l2 != scf_list_sentinel(d->_3ac_list_head));
+
+                       if (scf_vector_add(d->branch_ops->_breaks, c) < 0)
+                               return -1;
                }
-               assert(l2 != scf_list_sentinel(d->_3ac_list_head));
 
-               if (scf_vector_add(d->branch_ops->_breaks, c) < 0)
-                       return -1;
-       }
+               switch (jmp_end->op->type) {
 
-       int jmp_op = -1;
-       switch (jmp_end->op->type) {
+                       case SCF_OP_3AC_JNZ:
+                               jmp_op = SCF_OP_3AC_JZ;
+                               break;
+                       case SCF_OP_3AC_JZ:
+                               jmp_op = SCF_OP_3AC_JNZ;
+                               break;
+                       case SCF_OP_3AC_JLE:
+                               jmp_op = SCF_OP_3AC_JGT;
+                               break;
+                       case SCF_OP_3AC_JLT:
+                               jmp_op = SCF_OP_3AC_JGE;
+                               break;
+                       case SCF_OP_3AC_JGE:
+                               jmp_op = SCF_OP_3AC_JLT;
+                               break;
+                       case SCF_OP_3AC_JGT:
+                               jmp_op = SCF_OP_3AC_JLE;
+                               break;
 
-               case SCF_OP_3AC_JNZ:
-                       jmp_op = SCF_OP_3AC_JZ;
-                       break;
-               case SCF_OP_3AC_JZ:
-                       jmp_op = SCF_OP_3AC_JNZ;
-                       break;
-               case SCF_OP_3AC_JLE:
-                       jmp_op = SCF_OP_3AC_JGT;
-                       break;
-               case SCF_OP_3AC_JLT:
-                       jmp_op = SCF_OP_3AC_JGE;
-                       break;
-               case SCF_OP_3AC_JGE:
-                       jmp_op = SCF_OP_3AC_JLT;
-                       break;
-               case SCF_OP_3AC_JGT:
-                       jmp_op = SCF_OP_3AC_JLE;
-                       break;
+                       case SCF_OP_3AC_JA:
+                               jmp_op = SCF_OP_3AC_JBE;
+                               break;
+                       case SCF_OP_3AC_JAE:
+                               jmp_op = SCF_OP_3AC_JB;
+                               break;
 
-               case SCF_OP_3AC_JA:
-                       jmp_op = SCF_OP_3AC_JBE;
-                       break;
-               case SCF_OP_3AC_JAE:
-                       jmp_op = SCF_OP_3AC_JB;
-                       break;
+                       case SCF_OP_3AC_JB:
+                               jmp_op = SCF_OP_3AC_JAE;
+                               break;
+                       case SCF_OP_3AC_JBE:
+                               jmp_op = SCF_OP_3AC_JA;
+                               break;
 
-               case SCF_OP_3AC_JB:
-                       jmp_op = SCF_OP_3AC_JAE;
-                       break;
-               case SCF_OP_3AC_JBE:
-                       jmp_op = SCF_OP_3AC_JA;
-                       break;
+                       default:
+                               scf_loge("NOT support jmp op %d\n", jmp_end->op->type);
+                               return -1;
+                               break;
+               };
+       }
 
-               default:
-                       jmp_op = -1;
-                       break;
-       };
+       scf_3ac_code_t* loop  = NULL;
+       scf_3ac_code_t* start = NULL;
+
+       if (jmp_end) {
+               // add loop when true
+               loop = scf_3ac_jmp_code(jmp_op, NULL, NULL);
+               scf_list_add_tail(d->_3ac_list_head, &loop->list);
 
-       // add loop when true
-       scf_3ac_code_t* loop = scf_3ac_jmp_code(jmp_op, NULL, NULL);
-       scf_list_add_tail(d->_3ac_list_head, &loop->list);
+               // should get the real start here,
+               start = scf_list_data(scf_list_next(&jmp_end->list), scf_3ac_code_t, list);
+       } else {
+               loop = scf_3ac_jmp_code(SCF_OP_GOTO, NULL, NULL);
+               scf_list_add_tail(d->_3ac_list_head, &loop->list);
 
-       // should get the real start here,
-       scf_3ac_code_t* start = scf_list_data(scf_list_next(&jmp_end->list), scf_3ac_code_t, list);
+               start = scf_list_data(scf_list_next(start_prev), scf_3ac_code_t, list);
+       }
 
        dst       = loop->dsts->data[0];
        dst->code = start;
diff --git a/examples/for2.c b/examples/for2.c
new file mode 100644 (file)
index 0000000..636d89b
--- /dev/null
@@ -0,0 +1,12 @@
+int printf(const char* fmt, ...);
+
+int main()
+{
+       for (int i = 0; ; i++) {
+               printf("%d\n", i);
+               if (i >= 9)
+                       break;
+       }
+
+       return 0;
+}
index 415069e6869b7bf2a95b7599e21940cc64156dce..4cf58677d49a15ddeb2c9254277861b25d9d6943 100644 (file)
@@ -1502,26 +1502,28 @@ static int _scf_op_semantic_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes
        assert(4 == nb_nodes);
 
        scf_handler_data_t* d = data;
-       int ret = 0;
+       scf_variable_t*     r;
+       scf_node_t*         cond;
+       int i;
 
-       if (nodes[0]) {
-               ret = _scf_op_semantic_node(ast, nodes[0], d);
-               if (ret < 0) {
-                       scf_loge("\n");
-                       return ret;
-               }
-       }
+       for (i = 0; i < nb_nodes; i++) {
+               if (!nodes[i])
+                       continue;
 
-       scf_node_t* cond = nodes[1];
-       if (cond) {
-               ret = _scf_op_semantic_node(ast, cond, d);
+               int ret = _scf_op_semantic_node(ast, nodes[i], d);
                if (ret < 0) {
                        scf_loge("\n");
                        return ret;
                }
 
-               if (cond->nb_nodes > 0) { // the final expr is real cond expr
-                       scf_variable_t* r = _scf_operand_get(cond->nodes[cond->nb_nodes - 1]);
+               if (1 == i) {
+                       cond = nodes[i];
+
+                       if (cond->nb_nodes <= 0)
+                               continue;
+
+                       // the final expr is real cond expr
+                       r = _scf_operand_get(cond->nodes[cond->nb_nodes - 1]);
 
                        if (!r || !scf_variable_integer(r)) {
                                scf_loge("\n");
@@ -1530,18 +1532,6 @@ static int _scf_op_semantic_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes
                }
        }
 
-       int i;
-       for (i = 2; i < nb_nodes; i++) {
-               if (!nodes[i])
-                       continue;
-
-               ret = _scf_op_semantic_node(ast, nodes[i], d);
-               if (ret < 0) {
-                       scf_loge("\n");
-                       return ret;
-               }
-       }
-
        return 0;
 }