if a switch is unreachable then so are the case labels. Unlike normal labels they can't possibly be reached from not-yet parsed code, so there's no reason to enable codegen again for those.
Unified · Split
| @@ -62,7 +62,15 @@ ST_DATA int nocode_wanted; /* no code generation wanted */ · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | /* Clear 'nocode_wanted' at label if it was used */ | 63 | /* Clear 'nocode_wanted' at label if it was used */ |
| 64 | ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }} | 64 | ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }} |
| 65 | static int gind(void) { int t = ind; CODE_ON(); if (debug_modes) tcc_tcov_block_begin(tcc_state); return t; } | 65 | static int gind(int known_unreachable) |
| 66 | { | ||
| 67 | int t = ind; | ||
| 68 | if (!known_unreachable) | ||
| 69 | CODE_ON(); | ||
| 70 | if (debug_modes) | ||
| 71 | tcc_tcov_block_begin(tcc_state); | ||
| 72 | return t; | ||
| 73 | } | ||
| 66 | 74 | ||
| 67 | /* Set 'nocode_wanted' after unconditional jumps */ | 75 | /* Set 'nocode_wanted' after unconditional jumps */ |
| 68 | static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } | 76 | static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } |
| @@ -99,6 +107,7 @@ static struct switch_t { · 30 unmodified lines | |||
| 99 | int sym; | 107 | int sym; |
| 100 | } **p; int n; /* list of case ranges */ | 108 | } **p; int n; /* list of case ranges */ |
| 101 | int def_sym; /* default symbol */ | 109 | int def_sym; /* default symbol */ |
| 110 | int nocode_wanted; | ||
| 102 | int *bsym; | 111 | int *bsym; |
| 103 | struct scope *scope; | 112 | struct scope *scope; |
| 104 | struct switch_t *prev; | 113 | struct switch_t *prev; |
| @@ -6769,7 +6778,7 @@ again: · 6664 unmodified lines | |||
| 6769 | } | 6778 | } |
| 6770 | 6779 | ||
| 6771 | } else if (t == TOK_WHILE) { | 6780 | } else if (t == TOK_WHILE) { |
| 6772 | d = gind(); | 6781 | d = gind(0); |
| 6773 | skip('('); | 6782 | skip('('); |
| 6774 | gexpr(); | 6783 | gexpr(); |
| 6775 | skip(')'); | 6784 | skip(')'); |
| @@ -6869,7 +6878,7 @@ again: · 93 unmodified lines | |||
| 6869 | } | 6878 | } |
| 6870 | skip(';'); | 6879 | skip(';'); |
| 6871 | a = b = 0; | 6880 | a = b = 0; |
| 6872 | c = d = gind(); | 6881 | c = d = gind(0); |
| 6873 | if (tok != ';') { | 6882 | if (tok != ';') { |
| 6874 | gexpr(); | 6883 | gexpr(); |
| 6875 | a = gvtst(1, 0); | 6884 | a = gvtst(1, 0); |
| @@ -6877,7 +6886,7 @@ again: · 1 unmodified line | |||
| 6877 | skip(';'); | 6886 | skip(';'); |
| 6878 | if (tok != ')') { | 6887 | if (tok != ')') { |
| 6879 | e = gjmp(0); | 6888 | e = gjmp(0); |
| 6880 | d = gind(); | 6889 | d = gind(0); |
| 6881 | gexpr(); | 6890 | gexpr(); |
| 6882 | vpop(); | 6891 | vpop(); |
| 6883 | gjmp_addr(c); | 6892 | gjmp_addr(c); |
| @@ -6892,7 +6901,7 @@ again: · 8 unmodified lines | |||
| 6892 | 6901 | ||
| 6893 | } else if (t == TOK_DO) { | 6902 | } else if (t == TOK_DO) { |
| 6894 | a = b = 0; | 6903 | a = b = 0; |
| 6895 | d = gind(); | 6904 | d = gind(0); |
| 6896 | lblock(&a, &b); | 6905 | lblock(&a, &b); |
| 6897 | gsym(b); | 6906 | gsym(b); |
| 6898 | skip(TOK_WHILE); | 6907 | skip(TOK_WHILE); |
| @@ -6911,6 +6920,7 @@ again: · 12 unmodified lines | |||
| 6911 | sw->bsym = &a; | 6920 | sw->bsym = &a; |
| 6912 | sw->scope = cur_scope; | 6921 | sw->scope = cur_scope; |
| 6913 | sw->prev = cur_switch; | 6922 | sw->prev = cur_switch; |
| 6923 | sw->nocode_wanted = nocode_wanted; | ||
| 6914 | cur_switch = sw; | 6924 | cur_switch = sw; |
| 6915 | 6925 | ||
| 6916 | skip('('); | 6926 | skip('('); |
| @@ -6965,7 +6975,7 @@ again: · 48 unmodified lines | |||
| 6965 | } | 6975 | } |
| 6966 | if (debug_modes) | 6976 | if (debug_modes) |
| 6967 | tcc_tcov_reset_ind(tcc_state); | 6977 | tcc_tcov_reset_ind(tcc_state); |
| 6968 | cr->sym = gind(); | 6978 | cr->sym = gind(cur_switch->nocode_wanted); |
| 6969 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); | 6979 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); |
| 6970 | skip(':'); | 6980 | skip(':'); |
| 6971 | is_expr = 0; | 6981 | is_expr = 0; |
| @@ -6978,7 +6988,7 @@ again: · 6 unmodified lines | |||
| 6978 | tcc_error("too many 'default'"); | 6988 | tcc_error("too many 'default'"); |
| 6979 | if (debug_modes) | 6989 | if (debug_modes) |
| 6980 | tcc_tcov_reset_ind(tcc_state); | 6990 | tcc_tcov_reset_ind(tcc_state); |
| 6981 | cur_switch->def_sym = gind(); | 6991 | cur_switch->def_sym = gind(cur_switch->nocode_wanted); |
| 6982 | skip(':'); | 6992 | skip(':'); |
| 6983 | is_expr = 0; | 6993 | is_expr = 0; |
| 6984 | goto block_after_label; | 6994 | goto block_after_label; |
| @@ -7044,7 +7054,7 @@ again: · 59 unmodified lines | |||
| 7044 | } else { | 7054 | } else { |
| 7045 | s = label_push(&global_label_stack, t, LABEL_DEFINED); | 7055 | s = label_push(&global_label_stack, t, LABEL_DEFINED); |
| 7046 | } | 7056 | } |
| 7047 | s->jnext = gind(); | 7057 | s->jnext = gind(0); |
| 7048 | s->cleanupstate = cur_scope->cl.s; | 7058 | s->cleanupstate = cur_scope->cl.s; |
| 7049 | 7059 | ||
| 7050 | block_after_label: | 7060 | block_after_label: |
| @@ -1418,6 +1418,13 @@ void optimize_out_test(void) · 1417 unmodified lines | |||
| 1418 | undefined_function(); | 1418 | undefined_function(); |
| 1419 | } | 1419 | } |
| 1420 | 1420 | ||
| 1421 | if (0) { | ||
| 1422 | switch (defined_function()) { | ||
| 1423 | case 0: undefined_function(); break; | ||
| 1424 | default: undefined_function(); break; | ||
| 1425 | } | ||
| 1426 | } | ||
| 1427 | |||
| 1421 | /* Leave the "if(1)return; printf()" in this order and last in the function */ | 1428 | /* Leave the "if(1)return; printf()" in this order and last in the function */ |
| 1422 | if (1) | 1429 | if (1) |
| 1423 | return; | 1430 | return; |