mirror of
https://github.com/frida/tinycc
synced 2025-01-01 17:44:26 +03:00
opt: Make break and goto not fallthrough
As we can optimize dead code a bit already it's fitting to disable code emission after break and goto.
This commit is contained in:
parent
31c7ea0165
commit
ca435dc2e3
19
tccgen.c
19
tccgen.c
@ -5396,7 +5396,8 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
nocode_wanted |= 2;
|
||||
a = gvtst(1, 0);
|
||||
block(bsym, csym, 0);
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
if (cond != 1)
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
c = tok;
|
||||
if (c == TOK_ELSE) {
|
||||
next();
|
||||
@ -5406,10 +5407,12 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
gsym(a);
|
||||
block(bsym, csym, 0);
|
||||
gsym(d); /* patch else jmp */
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
if (cond != 0)
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
} else
|
||||
gsym(a);
|
||||
} else if (tok == TOK_WHILE) {
|
||||
int saved_nocode_wanted;
|
||||
nocode_wanted &= ~2;
|
||||
next();
|
||||
d = ind;
|
||||
@ -5420,7 +5423,9 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
a = gvtst(1, 0);
|
||||
b = 0;
|
||||
++local_scope;
|
||||
saved_nocode_wanted = nocode_wanted;
|
||||
block(&a, &b, 0);
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
--local_scope;
|
||||
if(!nocode_wanted)
|
||||
gjmp_addr(d);
|
||||
@ -5556,6 +5561,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
/* jump unless last stmt in top-level block */
|
||||
if (tok != '}' || local_scope != 1)
|
||||
rsym = gjmp(rsym);
|
||||
nocode_wanted |= 2;
|
||||
} else if (tok == TOK_BREAK) {
|
||||
/* compute jump */
|
||||
if (!bsym)
|
||||
@ -5563,6 +5569,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
*bsym = gjmp(*bsym);
|
||||
next();
|
||||
skip(';');
|
||||
nocode_wanted |= 2;
|
||||
} else if (tok == TOK_CONTINUE) {
|
||||
/* compute jump */
|
||||
if (!csym)
|
||||
@ -5573,6 +5580,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
skip(';');
|
||||
} else if (tok == TOK_FOR) {
|
||||
int e;
|
||||
int saved_nocode_wanted;
|
||||
nocode_wanted &= ~2;
|
||||
next();
|
||||
skip('(');
|
||||
@ -5607,7 +5615,9 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
gsym(e);
|
||||
}
|
||||
skip(')');
|
||||
saved_nocode_wanted = nocode_wanted;
|
||||
block(&a, &b, 0);
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
if(!nocode_wanted)
|
||||
gjmp_addr(c);
|
||||
gsym(a);
|
||||
@ -5617,13 +5627,16 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
|
||||
} else
|
||||
if (tok == TOK_DO) {
|
||||
int saved_nocode_wanted;
|
||||
nocode_wanted &= ~2;
|
||||
next();
|
||||
a = 0;
|
||||
b = 0;
|
||||
d = ind;
|
||||
vla_sp_restore();
|
||||
saved_nocode_wanted = nocode_wanted;
|
||||
block(&a, &b, 0);
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
skip(TOK_WHILE);
|
||||
skip('(');
|
||||
gsym(b);
|
||||
@ -5637,6 +5650,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
} else
|
||||
if (tok == TOK_SWITCH) {
|
||||
struct switch_t *saved, sw;
|
||||
int saved_nocode_wanted = nocode_wanted;
|
||||
next();
|
||||
skip('(');
|
||||
gexpr();
|
||||
@ -5650,6 +5664,7 @@ static void block(int *bsym, int *csym, int is_expr)
|
||||
saved = cur_switch;
|
||||
cur_switch = &sw;
|
||||
block(&a, csym, 0);
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
a = gjmp(a); /* add implicit break */
|
||||
/* case lookup */
|
||||
gsym(b);
|
||||
|
@ -1184,6 +1184,57 @@ void optimize_out(void)
|
||||
printf("oo:%d\n", defined_function());
|
||||
else
|
||||
printf("oo:%d\n", undefined_function());
|
||||
while (1) {
|
||||
printf("oow:%d\n", defined_function());
|
||||
break;
|
||||
printf("oow:%d\n", undefined_function());
|
||||
}
|
||||
j = 1;
|
||||
/* Following is a switch without {} block intentionally. */
|
||||
switch (j)
|
||||
case 1: break;
|
||||
printf ("oos:%d\n", defined_function());
|
||||
/* The following break shouldn't lead to disabled code after
|
||||
the while. */
|
||||
while (1)
|
||||
break;
|
||||
printf ("ool1:%d\n", defined_function());
|
||||
/* Same for the other types of loops. */
|
||||
do
|
||||
break;
|
||||
while (1);
|
||||
printf ("ool2:%d\n", defined_function());
|
||||
for (;;)
|
||||
break;
|
||||
printf ("ool3:%d\n", defined_function());
|
||||
/* Normal {} blocks without controlling statements
|
||||
shouldn't reactivate code emission */
|
||||
while (1) {
|
||||
{
|
||||
break;
|
||||
}
|
||||
printf ("ool4:%d\n", undefined_function());
|
||||
}
|
||||
j = 1;
|
||||
while (j) {
|
||||
if (j == 0)
|
||||
break; /* this break shouldn't disable code outside the if. */
|
||||
printf("ool5:%d\n", defined_function());
|
||||
j--;
|
||||
}
|
||||
|
||||
j = 1;
|
||||
while (j) {
|
||||
if (1)
|
||||
j--;
|
||||
else
|
||||
breakhere: break;
|
||||
printf("ool6:%d\n", defined_function());
|
||||
goto breakhere;
|
||||
}
|
||||
if (1)
|
||||
return;
|
||||
printf ("oor:%d\n", undefined_function());
|
||||
}
|
||||
|
||||
int defined_function(void)
|
||||
|
Loading…
Reference in New Issue
Block a user