tccgen: fix expr_cond for alt. nocode_wanted
making shure that both the active and the passive branches do exacly the same thing.
This commit is contained in:
		
							parent
							
								
									f843cadb6b
								
							
						
					
					
						commit
						e5efd18435
					
				
					 1 changed files with 76 additions and 72 deletions
				
			
		
							
								
								
									
										148
									
								
								tccgen.c
									
										
									
									
									
								
							
							
						
						
									
										148
									
								
								tccgen.c
									
										
									
									
									
								
							| 
						 | 
					@ -5150,72 +5150,62 @@ static int condition_3way(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void expr_cond(void)
 | 
					static void expr_cond(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv;
 | 
					    int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g;
 | 
				
			||||||
    int c;
 | 
					 | 
				
			||||||
    SValue sv;
 | 
					    SValue sv;
 | 
				
			||||||
    CType type, type1, type2;
 | 
					    CType type, type1, type2;
 | 
				
			||||||
 | 
					    int saved_nocode_wanted = nocode_wanted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expr_lor();
 | 
					    expr_lor();
 | 
				
			||||||
    if (tok == '?') {
 | 
					    if (tok == '?') {
 | 
				
			||||||
        next();
 | 
					        next();
 | 
				
			||||||
	c = condition_3way();
 | 
						c = condition_3way();
 | 
				
			||||||
        if (c >= 0) {
 | 
					        g = (tok == ':' && gnu_ext);
 | 
				
			||||||
            int saved_nocode_wanted = nocode_wanted;
 | 
					        if (c < 0) {
 | 
				
			||||||
            if (c) {
 | 
					            /* needed to avoid having different registers saved in
 | 
				
			||||||
                if (tok != ':' || !gnu_ext) {
 | 
					               each branch */
 | 
				
			||||||
                    vpop();
 | 
					            if (is_float(vtop->type.t)) {
 | 
				
			||||||
                    gexpr();
 | 
					                rc = RC_FLOAT;
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                skip(':');
 | 
					 | 
				
			||||||
                nocode_wanted = 1;
 | 
					 | 
				
			||||||
                expr_cond();
 | 
					 | 
				
			||||||
                vpop();
 | 
					 | 
				
			||||||
                nocode_wanted = saved_nocode_wanted;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                vpop();
 | 
					 | 
				
			||||||
                if (tok != ':' || !gnu_ext) {
 | 
					 | 
				
			||||||
                    nocode_wanted = 1;
 | 
					 | 
				
			||||||
                    gexpr();
 | 
					 | 
				
			||||||
                    vpop();
 | 
					 | 
				
			||||||
                    nocode_wanted = saved_nocode_wanted;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                skip(':');
 | 
					 | 
				
			||||||
                expr_cond();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            if (vtop != vstack) {
 | 
					 | 
				
			||||||
                /* needed to avoid having different registers saved in
 | 
					 | 
				
			||||||
                   each branch */
 | 
					 | 
				
			||||||
                if (is_float(vtop->type.t)) {
 | 
					 | 
				
			||||||
                    rc = RC_FLOAT;
 | 
					 | 
				
			||||||
#ifdef TCC_TARGET_X86_64
 | 
					#ifdef TCC_TARGET_X86_64
 | 
				
			||||||
                    if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
 | 
					                if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
 | 
				
			||||||
                        rc = RC_ST0;
 | 
					                    rc = RC_ST0;
 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					#endif
 | 
				
			||||||
		    rc = RC_INT;
 | 
					            } else
 | 
				
			||||||
		gv(rc);
 | 
					                rc = RC_INT;
 | 
				
			||||||
		save_regs(1);
 | 
					            save_regs(1);
 | 
				
			||||||
            }
 | 
					            gv(rc);
 | 
				
			||||||
            if (tok == ':' && gnu_ext) {
 | 
					            if (g)
 | 
				
			||||||
                gv_dup();
 | 
					                gv_dup();
 | 
				
			||||||
                tt = gvtst(1, 0);
 | 
					            tt = gvtst(1, 0);
 | 
				
			||||||
            } else {
 | 
					
 | 
				
			||||||
                tt = gvtst(1, 0);
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (!g)
 | 
				
			||||||
 | 
					                vpop();
 | 
				
			||||||
 | 
					            tt = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (1) {
 | 
				
			||||||
 | 
					            if (c == 0)
 | 
				
			||||||
 | 
					                nocode_wanted = 1;
 | 
				
			||||||
 | 
					            if (!g)
 | 
				
			||||||
                gexpr();
 | 
					                gexpr();
 | 
				
			||||||
            }
 | 
					
 | 
				
			||||||
            type1 = vtop->type;
 | 
					            type1 = vtop->type;
 | 
				
			||||||
            sv = *vtop; /* save value to handle it later */
 | 
					            sv = *vtop; /* save value to handle it later */
 | 
				
			||||||
            vtop--; /* no vpop so that FP stack is not flushed */
 | 
					            vtop--; /* no vpop so that FP stack is not flushed */
 | 
				
			||||||
            skip(':');
 | 
					            skip(':');
 | 
				
			||||||
            u = gjmp(0);
 | 
					 | 
				
			||||||
            gsym(tt);
 | 
					 | 
				
			||||||
            expr_cond();
 | 
					 | 
				
			||||||
            type2 = vtop->type;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            u = 0;
 | 
				
			||||||
 | 
					            if (c < 0)
 | 
				
			||||||
 | 
					                u = gjmp(0);
 | 
				
			||||||
 | 
					            gsym(tt);
 | 
				
			||||||
 | 
					            nocode_wanted = saved_nocode_wanted;
 | 
				
			||||||
 | 
					            if (c == 1)
 | 
				
			||||||
 | 
					                nocode_wanted = 1;
 | 
				
			||||||
 | 
					            expr_cond();
 | 
				
			||||||
 | 
					            nocode_wanted = saved_nocode_wanted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            type2 = vtop->type;
 | 
				
			||||||
            t1 = type1.t;
 | 
					            t1 = type1.t;
 | 
				
			||||||
            bt1 = t1 & VT_BTYPE;
 | 
					            bt1 = t1 & VT_BTYPE;
 | 
				
			||||||
            t2 = type2.t;
 | 
					            t2 = type2.t;
 | 
				
			||||||
| 
						 | 
					@ -5224,6 +5214,7 @@ static void expr_cond(void)
 | 
				
			||||||
            if (is_float(bt1) || is_float(bt2)) {
 | 
					            if (is_float(bt1) || is_float(bt2)) {
 | 
				
			||||||
                if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
 | 
					                if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
 | 
				
			||||||
                    type.t = VT_LDOUBLE;
 | 
					                    type.t = VT_LDOUBLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
 | 
					                } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
 | 
				
			||||||
                    type.t = VT_DOUBLE;
 | 
					                    type.t = VT_DOUBLE;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
| 
						 | 
					@ -5267,15 +5258,18 @@ static void expr_cond(void)
 | 
				
			||||||
            /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so
 | 
					            /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so
 | 
				
			||||||
               that `(expr ? a : b).mem` does not error  with "lvalue expected" */
 | 
					               that `(expr ? a : b).mem` does not error  with "lvalue expected" */
 | 
				
			||||||
            islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE);
 | 
					            islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE);
 | 
				
			||||||
 | 
					            islv &= c < 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* now we convert second operand */
 | 
					            /* now we convert second operand */
 | 
				
			||||||
            gen_cast(&type);
 | 
					            if (c != 1) {
 | 
				
			||||||
            if (islv) {
 | 
					                gen_cast(&type);
 | 
				
			||||||
                mk_pointer(&vtop->type);
 | 
					                if (islv) {
 | 
				
			||||||
                gaddrof();
 | 
					                    mk_pointer(&vtop->type);
 | 
				
			||||||
 | 
					                    gaddrof();
 | 
				
			||||||
 | 
					                } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
 | 
				
			||||||
 | 
					                    gaddrof();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
 | 
					
 | 
				
			||||||
                gaddrof();
 | 
					 | 
				
			||||||
            rc = RC_INT;
 | 
					            rc = RC_INT;
 | 
				
			||||||
            if (is_float(type.t)) {
 | 
					            if (is_float(type.t)) {
 | 
				
			||||||
                rc = RC_FLOAT;
 | 
					                rc = RC_FLOAT;
 | 
				
			||||||
| 
						 | 
					@ -5287,26 +5281,36 @@ static void expr_cond(void)
 | 
				
			||||||
            } else if ((type.t & VT_BTYPE) == VT_LLONG) {
 | 
					            } else if ((type.t & VT_BTYPE) == VT_LLONG) {
 | 
				
			||||||
                /* for long longs, we use fixed registers to avoid having
 | 
					                /* for long longs, we use fixed registers to avoid having
 | 
				
			||||||
                   to handle a complicated move */
 | 
					                   to handle a complicated move */
 | 
				
			||||||
                rc = RC_IRET; 
 | 
					                rc = RC_IRET;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            r2 = gv(rc);
 | 
					            tt = r2 = 0;
 | 
				
			||||||
 | 
					            if (c < 0) {
 | 
				
			||||||
 | 
					                r2 = gv(rc);
 | 
				
			||||||
 | 
					                tt = gjmp(0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            gsym(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* this is horrible, but we must also convert first
 | 
					            /* this is horrible, but we must also convert first
 | 
				
			||||||
               operand */
 | 
					               operand */
 | 
				
			||||||
            tt = gjmp(0);
 | 
					            vpushv(&sv);
 | 
				
			||||||
            gsym(u);
 | 
					            if (c != 2) {
 | 
				
			||||||
            /* put again first value and cast it */
 | 
					                gen_cast(&type);
 | 
				
			||||||
            *vtop = sv;
 | 
					                if (islv) {
 | 
				
			||||||
            gen_cast(&type);
 | 
					                    mk_pointer(&vtop->type);
 | 
				
			||||||
            if (islv) {
 | 
					                    gaddrof();
 | 
				
			||||||
                mk_pointer(&vtop->type);
 | 
					                } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
 | 
				
			||||||
                gaddrof();
 | 
					                    gaddrof();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (c != 0)
 | 
				
			||||||
 | 
					                vswap();
 | 
				
			||||||
 | 
					            vtop--;
 | 
				
			||||||
 | 
					            if (c < 0) {
 | 
				
			||||||
 | 
					                r1 = gv(rc);
 | 
				
			||||||
 | 
					                move_reg(r2, r1, type.t);
 | 
				
			||||||
 | 
					                vtop->r = r2;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
 | 
					 | 
				
			||||||
                gaddrof();
 | 
					 | 
				
			||||||
            r1 = gv(rc);
 | 
					 | 
				
			||||||
            move_reg(r2, r1, type.t);
 | 
					 | 
				
			||||||
            vtop->r = r2;
 | 
					 | 
				
			||||||
            gsym(tt);
 | 
					            gsym(tt);
 | 
				
			||||||
            if (islv)
 | 
					            if (islv)
 | 
				
			||||||
                indir();
 | 
					                indir();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue