| @@ -62,7 +62,8 @@ ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; · 61 unmodified lines |
| 62 | 62 | |
| 63 | 63 | ST_DATA struct switch_t { |
| 64 | 64 | struct case_t { |
| 65 | | − int v1, v2, sym; |
| 65 | + int64_t v1, v2; |
| 66 | + int sym; |
| 66 | 67 | } **p; int n; /* list of case ranges */ |
| 67 | 68 | int def_sym; /* default symbol */ |
| 68 | 69 | } *cur_switch; /* current switch */ |
| @@ -86,6 +87,7 @@ static void vla_sp_restore(void); · 17 unmodified lines |
| 86 | 87 | static void vla_sp_restore_root(void); |
| 87 | 88 | static int is_compatible_parameter_types(CType *type1, CType *type2); |
| 88 | 89 | static void expr_type(CType *type); |
| 90 | +static inline int64_t expr_const64(void); |
| 89 | 91 | ST_FUNC void vpush64(int ty, unsigned long long v); |
| 90 | 92 | ST_FUNC void vpush(CType *type); |
| 91 | 93 | ST_FUNC int gvtst(int inv, int t); |
| @@ -434,7 +436,7 @@ ST_INLN Sym *sym_find(int v) · 342 unmodified lines |
| 434 | 436 | } |
| 435 | 437 | |
| 436 | 438 | /* push a given symbol on the symbol stack */ |
| 437 | | −ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) |
| 439 | +ST_FUNC Sym *sym_push(int v, CType *type, int r, long c) |
| 438 | 440 | { |
| 439 | 441 | Sym *s, **ps; |
| 440 | 442 | TokenSym *ts; |
| @@ -466,7 +468,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) · 25 unmodified lines |
| 466 | 468 | } |
| 467 | 469 | |
| 468 | 470 | /* push a global identifier */ |
| 469 | | −ST_FUNC Sym *global_identifier_push(int v, int t, int c) |
| 471 | +ST_FUNC Sym *global_identifier_push(int v, int t, long c) |
| 470 | 472 | { |
| 471 | 473 | Sym *s, **ps; |
| 472 | 474 | s = sym_push2(&global_stack, v, t, c); |
| @@ -698,7 +700,7 @@ ST_FUNC void vpush_global_sym(CType *type, int v) · 225 unmodified lines |
| 698 | 700 | vpushsym(type, external_global_sym(v, type, 0)); |
| 699 | 701 | } |
| 700 | 702 | |
| 701 | | −ST_FUNC void vset(CType *type, int r, int v) |
| 703 | +ST_FUNC void vset(CType *type, int r, long v) |
| 702 | 704 | { |
| 703 | 705 | CValue cval; |
| 704 | 706 | |
| @@ -1716,6 +1718,9 @@ static void gen_opic(int op) · 1011 unmodified lines |
| 1716 | 1718 | default: |
| 1717 | 1719 | goto general_case; |
| 1718 | 1720 | } |
| 1721 | + if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR)) |
| 1722 | + l1 = ((uint32_t)l1 | |
| 1723 | + (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000))); |
| 1719 | 1724 | v1->c.i = l1; |
| 1720 | 1725 | vtop--; |
| 1721 | 1726 | } else { |
| @@ -3248,7 +3253,8 @@ static Sym * find_field (CType *type, int v) · 1526 unmodified lines |
| 3248 | 3253 | /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ |
| 3249 | 3254 | static void struct_decl(CType *type, AttributeDef *ad, int u) |
| 3250 | 3255 | { |
| 3251 | | − int a, v, size, align, maxalign, c, offset, flexible, extra_bytes; |
| 3256 | + int a, v, size, align, maxalign, offset, flexible, extra_bytes; |
| 3257 | + long c; |
| 3252 | 3258 | int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt; |
| 3253 | 3259 | Sym *s, *ss, *ass, **ps; |
| 3254 | 3260 | AttributeDef ad1; |
| @@ -3293,7 +3299,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 38 unmodified lines |
| 3293 | 3299 | /* non empty enums are not allowed */ |
| 3294 | 3300 | if (a == TOK_ENUM) { |
| 3295 | 3301 | int seen_neg = 0; |
| 3302 | + int seen_wide = 0; |
| 3296 | 3303 | for(;;) { |
| 3304 | + CType *t = &int_type; |
| 3297 | 3305 | v = tok; |
| 3298 | 3306 | if (v < TOK_UIDENT) |
| 3299 | 3307 | expect("identifier"); |
| @@ -3304,12 +3312,23 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 4 unmodified lines |
| 3304 | 3312 | next(); |
| 3305 | 3313 | if (tok == '=') { |
| 3306 | 3314 | next(); |
| 3315 | +#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64) |
| 3316 | + c = expr_const64(); |
| 3317 | +#else |
| 3318 | + /* We really want to support long long enums |
| 3319 | + on i386 as well, but the Sym structure only |
| 3320 | + holds a 'long' for associated constants, |
| 3321 | + and enlarging it would bump its size (no |
| 3322 | + available padding). So punt for now. */ |
| 3307 | 3323 | c = expr_const(); |
| 3324 | +#endif |
| 3308 | 3325 | } |
| 3309 | 3326 | if (c < 0) |
| 3310 | 3327 | seen_neg = 1; |
| 3328 | + if (c != (int)c && (unsigned long)c != (unsigned int)c) |
| 3329 | + seen_wide = 1, t = &size_type; |
| 3311 | 3330 | /* enum symbols have static storage */ |
| 3312 | | − ss = sym_push(v, &int_type, VT_CONST, c); |
| 3331 | + ss = sym_push(v, t, VT_CONST, c); |
| 3313 | 3332 | ss->type.t |= VT_STATIC; |
| 3314 | 3333 | if (tok != ',') |
| 3315 | 3334 | break; |
| @@ -3321,7 +3340,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 5 unmodified lines |
| 3321 | 3340 | } |
| 3322 | 3341 | if (!seen_neg) |
| 3323 | 3342 | s->a.unsigned_enum = 1; |
| 3324 | | − s->c = type_size(&int_type, &align); |
| 3343 | + s->c = type_size(seen_wide ? &size_type : &int_type, &align); |
| 3325 | 3344 | skip('}'); |
| 3326 | 3345 | } else { |
| 3327 | 3346 | maxalign = 1; |
| @@ -4355,10 +4374,11 @@ ST_FUNC void unary(void) · 1027 unmodified lines |
| 4355 | 4374 | break; |
| 4356 | 4375 | case TOK_builtin_choose_expr: |
| 4357 | 4376 | { |
| 4358 | | − int saved_nocode_wanted, c; |
| 4377 | + int saved_nocode_wanted; |
| 4378 | + int64_t c; |
| 4359 | 4379 | next(); |
| 4360 | 4380 | skip('('); |
| 4361 | | − c = expr_const(); |
| 4381 | + c = expr_const64(); |
| 4362 | 4382 | skip(','); |
| 4363 | 4383 | if (!c) { |
| 4364 | 4384 | saved_nocode_wanted = nocode_wanted; |
| @@ -5272,9 +5292,9 @@ static void expr_const1(void) · 907 unmodified lines |
| 5272 | 5292 | } |
| 5273 | 5293 | |
| 5274 | 5294 | /* parse an integer constant and return its value. */ |
| 5275 | | −ST_FUNC int expr_const(void) |
| 5295 | +static inline int64_t expr_const64(void) |
| 5276 | 5296 | { |
| 5277 | | − int c; |
| 5297 | + int64_t c; |
| 5278 | 5298 | expr_const1(); |
| 5279 | 5299 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
| 5280 | 5300 | expect("constant expression"); |
| @@ -5283,6 +5303,18 @@ ST_FUNC int expr_const(void) · 2 unmodified lines |
| 5283 | 5303 | return c; |
| 5284 | 5304 | } |
| 5285 | 5305 | |
| 5306 | +/* parse an integer constant and return its value. |
| 5307 | + Complain if it doesn't fit 32bit (signed or unsigned). */ |
| 5308 | +ST_FUNC int expr_const(void) |
| 5309 | +{ |
| 5310 | + int c; |
| 5311 | + int64_t wc = expr_const64(); |
| 5312 | + c = wc; |
| 5313 | + if (c != wc && (unsigned)c != wc) |
| 5314 | + tcc_error("constant exceeds 32 bit"); |
| 5315 | + return c; |
| 5316 | +} |
| 5317 | + |
| 5286 | 5318 | /* return the label token if current token is a label, otherwise |
| 5287 | 5319 | return zero */ |
| 5288 | 5320 | static int is_label(void) |
| @@ -5325,34 +5357,36 @@ static void label_or_decl(int l) · 36 unmodified lines |
| 5325 | 5357 | |
| 5326 | 5358 | static int case_cmp(const void *pa, const void *pb) |
| 5327 | 5359 | { |
| 5328 | | − int a = (*(struct case_t**) pa)->v1; |
| 5329 | | − int b = (*(struct case_t**) pb)->v1; |
| 5360 | + int64_t a = (*(struct case_t**) pa)->v1; |
| 5361 | + int64_t b = (*(struct case_t**) pb)->v1; |
| 5330 | 5362 | return a < b ? -1 : a > b; |
| 5331 | 5363 | } |
| 5332 | 5364 | |
| 5333 | | −static int gcase(struct case_t **base, int len, int case_reg, int *bsym) |
| 5365 | +static void gcase(struct case_t **base, int len, int *bsym) |
| 5334 | 5366 | { |
| 5335 | 5367 | struct case_t *p; |
| 5336 | 5368 | int e; |
| 5369 | + int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG; |
| 5370 | + gv(RC_INT); |
| 5337 | 5371 | while (len > 4) { |
| 5338 | 5372 | /* binary search */ |
| 5339 | 5373 | p = base[len/2]; |
| 5340 | | − vseti(case_reg, 0); |
| 5341 | 5374 | vdup(); |
| 5342 | | − vpushi(p->v2); |
| 5375 | + if (ll) |
| 5376 | + vpushll(p->v2); |
| 5377 | + else |
| 5378 | + vpushi(p->v2); |
| 5343 | 5379 | gen_op(TOK_LE); |
| 5344 | 5380 | e = gtst(1, 0); |
| 5345 | | − case_reg = gv(RC_INT); |
| 5346 | | − vpop(); |
| 5347 | | − vseti(case_reg, 0); |
| 5348 | 5381 | vdup(); |
| 5349 | | − vpushi(p->v1); |
| 5382 | + if (ll) |
| 5383 | + vpushll(p->v1); |
| 5384 | + else |
| 5385 | + vpushi(p->v1); |
| 5350 | 5386 | gen_op(TOK_GE); |
| 5351 | 5387 | gtst_addr(0, p->sym); /* v1 <= x <= v2 */ |
| 5352 | | − case_reg = gv(RC_INT); |
| 5353 | | − vpop(); |
| 5354 | 5388 | /* x < v1 */ |
| 5355 | | − case_reg = gcase(base, len/2, case_reg, bsym); |
| 5389 | + gcase(base, len/2, bsym); |
| 5356 | 5390 | if (cur_switch->def_sym) |
| 5357 | 5391 | gjmp_addr(cur_switch->def_sym); |
| 5358 | 5392 | else |
| @@ -5365,28 +5399,27 @@ static int gcase(struct case_t **base, int len, int case_reg, int *bsym) · 6 unmodified lines |
| 5365 | 5399 | /* linear scan */ |
| 5366 | 5400 | while (len--) { |
| 5367 | 5401 | p = *base++; |
| 5368 | | − vseti(case_reg, 0); |
| 5369 | 5402 | vdup(); |
| 5370 | | − vpushi(p->v2); |
| 5403 | + if (ll) |
| 5404 | + vpushll(p->v2); |
| 5405 | + else |
| 5406 | + vpushi(p->v2); |
| 5371 | 5407 | if (p->v1 == p->v2) { |
| 5372 | 5408 | gen_op(TOK_EQ); |
| 5373 | 5409 | gtst_addr(0, p->sym); |
| 5374 | 5410 | } else { |
| 5375 | 5411 | gen_op(TOK_LE); |
| 5376 | 5412 | e = gtst(1, 0); |
| 5377 | | − case_reg = gv(RC_INT); |
| 5378 | | − vpop(); |
| 5379 | | − vseti(case_reg, 0); |
| 5380 | 5413 | vdup(); |
| 5381 | | − vpushi(p->v1); |
| 5414 | + if (ll) |
| 5415 | + vpushll(p->v1); |
| 5416 | + else |
| 5417 | + vpushi(p->v1); |
| 5382 | 5418 | gen_op(TOK_GE); |
| 5383 | 5419 | gtst_addr(0, p->sym); |
| 5384 | 5420 | gsym(e); |
| 5385 | 5421 | } |
| 5386 | | − case_reg = gv(RC_INT); |
| 5387 | | − vpop(); |
| 5388 | 5422 | } |
| 5389 | | − return case_reg; |
| 5390 | 5423 | } |
| 5391 | 5424 | |
| 5392 | 5425 | static void block(int *bsym, int *csym, int is_expr) |
| @@ -5675,13 +5708,12 @@ static void block(int *bsym, int *csym, int is_expr) · 282 unmodified lines |
| 5675 | 5708 | if (tok == TOK_SWITCH) { |
| 5676 | 5709 | struct switch_t *saved, sw; |
| 5677 | 5710 | int saved_nocode_wanted = nocode_wanted; |
| 5711 | + SValue switchval; |
| 5678 | 5712 | next(); |
| 5679 | 5713 | skip('('); |
| 5680 | 5714 | gexpr(); |
| 5681 | | − /* XXX: other types than integer */ |
| 5682 | | − c = gv(RC_INT); |
| 5683 | | − vpop(); |
| 5684 | 5715 | skip(')'); |
| 5716 | + switchval = *vtop--; |
| 5685 | 5717 | a = 0; |
| 5686 | 5718 | b = gjmp(0); /* jump to first case */ |
| 5687 | 5719 | sw.p = NULL; sw.n = 0; sw.def_sym = 0; |
| @@ -5697,7 +5729,13 @@ static void block(int *bsym, int *csym, int is_expr) · 9 unmodified lines |
| 5697 | 5729 | for (b = 1; b < sw.n; b++) |
| 5698 | 5730 | if (sw.p[b - 1]->v2 >= sw.p[b]->v1) |
| 5699 | 5731 | tcc_error("duplicate case value"); |
| 5700 | | − gcase(sw.p, sw.n, c, &a); |
| 5732 | + /* Our switch table sorting is signed, so the compared |
| 5733 | + value needs to be as well when it's 64bit. */ |
| 5734 | + if ((switchval.type.t & VT_BTYPE) == VT_LLONG) |
| 5735 | + switchval.type.t &= ~VT_UNSIGNED; |
| 5736 | + vpushv(&switchval); |
| 5737 | + gcase(sw.p, sw.n, &a); |
| 5738 | + vpop(); |
| 5701 | 5739 | if (sw.def_sym) |
| 5702 | 5740 | gjmp_addr(sw.def_sym); |
| 5703 | 5741 | } |
| @@ -5712,10 +5750,10 @@ static void block(int *bsym, int *csym, int is_expr) · 8 unmodified lines |
| 5712 | 5750 | expect("switch"); |
| 5713 | 5751 | nocode_wanted &= ~2; |
| 5714 | 5752 | next(); |
| 5715 | | − cr->v1 = cr->v2 = expr_const(); |
| 5753 | + cr->v1 = cr->v2 = expr_const64(); |
| 5716 | 5754 | if (gnu_ext && tok == TOK_DOTS) { |
| 5717 | 5755 | next(); |
| 5718 | | − cr->v2 = expr_const(); |
| 5756 | + cr->v2 = expr_const64(); |
| 5719 | 5757 | if (cr->v2 < cr->v1) |
| 5720 | 5758 | tcc_warning("empty case range"); |
| 5721 | 5759 | } |