| @@ -62,7 +62,8 @@ ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; · 61 unmodified lines |
| 62 | | 62 | |
| 63 | ST_DATA struct switch_t { | 63 | ST_DATA struct switch_t { |
| 64 | struct case_t { | 64 | struct case_t { |
| 65 | int v1, v2, sym; | 65 | int64_t v1, v2; |
| | 66 | int sym; |
| 66 | } **p; int n; /* list of case ranges */ | 67 | } **p; int n; /* list of case ranges */ |
| 67 | int def_sym; /* default symbol */ | 68 | int def_sym; /* default symbol */ |
| 68 | } *cur_switch; /* current switch */ | 69 | } *cur_switch; /* current switch */ |
| @@ -86,6 +87,7 @@ static void vla_sp_restore(void); · 17 unmodified lines |
| 86 | static void vla_sp_restore_root(void); | 87 | static void vla_sp_restore_root(void); |
| 87 | static int is_compatible_parameter_types(CType *type1, CType *type2); | 88 | static int is_compatible_parameter_types(CType *type1, CType *type2); |
| 88 | static void expr_type(CType *type); | 89 | static void expr_type(CType *type); |
| | 90 | static inline int64_t expr_const64(void); |
| 89 | ST_FUNC void vpush64(int ty, unsigned long long v); | 91 | ST_FUNC void vpush64(int ty, unsigned long long v); |
| 90 | ST_FUNC void vpush(CType *type); | 92 | ST_FUNC void vpush(CType *type); |
| 91 | ST_FUNC int gvtst(int inv, int t); | 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 | /* push a given symbol on the symbol stack */ | 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 | Sym *s, **ps; | 441 | Sym *s, **ps; |
| 440 | TokenSym *ts; | 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 | /* push a global identifier */ | 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 | Sym *s, **ps; | 473 | Sym *s, **ps; |
| 472 | s = sym_push2(&global_stack, v, t, c); | 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 | vpushsym(type, external_global_sym(v, type, 0)); | 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 | CValue cval; | 705 | CValue cval; |
| 704 | | 706 | |
| @@ -1716,6 +1718,9 @@ static void gen_opic(int op) · 1011 unmodified lines |
| 1716 | default: | 1718 | default: |
| 1717 | goto general_case; | 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 | v1->c.i = l1; | 1724 | v1->c.i = l1; |
| 1720 | vtop--; | 1725 | vtop--; |
| 1721 | } else { | 1726 | } else { |
| @@ -3248,7 +3253,8 @@ static Sym * find_field (CType *type, int v) · 1526 unmodified lines |
| 3248 | /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ | 3253 | /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ |
| 3249 | static void struct_decl(CType *type, AttributeDef *ad, int u) | 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 | int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt; | 3258 | int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt; |
| 3253 | Sym *s, *ss, *ass, **ps; | 3259 | Sym *s, *ss, *ass, **ps; |
| 3254 | AttributeDef ad1; | 3260 | AttributeDef ad1; |
| @@ -3293,7 +3299,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 38 unmodified lines |
| 3293 | /* non empty enums are not allowed */ | 3299 | /* non empty enums are not allowed */ |
| 3294 | if (a == TOK_ENUM) { | 3300 | if (a == TOK_ENUM) { |
| 3295 | int seen_neg = 0; | 3301 | int seen_neg = 0; |
| | 3302 | int seen_wide = 0; |
| 3296 | for(;;) { | 3303 | for(;;) { |
| | 3304 | CType *t = &int_type; |
| 3297 | v = tok; | 3305 | v = tok; |
| 3298 | if (v < TOK_UIDENT) | 3306 | if (v < TOK_UIDENT) |
| 3299 | expect("identifier"); | 3307 | expect("identifier"); |
| @@ -3304,12 +3312,23 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 4 unmodified lines |
| 3304 | next(); | 3312 | next(); |
| 3305 | if (tok == '=') { | 3313 | if (tok == '=') { |
| 3306 | next(); | 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 | c = expr_const(); | 3323 | c = expr_const(); |
| | 3324 | #endif |
| 3308 | } | 3325 | } |
| 3309 | if (c < 0) | 3326 | if (c < 0) |
| 3310 | seen_neg = 1; | 3327 | seen_neg = 1; |
| | 3328 | if (c != (int)c && (unsigned long)c != (unsigned int)c) |
| | 3329 | seen_wide = 1, t = &size_type; |
| 3311 | /* enum symbols have static storage */ | 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 | ss->type.t |= VT_STATIC; | 3332 | ss->type.t |= VT_STATIC; |
| 3314 | if (tok != ',') | 3333 | if (tok != ',') |
| 3315 | break; | 3334 | break; |
| @@ -3321,7 +3340,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 5 unmodified lines |
| 3321 | } | 3340 | } |
| 3322 | if (!seen_neg) | 3341 | if (!seen_neg) |
| 3323 | s->a.unsigned_enum = 1; | 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 | skip('}'); | 3344 | skip('}'); |
| 3326 | } else { | 3345 | } else { |
| 3327 | maxalign = 1; | 3346 | maxalign = 1; |
| @@ -4355,10 +4374,11 @@ ST_FUNC void unary(void) · 1027 unmodified lines |
| 4355 | break; | 4374 | break; |
| 4356 | case TOK_builtin_choose_expr: | 4375 | case TOK_builtin_choose_expr: |
| 4357 | { | 4376 | { |
| 4358 | int saved_nocode_wanted, c; | 4377 | int saved_nocode_wanted; |
| | 4378 | int64_t c; |
| 4359 | next(); | 4379 | next(); |
| 4360 | skip('('); | 4380 | skip('('); |
| 4361 | c = expr_const(); | 4381 | c = expr_const64(); |
| 4362 | skip(','); | 4382 | skip(','); |
| 4363 | if (!c) { | 4383 | if (!c) { |
| 4364 | saved_nocode_wanted = nocode_wanted; | 4384 | saved_nocode_wanted = nocode_wanted; |
| @@ -5272,9 +5292,9 @@ static void expr_const1(void) · 907 unmodified lines |
| 5272 | } | 5292 | } |
| 5273 | | 5293 | |
| 5274 | /* parse an integer constant and return its value. */ | 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 | expr_const1(); | 5298 | expr_const1(); |
| 5279 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) | 5299 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
| 5280 | expect("constant expression"); | 5300 | expect("constant expression"); |
| @@ -5283,6 +5303,18 @@ ST_FUNC int expr_const(void) · 2 unmodified lines |
| 5283 | return c; | 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 | /* return the label token if current token is a label, otherwise | 5318 | /* return the label token if current token is a label, otherwise |
| 5287 | return zero */ | 5319 | return zero */ |
| 5288 | static int is_label(void) | 5320 | static int is_label(void) |
| @@ -5325,34 +5357,36 @@ static void label_or_decl(int l) · 36 unmodified lines |
| 5325 | | 5357 | |
| 5326 | static int case_cmp(const void *pa, const void *pb) | 5358 | static int case_cmp(const void *pa, const void *pb) |
| 5327 | { | 5359 | { |
| 5328 | int a = (*(struct case_t**) pa)->v1; | 5360 | int64_t a = (*(struct case_t**) pa)->v1; |
| 5329 | int b = (*(struct case_t**) pb)->v1; | 5361 | int64_t b = (*(struct case_t**) pb)->v1; |
| 5330 | return a < b ? -1 : a > b; | 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 | struct case_t *p; | 5367 | struct case_t *p; |
| 5336 | int e; | 5368 | int e; |
| | 5369 | int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG; |
| | 5370 | gv(RC_INT); |
| 5337 | while (len > 4) { | 5371 | while (len > 4) { |
| 5338 | /* binary search */ | 5372 | /* binary search */ |
| 5339 | p = base[len/2]; | 5373 | p = base[len/2]; |
| 5340 | vseti(case_reg, 0); | | |
| 5341 | vdup(); | 5374 | vdup(); |
| 5342 | vpushi(p->v2); | 5375 | if (ll) |
| | 5376 | vpushll(p->v2); |
| | 5377 | else |
| | 5378 | vpushi(p->v2); |
| 5343 | gen_op(TOK_LE); | 5379 | gen_op(TOK_LE); |
| 5344 | e = gtst(1, 0); | 5380 | e = gtst(1, 0); |
| 5345 | case_reg = gv(RC_INT); | | |
| 5346 | vpop(); | | |
| 5347 | vseti(case_reg, 0); | | |
| 5348 | vdup(); | 5381 | vdup(); |
| 5349 | vpushi(p->v1); | 5382 | if (ll) |
| | 5383 | vpushll(p->v1); |
| | 5384 | else |
| | 5385 | vpushi(p->v1); |
| 5350 | gen_op(TOK_GE); | 5386 | gen_op(TOK_GE); |
| 5351 | gtst_addr(0, p->sym); /* v1 <= x <= v2 */ | 5387 | gtst_addr(0, p->sym); /* v1 <= x <= v2 */ |
| 5352 | case_reg = gv(RC_INT); | | |
| 5353 | vpop(); | | |
| 5354 | /* x < v1 */ | 5388 | /* x < v1 */ |
| 5355 | case_reg = gcase(base, len/2, case_reg, bsym); | 5389 | gcase(base, len/2, bsym); |
| 5356 | if (cur_switch->def_sym) | 5390 | if (cur_switch->def_sym) |
| 5357 | gjmp_addr(cur_switch->def_sym); | 5391 | gjmp_addr(cur_switch->def_sym); |
| 5358 | else | 5392 | else |
| @@ -5365,28 +5399,27 @@ static int gcase(struct case_t **base, int len, int case_reg, int *bsym) · 6 unmodified lines |
| 5365 | /* linear scan */ | 5399 | /* linear scan */ |
| 5366 | while (len--) { | 5400 | while (len--) { |
| 5367 | p = *base++; | 5401 | p = *base++; |
| 5368 | vseti(case_reg, 0); | | |
| 5369 | vdup(); | 5402 | vdup(); |
| 5370 | vpushi(p->v2); | 5403 | if (ll) |
| | 5404 | vpushll(p->v2); |
| | 5405 | else |
| | 5406 | vpushi(p->v2); |
| 5371 | if (p->v1 == p->v2) { | 5407 | if (p->v1 == p->v2) { |
| 5372 | gen_op(TOK_EQ); | 5408 | gen_op(TOK_EQ); |
| 5373 | gtst_addr(0, p->sym); | 5409 | gtst_addr(0, p->sym); |
| 5374 | } else { | 5410 | } else { |
| 5375 | gen_op(TOK_LE); | 5411 | gen_op(TOK_LE); |
| 5376 | e = gtst(1, 0); | 5412 | e = gtst(1, 0); |
| 5377 | case_reg = gv(RC_INT); | | |
| 5378 | vpop(); | | |
| 5379 | vseti(case_reg, 0); | | |
| 5380 | vdup(); | 5413 | vdup(); |
| 5381 | vpushi(p->v1); | 5414 | if (ll) |
| | 5415 | vpushll(p->v1); |
| | 5416 | else |
| | 5417 | vpushi(p->v1); |
| 5382 | gen_op(TOK_GE); | 5418 | gen_op(TOK_GE); |
| 5383 | gtst_addr(0, p->sym); | 5419 | gtst_addr(0, p->sym); |
| 5384 | gsym(e); | 5420 | gsym(e); |
| 5385 | } | 5421 | } |
| 5386 | case_reg = gv(RC_INT); | | |
| 5387 | vpop(); | | |
| 5388 | } | 5422 | } |
| 5389 | return case_reg; | | |
| 5390 | } | 5423 | } |
| 5391 | | 5424 | |
| 5392 | static void block(int *bsym, int *csym, int is_expr) | 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 | if (tok == TOK_SWITCH) { | 5708 | if (tok == TOK_SWITCH) { |
| 5676 | struct switch_t *saved, sw; | 5709 | struct switch_t *saved, sw; |
| 5677 | int saved_nocode_wanted = nocode_wanted; | 5710 | int saved_nocode_wanted = nocode_wanted; |
| | 5711 | SValue switchval; |
| 5678 | next(); | 5712 | next(); |
| 5679 | skip('('); | 5713 | skip('('); |
| 5680 | gexpr(); | 5714 | gexpr(); |
| 5681 | /* XXX: other types than integer */ | | |
| 5682 | c = gv(RC_INT); | | |
| 5683 | vpop(); | | |
| 5684 | skip(')'); | 5715 | skip(')'); |
| | 5716 | switchval = *vtop--; |
| 5685 | a = 0; | 5717 | a = 0; |
| 5686 | b = gjmp(0); /* jump to first case */ | 5718 | b = gjmp(0); /* jump to first case */ |
| 5687 | sw.p = NULL; sw.n = 0; sw.def_sym = 0; | 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 | for (b = 1; b < sw.n; b++) | 5729 | for (b = 1; b < sw.n; b++) |
| 5698 | if (sw.p[b - 1]->v2 >= sw.p[b]->v1) | 5730 | if (sw.p[b - 1]->v2 >= sw.p[b]->v1) |
| 5699 | tcc_error("duplicate case value"); | 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 | if (sw.def_sym) | 5739 | if (sw.def_sym) |
| 5702 | gjmp_addr(sw.def_sym); | 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 | expect("switch"); | 5750 | expect("switch"); |
| 5713 | nocode_wanted &= ~2; | 5751 | nocode_wanted &= ~2; |
| 5714 | next(); | 5752 | next(); |
| 5715 | cr->v1 = cr->v2 = expr_const(); | 5753 | cr->v1 = cr->v2 = expr_const64(); |
| 5716 | if (gnu_ext && tok == TOK_DOTS) { | 5754 | if (gnu_ext && tok == TOK_DOTS) { |
| 5717 | next(); | 5755 | next(); |
| 5718 | cr->v2 = expr_const(); | 5756 | cr->v2 = expr_const64(); |
| 5719 | if (cr->v2 < cr->v1) | 5757 | if (cr->v2 < cr->v1) |
| 5720 | tcc_warning("empty case range"); | 5758 | tcc_warning("empty case range"); |
| 5721 | } | 5759 | } |