| @@ -79,8 +79,18 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in · 78 unmodified lines |
| 79 | 79 | ST_DATA int func_vc; |
| 80 | 80 | static int last_line_num, new_file, func_ind; /* debug info control */ |
| 81 | 81 | ST_DATA const char *funcname; |
| 82 | +ST_DATA CType int_type, func_old_type, char_pointer_type; |
| 82 | 83 | |
| 83 | | −ST_DATA CType char_pointer_type, func_old_type, int_type, size_type, ptrdiff_type; |
| 84 | +#if PTR_SIZE == 4 |
| 85 | +#define VT_SIZE_T (VT_INT | VT_UNSIGNED) |
| 86 | +#define VT_PTRDIFF_T VT_INT |
| 87 | +#elif LONG_SIZE == 4 |
| 88 | +#define VT_SIZE_T (VT_LLONG | VT_UNSIGNED) |
| 89 | +#define VT_PTRDIFF_T VT_LLONG |
| 90 | +#else |
| 91 | +#define VT_SIZE_T (VT_LONG | VT_LLONG | VT_UNSIGNED) |
| 92 | +#define VT_PTRDIFF_T (VT_LONG | VT_LLONG) |
| 93 | +#endif |
| 84 | 94 | |
| 85 | 95 | ST_DATA struct switch_t { |
| 86 | 96 | struct case_t { |
| @@ -149,6 +159,7 @@ static void skip_or_save_block(TokenString **str); · 62 unmodified lines |
| 149 | 159 | static void gv_dup(void); |
| 150 | 160 | static int get_temp_local_var(int size,int align); |
| 151 | 161 | static void clear_temp_local_var_list(); |
| 162 | +static void cast_error(CType *st, CType *dt); |
| 152 | 163 | |
| 153 | 164 | ST_INLN int is_float(int t) |
| 154 | 165 | { |
| @@ -162,6 +173,7 @@ ST_INLN int is_float(int t) · 7 unmodified lines |
| 162 | 173 | static inline int is_integer_btype(int bt) |
| 163 | 174 | { |
| 164 | 175 | return bt == VT_BYTE |
| 176 | + || bt == VT_BOOL |
| 165 | 177 | || bt == VT_SHORT |
| 166 | 178 | || bt == VT_INT |
| 167 | 179 | || bt == VT_LLONG; |
| @@ -439,16 +451,6 @@ ST_FUNC void tccgen_init(TCCState *s1) · 271 unmodified lines |
| 439 | 451 | int_type.t = VT_INT; |
| 440 | 452 | char_pointer_type.t = VT_BYTE; |
| 441 | 453 | mk_pointer(&char_pointer_type); |
| 442 | | −#if PTR_SIZE == 4 |
| 443 | | − size_type.t = VT_INT | VT_UNSIGNED; |
| 444 | | − ptrdiff_type.t = VT_INT; |
| 445 | | −#elif LONG_SIZE == 4 |
| 446 | | − size_type.t = VT_LLONG | VT_UNSIGNED; |
| 447 | | − ptrdiff_type.t = VT_LLONG; |
| 448 | | −#else |
| 449 | | − size_type.t = VT_LONG | VT_LLONG | VT_UNSIGNED; |
| 450 | | − ptrdiff_type.t = VT_LONG | VT_LLONG; |
| 451 | | −#endif |
| 452 | 454 | func_old_type.t = VT_FUNC; |
| 453 | 455 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); |
| 454 | 456 | func_old_type.ref->f.func_call = FUNC_CDECL; |
| @@ -922,36 +924,32 @@ ST_FUNC void vpop(void) · 467 unmodified lines |
| 922 | 924 | } |
| 923 | 925 | |
| 924 | 926 | /* push constant of type "type" with useless value */ |
| 925 | | −ST_FUNC void vpush(CType *type) |
| 927 | +static void vpush(CType *type) |
| 926 | 928 | { |
| 927 | 929 | vset(type, VT_CONST, 0); |
| 928 | 930 | } |
| 929 | 931 | |
| 930 | | −/* push integer constant */ |
| 931 | | −ST_FUNC void vpushi(int v) |
| 932 | +/* push arbitrary 64bit constant */ |
| 933 | +static void vpush64(int ty, unsigned long long v) |
| 932 | 934 | { |
| 933 | 935 | CValue cval; |
| 936 | + CType ctype; |
| 937 | + ctype.t = ty; |
| 938 | + ctype.ref = NULL; |
| 934 | 939 | cval.i = v; |
| 935 | | − vsetc(&int_type, VT_CONST, &cval); |
| 940 | + vsetc(&ctype, VT_CONST, &cval); |
| 936 | 941 | } |
| 937 | 942 | |
| 938 | | −/* push a pointer sized constant */ |
| 939 | | −static void vpushs(addr_t v) |
| 943 | +/* push integer constant */ |
| 944 | +ST_FUNC void vpushi(int v) |
| 940 | 945 | { |
| 941 | | − CValue cval; |
| 942 | | − cval.i = v; |
| 943 | | − vsetc(&size_type, VT_CONST, &cval); |
| 946 | + vpush64(VT_INT, v); |
| 944 | 947 | } |
| 945 | 948 | |
| 946 | | −/* push arbitrary 64bit constant */ |
| 947 | | −ST_FUNC void vpush64(int ty, unsigned long long v) |
| 949 | +/* push a pointer sized constant */ |
| 950 | +static void vpushs(addr_t v) |
| 948 | 951 | { |
| 949 | | − CValue cval; |
| 950 | | − CType ctype; |
| 951 | | − ctype.t = ty; |
| 952 | | − ctype.ref = NULL; |
| 953 | | − cval.i = v; |
| 954 | | − vsetc(&ctype, VT_CONST, &cval); |
| 952 | + vpush64(VT_SIZE_T, v); |
| 955 | 953 | } |
| 956 | 954 | |
| 957 | 955 | /* push long long constant */ |
| @@ -963,7 +961,6 @@ static inline void vpushll(long long v) · 5 unmodified lines |
| 963 | 961 | ST_FUNC void vset(CType *type, int r, int v) |
| 964 | 962 | { |
| 965 | 963 | CValue cval; |
| 966 | | − |
| 967 | 964 | cval.i = v; |
| 968 | 965 | vsetc(type, r, &cval); |
| 969 | 966 | } |
| @@ -1099,6 +1096,23 @@ static int gvtst(int inv, int t) · 129 unmodified lines |
| 1099 | 1096 | return t; |
| 1100 | 1097 | } |
| 1101 | 1098 | |
| 1099 | +/* generate a zero or nozero test */ |
| 1100 | +static void gen_test_zero(int op) |
| 1101 | +{ |
| 1102 | + if (vtop->r == VT_CMP) { |
| 1103 | + int j; |
| 1104 | + if (op == TOK_EQ) { |
| 1105 | + j = vtop->jfalse; |
| 1106 | + vtop->jfalse = vtop->jtrue; |
| 1107 | + vtop->jtrue = j; |
| 1108 | + vtop->cmp_op ^= 1; |
| 1109 | + } |
| 1110 | + } else { |
| 1111 | + vpushi(0); |
| 1112 | + gen_op(op); |
| 1113 | + } |
| 1114 | +} |
| 1115 | + |
| 1102 | 1116 | /* ------------------------------------------------------------------------- */ |
| 1103 | 1117 | /* push a symbol value of TYPE */ |
| 1104 | 1118 | static inline void vpushsym(CType *type, Sym *sym) |
| @@ -1350,44 +1364,34 @@ ST_FUNC void save_reg(int r) · 245 unmodified lines |
| 1350 | 1364 | if seen up to (vtop - n) stack entry */ |
| 1351 | 1365 | ST_FUNC void save_reg_upstack(int r, int n) |
| 1352 | 1366 | { |
| 1353 | | − int l, saved, size, align; |
| 1367 | + int l, size, align, bt; |
| 1354 | 1368 | SValue *p, *p1, sv; |
| 1355 | | − CType *type; |
| 1356 | 1369 | |
| 1357 | 1370 | if ((r &= VT_VALMASK) >= VT_CONST) |
| 1358 | 1371 | return; |
| 1359 | 1372 | if (nocode_wanted) |
| 1360 | 1373 | return; |
| 1361 | | − |
| 1362 | | − /* modify all stack values */ |
| 1363 | | − saved = 0; |
| 1364 | 1374 | l = 0; |
| 1365 | 1375 | for(p = vstack, p1 = vtop - n; p <= p1; p++) { |
| 1366 | | − if ((p->r & VT_VALMASK) == r || (p->r2 & VT_VALMASK) == r) { |
| 1376 | + if ((p->r & VT_VALMASK) == r || p->r2 == r) { |
| 1367 | 1377 | /* must save value on stack if not already done */ |
| 1368 | | − if (!saved) { |
| 1369 | | − /* NOTE: must reload 'r' because r might be equal to r2 */ |
| 1370 | | − r = p->r & VT_VALMASK; |
| 1371 | | − /* store register in the stack */ |
| 1372 | | − type = &p->type; |
| 1373 | | − if ((p->r & VT_LVAL) || |
| 1374 | | − (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG)) |
| 1375 | | −#if PTR_SIZE == 8 |
| 1376 | | − type = &char_pointer_type; |
| 1377 | | −#else |
| 1378 | | − type = &int_type; |
| 1379 | | −#endif |
| 1380 | | − size = type_size(type, &align); |
| 1378 | + if (!l) { |
| 1379 | + bt = p->type.t & VT_BTYPE; |
| 1380 | + if (bt == VT_VOID) |
| 1381 | + continue; |
| 1382 | + if ((p->r & VT_LVAL) || bt == VT_FUNC) |
| 1383 | + bt = VT_PTR; |
| 1384 | + sv.type.t = bt; |
| 1385 | + size = type_size(&sv.type, &align); |
| 1381 | 1386 | #ifdef CONFIG_TCC_BCHECK |
| 1382 | 1387 | if (tcc_state->do_bounds_check) |
| 1383 | 1388 | l = loc = (loc - size) & -align; |
| 1384 | 1389 | else |
| 1385 | 1390 | #endif |
| 1386 | | − l=get_temp_local_var(size,align); |
| 1387 | | − sv.type.t = type->t; |
| 1391 | + l = get_temp_local_var(size,align); |
| 1388 | 1392 | sv.r = VT_LOCAL | VT_LVAL; |
| 1389 | 1393 | sv.c.i = l; |
| 1390 | | − store(r, &sv); |
| 1394 | + store(p->r & VT_VALMASK, &sv); |
| 1391 | 1395 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
| 1392 | 1396 | /* x86 specific: need to pop fp register ST0 if saved */ |
| 1393 | 1397 | if (r == TREG_ST0) { |
| @@ -1395,11 +1399,10 @@ ST_FUNC void save_reg_upstack(int r, int n) · 1 unmodified line |
| 1395 | 1399 | } |
| 1396 | 1400 | #endif |
| 1397 | 1401 | /* special long long case */ |
| 1398 | | − if (p->r2 < VT_CONST && USING_TWO_WORDS(type->t)) { |
| 1402 | + if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) { |
| 1399 | 1403 | sv.c.i += PTR_SIZE; |
| 1400 | 1404 | store(p->r2, &sv); |
| 1401 | 1405 | } |
| 1402 | | − saved = 1; |
| 1403 | 1406 | } |
| 1404 | 1407 | /* mark that stack entry as being saved on the stack */ |
| 1405 | 1408 | if (p->r & VT_LVAL) { |
| @@ -1771,7 +1774,7 @@ ST_FUNC int gv(int rc) · 365 unmodified lines |
| 1771 | 1774 | if (!r_ok) |
| 1772 | 1775 | r = get_reg(rc); |
| 1773 | 1776 | if (rc2) { |
| 1774 | | − int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : ptrdiff_type.t; |
| 1777 | + int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T; |
| 1775 | 1778 | int original_type = vtop->type.t; |
| 1776 | 1779 | |
| 1777 | 1780 | /* two register type load : |
| @@ -1793,9 +1796,9 @@ ST_FUNC int gv(int rc) · 15 unmodified lines |
| 1793 | 1796 | vdup(); |
| 1794 | 1797 | vtop[-1].r = r; /* save register value */ |
| 1795 | 1798 | /* increment pointer to get second word */ |
| 1796 | | − vtop->type.t = ptrdiff_type.t; |
| 1799 | + vtop->type.t = VT_PTRDIFF_T; |
| 1797 | 1800 | gaddrof(); |
| 1798 | | − vpushi(PTR_SIZE); |
| 1801 | + vpushs(PTR_SIZE); |
| 1799 | 1802 | gen_op('+'); |
| 1800 | 1803 | vtop->r |= VT_LVAL; |
| 1801 | 1804 | vtop->type.t = load_type; |
| @@ -2521,7 +2524,7 @@ redo: · 719 unmodified lines |
| 2521 | 2524 | } |
| 2522 | 2525 | vrott(3); |
| 2523 | 2526 | gen_opic(op); |
| 2524 | | − vtop->type.t = ptrdiff_type.t; |
| 2527 | + vtop->type.t = VT_PTRDIFF_T; |
| 2525 | 2528 | vswap(); |
| 2526 | 2529 | gen_op(TOK_PDIV); |
| 2527 | 2530 | } else { |
| @@ -2712,41 +2715,17 @@ static void gen_cvt_ftoi1(int t) · 184 unmodified lines |
| 2712 | 2715 | } |
| 2713 | 2716 | #endif |
| 2714 | 2717 | |
| 2715 | | −/* force char or short cast */ |
| 2716 | | −static void force_charshort_cast(int t) |
| 2718 | +/* special delayed cast for char/short */ |
| 2719 | +static void force_charshort_cast(void) |
| 2717 | 2720 | { |
| 2718 | | − int bits, dbt; |
| 2719 | | − |
| 2720 | | − /* cannot cast static initializers */ |
| 2721 | | − if (STATIC_DATA_WANTED) |
| 2722 | | − return; |
| 2723 | | − |
| 2724 | | − dbt = t & VT_BTYPE; |
| 2725 | | − /* XXX: add optimization if lvalue : just change type and offset */ |
| 2726 | | − if (dbt == VT_BYTE) |
| 2727 | | − bits = 8; |
| 2728 | | − else |
| 2729 | | − bits = 16; |
| 2730 | | − if (t & VT_UNSIGNED) { |
| 2731 | | − vpushi((1 << bits) - 1); |
| 2732 | | − gen_op('&'); |
| 2733 | | − } else { |
| 2734 | | − if ((vtop->type.t & VT_BTYPE) == VT_LLONG) |
| 2735 | | − bits = 64 - bits; |
| 2736 | | − else |
| 2737 | | − bits = 32 - bits; |
| 2738 | | − vpushi(bits); |
| 2739 | | − gen_op(TOK_SHL); |
| 2740 | | − /* result must be signed or the SAR is converted to an SHL |
| 2741 | | − This was not the case when "t" was a signed short |
| 2742 | | − and the last value on the stack was an unsigned int */ |
| 2743 | | − vtop->type.t &= ~VT_UNSIGNED; |
| 2744 | | − vpushi(bits); |
| 2745 | | − gen_op(TOK_SAR); |
| 2746 | | − } |
| 2721 | + int sbt = BFGET(vtop->r, VT_MUSTCAST) == 2 ? VT_LLONG : VT_INT; |
| 2722 | + int dbt = vtop->type.t; |
| 2723 | + vtop->r &= ~VT_MUSTCAST; |
| 2724 | + vtop->type.t = sbt; |
| 2725 | + gen_cast_s(dbt == VT_BOOL ? VT_BYTE|VT_UNSIGNED : dbt); |
| 2726 | + vtop->type.t = dbt; |
| 2747 | 2727 | } |
| 2748 | 2728 | |
| 2749 | | −/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ |
| 2750 | 2729 | static void gen_cast_s(int t) |
| 2751 | 2730 | { |
| 2752 | 2731 | CType type; |
| @@ -2755,31 +2734,33 @@ static void gen_cast_s(int t) · 2 unmodified lines |
| 2755 | 2734 | gen_cast(&type); |
| 2756 | 2735 | } |
| 2757 | 2736 | |
| 2737 | +/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ |
| 2758 | 2738 | static void gen_cast(CType *type) |
| 2759 | 2739 | { |
| 2760 | | − int sbt, dbt, sf, df, c, p; |
| 2740 | + int sbt, dbt, sf, df, c; |
| 2741 | + int dbt_bt, sbt_bt, ds, ss, bits, trunc; |
| 2761 | 2742 | |
| 2762 | 2743 | /* special delayed cast for char/short */ |
| 2763 | | − /* XXX: in some cases (multiple cascaded casts), it may still |
| 2764 | | − be incorrect */ |
| 2765 | | − if (vtop->r & VT_MUSTCAST) { |
| 2766 | | − vtop->r &= ~VT_MUSTCAST; |
| 2767 | | − force_charshort_cast(vtop->type.t); |
| 2768 | | − } |
| 2744 | + if (vtop->r & VT_MUSTCAST) |
| 2745 | + force_charshort_cast(); |
| 2769 | 2746 | |
| 2770 | 2747 | /* bitfields first get cast to ints */ |
| 2771 | | − if (vtop->type.t & VT_BITFIELD) { |
| 2748 | + if (vtop->type.t & VT_BITFIELD) |
| 2772 | 2749 | gv(RC_INT); |
| 2773 | | − } |
| 2774 | 2750 | |
| 2775 | 2751 | dbt = type->t & (VT_BTYPE | VT_UNSIGNED); |
| 2776 | 2752 | sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); |
| 2753 | + if (sbt == VT_FUNC) |
| 2754 | + sbt = VT_PTR; |
| 2777 | 2755 | |
| 2756 | +again: |
| 2778 | 2757 | if (sbt != dbt) { |
| 2779 | 2758 | sf = is_float(sbt); |
| 2780 | 2759 | df = is_float(dbt); |
| 2760 | + dbt_bt = dbt & VT_BTYPE; |
| 2761 | + sbt_bt = sbt & VT_BTYPE; |
| 2762 | + |
| 2781 | 2763 | c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; |
| 2782 | | − p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM); |
| 2783 | 2764 | #if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 |
| 2784 | 2765 | c &= (dbt != VT_LDOUBLE) | !!nocode_wanted; |
| 2785 | 2766 | #endif |
| @@ -2792,7 +2773,7 @@ static void gen_cast(CType *type) · 6 unmodified lines |
| 2792 | 2773 | vtop->c.ld = vtop->c.d; |
| 2793 | 2774 | |
| 2794 | 2775 | if (df) { |
| 2795 | | − if ((sbt & VT_BTYPE) == VT_LLONG) { |
| 2776 | + if (sbt_bt == VT_LLONG) { |
| 2796 | 2777 | if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63)) |
| 2797 | 2778 | vtop->c.ld = vtop->c.i; |
| 2798 | 2779 | else |
| @@ -2808,164 +2789,173 @@ static void gen_cast(CType *type) · 9 unmodified lines |
| 2808 | 2789 | vtop->c.f = (float)vtop->c.ld; |
| 2809 | 2790 | else if (dbt == VT_DOUBLE) |
| 2810 | 2791 | vtop->c.d = (double)vtop->c.ld; |
| 2811 | | − } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) { |
| 2812 | | − vtop->c.i = vtop->c.ld; |
| 2813 | 2792 | } else if (sf && dbt == VT_BOOL) { |
| 2814 | 2793 | vtop->c.i = (vtop->c.ld != 0); |
| 2815 | 2794 | } else { |
| 2816 | 2795 | if(sf) |
| 2817 | 2796 | vtop->c.i = vtop->c.ld; |
| 2818 | | − else if (sbt == (VT_LLONG|VT_UNSIGNED)) |
| 2797 | + else if (sbt_bt == VT_LLONG || (PTR_SIZE == 8 && sbt == VT_PTR)) |
| 2819 | 2798 | ; |
| 2820 | 2799 | else if (sbt & VT_UNSIGNED) |
| 2821 | 2800 | vtop->c.i = (uint32_t)vtop->c.i; |
| 2822 | | −#if PTR_SIZE == 8 |
| 2823 | | − else if (sbt == VT_PTR) |
| 2824 | | − ; |
| 2825 | | −#endif |
| 2826 | | − else if (sbt != VT_LLONG) |
| 2827 | | − vtop->c.i = ((uint32_t)vtop->c.i | |
| 2828 | | − -(vtop->c.i & 0x80000000)); |
| 2801 | + else |
| 2802 | + vtop->c.i = ((uint32_t)vtop->c.i | -(vtop->c.i & 0x80000000)); |
| 2829 | 2803 | |
| 2830 | | − if (dbt == (VT_LLONG|VT_UNSIGNED)) |
| 2804 | + if (dbt_bt == VT_LLONG || (PTR_SIZE == 8 && dbt == VT_PTR)) |
| 2831 | 2805 | ; |
| 2832 | 2806 | else if (dbt == VT_BOOL) |
| 2833 | 2807 | vtop->c.i = (vtop->c.i != 0); |
| 2834 | | −#if PTR_SIZE == 8 |
| 2835 | | − else if (dbt == VT_PTR) |
| 2836 | | − ; |
| 2837 | | −#endif |
| 2838 | | − else if (dbt != VT_LLONG) { |
| 2839 | | − uint32_t m = ((dbt & VT_BTYPE) == VT_BYTE ? 0xff : |
| 2840 | | − (dbt & VT_BTYPE) == VT_SHORT ? 0xffff : |
| 2841 | | − 0xffffffff); |
| 2808 | + else { |
| 2809 | + uint32_t m = dbt_bt == VT_BYTE ? 0xff : |
| 2810 | + dbt_bt == VT_SHORT ? 0xffff : |
| 2811 | + 0xffffffff; |
| 2842 | 2812 | vtop->c.i &= m; |
| 2843 | 2813 | if (!(dbt & VT_UNSIGNED)) |
| 2844 | 2814 | vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1)); |
| 2845 | 2815 | } |
| 2846 | 2816 | } |
| 2847 | | − } else if (p && dbt == VT_BOOL) { |
| 2817 | + goto done; |
| 2818 | + |
| 2819 | + } else if (dbt == VT_BOOL |
| 2820 | + && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) |
| 2821 | + == (VT_CONST | VT_SYM)) { |
| 2822 | + /* addresses are considered non-zero (see tcctest.c:sinit23) */ |
| 2848 | 2823 | vtop->r = VT_CONST; |
| 2849 | 2824 | vtop->c.i = 1; |
| 2850 | | − } else { |
| 2851 | | − /* non constant case: generate code */ |
| 2825 | + goto done; |
| 2826 | + } |
| 2827 | + |
| 2828 | + /* cannot generate code for global or static initializers */ |
| 2829 | + if (STATIC_DATA_WANTED) |
| 2830 | + goto done; |
| 2831 | + |
| 2832 | + /* non constant case: generate code */ |
| 2833 | + if (dbt == VT_BOOL) { |
| 2834 | + gen_test_zero(TOK_NE); |
| 2835 | + goto done; |
| 2836 | + } |
| 2837 | + |
| 2838 | + if (sf || df) { |
| 2852 | 2839 | if (sf && df) { |
| 2853 | 2840 | /* convert from fp to fp */ |
| 2854 | 2841 | gen_cvt_ftof(dbt); |
| 2855 | 2842 | } else if (df) { |
| 2856 | 2843 | /* convert int to fp */ |
| 2857 | 2844 | gen_cvt_itof1(dbt); |
| 2858 | | − } else if (sf) { |
| 2845 | + } else { |
| 2859 | 2846 | /* convert fp to int */ |
| 2860 | | − if (dbt == VT_BOOL) { |
| 2861 | | − vpushi(0); |
| 2862 | | − gen_op(TOK_NE); |
| 2863 | | − } else { |
| 2864 | | − /* we handle char/short/etc... with generic code */ |
| 2865 | | − if (dbt != (VT_INT | VT_UNSIGNED) && |
| 2866 | | − dbt != (VT_LLONG | VT_UNSIGNED) && |
| 2867 | | − dbt != VT_LLONG) |
| 2868 | | − dbt = VT_INT; |
| 2869 | | − gen_cvt_ftoi1(dbt); |
| 2870 | | − if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) { |
| 2871 | | − /* additional cast for char/short... */ |
| 2872 | | − vtop->type.t = dbt; |
| 2873 | | − gen_cast(type); |
| 2874 | | − } |
| 2875 | | − } |
| 2847 | + sbt = dbt; |
| 2848 | + if (dbt_bt != VT_LLONG && dbt_bt != VT_INT) |
| 2849 | + sbt = VT_INT; |
| 2850 | + gen_cvt_ftoi1(sbt); |
| 2851 | + goto again; /* may need char/short cast */ |
| 2852 | + } |
| 2853 | + goto done; |
| 2854 | + } |
| 2855 | + |
| 2856 | + ds = btype_size(dbt_bt); |
| 2857 | + ss = btype_size(sbt_bt); |
| 2858 | + if (ds == 0 || ss == 0) { |
| 2859 | + if (dbt_bt == VT_VOID) |
| 2860 | + goto done; |
| 2861 | + cast_error(&vtop->type, type); |
| 2862 | + } |
| 2863 | + if (IS_ENUM(type->t) && type->ref->c < 0) |
| 2864 | + tcc_error("cast to incomplete type"); |
| 2865 | + |
| 2866 | + /* same size and no sign conversion needed */ |
| 2867 | + if (ds == ss && ds >= 4) |
| 2868 | + goto done; |
| 2869 | + if (dbt_bt == VT_PTR || sbt_bt == VT_PTR) { |
| 2870 | + tcc_warning("cast between pointer and integer of different size"); |
| 2871 | + if (sbt_bt == VT_PTR) { |
| 2872 | + /* put integer type to allow logical operations below */ |
| 2873 | + vtop->type.t = (PTR_SIZE == 8 ? VT_LLONG : VT_INT); |
| 2874 | + } |
| 2875 | + } |
| 2876 | + |
| 2877 | + /* processor allows { int a = 0, b = *(char*)&a; } |
| 2878 | + That means that if we cast to less width, we can just |
| 2879 | + change the type and read it still later. */ |
| 2880 | + #define ALLOW_SUBTYPE_ACCESS 1 |
| 2881 | + |
| 2882 | + if (ALLOW_SUBTYPE_ACCESS && (vtop->r & VT_LVAL)) { |
| 2883 | + /* value still in memory */ |
| 2884 | + if (ds <= ss) |
| 2885 | + goto done; |
| 2886 | + /* ss <= 4 here */ |
| 2887 | + if (ds <= 4) { |
| 2888 | + gv(RC_INT); |
| 2889 | + goto done; /* no 64bit envolved */ |
| 2890 | + } |
| 2891 | + } |
| 2892 | + gv(RC_INT); |
| 2893 | + |
| 2894 | + trunc = 0; |
| 2876 | 2895 | #if PTR_SIZE == 4 |
| 2877 | | − } else if ((dbt & VT_BTYPE) == VT_LLONG) { |
| 2878 | | − if ((sbt & VT_BTYPE) != VT_LLONG) { |
| 2879 | | − /* scalar to long long */ |
| 2880 | | − /* machine independent conversion */ |
| 2881 | | − gv(RC_INT); |
| 2882 | | − /* generate high word */ |
| 2883 | | − if (sbt == (VT_INT | VT_UNSIGNED)) { |
| 2884 | | − vpushi(0); |
| 2885 | | − gv(RC_INT); |
| 2886 | | − } else { |
| 2887 | | − if (sbt == VT_PTR) { |
| 2888 | | − /* cast from pointer to int before we apply |
| 2889 | | − shift operation, which pointers don't support*/ |
| 2890 | | − gen_cast_s(VT_INT); |
| 2891 | | − } |
| 2892 | | − gv_dup(); |
| 2893 | | − vpushi(31); |
| 2894 | | − gen_op(TOK_SAR); |
| 2895 | | − } |
| 2896 | | − /* patch second register */ |
| 2897 | | − vtop[-1].r2 = vtop->r; |
| 2898 | | − vpop(); |
| 2899 | | − } |
| 2900 | | −#else |
| 2901 | | − } else if ((dbt & VT_BTYPE) == VT_LLONG || |
| 2902 | | − (dbt & VT_BTYPE) == VT_PTR || |
| 2903 | | − (dbt & VT_BTYPE) == VT_FUNC) { |
| 2904 | | − if ((sbt & VT_BTYPE) != VT_LLONG && |
| 2905 | | − (sbt & VT_BTYPE) != VT_PTR && |
| 2906 | | − (sbt & VT_BTYPE) != VT_FUNC) { |
| 2907 | | − /* need to convert from 32bit to 64bit */ |
| 2908 | | − gv(RC_INT); |
| 2909 | | − if (sbt != (VT_INT | VT_UNSIGNED)) { |
| 2910 | | −#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_RISCV64) |
| 2911 | | − gen_cvt_sxtw(); |
| 2912 | | −#elif defined(TCC_TARGET_X86_64) |
| 2913 | | − int r = gv(RC_INT); |
| 2914 | | − /* x86_64 specific: movslq */ |
| 2915 | | − o(0x6348); |
| 2916 | | − o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r)); |
| 2917 | | −#else |
| 2918 | | −#error |
| 2919 | | −#endif |
| 2920 | | − } else if (sbt & VT_UNSIGNED) { |
| 2921 | | −#if defined(TCC_TARGET_RISCV64) |
| 2922 | | − /* RISC-V keeps 32bit vals in registers sign-extended. |
| 2923 | | − So here we need a zero-extension. */ |
| 2924 | | − vtop->type.t = VT_LLONG; |
| 2925 | | − vpushi(32); |
| 2926 | | − gen_op(TOK_SHL); |
| 2927 | | − vpushi(32); |
| 2928 | | − gen_op(TOK_SHR); |
| 2929 | | −#endif |
| 2930 | | − } |
| 2931 | | − } |
| 2932 | | −#endif |
| 2933 | | − } else if (dbt == VT_BOOL) { |
| 2934 | | − /* scalar to bool */ |
| 2896 | + if (ds == 8) { |
| 2897 | + /* generate high word */ |
| 2898 | + if (sbt & VT_UNSIGNED) { |
| 2935 | 2899 | vpushi(0); |
| 2936 | | − gen_op(TOK_NE); |
| 2937 | | − } else if ((dbt & VT_BTYPE) == VT_BYTE || |
| 2938 | | − (dbt & VT_BTYPE) == VT_SHORT) { |
| 2939 | | − if (sbt == VT_PTR) { |
| 2940 | | − vtop->type.t = VT_INT; |
| 2941 | | − tcc_warning("nonportable conversion from pointer to char/short"); |
| 2942 | | − } |
| 2943 | | − force_charshort_cast(dbt); |
| 2944 | | − } else if ((dbt & VT_BTYPE) == VT_INT) { |
| 2945 | | − /* scalar to int */ |
| 2946 | | − if ((sbt & VT_BTYPE) == VT_LLONG) { |
| 2947 | | −#if PTR_SIZE == 4 |
| 2948 | | − /* from long long: just take low order word */ |
| 2949 | | − lexpand(); |
| 2950 | | − vpop(); |
| 2900 | + gv(RC_INT); |
| 2901 | + } else { |
| 2902 | + gv_dup(); |
| 2903 | + vpushi(31); |
| 2904 | + gen_op(TOK_SAR); |
| 2905 | + } |
| 2906 | + lbuild(dbt); |
| 2907 | + } else if (ss == 8) { |
| 2908 | + /* from long long: just take low order word */ |
| 2909 | + lexpand(); |
| 2910 | + vpop(); |
| 2911 | + } |
| 2912 | + ss = 4; |
| 2913 | + |
| 2914 | +#elif PTR_SIZE == 8 |
| 2915 | + if (ds == 8) { |
| 2916 | + /* need to convert from 32bit to 64bit */ |
| 2917 | + if (sbt & VT_UNSIGNED) { |
| 2918 | +#if defined(TCC_TARGET_RISCV64) |
| 2919 | + /* RISC-V keeps 32bit vals in registers sign-extended. |
| 2920 | + So here we need a zero-extension. */ |
| 2921 | + trunc = 32; |
| 2951 | 2922 | #else |
| 2952 | | − if (dbt & VT_UNSIGNED) { |
| 2953 | | − /* XXX some architectures (e.g. risc-v) would like it |
| 2954 | | − better for this merely being a 32-to-64 sign or zero- |
| 2955 | | − extension. */ |
| 2956 | | − vpushi(0xffffffff); |
| 2957 | | − vtop->type.t |= VT_UNSIGNED; |
| 2958 | | − gen_op('&'); |
| 2959 | | − } else { |
| 2960 | | − } |
| 2923 | + goto done; |
| 2961 | 2924 | #endif |
| 2962 | | − } |
| 2925 | + } else { |
| 2926 | + gen_cvt_sxtw(); |
| 2927 | + goto done; |
| 2963 | 2928 | } |
| 2964 | | − if ((vtop->r & VT_LVAL) |
| 2965 | | − && (dbt & VT_BTYPE) != (sbt & VT_BTYPE)) |
| 2966 | | − gv(RC_INT); |
| 2929 | + ss = ds, ds = 4, dbt = sbt; |
| 2930 | + } else if (ss == 8) { |
| 2931 | + /* XXX some architectures (e.g. risc-v) would like it |
| 2932 | + better for this merely being a 32-to-64 sign or zero- |
| 2933 | + extension. */ |
| 2934 | + trunc = 32; /* zero upper 32 bits */ |
| 2935 | + } else { |
| 2936 | + ss = 4; |
| 2967 | 2937 | } |
| 2938 | +#endif |
| 2939 | + |
| 2940 | + if (ds >= ss) |
| 2941 | + goto done; |
| 2942 | +#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64 |
| 2943 | + if (ss == 4) { |
| 2944 | + gen_cvt_csti(dbt); |
| 2945 | + goto done; |
| 2946 | + } |
| 2947 | +#endif |
| 2948 | + bits = (ss - ds) * 8; |
| 2949 | + /* for unsigned, gen_op will convert SAR to SHR */ |
| 2950 | + vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED); |
| 2951 | + vpushi(bits); |
| 2952 | + gen_op(TOK_SHL); |
| 2953 | + vpushi(bits - trunc); |
| 2954 | + gen_op(TOK_SAR); |
| 2955 | + vpushi(trunc); |
| 2956 | + gen_op(TOK_SHR); |
| 2968 | 2957 | } |
| 2958 | +done: |
| 2969 | 2959 | vtop->type = *type; |
| 2970 | 2960 | vtop->type.t &= ~ ( VT_CONSTANT | VT_VOLATILE | VT_ARRAY ); |
| 2971 | 2961 | } |
| @@ -3293,25 +3283,30 @@ static void type_to_str(char *buf, int buf_size, · 321 unmodified lines |
| 3293 | 3283 | no_var: ; |
| 3294 | 3284 | } |
| 3295 | 3285 | |
| 3286 | +static void cast_error(CType *st, CType *dt) |
| 3287 | +{ |
| 3288 | + char buf1[256], buf2[256]; |
| 3289 | + type_to_str(buf1, sizeof(buf1), st, NULL); |
| 3290 | + type_to_str(buf2, sizeof(buf2), dt, NULL); |
| 3291 | + tcc_error("cannot convert '%s' to '%s'", buf1, buf2); |
| 3292 | +} |
| 3293 | + |
| 3296 | 3294 | /* verify type compatibility to store vtop in 'dt' type */ |
| 3297 | 3295 | static void verify_assign_cast(CType *dt) |
| 3298 | 3296 | { |
| 3299 | 3297 | CType *st, *type1, *type2; |
| 3300 | | − char buf1[256], buf2[256]; |
| 3301 | 3298 | int dbt, sbt, qualwarn, lvl; |
| 3302 | 3299 | |
| 3303 | 3300 | st = &vtop->type; /* source type */ |
| 3304 | 3301 | dbt = dt->t & VT_BTYPE; |
| 3305 | 3302 | sbt = st->t & VT_BTYPE; |
| 3306 | | − if (sbt == VT_VOID || dbt == VT_VOID) { |
| 3307 | | − if (sbt == VT_VOID && dbt == VT_VOID) |
| 3308 | | − ; /* It is Ok if both are void */ |
| 3309 | | − else |
| 3310 | | − tcc_error("cannot cast from/to void"); |
| 3311 | | − } |
| 3312 | 3303 | if (dt->t & VT_CONSTANT) |
| 3313 | 3304 | tcc_warning("assignment of read-only location"); |
| 3314 | 3305 | switch(dbt) { |
| 3306 | + case VT_VOID: |
| 3307 | + if (sbt != dbt) |
| 3308 | + tcc_error("assignment to void expression"); |
| 3309 | + break; |
| 3315 | 3310 | case VT_PTR: |
| 3316 | 3311 | /* special cases for pointers */ |
| 3317 | 3312 | /* '0' can also be a pointer */ |
| @@ -3375,10 +3370,8 @@ static void verify_assign_cast(CType *dt) · 57 unmodified lines |
| 3375 | 3370 | case VT_STRUCT: |
| 3376 | 3371 | case_VT_STRUCT: |
| 3377 | 3372 | if (!is_compatible_unqualified_types(dt, st)) { |
| 3378 | | − error: |
| 3379 | | − type_to_str(buf1, sizeof(buf1), st, NULL); |
| 3380 | | − type_to_str(buf2, sizeof(buf2), dt, NULL); |
| 3381 | | − tcc_error("cannot cast '%s' to '%s'", buf1, buf2); |
| 3373 | + error: |
| 3374 | + cast_error(st, dt); |
| 3382 | 3375 | } |
| 3383 | 3376 | break; |
| 3384 | 3377 | } |
| @@ -3495,7 +3488,7 @@ ST_FUNC void vstore(void) · 110 unmodified lines |
| 3495 | 3488 | if ((vtop->r & VT_MUSTCAST) |
| 3496 | 3489 | && btype_size(dbt) > btype_size(sbt) |
| 3497 | 3490 | ) |
| 3498 | | − force_charshort_cast(dbt); |
| 3491 | + force_charshort_cast(); |
| 3499 | 3492 | delayed_cast = 1; |
| 3500 | 3493 | } else { |
| 3501 | 3494 | gen_cast(&vtop[-1].type); |
| @@ -3512,7 +3505,7 @@ ST_FUNC void vstore(void) · 10 unmodified lines |
| 3512 | 3505 | gv(RC_TYPE(dbt)); /* generate value */ |
| 3513 | 3506 | |
| 3514 | 3507 | if (delayed_cast) { |
| 3515 | | − vtop->r |= VT_MUSTCAST; |
| 3508 | + vtop->r |= BFVAL(VT_MUSTCAST, (sbt == VT_LLONG) + 1); |
| 3516 | 3509 | //tcc_warning("deley cast %x -> %x", sbt, dbt); |
| 3517 | 3510 | vtop->type.t = ft & VT_TYPE; |
| 3518 | 3511 | } |
| @@ -3521,7 +3514,7 @@ ST_FUNC void vstore(void) · 2 unmodified lines |
| 3521 | 3514 | if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { |
| 3522 | 3515 | SValue sv; |
| 3523 | 3516 | r = get_reg(RC_INT); |
| 3524 | | − sv.type.t = ptrdiff_type.t; |
| 3517 | + sv.type.t = VT_PTRDIFF_T; |
| 3525 | 3518 | sv.r = VT_LOCAL | VT_LVAL; |
| 3526 | 3519 | sv.c.i = vtop[-1].c.i; |
| 3527 | 3520 | load(r, &sv); |
| @@ -3532,12 +3525,12 @@ ST_FUNC void vstore(void) · 4 unmodified lines |
| 3532 | 3525 | /* two word case handling : |
| 3533 | 3526 | store second register at word + 4 (or +8 for x86-64) */ |
| 3534 | 3527 | if (USING_TWO_WORDS(dbt)) { |
| 3535 | | − int load_type = (dbt == VT_QFLOAT) ? VT_DOUBLE : ptrdiff_type.t; |
| 3528 | + int load_type = (dbt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T; |
| 3536 | 3529 | vtop[-1].type.t = load_type; |
| 3537 | 3530 | store(r, vtop - 1); |
| 3538 | 3531 | vswap(); |
| 3539 | 3532 | /* convert to int to increment easily */ |
| 3540 | | − vtop->type.t = ptrdiff_type.t; |
| 3533 | + vtop->type.t = VT_PTRDIFF_T; |
| 3541 | 3534 | gaddrof(); |
| 3542 | 3535 | vpushs(PTR_SIZE); |
| 3543 | 3536 | gen_op('+'); |
| @@ -4861,6 +4854,8 @@ static void gfunc_param_typed(Sym *func, Sym *arg) · 1317 unmodified lines |
| 4861 | 4854 | type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); |
| 4862 | 4855 | type.ref = vtop->type.ref; |
| 4863 | 4856 | gen_cast(&type); |
| 4857 | + } else if (vtop->r & VT_MUSTCAST) { |
| 4858 | + force_charshort_cast(); |
| 4864 | 4859 | } |
| 4865 | 4860 | } else if (arg == NULL) { |
| 4866 | 4861 | tcc_error("too many arguments to function"); |
| @@ -5094,16 +5089,7 @@ ST_FUNC void unary(void) · 227 unmodified lines |
| 5094 | 5089 | case '!': |
| 5095 | 5090 | next(); |
| 5096 | 5091 | unary(); |
| 5097 | | − if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 5098 | | − gen_cast_s(VT_BOOL); |
| 5099 | | − vtop->c.i = !vtop->c.i; |
| 5100 | | − } else if (vtop->r == VT_CMP) { |
| 5101 | | − vtop->cmp_op ^= 1; |
| 5102 | | − n = vtop->jfalse, vtop->jfalse = vtop->jtrue, vtop->jtrue = n; |
| 5103 | | − } else { |
| 5104 | | − vpushi(0); |
| 5105 | | − gen_op(TOK_EQ); |
| 5106 | | − } |
| 5092 | + gen_test_zero(TOK_EQ); |
| 5107 | 5093 | break; |
| 5108 | 5094 | case '~': |
| 5109 | 5095 | next(); |
| @@ -6491,17 +6477,23 @@ again: · 1381 unmodified lines |
| 6491 | 6477 | next(); |
| 6492 | 6478 | |
| 6493 | 6479 | } else if (t == TOK_RETURN) { |
| 6494 | | − a = tok != ';'; |
| 6495 | 6480 | b = (func_vt.t & VT_BTYPE) != VT_VOID; |
| 6496 | | − if (a) |
| 6497 | | − gexpr(), gen_assign_cast(&func_vt); |
| 6481 | + if (tok != ';') { |
| 6482 | + gexpr(); |
| 6483 | + if (b) { |
| 6484 | + gen_assign_cast(&func_vt); |
| 6485 | + } else { |
| 6486 | + if (vtop->type.t != VT_VOID) |
| 6487 | + tcc_warning("void function returns a value"); |
| 6488 | + vtop--; |
| 6489 | + } |
| 6490 | + } else if (b) { |
| 6491 | + tcc_warning("'return' with no value"); |
| 6492 | + b = 0; |
| 6493 | + } |
| 6498 | 6494 | leave_scope(root_scope); |
| 6499 | | − if (a && b) |
| 6495 | + if (b) |
| 6500 | 6496 | gfunc_return(&func_vt); |
| 6501 | | − else if (a) |
| 6502 | | − vtop--; |
| 6503 | | − else if (b) |
| 6504 | | − tcc_warning("'return' with no value."); |
| 6505 | 6497 | skip(';'); |
| 6506 | 6498 | /* jump unless last stmt in top-level block */ |
| 6507 | 6499 | if (tok != '}' || local_scope != 1) |