| @@ -79,8 +79,18 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in · 78 unmodified lines |
| 79 | ST_DATA int func_vc; | 79 | ST_DATA int func_vc; |
| 80 | static int last_line_num, new_file, func_ind; /* debug info control */ | 80 | static int last_line_num, new_file, func_ind; /* debug info control */ |
| 81 | ST_DATA const char *funcname; | 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 | ST_DATA struct switch_t { | 95 | ST_DATA struct switch_t { |
| 86 | struct case_t { | 96 | struct case_t { |
| @@ -149,6 +159,7 @@ static void skip_or_save_block(TokenString **str); · 62 unmodified lines |
| 149 | static void gv_dup(void); | 159 | static void gv_dup(void); |
| 150 | static int get_temp_local_var(int size,int align); | 160 | static int get_temp_local_var(int size,int align); |
| 151 | static void clear_temp_local_var_list(); | 161 | static void clear_temp_local_var_list(); |
| | 162 | static void cast_error(CType *st, CType *dt); |
| 152 | | 163 | |
| 153 | ST_INLN int is_float(int t) | 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 | static inline int is_integer_btype(int bt) | 173 | static inline int is_integer_btype(int bt) |
| 163 | { | 174 | { |
| 164 | return bt == VT_BYTE | 175 | return bt == VT_BYTE |
| | 176 | || bt == VT_BOOL |
| 165 | || bt == VT_SHORT | 177 | || bt == VT_SHORT |
| 166 | || bt == VT_INT | 178 | || bt == VT_INT |
| 167 | || bt == VT_LLONG; | 179 | || bt == VT_LLONG; |
| @@ -439,16 +451,6 @@ ST_FUNC void tccgen_init(TCCState *s1) · 271 unmodified lines |
| 439 | int_type.t = VT_INT; | 451 | int_type.t = VT_INT; |
| 440 | char_pointer_type.t = VT_BYTE; | 452 | char_pointer_type.t = VT_BYTE; |
| 441 | mk_pointer(&char_pointer_type); | 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 | func_old_type.t = VT_FUNC; | 454 | func_old_type.t = VT_FUNC; |
| 453 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); | 455 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); |
| 454 | func_old_type.ref->f.func_call = FUNC_CDECL; | 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 | /* push constant of type "type" with useless value */ | 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 | vset(type, VT_CONST, 0); | 929 | vset(type, VT_CONST, 0); |
| 928 | } | 930 | } |
| 929 | | 931 | |
| 930 | /* push integer constant */ | 932 | /* push arbitrary 64bit constant */ |
| 931 | ST_FUNC void vpushi(int v) | 933 | static void vpush64(int ty, unsigned long long v) |
| 932 | { | 934 | { |
| 933 | CValue cval; | 935 | CValue cval; |
| | 936 | CType ctype; |
| | 937 | ctype.t = ty; |
| | 938 | ctype.ref = NULL; |
| 934 | cval.i = v; | 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 */ | 943 | /* push integer constant */ |
| 939 | static void vpushs(addr_t v) | 944 | ST_FUNC void vpushi(int v) |
| 940 | { | 945 | { |
| 941 | CValue cval; | 946 | vpush64(VT_INT, v); |
| 942 | cval.i = v; | | |
| 943 | vsetc(&size_type, VT_CONST, &cval); | | |
| 944 | } | 947 | } |
| 945 | | 948 | |
| 946 | /* push arbitrary 64bit constant */ | 949 | /* push a pointer sized constant */ |
| 947 | ST_FUNC void vpush64(int ty, unsigned long long v) | 950 | static void vpushs(addr_t v) |
| 948 | { | 951 | { |
| 949 | CValue cval; | 952 | vpush64(VT_SIZE_T, v); |
| 950 | CType ctype; | | |
| 951 | ctype.t = ty; | | |
| 952 | ctype.ref = NULL; | | |
| 953 | cval.i = v; | | |
| 954 | vsetc(&ctype, VT_CONST, &cval); | | |
| 955 | } | 953 | } |
| 956 | | 954 | |
| 957 | /* push long long constant */ | 955 | /* push long long constant */ |
| @@ -963,7 +961,6 @@ static inline void vpushll(long long v) · 5 unmodified lines |
| 963 | ST_FUNC void vset(CType *type, int r, int v) | 961 | ST_FUNC void vset(CType *type, int r, int v) |
| 964 | { | 962 | { |
| 965 | CValue cval; | 963 | CValue cval; |
| 966 | | | |
| 967 | cval.i = v; | 964 | cval.i = v; |
| 968 | vsetc(type, r, &cval); | 965 | vsetc(type, r, &cval); |
| 969 | } | 966 | } |
| @@ -1099,6 +1096,23 @@ static int gvtst(int inv, int t) · 129 unmodified lines |
| 1099 | return t; | 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 | /* push a symbol value of TYPE */ | 1117 | /* push a symbol value of TYPE */ |
| 1104 | static inline void vpushsym(CType *type, Sym *sym) | 1118 | static inline void vpushsym(CType *type, Sym *sym) |
| @@ -1350,44 +1364,34 @@ ST_FUNC void save_reg(int r) · 245 unmodified lines |
| 1350 | if seen up to (vtop - n) stack entry */ | 1364 | if seen up to (vtop - n) stack entry */ |
| 1351 | ST_FUNC void save_reg_upstack(int r, int n) | 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 | SValue *p, *p1, sv; | 1368 | SValue *p, *p1, sv; |
| 1355 | CType *type; | | |
| 1356 | | 1369 | |
| 1357 | if ((r &= VT_VALMASK) >= VT_CONST) | 1370 | if ((r &= VT_VALMASK) >= VT_CONST) |
| 1358 | return; | 1371 | return; |
| 1359 | if (nocode_wanted) | 1372 | if (nocode_wanted) |
| 1360 | return; | 1373 | return; |
| 1361 | | | |
| 1362 | /* modify all stack values */ | | |
| 1363 | saved = 0; | | |
| 1364 | l = 0; | 1374 | l = 0; |
| 1365 | for(p = vstack, p1 = vtop - n; p <= p1; p++) { | 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 | /* must save value on stack if not already done */ | 1377 | /* must save value on stack if not already done */ |
| 1368 | if (!saved) { | 1378 | if (!l) { |
| 1369 | /* NOTE: must reload 'r' because r might be equal to r2 */ | 1379 | bt = p->type.t & VT_BTYPE; |
| 1370 | r = p->r & VT_VALMASK; | 1380 | if (bt == VT_VOID) |
| 1371 | /* store register in the stack */ | 1381 | continue; |
| 1372 | type = &p->type; | 1382 | if ((p->r & VT_LVAL) || bt == VT_FUNC) |
| 1373 | if ((p->r & VT_LVAL) || | 1383 | bt = VT_PTR; |
| 1374 | (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG)) | 1384 | sv.type.t = bt; |
| 1375 | #if PTR_SIZE == 8 | 1385 | size = type_size(&sv.type, &align); |
| 1376 | type = &char_pointer_type; | | |
| 1377 | #else | | |
| 1378 | type = &int_type; | | |
| 1379 | #endif | | |
| 1380 | size = type_size(type, &align); | | |
| 1381 | #ifdef CONFIG_TCC_BCHECK | 1386 | #ifdef CONFIG_TCC_BCHECK |
| 1382 | if (tcc_state->do_bounds_check) | 1387 | if (tcc_state->do_bounds_check) |
| 1383 | l = loc = (loc - size) & -align; | 1388 | l = loc = (loc - size) & -align; |
| 1384 | else | 1389 | else |
| 1385 | #endif | 1390 | #endif |
| 1386 | l=get_temp_local_var(size,align); | 1391 | l = get_temp_local_var(size,align); |
| 1387 | sv.type.t = type->t; | | |
| 1388 | sv.r = VT_LOCAL | VT_LVAL; | 1392 | sv.r = VT_LOCAL | VT_LVAL; |
| 1389 | sv.c.i = l; | 1393 | sv.c.i = l; |
| 1390 | store(r, &sv); | 1394 | store(p->r & VT_VALMASK, &sv); |
| 1391 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) | 1395 | #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) |
| 1392 | /* x86 specific: need to pop fp register ST0 if saved */ | 1396 | /* x86 specific: need to pop fp register ST0 if saved */ |
| 1393 | if (r == TREG_ST0) { | 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 | #endif | 1400 | #endif |
| 1397 | /* special long long case */ | 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 | sv.c.i += PTR_SIZE; | 1403 | sv.c.i += PTR_SIZE; |
| 1400 | store(p->r2, &sv); | 1404 | store(p->r2, &sv); |
| 1401 | } | 1405 | } |
| 1402 | saved = 1; | | |
| 1403 | } | 1406 | } |
| 1404 | /* mark that stack entry as being saved on the stack */ | 1407 | /* mark that stack entry as being saved on the stack */ |
| 1405 | if (p->r & VT_LVAL) { | 1408 | if (p->r & VT_LVAL) { |
| @@ -1771,7 +1774,7 @@ ST_FUNC int gv(int rc) · 365 unmodified lines |
| 1771 | if (!r_ok) | 1774 | if (!r_ok) |
| 1772 | r = get_reg(rc); | 1775 | r = get_reg(rc); |
| 1773 | if (rc2) { | 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 | int original_type = vtop->type.t; | 1778 | int original_type = vtop->type.t; |
| 1776 | | 1779 | |
| 1777 | /* two register type load : | 1780 | /* two register type load : |
| @@ -1793,9 +1796,9 @@ ST_FUNC int gv(int rc) · 15 unmodified lines |
| 1793 | vdup(); | 1796 | vdup(); |
| 1794 | vtop[-1].r = r; /* save register value */ | 1797 | vtop[-1].r = r; /* save register value */ |
| 1795 | /* increment pointer to get second word */ | 1798 | /* increment pointer to get second word */ |
| 1796 | vtop->type.t = ptrdiff_type.t; | 1799 | vtop->type.t = VT_PTRDIFF_T; |
| 1797 | gaddrof(); | 1800 | gaddrof(); |
| 1798 | vpushi(PTR_SIZE); | 1801 | vpushs(PTR_SIZE); |
| 1799 | gen_op('+'); | 1802 | gen_op('+'); |
| 1800 | vtop->r |= VT_LVAL; | 1803 | vtop->r |= VT_LVAL; |
| 1801 | vtop->type.t = load_type; | 1804 | vtop->type.t = load_type; |
| @@ -2521,7 +2524,7 @@ redo: · 719 unmodified lines |
| 2521 | } | 2524 | } |
| 2522 | vrott(3); | 2525 | vrott(3); |
| 2523 | gen_opic(op); | 2526 | gen_opic(op); |
| 2524 | vtop->type.t = ptrdiff_type.t; | 2527 | vtop->type.t = VT_PTRDIFF_T; |
| 2525 | vswap(); | 2528 | vswap(); |
| 2526 | gen_op(TOK_PDIV); | 2529 | gen_op(TOK_PDIV); |
| 2527 | } else { | 2530 | } else { |
| @@ -2712,41 +2715,17 @@ static void gen_cvt_ftoi1(int t) · 184 unmodified lines |
| 2712 | } | 2715 | } |
| 2713 | #endif | 2716 | #endif |
| 2714 | | 2717 | |
| 2715 | /* force char or short cast */ | 2718 | /* special delayed cast for char/short */ |
| 2716 | static void force_charshort_cast(int t) | 2719 | static void force_charshort_cast(void) |
| 2717 | { | 2720 | { |
| 2718 | int bits, dbt; | 2721 | int sbt = BFGET(vtop->r, VT_MUSTCAST) == 2 ? VT_LLONG : VT_INT; |
| 2719 | | 2722 | int dbt = vtop->type.t; |
| 2720 | /* cannot cast static initializers */ | 2723 | vtop->r &= ~VT_MUSTCAST; |
| 2721 | if (STATIC_DATA_WANTED) | 2724 | vtop->type.t = sbt; |
| 2722 | return; | 2725 | gen_cast_s(dbt == VT_BOOL ? VT_BYTE|VT_UNSIGNED : dbt); |
| 2723 | | 2726 | vtop->type.t = dbt; |
| 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 | } | | |
| 2747 | } | 2727 | } |
| 2748 | | 2728 | |
| 2749 | /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ | | |
| 2750 | static void gen_cast_s(int t) | 2729 | static void gen_cast_s(int t) |
| 2751 | { | 2730 | { |
| 2752 | CType type; | 2731 | CType type; |
| @@ -2755,31 +2734,33 @@ static void gen_cast_s(int t) · 2 unmodified lines |
| 2755 | gen_cast(&type); | 2734 | gen_cast(&type); |
| 2756 | } | 2735 | } |
| 2757 | | 2736 | |
| | 2737 | /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ |
| 2758 | static void gen_cast(CType *type) | 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 | /* special delayed cast for char/short */ | 2743 | /* special delayed cast for char/short */ |
| 2763 | /* XXX: in some cases (multiple cascaded casts), it may still | 2744 | if (vtop->r & VT_MUSTCAST) |
| 2764 | be incorrect */ | 2745 | force_charshort_cast(); |
| 2765 | if (vtop->r & VT_MUSTCAST) { | | |
| 2766 | vtop->r &= ~VT_MUSTCAST; | | |
| 2767 | force_charshort_cast(vtop->type.t); | | |
| 2768 | } | | |
| 2769 | | 2746 | |
| 2770 | /* bitfields first get cast to ints */ | 2747 | /* bitfields first get cast to ints */ |
| 2771 | if (vtop->type.t & VT_BITFIELD) { | 2748 | if (vtop->type.t & VT_BITFIELD) |
| 2772 | gv(RC_INT); | 2749 | gv(RC_INT); |
| 2773 | } | | |
| 2774 | | 2750 | |
| 2775 | dbt = type->t & (VT_BTYPE | VT_UNSIGNED); | 2751 | dbt = type->t & (VT_BTYPE | VT_UNSIGNED); |
| 2776 | sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); | 2752 | sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); |
| | 2753 | if (sbt == VT_FUNC) |
| | 2754 | sbt = VT_PTR; |
| 2777 | | 2755 | |
| | 2756 | again: |
| 2778 | if (sbt != dbt) { | 2757 | if (sbt != dbt) { |
| 2779 | sf = is_float(sbt); | 2758 | sf = is_float(sbt); |
| 2780 | df = is_float(dbt); | 2759 | df = is_float(dbt); |
| | 2760 | dbt_bt = dbt & VT_BTYPE; |
| | 2761 | sbt_bt = sbt & VT_BTYPE; |
| | 2762 | |
| 2781 | c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; | 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 | #if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 | 2764 | #if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 |
| 2784 | c &= (dbt != VT_LDOUBLE) | !!nocode_wanted; | 2765 | c &= (dbt != VT_LDOUBLE) | !!nocode_wanted; |
| 2785 | #endif | 2766 | #endif |
| @@ -2792,7 +2773,7 @@ static void gen_cast(CType *type) · 6 unmodified lines |
| 2792 | vtop->c.ld = vtop->c.d; | 2773 | vtop->c.ld = vtop->c.d; |
| 2793 | | 2774 | |
| 2794 | if (df) { | 2775 | if (df) { |
| 2795 | if ((sbt & VT_BTYPE) == VT_LLONG) { | 2776 | if (sbt_bt == VT_LLONG) { |
| 2796 | if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63)) | 2777 | if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63)) |
| 2797 | vtop->c.ld = vtop->c.i; | 2778 | vtop->c.ld = vtop->c.i; |
| 2798 | else | 2779 | else |
| @@ -2808,164 +2789,173 @@ static void gen_cast(CType *type) · 9 unmodified lines |
| 2808 | vtop->c.f = (float)vtop->c.ld; | 2789 | vtop->c.f = (float)vtop->c.ld; |
| 2809 | else if (dbt == VT_DOUBLE) | 2790 | else if (dbt == VT_DOUBLE) |
| 2810 | vtop->c.d = (double)vtop->c.ld; | 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 | } else if (sf && dbt == VT_BOOL) { | 2792 | } else if (sf && dbt == VT_BOOL) { |
| 2814 | vtop->c.i = (vtop->c.ld != 0); | 2793 | vtop->c.i = (vtop->c.ld != 0); |
| 2815 | } else { | 2794 | } else { |
| 2816 | if(sf) | 2795 | if(sf) |
| 2817 | vtop->c.i = vtop->c.ld; | 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 | else if (sbt & VT_UNSIGNED) | 2799 | else if (sbt & VT_UNSIGNED) |
| 2821 | vtop->c.i = (uint32_t)vtop->c.i; | 2800 | vtop->c.i = (uint32_t)vtop->c.i; |
| 2822 | #if PTR_SIZE == 8 | 2801 | else |
| 2823 | else if (sbt == VT_PTR) | 2802 | vtop->c.i = ((uint32_t)vtop->c.i | -(vtop->c.i & 0x80000000)); |
| 2824 | ; | | |
| 2825 | #endif | | |
| 2826 | else if (sbt != VT_LLONG) | | |
| 2827 | vtop->c.i = ((uint32_t)vtop->c.i | | | |
| 2828 | -(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 | else if (dbt == VT_BOOL) | 2806 | else if (dbt == VT_BOOL) |
| 2833 | vtop->c.i = (vtop->c.i != 0); | 2807 | vtop->c.i = (vtop->c.i != 0); |
| 2834 | #if PTR_SIZE == 8 | 2808 | else { |
| 2835 | else if (dbt == VT_PTR) | 2809 | uint32_t m = dbt_bt == VT_BYTE ? 0xff : |
| 2836 | ; | 2810 | dbt_bt == VT_SHORT ? 0xffff : |
| 2837 | #endif | 2811 | 0xffffffff; |
| 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); | | |
| 2842 | vtop->c.i &= m; | 2812 | vtop->c.i &= m; |
| 2843 | if (!(dbt & VT_UNSIGNED)) | 2813 | if (!(dbt & VT_UNSIGNED)) |
| 2844 | vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1)); | 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 | vtop->r = VT_CONST; | 2823 | vtop->r = VT_CONST; |
| 2849 | vtop->c.i = 1; | 2824 | vtop->c.i = 1; |
| 2850 | } else { | 2825 | goto done; |
| 2851 | /* non constant case: generate code */ | 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 | if (sf && df) { | 2839 | if (sf && df) { |
| 2853 | /* convert from fp to fp */ | 2840 | /* convert from fp to fp */ |
| 2854 | gen_cvt_ftof(dbt); | 2841 | gen_cvt_ftof(dbt); |
| 2855 | } else if (df) { | 2842 | } else if (df) { |
| 2856 | /* convert int to fp */ | 2843 | /* convert int to fp */ |
| 2857 | gen_cvt_itof1(dbt); | 2844 | gen_cvt_itof1(dbt); |
| 2858 | } else if (sf) { | 2845 | } else { |
| 2859 | /* convert fp to int */ | 2846 | /* convert fp to int */ |
| 2860 | if (dbt == VT_BOOL) { | 2847 | sbt = dbt; |
| 2861 | vpushi(0); | 2848 | if (dbt_bt != VT_LLONG && dbt_bt != VT_INT) |
| 2862 | gen_op(TOK_NE); | 2849 | sbt = VT_INT; |
| 2863 | } else { | 2850 | gen_cvt_ftoi1(sbt); |
| 2864 | /* we handle char/short/etc... with generic code */ | 2851 | goto again; /* may need char/short cast */ |
| 2865 | if (dbt != (VT_INT | VT_UNSIGNED) && | 2852 | } |
| 2866 | dbt != (VT_LLONG | VT_UNSIGNED) && | 2853 | goto done; |
| 2867 | dbt != VT_LLONG) | 2854 | } |
| 2868 | dbt = VT_INT; | 2855 | |
| 2869 | gen_cvt_ftoi1(dbt); | 2856 | ds = btype_size(dbt_bt); |
| 2870 | if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) { | 2857 | ss = btype_size(sbt_bt); |
| 2871 | /* additional cast for char/short... */ | 2858 | if (ds == 0 || ss == 0) { |
| 2872 | vtop->type.t = dbt; | 2859 | if (dbt_bt == VT_VOID) |
| 2873 | gen_cast(type); | 2860 | goto done; |
| 2874 | } | 2861 | cast_error(&vtop->type, type); |
| 2875 | } | 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 | #if PTR_SIZE == 4 | 2895 | #if PTR_SIZE == 4 |
| 2877 | } else if ((dbt & VT_BTYPE) == VT_LLONG) { | 2896 | if (ds == 8) { |
| 2878 | if ((sbt & VT_BTYPE) != VT_LLONG) { | 2897 | /* generate high word */ |
| 2879 | /* scalar to long long */ | 2898 | if (sbt & VT_UNSIGNED) { |
| 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 */ | | |
| 2935 | vpushi(0); | 2899 | vpushi(0); |
| 2936 | gen_op(TOK_NE); | 2900 | gv(RC_INT); |
| 2937 | } else if ((dbt & VT_BTYPE) == VT_BYTE || | 2901 | } else { |
| 2938 | (dbt & VT_BTYPE) == VT_SHORT) { | 2902 | gv_dup(); |
| 2939 | if (sbt == VT_PTR) { | 2903 | vpushi(31); |
| 2940 | vtop->type.t = VT_INT; | 2904 | gen_op(TOK_SAR); |
| 2941 | tcc_warning("nonportable conversion from pointer to char/short"); | 2905 | } |
| 2942 | } | 2906 | lbuild(dbt); |
| 2943 | force_charshort_cast(dbt); | 2907 | } else if (ss == 8) { |
| 2944 | } else if ((dbt & VT_BTYPE) == VT_INT) { | 2908 | /* from long long: just take low order word */ |
| 2945 | /* scalar to int */ | 2909 | lexpand(); |
| 2946 | if ((sbt & VT_BTYPE) == VT_LLONG) { | 2910 | vpop(); |
| 2947 | #if PTR_SIZE == 4 | 2911 | } |
| 2948 | /* from long long: just take low order word */ | 2912 | ss = 4; |
| 2949 | lexpand(); | 2913 | |
| 2950 | vpop(); | 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 | #else | 2922 | #else |
| 2952 | if (dbt & VT_UNSIGNED) { | 2923 | goto done; |
| 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 | } | | |
| 2961 | #endif | 2924 | #endif |
| 2962 | } | 2925 | } else { |
| | 2926 | gen_cvt_sxtw(); |
| | 2927 | goto done; |
| 2963 | } | 2928 | } |
| 2964 | if ((vtop->r & VT_LVAL) | 2929 | ss = ds, ds = 4, dbt = sbt; |
| 2965 | && (dbt & VT_BTYPE) != (sbt & VT_BTYPE)) | 2930 | } else if (ss == 8) { |
| 2966 | gv(RC_INT); | 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 | vtop->type = *type; | 2959 | vtop->type = *type; |
| 2970 | vtop->type.t &= ~ ( VT_CONSTANT | VT_VOLATILE | VT_ARRAY ); | 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 | no_var: ; | 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 | /* verify type compatibility to store vtop in 'dt' type */ | 3294 | /* verify type compatibility to store vtop in 'dt' type */ |
| 3297 | static void verify_assign_cast(CType *dt) | 3295 | static void verify_assign_cast(CType *dt) |
| 3298 | { | 3296 | { |
| 3299 | CType *st, *type1, *type2; | 3297 | CType *st, *type1, *type2; |
| 3300 | char buf1[256], buf2[256]; | | |
| 3301 | int dbt, sbt, qualwarn, lvl; | 3298 | int dbt, sbt, qualwarn, lvl; |
| 3302 | | 3299 | |
| 3303 | st = &vtop->type; /* source type */ | 3300 | st = &vtop->type; /* source type */ |
| 3304 | dbt = dt->t & VT_BTYPE; | 3301 | dbt = dt->t & VT_BTYPE; |
| 3305 | sbt = st->t & VT_BTYPE; | 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 | if (dt->t & VT_CONSTANT) | 3303 | if (dt->t & VT_CONSTANT) |
| 3313 | tcc_warning("assignment of read-only location"); | 3304 | tcc_warning("assignment of read-only location"); |
| 3314 | switch(dbt) { | 3305 | switch(dbt) { |
| | 3306 | case VT_VOID: |
| | 3307 | if (sbt != dbt) |
| | 3308 | tcc_error("assignment to void expression"); |
| | 3309 | break; |
| 3315 | case VT_PTR: | 3310 | case VT_PTR: |
| 3316 | /* special cases for pointers */ | 3311 | /* special cases for pointers */ |
| 3317 | /* '0' can also be a pointer */ | 3312 | /* '0' can also be a pointer */ |
| @@ -3375,10 +3370,8 @@ static void verify_assign_cast(CType *dt) · 57 unmodified lines |
| 3375 | case VT_STRUCT: | 3370 | case VT_STRUCT: |
| 3376 | case_VT_STRUCT: | 3371 | case_VT_STRUCT: |
| 3377 | if (!is_compatible_unqualified_types(dt, st)) { | 3372 | if (!is_compatible_unqualified_types(dt, st)) { |
| 3378 | error: | 3373 | error: |
| 3379 | type_to_str(buf1, sizeof(buf1), st, NULL); | 3374 | cast_error(st, dt); |
| 3380 | type_to_str(buf2, sizeof(buf2), dt, NULL); | | |
| 3381 | tcc_error("cannot cast '%s' to '%s'", buf1, buf2); | | |
| 3382 | } | 3375 | } |
| 3383 | break; | 3376 | break; |
| 3384 | } | 3377 | } |
| @@ -3495,7 +3488,7 @@ ST_FUNC void vstore(void) · 110 unmodified lines |
| 3495 | if ((vtop->r & VT_MUSTCAST) | 3488 | if ((vtop->r & VT_MUSTCAST) |
| 3496 | && btype_size(dbt) > btype_size(sbt) | 3489 | && btype_size(dbt) > btype_size(sbt) |
| 3497 | ) | 3490 | ) |
| 3498 | force_charshort_cast(dbt); | 3491 | force_charshort_cast(); |
| 3499 | delayed_cast = 1; | 3492 | delayed_cast = 1; |
| 3500 | } else { | 3493 | } else { |
| 3501 | gen_cast(&vtop[-1].type); | 3494 | gen_cast(&vtop[-1].type); |
| @@ -3512,7 +3505,7 @@ ST_FUNC void vstore(void) · 10 unmodified lines |
| 3512 | gv(RC_TYPE(dbt)); /* generate value */ | 3505 | gv(RC_TYPE(dbt)); /* generate value */ |
| 3513 | | 3506 | |
| 3514 | if (delayed_cast) { | 3507 | if (delayed_cast) { |
| 3515 | vtop->r |= VT_MUSTCAST; | 3508 | vtop->r |= BFVAL(VT_MUSTCAST, (sbt == VT_LLONG) + 1); |
| 3516 | //tcc_warning("deley cast %x -> %x", sbt, dbt); | 3509 | //tcc_warning("deley cast %x -> %x", sbt, dbt); |
| 3517 | vtop->type.t = ft & VT_TYPE; | 3510 | vtop->type.t = ft & VT_TYPE; |
| 3518 | } | 3511 | } |
| @@ -3521,7 +3514,7 @@ ST_FUNC void vstore(void) · 2 unmodified lines |
| 3521 | if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { | 3514 | if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { |
| 3522 | SValue sv; | 3515 | SValue sv; |
| 3523 | r = get_reg(RC_INT); | 3516 | r = get_reg(RC_INT); |
| 3524 | sv.type.t = ptrdiff_type.t; | 3517 | sv.type.t = VT_PTRDIFF_T; |
| 3525 | sv.r = VT_LOCAL | VT_LVAL; | 3518 | sv.r = VT_LOCAL | VT_LVAL; |
| 3526 | sv.c.i = vtop[-1].c.i; | 3519 | sv.c.i = vtop[-1].c.i; |
| 3527 | load(r, &sv); | 3520 | load(r, &sv); |
| @@ -3532,12 +3525,12 @@ ST_FUNC void vstore(void) · 4 unmodified lines |
| 3532 | /* two word case handling : | 3525 | /* two word case handling : |
| 3533 | store second register at word + 4 (or +8 for x86-64) */ | 3526 | store second register at word + 4 (or +8 for x86-64) */ |
| 3534 | if (USING_TWO_WORDS(dbt)) { | 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 | vtop[-1].type.t = load_type; | 3529 | vtop[-1].type.t = load_type; |
| 3537 | store(r, vtop - 1); | 3530 | store(r, vtop - 1); |
| 3538 | vswap(); | 3531 | vswap(); |
| 3539 | /* convert to int to increment easily */ | 3532 | /* convert to int to increment easily */ |
| 3540 | vtop->type.t = ptrdiff_type.t; | 3533 | vtop->type.t = VT_PTRDIFF_T; |
| 3541 | gaddrof(); | 3534 | gaddrof(); |
| 3542 | vpushs(PTR_SIZE); | 3535 | vpushs(PTR_SIZE); |
| 3543 | gen_op('+'); | 3536 | gen_op('+'); |
| @@ -4861,6 +4854,8 @@ static void gfunc_param_typed(Sym *func, Sym *arg) · 1317 unmodified lines |
| 4861 | type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); | 4854 | type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); |
| 4862 | type.ref = vtop->type.ref; | 4855 | type.ref = vtop->type.ref; |
| 4863 | gen_cast(&type); | 4856 | gen_cast(&type); |
| | 4857 | } else if (vtop->r & VT_MUSTCAST) { |
| | 4858 | force_charshort_cast(); |
| 4864 | } | 4859 | } |
| 4865 | } else if (arg == NULL) { | 4860 | } else if (arg == NULL) { |
| 4866 | tcc_error("too many arguments to function"); | 4861 | tcc_error("too many arguments to function"); |
| @@ -5094,16 +5089,7 @@ ST_FUNC void unary(void) · 227 unmodified lines |
| 5094 | case '!': | 5089 | case '!': |
| 5095 | next(); | 5090 | next(); |
| 5096 | unary(); | 5091 | unary(); |
| 5097 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { | 5092 | gen_test_zero(TOK_EQ); |
| 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 | } | | |
| 5107 | break; | 5093 | break; |
| 5108 | case '~': | 5094 | case '~': |
| 5109 | next(); | 5095 | next(); |
| @@ -6491,17 +6477,23 @@ again: · 1381 unmodified lines |
| 6491 | next(); | 6477 | next(); |
| 6492 | | 6478 | |
| 6493 | } else if (t == TOK_RETURN) { | 6479 | } else if (t == TOK_RETURN) { |
| 6494 | a = tok != ';'; | | |
| 6495 | b = (func_vt.t & VT_BTYPE) != VT_VOID; | 6480 | b = (func_vt.t & VT_BTYPE) != VT_VOID; |
| 6496 | if (a) | 6481 | if (tok != ';') { |
| 6497 | gexpr(), gen_assign_cast(&func_vt); | 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 | leave_scope(root_scope); | 6494 | leave_scope(root_scope); |
| 6499 | if (a && b) | 6495 | if (b) |
| 6500 | gfunc_return(&func_vt); | 6496 | gfunc_return(&func_vt); |
| 6501 | else if (a) | | |
| 6502 | vtop--; | | |
| 6503 | else if (b) | | |
| 6504 | tcc_warning("'return' with no value."); | | |
| 6505 | skip(';'); | 6497 | skip(';'); |
| 6506 | /* jump unless last stmt in top-level block */ | 6498 | /* jump unless last stmt in top-level block */ |
| 6507 | if (tok != '}' || local_scope != 1) | 6499 | if (tok != '}' || local_scope != 1) |