aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorgrischka <grischka>2016-12-18 18:55:55 +0100
committergrischka <grischka>2016-12-18 18:55:55 +0100
commite5efd184358e4a4a48c05f6e92b78066a4f98e2a (patch)
treeea947b7f17940a296864123e4773c277024e9fa5 /tccgen.c
parentf843cadb6bc07b3b3de6786233df4592d2d5f60d (diff)
downloadtinycc-e5efd184358e4a4a48c05f6e92b78066a4f98e2a.tar.gz
tinycc-e5efd184358e4a4a48c05f6e92b78066a4f98e2a.tar.bz2
tccgen: fix expr_cond for alt. nocode_wanted
making shure that both the active and the passive branches do exacly the same thing.
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c144
1 files changed, 74 insertions, 70 deletions
diff --git a/tccgen.c b/tccgen.c
index cb013d1..f346b13 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -5150,72 +5150,62 @@ static int condition_3way(void)
static void expr_cond(void)
{
- int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv;
- int c;
+ int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g;
SValue sv;
CType type, type1, type2;
+ int saved_nocode_wanted = nocode_wanted;
expr_lor();
if (tok == '?') {
next();
c = condition_3way();
- if (c >= 0) {
- int saved_nocode_wanted = nocode_wanted;
- 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
- each branch */
- if (is_float(vtop->type.t)) {
- rc = RC_FLOAT;
+ g = (tok == ':' && gnu_ext);
+ if (c < 0) {
+ /* needed to avoid having different registers saved in
+ each branch */
+ if (is_float(vtop->type.t)) {
+ rc = RC_FLOAT;
#ifdef TCC_TARGET_X86_64
- if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
- rc = RC_ST0;
- }
-#endif
+ if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
+ rc = RC_ST0;
}
- else
- rc = RC_INT;
- gv(rc);
- save_regs(1);
- }
- if (tok == ':' && gnu_ext) {
+#endif
+ } else
+ rc = RC_INT;
+ save_regs(1);
+ gv(rc);
+ if (g)
gv_dup();
- tt = gvtst(1, 0);
- } else {
- tt = gvtst(1, 0);
+ tt = gvtst(1, 0);
+
+ } else {
+ if (!g)
+ vpop();
+ tt = 0;
+ }
+
+ if (1) {
+ if (c == 0)
+ nocode_wanted = 1;
+ if (!g)
gexpr();
- }
+
type1 = vtop->type;
sv = *vtop; /* save value to handle it later */
vtop--; /* no vpop so that FP stack is not flushed */
skip(':');
- u = gjmp(0);
+
+ u = 0;
+ if (c < 0)
+ u = gjmp(0);
gsym(tt);
+ nocode_wanted = saved_nocode_wanted;
+ if (c == 1)
+ nocode_wanted = 1;
expr_cond();
- type2 = vtop->type;
+ nocode_wanted = saved_nocode_wanted;
+ type2 = vtop->type;
t1 = type1.t;
bt1 = t1 & VT_BTYPE;
t2 = type2.t;
@@ -5224,6 +5214,7 @@ static void expr_cond(void)
if (is_float(bt1) || is_float(bt2)) {
if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
type.t = VT_LDOUBLE;
+
} else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
type.t = VT_DOUBLE;
} else {
@@ -5267,15 +5258,18 @@ static void expr_cond(void)
/* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so
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 &= c < 0;
/* now we convert second operand */
- gen_cast(&type);
- if (islv) {
- mk_pointer(&vtop->type);
- gaddrof();
+ if (c != 1) {
+ gen_cast(&type);
+ if (islv) {
+ 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;
if (is_float(type.t)) {
rc = RC_FLOAT;
@@ -5287,26 +5281,36 @@ static void expr_cond(void)
} else if ((type.t & VT_BTYPE) == VT_LLONG) {
/* for long longs, we use fixed registers to avoid having
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
operand */
- tt = gjmp(0);
- gsym(u);
- /* put again first value and cast it */
- *vtop = sv;
- gen_cast(&type);
- if (islv) {
- mk_pointer(&vtop->type);
- gaddrof();
+ vpushv(&sv);
+ if (c != 2) {
+ gen_cast(&type);
+ if (islv) {
+ mk_pointer(&vtop->type);
+ gaddrof();
+ } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
+ 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);
if (islv)
indir();