forked from Mirrors/tinycc
tccgen: fix expr_cond for alt. nocode_wanted
making shure that both the active and the passive branches do exacly the same thing.master
parent
f843cadb6b
commit
e5efd18435
92
tccgen.c
92
tccgen.c
|
@ -5150,41 +5150,17 @@ 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) {
|
|
||||||
if (tok != ':' || !gnu_ext) {
|
|
||||||
vpop();
|
|
||||||
gexpr();
|
|
||||||
}
|
|
||||||
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
|
/* needed to avoid having different registers saved in
|
||||||
each branch */
|
each branch */
|
||||||
if (is_float(vtop->type.t)) {
|
if (is_float(vtop->type.t)) {
|
||||||
|
@ -5194,28 +5170,42 @@ static void expr_cond(void)
|
||||||
rc = RC_ST0;
|
rc = RC_ST0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
rc = RC_INT;
|
rc = RC_INT;
|
||||||
gv(rc);
|
|
||||||
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 {
|
} else {
|
||||||
tt = gvtst(1, 0);
|
if (!g)
|
||||||
gexpr();
|
vpop();
|
||||||
|
tt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (1) {
|
||||||
|
if (c == 0)
|
||||||
|
nocode_wanted = 1;
|
||||||
|
if (!g)
|
||||||
|
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 = 0;
|
||||||
|
if (c < 0)
|
||||||
u = gjmp(0);
|
u = gjmp(0);
|
||||||
gsym(tt);
|
gsym(tt);
|
||||||
|
nocode_wanted = saved_nocode_wanted;
|
||||||
|
if (c == 1)
|
||||||
|
nocode_wanted = 1;
|
||||||
expr_cond();
|
expr_cond();
|
||||||
type2 = vtop->type;
|
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 */
|
||||||
|
if (c != 1) {
|
||||||
gen_cast(&type);
|
gen_cast(&type);
|
||||||
if (islv) {
|
if (islv) {
|
||||||
mk_pointer(&vtop->type);
|
mk_pointer(&vtop->type);
|
||||||
gaddrof();
|
gaddrof();
|
||||||
}
|
} else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
|
||||||
else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
|
|
||||||
gaddrof();
|
gaddrof();
|
||||||
|
}
|
||||||
|
|
||||||
rc = RC_INT;
|
rc = RC_INT;
|
||||||
if (is_float(type.t)) {
|
if (is_float(type.t)) {
|
||||||
rc = RC_FLOAT;
|
rc = RC_FLOAT;
|
||||||
|
@ -5290,23 +5284,33 @@ static void expr_cond(void)
|
||||||
rc = RC_IRET;
|
rc = RC_IRET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tt = r2 = 0;
|
||||||
|
if (c < 0) {
|
||||||
r2 = gv(rc);
|
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 */
|
|
||||||
*vtop = sv;
|
|
||||||
gen_cast(&type);
|
gen_cast(&type);
|
||||||
if (islv) {
|
if (islv) {
|
||||||
mk_pointer(&vtop->type);
|
mk_pointer(&vtop->type);
|
||||||
gaddrof();
|
gaddrof();
|
||||||
}
|
} else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
|
||||||
else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
|
|
||||||
gaddrof();
|
gaddrof();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c != 0)
|
||||||
|
vswap();
|
||||||
|
vtop--;
|
||||||
|
if (c < 0) {
|
||||||
r1 = gv(rc);
|
r1 = gv(rc);
|
||||||
move_reg(r2, r1, type.t);
|
move_reg(r2, r1, type.t);
|
||||||
vtop->r = r2;
|
vtop->r = r2;
|
||||||
|
}
|
||||||
gsym(tt);
|
gsym(tt);
|
||||||
if (islv)
|
if (islv)
|
||||||
indir();
|
indir();
|
||||||
|
|
Loading…
Reference in New Issue