@@ -662,6 +662,9 @@ void read_char_param(block_t *parent, basic_block_t *bb)
662662 add_insn (parent , bb , OP_load_constant , ph1_ir -> dest , NULL , NULL , 0 , NULL );
663663}
664664
665+ void read_log_and_operation (block_t * parent ,
666+ basic_block_t * * bb ,
667+ char * label_else );
665668void read_ternary_operation (block_t * parent , basic_block_t * * bb );
666669void read_func_parameters (block_t * parent , basic_block_t * * bb )
667670{
@@ -973,20 +976,37 @@ void read_expr_operand(block_t *parent, basic_block_t **bb)
973976 }
974977}
975978
979+ void finalize_log_and (block_t * parent ,
980+ basic_block_t * * bb ,
981+ char * label_else ,
982+ basic_block_t * else_bb );
983+
976984void read_expr (block_t * parent , basic_block_t * * bb )
977985{
978986 ph1_ir_t * ph1_ir ;
979987 var_t * vd ;
980988 opcode_t oper_stack [10 ];
981989 int oper_stack_idx = 0 ;
982990
991+ /* These variables used for parsing logical-and operation. False branch of
992+ * each logical-and operand points to the same basic block.
993+ */
994+ bool has_log_and = false;
995+ basic_block_t * else_bb = bb_create (parent );
996+ char land_else_label [MAX_VAR_LEN ];
997+ strcpy (land_else_label , gen_label ());
998+
983999 read_expr_operand (parent , bb );
9841000
9851001 opcode_t op = get_operator ();
9861002 if (op == OP_generic || op == OP_ternary )
9871003 return ;
988-
989- oper_stack [oper_stack_idx ++ ] = op ;
1004+ if (op == OP_log_and ) {
1005+ bb_connect (* bb , else_bb , ELSE );
1006+ read_log_and_operation (parent , bb , land_else_label );
1007+ has_log_and = true;
1008+ } else
1009+ oper_stack [oper_stack_idx ++ ] = op ;
9901010 read_expr_operand (parent , bb );
9911011 op = get_operator ();
9921012
@@ -1011,8 +1031,25 @@ void read_expr(block_t *parent, basic_block_t **bb)
10111031 same = 1 ;
10121032 } while (oper_stack_idx > 0 && same == 0 );
10131033 }
1034+ if (op == OP_log_and ) {
1035+ bb_connect (* bb , else_bb , ELSE );
1036+ read_log_and_operation (parent , bb , land_else_label );
1037+ has_log_and = true;
1038+ }
1039+ /* When encountering an operator with lower priority, conclude the
1040+ * current logical-and and create a new "else" basic block for next
1041+ * logical-and operator.
1042+ */
1043+ if (has_log_and &&
1044+ get_operator_prio (op ) < get_operator_prio (OP_log_and )) {
1045+ finalize_log_and (parent , bb , land_else_label , else_bb );
1046+ else_bb = bb_create (parent );
1047+ strcpy (land_else_label , gen_label ());
1048+ has_log_and = false;
1049+ }
10141050 read_expr_operand (parent , bb );
1015- oper_stack [oper_stack_idx ++ ] = op ;
1051+ if (op != OP_log_and )
1052+ oper_stack [oper_stack_idx ++ ] = op ;
10161053 op = get_operator ();
10171054 }
10181055
@@ -1027,6 +1064,9 @@ void read_expr(block_t *parent, basic_block_t **bb)
10271064 add_insn (parent , * bb , ph1_ir -> op , ph1_ir -> dest , ph1_ir -> src0 ,
10281065 ph1_ir -> src1 , 0 , NULL );
10291066 }
1067+ if (has_log_and ) {
1068+ finalize_log_and (parent , bb , land_else_label , else_bb );
1069+ }
10301070}
10311071
10321072/* Return the address that an expression points to, or evaluate its value.
@@ -1343,6 +1383,127 @@ void read_lvalue(lvalue_t *lvalue,
13431383 }
13441384}
13451385
1386+ void read_log_and_operation (block_t * parent ,
1387+ basic_block_t * * bb ,
1388+ char * label_else )
1389+ {
1390+ char label_true [MAX_VAR_LEN ];
1391+ var_t * vd ;
1392+ ph1_ir_t * ph1_ir ;
1393+ strcpy (label_true , gen_label ());
1394+
1395+ /* test the operand before the logical-and operator */
1396+ ph1_ir = add_ph1_ir (OP_branch );
1397+ ph1_ir -> dest = opstack_pop ();
1398+ vd = require_var (parent );
1399+ strcpy (vd -> var_name , label_true );
1400+ ph1_ir -> src0 = vd ;
1401+ vd = require_var (parent );
1402+ strcpy (vd -> var_name , label_else );
1403+ ph1_ir -> src1 = vd ;
1404+ add_insn (parent , * bb , OP_branch , NULL , ph1_ir -> dest , NULL , 0 , NULL );
1405+
1406+ /* true branch label */
1407+ ph1_ir = add_ph1_ir (OP_label );
1408+ vd = require_var (parent );
1409+ strcpy (vd -> var_name , label_true );
1410+ ph1_ir -> src0 = vd ;
1411+
1412+ basic_block_t * then_ = bb_create (parent );
1413+ bb_connect (* bb , then_ , THEN );
1414+
1415+ bb [0 ] = then_ ;
1416+ }
1417+
1418+ void finalize_log_and (block_t * parent ,
1419+ basic_block_t * * bb ,
1420+ char * label_else ,
1421+ basic_block_t * else_bb )
1422+ {
1423+ basic_block_t * then_next_ = bb_create (parent );
1424+ basic_block_t * end_ = bb_create (parent );
1425+ bb_connect (* bb , then_next_ , THEN );
1426+ bb_connect (* bb , else_bb , ELSE );
1427+ bb_connect (then_next_ , end_ , NEXT );
1428+ bb_connect (else_bb , end_ , NEXT );
1429+ char label_and_true [MAX_VAR_LEN ], label_end [MAX_VAR_LEN ];
1430+ strcpy (label_and_true , gen_label ());
1431+ strcpy (label_end , gen_label ());
1432+ var_t * and_res ;
1433+
1434+ /* create branch instruction for final logical-and operand */
1435+ ph1_ir_t * ph1_ir = add_ph1_ir (OP_branch );
1436+ var_t * vd = opstack_pop ();
1437+ ph1_ir -> dest = vd ;
1438+ vd = require_var (parent );
1439+ strcpy (vd -> var_name , label_and_true );
1440+ ph1_ir -> src0 = vd ;
1441+ vd = require_var (parent );
1442+ strcpy (vd -> var_name , label_else );
1443+ ph1_ir -> src1 = vd ;
1444+ add_insn (parent , * bb , OP_branch , NULL , ph1_ir -> dest , NULL , 0 , NULL );
1445+
1446+ /* true branch of the logical-and operation */
1447+ ph1_ir = add_ph1_ir (OP_label );
1448+ vd = require_var (parent );
1449+ strcpy (vd -> var_name , label_and_true );
1450+ ph1_ir -> dest = vd ;
1451+
1452+ ph1_ir = add_ph1_ir (OP_load_constant );
1453+ vd = require_var (parent );
1454+ strcpy (vd -> var_name , gen_name ());
1455+ vd -> init_val = 1 ;
1456+ ph1_ir -> dest = vd ;
1457+ add_insn (parent , then_next_ , OP_load_constant , ph1_ir -> dest , NULL , NULL , 0 ,
1458+ NULL );
1459+
1460+ ph1_ir = add_ph1_ir (OP_assign );
1461+ and_res = require_var (parent );
1462+ strcpy (and_res -> var_name , gen_name ());
1463+ ph1_ir -> dest = and_res ;
1464+ ph1_ir -> src0 = vd ;
1465+ add_insn (parent , then_next_ , OP_assign , ph1_ir -> dest , ph1_ir -> src0 , NULL , 0 ,
1466+ NULL );
1467+
1468+ /* end of true branch, jump over the false branch */
1469+ ph1_ir = add_ph1_ir (OP_jump );
1470+ vd = require_var (parent );
1471+ strcpy (vd -> var_name , label_end );
1472+ ph1_ir -> dest = vd ;
1473+
1474+ /* false branch of logical-and operation */
1475+ ph1_ir = add_ph1_ir (OP_label );
1476+ vd = require_var (parent );
1477+ strcpy (vd -> var_name , label_else );
1478+ ph1_ir -> src0 = vd ;
1479+
1480+ ph1_ir = add_ph1_ir (OP_load_constant );
1481+ vd = require_var (parent );
1482+ strcpy (vd -> var_name , gen_name ());
1483+ vd -> init_val = 0 ;
1484+ ph1_ir -> dest = vd ;
1485+ add_insn (parent , else_bb , OP_load_constant , ph1_ir -> dest , NULL , NULL , 0 ,
1486+ NULL );
1487+
1488+ /* final basic block to retrieve the value from one of previous basic block
1489+ */
1490+ ph1_ir = add_ph1_ir (OP_assign );
1491+ ph1_ir -> dest = and_res ;
1492+ ph1_ir -> src0 = vd ;
1493+ add_insn (parent , else_bb , OP_assign , ph1_ir -> dest , ph1_ir -> src0 , NULL , 0 ,
1494+ NULL );
1495+
1496+ ph1_ir = add_ph1_ir (OP_label );
1497+ vd = require_var (parent );
1498+ strcpy (vd -> var_name , label_end );
1499+ ph1_ir -> src0 = vd ;
1500+
1501+ and_res -> is_log_and_ret = true;
1502+ opstack_push (and_res );
1503+
1504+ bb [0 ] = end_ ;
1505+ }
1506+
13461507void read_ternary_operation (block_t * parent , basic_block_t * * bb )
13471508{
13481509 char true_label [MAX_VAR_LEN ], false_label [MAX_VAR_LEN ];
@@ -2074,6 +2235,8 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
20742235 strcpy (var_break -> var_name , label_end );
20752236 break_exit [break_exit_idx ++ ] = var_break ;
20762237
2238+ basic_block_t * cond = bb_create (parent );
2239+ cond = bb ;
20772240 lex_expect (T_open_bracket );
20782241 read_expr (parent , & bb );
20792242 lex_expect (T_close_bracket );
@@ -2118,7 +2281,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
21182281
21192282 /* return, break, continue */
21202283 if (body_ )
2121- bb_connect (body_ , bb , NEXT );
2284+ bb_connect (body_ , cond , NEXT );
21222285
21232286 return else_ ;
21242287 }
@@ -2365,9 +2528,9 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
23652528
23662529 basic_block_t * cond_ = bb_create (blk );
23672530 basic_block_t * for_end = bb_create (parent );
2531+ basic_block_t * cond_start = cond_ ;
23682532 break_bb [break_exit_idx ] = for_end ;
23692533 bb_connect (setup , cond_ , NEXT );
2370- bb_connect (cond_ , for_end , ELSE );
23712534
23722535 /* condition - check before the loop */
23732536 ph1_ir = add_ph1_ir (OP_label );
@@ -2388,6 +2551,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
23882551 add_insn (blk , cond_ , OP_load_constant , ph1_ir -> dest , NULL , NULL , 0 ,
23892552 NULL );
23902553 }
2554+ bb_connect (cond_ , for_end , ELSE );
23912555
23922556 ph1_ir = add_ph1_ir (OP_branch );
23932557 ph1_ir -> dest = opstack_pop ();
@@ -2443,7 +2607,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
24432607
24442608 if (body_ ) {
24452609 bb_connect (body_ , inc_ , NEXT );
2446- bb_connect (inc_ , cond_ , NEXT );
2610+ bb_connect (inc_ , cond_start , NEXT );
24472611 } else {
24482612 /* TODO: Release dangling inc basic block */
24492613 }
0 commit comments