| @@ -90,7 +90,7 @@ static CString initstr; · 89 unmodified lines |
| 90 | static struct switch_t { | 90 | static struct switch_t { |
| 91 | struct case_t { | 91 | struct case_t { |
| 92 | int64_t v1, v2; | 92 | int64_t v1, v2; |
| 93 | int sym; | 93 | int ind, line; |
| 94 | } **p; int n; /* list of case ranges */ | 94 | } **p; int n; /* list of case ranges */ |
| 95 | int def_sym; /* default symbol */ | 95 | int def_sym; /* default symbol */ |
| 96 | int nocode_wanted; | 96 | int nocode_wanted; |
| @@ -2236,7 +2236,11 @@ static void gen_opl(int op) · 2139 unmodified lines |
| 2236 | vtop[-1] = vtop[-2]; | 2236 | vtop[-1] = vtop[-2]; |
| 2237 | vtop[-2] = tmp; | 2237 | vtop[-2] = tmp; |
| 2238 | /* stack: L1 L2 H1 H2 */ | 2238 | /* stack: L1 L2 H1 H2 */ |
| 2239 | save_regs(4); | 2239 | if (!cur_switch || cur_switch->bsym) { |
| | 2240 | /* avoid differnt registers being saved in branches. |
| | 2241 | This is not needed when comparing switch cases */ |
| | 2242 | save_regs(4); |
| | 2243 | } |
| 2240 | /* compare high */ | 2244 | /* compare high */ |
| 2241 | op1 = op; | 2245 | op1 = op; |
| 2242 | /* when values are equal, we need to compare low words. since | 2246 | /* when values are equal, we need to compare low words. since |
| @@ -2285,6 +2289,18 @@ static void gen_opl(int op) · 42 unmodified lines |
| 2285 | } | 2289 | } |
| 2286 | #endif | 2290 | #endif |
| 2287 | | 2291 | |
| | 2292 | /* normalize values */ |
| | 2293 | static uint64_t value64(uint64_t l1, int t) |
| | 2294 | { |
| | 2295 | if ((t & VT_BTYPE) == VT_LLONG |
| | 2296 | || (PTR_SIZE == 8 && (t & VT_BTYPE) == VT_PTR)) |
| | 2297 | return l1; |
| | 2298 | else if (t & VT_UNSIGNED) |
| | 2299 | return (uint32_t)l1; |
| | 2300 | else |
| | 2301 | return (uint32_t)l1 | -(l1 & 0x80000000); |
| | 2302 | } |
| | 2303 | |
| 2288 | static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b) | 2304 | static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b) |
| 2289 | { | 2305 | { |
| 2290 | uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b); | 2306 | uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b); |
| @@ -2306,18 +2322,11 @@ static void gen_opic(int op) · 15 unmodified lines |
| 2306 | int t2 = v2->type.t & VT_BTYPE; | 2322 | int t2 = v2->type.t & VT_BTYPE; |
| 2307 | int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; | 2323 | int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
| 2308 | int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; | 2324 | int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
| 2309 | uint64_t l1 = c1 ? v1->c.i : 0; | 2325 | uint64_t l1 = c1 ? value64(v1->c.i, v1->type.t) : 0; |
| 2310 | uint64_t l2 = c2 ? v2->c.i : 0; | 2326 | uint64_t l2 = c2 ? value64(v2->c.i, v2->type.t) : 0; |
| 2311 | int shm = (t1 == VT_LLONG) ? 63 : 31; | 2327 | int shm = (t1 == VT_LLONG) ? 63 : 31; |
| 2312 | int r; | 2328 | int r; |
| 2313 | | 2329 | |
| 2314 | if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) | | |
| 2315 | l1 = ((uint32_t)l1 | | | |
| 2316 | (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); | | |
| 2317 | if (t2 != VT_LLONG && (PTR_SIZE != 8 || t2 != VT_PTR)) | | |
| 2318 | l2 = ((uint32_t)l2 | | | |
| 2319 | (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000))); | | |
| 2320 | | | |
| 2321 | if (c1 && c2) { | 2330 | if (c1 && c2) { |
| 2322 | switch(op) { | 2331 | switch(op) { |
| 2323 | case '+': l1 += l2; break; | 2332 | case '+': l1 += l2; break; |
| @@ -2367,10 +2376,7 @@ static void gen_opic(int op) · 43 unmodified lines |
| 2367 | default: | 2376 | default: |
| 2368 | goto general_case; | 2377 | goto general_case; |
| 2369 | } | 2378 | } |
| 2370 | if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) | 2379 | v1->c.i = value64(l1, v1->type.t); |
| 2371 | l1 = ((uint32_t)l1 | | | |
| 2372 | (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); | | |
| 2373 | v1->c.i = l1; | | |
| 2374 | v1->r |= v2->r & VT_NONCONST; | 2380 | v1->r |= v2->r & VT_NONCONST; |
| 2375 | vtop--; | 2381 | vtop--; |
| 2376 | } else { | 2382 | } else { |
| @@ -6701,79 +6707,74 @@ static void check_func_return(void) · 4324 unmodified lines |
| 6701 | /* ------------------------------------------------------------------------- */ | 6707 | /* ------------------------------------------------------------------------- */ |
| 6702 | /* switch/case */ | 6708 | /* switch/case */ |
| 6703 | | 6709 | |
| 6704 | static int case_cmpi(const void *pa, const void *pb) | 6710 | static int case_cmp(uint64_t a, uint64_t b) |
| 6705 | { | 6711 | { |
| 6706 | int64_t a = (*(struct case_t**) pa)->v1; | 6712 | if (cur_switch->sv.type.t & VT_UNSIGNED) |
| 6707 | int64_t b = (*(struct case_t**) pb)->v1; | 6713 | return a < b ? -1 : a > b; |
| 6708 | return a < b ? -1 : a > b; | 6714 | else |
| | 6715 | return (int64_t)a < (int64_t)b ? -1 : (int64_t)a > (int64_t)b; |
| 6709 | } | 6716 | } |
| 6710 | | 6717 | |
| 6711 | static int case_cmpu(const void *pa, const void *pb) | 6718 | static int case_cmp_qs(const void *pa, const void *pb) |
| 6712 | { | 6719 | { |
| 6713 | uint64_t a = (uint64_t)(*(struct case_t**) pa)->v1; | 6720 | return case_cmp((*(struct case_t**)pa)->v1, (*(struct case_t**)pb)->v1); |
| 6714 | uint64_t b = (uint64_t)(*(struct case_t**) pb)->v1; | | |
| 6715 | return a < b ? -1 : a > b; | | |
| 6716 | } | 6721 | } |
| 6717 | | 6722 | |
| 6718 | static void gtst_addr(int t, int a) | 6723 | static void case_sort(struct switch_t *sw) |
| 6719 | { | 6724 | { |
| 6720 | gsym_addr(gvtst(0, t), a); | 6725 | struct case_t **p; |
| | 6726 | if (sw->n < 2) |
| | 6727 | return; |
| | 6728 | qsort(sw->p, sw->n, sizeof *sw->p, case_cmp_qs); |
| | 6729 | p = sw->p; |
| | 6730 | while (p < sw->p + sw->n - 1) { |
| | 6731 | if (case_cmp(p[0]->v2, p[1]->v1) >= 0) { |
| | 6732 | int l1 = p[0]->line, l2 = p[1]->line; |
| | 6733 | /* using special format "%i:..." to show specific line */ |
| | 6734 | tcc_error("%i:duplicate case value", l1 > l2 ? l1 : l2); |
| | 6735 | } else if (p[0]->v2 + 1 == p[1]->v1 && p[0]->ind == p[1]->ind) { |
| | 6736 | /* treat "case 1: case 2: case 3:" like "case 1 ... 3: */ |
| | 6737 | p[1]->v1 = p[0]->v1; |
| | 6738 | tcc_free(p[0]); |
| | 6739 | memmove(p, p + 1, (--sw->n - (p - sw->p)) * sizeof *p); |
| | 6740 | } else |
| | 6741 | ++p; |
| | 6742 | } |
| 6721 | } | 6743 | } |
| 6722 | | 6744 | |
| 6723 | static void gcase(struct case_t **base, int len, int *bsym) | 6745 | static int gcase(struct case_t **base, int len, int dsym) |
| 6724 | { | 6746 | { |
| 6725 | struct case_t *p; | 6747 | struct case_t *p; |
| 6726 | int e; | 6748 | int t, l2, e; |
| 6727 | int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG; | 6749 | |
| 6728 | while (len > 8) { | 6750 | t = vtop->type.t & VT_BTYPE; |
| 6729 | /* binary search */ | 6751 | if (t != VT_LLONG) |
| 6730 | p = base[len/2]; | 6752 | t = VT_INT; |
| 6731 | vdup(); | 6753 | while (len) { |
| 6732 | if (ll) | 6754 | /* binary search while len > 8, else linear */ |
| 6733 | vpushll(p->v2); | 6755 | l2 = len > 8 ? len/2 : 0; |
| 6734 | else | 6756 | p = base[l2]; |
| 6735 | vpushi(p->v2); | 6757 | vdup(), vpush64(t, p->v2); |
| 6736 | gen_op(TOK_LE); | 6758 | if (l2 == 0 && p->v1 == p->v2) { |
| 6737 | e = gvtst(1, 0); | 6759 | gen_op(TOK_EQ); /* jmp to case when equal */ |
| 6738 | vdup(); | 6760 | gsym_addr(gvtst(0, 0), p->ind); |
| 6739 | if (ll) | | |
| 6740 | vpushll(p->v1); | | |
| 6741 | else | | |
| 6742 | vpushi(p->v1); | | |
| 6743 | gen_op(TOK_GE); | | |
| 6744 | gtst_addr(0, p->sym); /* v1 <= x <= v2 */ | | |
| 6745 | /* x < v1 */ | | |
| 6746 | gcase(base, len/2, bsym); | | |
| 6747 | /* x > v2 */ | | |
| 6748 | gsym(e); | | |
| 6749 | e = len/2 + 1; | | |
| 6750 | base += e; len -= e; | | |
| 6751 | } | | |
| 6752 | /* linear scan */ | | |
| 6753 | while (len--) { | | |
| 6754 | p = *base++; | | |
| 6755 | vdup(); | | |
| 6756 | if (ll) | | |
| 6757 | vpushll(p->v2); | | |
| 6758 | else | | |
| 6759 | vpushi(p->v2); | | |
| 6760 | if (p->v1 == p->v2) { | | |
| 6761 | gen_op(TOK_EQ); | | |
| 6762 | gtst_addr(0, p->sym); | | |
| 6763 | } else { | 6761 | } else { |
| 6764 | gen_op(TOK_LE); | 6762 | /* case v1 ... v2 */ |
| 6765 | e = gvtst(1, 0); | 6763 | gen_op(TOK_GT); /* jmp over when > V2 */ |
| 6766 | vdup(); | 6764 | if (len == 1) /* last case test jumps to default when false */ |
| 6767 | if (ll) | 6765 | dsym = gvtst(0, dsym), e = 0; |
| 6768 | vpushll(p->v1); | 6766 | else |
| 6769 | else | 6767 | e = gvtst(0, 0); |
| 6770 | vpushi(p->v1); | 6768 | vdup(), vpush64(t, p->v1); |
| 6771 | gen_op(TOK_GE); | 6769 | gen_op(TOK_GE); /* jmp to case when >= V1 */ |
| 6772 | gtst_addr(0, p->sym); | 6770 | gsym_addr(gvtst(0, 0), p->ind); |
| | 6771 | dsym = gcase(base, l2, dsym); |
| 6773 | gsym(e); | 6772 | gsym(e); |
| 6774 | } | 6773 | } |
| | 6774 | ++l2, base += l2, len -= l2; |
| 6775 | } | 6775 | } |
| 6776 | *bsym = gjmp(*bsym); | 6776 | /* jump automagically will suppress more jumps */ |
| | 6777 | return gjmp(dsym); |
| 6777 | } | 6778 | } |
| 6778 | | 6779 | |
| 6779 | static void end_switch(void) | 6780 | static void end_switch(void) |
| @@ -6791,8 +6792,8 @@ static void try_call_scope_cleanup(Sym *stop) · 11 unmodified lines |
| 6791 | { | 6792 | { |
| 6792 | Sym *cls = cur_scope->cl.s; | 6793 | Sym *cls = cur_scope->cl.s; |
| 6793 | | 6794 | |
| 6794 | for (; cls != stop; cls = cls->ncl) { | 6795 | for (; cls != stop; cls = cls->next) { |
| 6795 | Sym *fs = cls->next; | 6796 | Sym *fs = cls->cleanup_func; |
| 6796 | Sym *vs = cls->prev_tok; | 6797 | Sym *vs = cls->prev_tok; |
| 6797 | | 6798 | |
| 6798 | vpushsym(&fs->type, fs); | 6799 | vpushsym(&fs->type, fs); |
| @@ -6814,11 +6815,11 @@ static void try_call_cleanup_goto(Sym *cleanupstate) · 15 unmodified lines |
| 6814 | | 6815 | |
| 6815 | /* search NCA of both cleanup chains given parents and initial depth */ | 6816 | /* search NCA of both cleanup chains given parents and initial depth */ |
| 6816 | ocd = cleanupstate ? cleanupstate->v & ~SYM_FIELD : 0; | 6817 | ocd = cleanupstate ? cleanupstate->v & ~SYM_FIELD : 0; |
| 6817 | for (ccd = cur_scope->cl.n, oc = cleanupstate; ocd > ccd; --ocd, oc = oc->ncl) | 6818 | for (ccd = cur_scope->cl.n, oc = cleanupstate; ocd > ccd; --ocd, oc = oc->next) |
| 6818 | ; | 6819 | ; |
| 6819 | for (cc = cur_scope->cl.s; ccd > ocd; --ccd, cc = cc->ncl) | 6820 | for (cc = cur_scope->cl.s; ccd > ocd; --ccd, cc = cc->next) |
| 6820 | ; | 6821 | ; |
| 6821 | for (; cc != oc; cc = cc->ncl, oc = oc->ncl, --ccd) | 6822 | for (; cc != oc; cc = cc->next, oc = oc->next, --ccd) |
| 6822 | ; | 6823 | ; |
| 6823 | | 6824 | |
| 6824 | try_call_scope_cleanup(cc); | 6825 | try_call_scope_cleanup(cc); |
| @@ -7153,6 +7154,8 @@ again: · 328 unmodified lines |
| 7153 | skip('('); | 7154 | skip('('); |
| 7154 | gexpr(); | 7155 | gexpr(); |
| 7155 | skip(')'); | 7156 | skip(')'); |
| | 7157 | if (!is_integer_btype(vtop->type.t & VT_BTYPE)) |
| | 7158 | tcc_error("switch value not an integer"); |
| 7156 | sw->sv = *vtop--; /* save switch value */ | 7159 | sw->sv = *vtop--; /* save switch value */ |
| 7157 | a = 0; | 7160 | a = 0; |
| 7158 | b = gjmp(0); /* jump to first case */ | 7161 | b = gjmp(0); /* jump to first case */ |
| @@ -7161,21 +7164,13 @@ again: · 2 unmodified lines |
| 7161 | /* case lookup */ | 7164 | /* case lookup */ |
| 7162 | gsym(b); | 7165 | gsym(b); |
| 7163 | prev_scope_s(&o); | 7166 | prev_scope_s(&o); |
| 7164 | | | |
| 7165 | if (sw->nocode_wanted) | 7167 | if (sw->nocode_wanted) |
| 7166 | goto skip_switch; | 7168 | goto skip_switch; |
| 7167 | if (sw->sv.type.t & VT_UNSIGNED) | 7169 | case_sort(sw); |
| 7168 | qsort(sw->p, sw->n, sizeof(void*), case_cmpu); | 7170 | sw->bsym = NULL; /* marker for 32bit:gen_opl() */ |
| 7169 | else | | |
| 7170 | qsort(sw->p, sw->n, sizeof(void*), case_cmpi); | | |
| 7171 | for (b = 1; b < sw->n; b++) | | |
| 7172 | if (sw->sv.type.t & VT_UNSIGNED | | |
| 7173 | ? (uint64_t)sw->p[b - 1]->v2 >= (uint64_t)sw->p[b]->v1 | | |
| 7174 | : sw->p[b - 1]->v2 >= sw->p[b]->v1) | | |
| 7175 | tcc_error("duplicate case value"); | | |
| 7176 | vpushv(&sw->sv); | 7171 | vpushv(&sw->sv); |
| 7177 | gv(RC_INT); | 7172 | gv(RC_INT); |
| 7178 | d = 0, gcase(sw->p, sw->n, &d); | 7173 | d = gcase(sw->p, sw->n, 0); |
| 7179 | vpop(); | 7174 | vpop(); |
| 7180 | if (sw->def_sym) | 7175 | if (sw->def_sym) |
| 7181 | gsym_addr(d, sw->def_sym); | 7176 | gsym_addr(d, sw->def_sym); |
| @@ -7192,17 +7187,18 @@ again: · 10 unmodified lines |
| 7192 | expect("switch"); | 7187 | expect("switch"); |
| 7193 | cr = tcc_malloc(sizeof(struct case_t)); | 7188 | cr = tcc_malloc(sizeof(struct case_t)); |
| 7194 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); | 7189 | dynarray_add(&cur_switch->p, &cur_switch->n, cr); |
| 7195 | cr->v1 = cr->v2 = expr_const64(); | 7190 | t = cur_switch->sv.type.t; |
| 7196 | if (gnu_ext && tok == TOK_DOTS) { | 7191 | cr->v1 = cr->v2 = value64(expr_const64(), t); |
| | 7192 | if (tok == TOK_DOTS && gnu_ext) { |
| 7197 | next(); | 7193 | next(); |
| 7198 | cr->v2 = expr_const64(); | 7194 | cr->v2 = value64(expr_const64(), t); |
| 7199 | if ((!(cur_switch->sv.type.t & VT_UNSIGNED) && cr->v2 < cr->v1) | 7195 | if (case_cmp(cr->v2, cr->v1) < 0) |
| 7200 | || (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1)) | | |
| 7201 | tcc_warning("empty case range"); | 7196 | tcc_warning("empty case range"); |
| 7202 | } | 7197 | } |
| 7203 | /* case and default are unreachable from a switch under nocode_wanted */ | 7198 | /* case and default are unreachable from a switch under nocode_wanted */ |
| 7204 | if (!cur_switch->nocode_wanted) | 7199 | if (!cur_switch->nocode_wanted) |
| 7205 | cr->sym = gind(); | 7200 | cr->ind = gind(); |
| | 7201 | cr->line = file->line_num; |
| 7206 | skip(':'); | 7202 | skip(':'); |
| 7207 | goto block_after_label; | 7203 | goto block_after_label; |
| 7208 | | 7204 | |
| @@ -7211,7 +7207,7 @@ again: · 2 unmodified lines |
| 7211 | expect("switch"); | 7207 | expect("switch"); |
| 7212 | if (cur_switch->def_sym) | 7208 | if (cur_switch->def_sym) |
| 7213 | tcc_error("too many 'default'"); | 7209 | tcc_error("too many 'default'"); |
| 7214 | cur_switch->def_sym = cur_switch->nocode_wanted ? 1 : gind(); | 7210 | cur_switch->def_sym = cur_switch->nocode_wanted ? -1 : gind(); |
| 7215 | skip(':'); | 7211 | skip(':'); |
| 7216 | goto block_after_label; | 7212 | goto block_after_label; |
| 7217 | | 7213 | |
| @@ -7244,7 +7240,7 @@ again: · 26 unmodified lines |
| 7244 | s->jnext = gjmp(s->jnext); | 7240 | s->jnext = gjmp(s->jnext); |
| 7245 | } else { | 7241 | } else { |
| 7246 | try_call_cleanup_goto(s->cleanupstate); | 7242 | try_call_cleanup_goto(s->cleanupstate); |
| 7247 | gjmp_addr(s->jnext); | 7243 | gjmp_addr(s->jind); |
| 7248 | } | 7244 | } |
| 7249 | next(); | 7245 | next(); |
| 7250 | | 7246 | |
| @@ -7275,7 +7271,7 @@ again: · 24 unmodified lines |
| 7275 | } else { | 7271 | } else { |
| 7276 | s = label_push(&global_label_stack, t, LABEL_DEFINED); | 7272 | s = label_push(&global_label_stack, t, LABEL_DEFINED); |
| 7277 | } | 7273 | } |
| 7278 | s->jnext = gind(); | 7274 | s->jind = gind(); |
| 7279 | s->cleanupstate = cur_scope->cl.s; | 7275 | s->cleanupstate = cur_scope->cl.s; |
| 7280 | | 7276 | |
| 7281 | block_after_label: | 7277 | block_after_label: |
| @@ -8132,8 +8128,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 850 unmodified lines |
| 8132 | Sym *cls = sym_push2(&all_cleanups, | 8128 | Sym *cls = sym_push2(&all_cleanups, |
| 8133 | SYM_FIELD | ++cur_scope->cl.n, 0, 0); | 8129 | SYM_FIELD | ++cur_scope->cl.n, 0, 0); |
| 8134 | cls->prev_tok = sym; | 8130 | cls->prev_tok = sym; |
| 8135 | cls->next = ad->cleanup_func; | 8131 | cls->cleanup_func = ad->cleanup_func; |
| 8136 | cls->ncl = cur_scope->cl.s; | 8132 | cls->next = cur_scope->cl.s; |
| 8137 | cur_scope->cl.s = cls; | 8133 | cur_scope->cl.s = cls; |
| 8138 | } | 8134 | } |
| 8139 | | 8135 | |