add some features for more complete 'long' support tcc.h: - use LONG_SIZE=4/8 instead of TCC_LONG_ARE_64_BIT tccgen.c: - add ptrdiff_type, update size_type - support shift and ?: operations - support long enum types - display 'long' from type_to_str - nwchar_t is unsigned short on windows - unrelated: use memcpy in init_putv for long doubles to avoid random bytes in the image (if tcc was compiled by gcc) for diff purposes. tccpp.c: - make parse_number return correct types - improve multi-character-constants 'XX' 'abcd' Changelog: - update
Unified · Split
| @@ -9,11 +9,10 @@ User interface: · 8 unmodified lines | ||
| 9 | 9 | - -mno-sse on x86-64 disables use of SSE instructions |
| 10 | 10 | - @listfile support (Vlad Vissoultchev) |
| 11 | 11 | - tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka) |
| 12 | −- CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support | |
| 12 | +- CPATH, C_INCLUDE_PATH and LIBRARY_PATH environment variables support | |
| 13 | 13 | (Andrew Aladjev, Urs Janssen) |
| 14 | 14 | |
| 15 | 15 | Platforms: |
| 16 | −- Bootstrap native Windows 32/64 compiler using Cygwin+gcc (Christian Jullien) | |
| 17 | 16 | - new AARCH64 (arm64) target (Edmund Grimley Evans) |
| 18 | 17 | - vastly improved support for ARM hard float calling convention |
| 19 | 18 | (Thomas Preud'homme, Daniel Glöckner) |
| @@ -22,6 +21,7 @@ Platforms: · 2 unmodified lines | ||
| 22 | 21 | - ABI tests with native compiler using libtcc (James Lyon) |
| 23 | 22 | - UNICODE startup code supports wmain and wWinMain (YX Hao) |
| 24 | 23 | - shared libraries for x86_64 (Michael Matz) |
| 24 | +- Bootstrap native Windows 32/64 compiler using Cygwin+gcc (Christian Jullien) | |
| 25 | 25 | |
| 26 | 26 | Features: |
| 27 | 27 | - VLA (variable length array) improved (James Lyon, Pip Cet) |
| @@ -35,6 +35,8 @@ Features: · 7 unmodified lines | ||
| 35 | 35 | - standard conforming (and GCC compatible) struct initialization |
| 36 | 36 | (Michael Matz) |
| 37 | 37 | - bit-field layout made compatible with GCC (Michael Matz) |
| 38 | +- UTF8 in string literals supported (Zdenek Pavlas) | |
| 39 | +_ _Generic(...) supported (Matthias Gatto) | |
| 38 | 40 | |
| 39 | 41 | Licensing: |
| 40 | 42 | - TinyCC partly relicensed to MIT license (See RELICENSING file). |
| @@ -836,21 +836,21 @@ LIBTCCAPI TCCState *tcc_new(void) · 835 unmodified lines | ||
| 836 | 836 | # endif |
| 837 | 837 | |
| 838 | 838 | /* TinyCC & gcc defines */ |
| 839 | −#if defined(TCC_TARGET_PE) && PTR_SIZE == 8 | |
| 839 | +#if PTR_SIZE == 4 | |
| 840 | + /* 32bit systems. */ | |
| 841 | + tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); | |
| 842 | + tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); | |
| 843 | + tcc_define_symbol(s, "__ILP32__", NULL); | |
| 844 | +#elif LONG_SIZE == 4 | |
| 840 | 845 | /* 64bit Windows. */ |
| 841 | 846 | tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long"); |
| 842 | 847 | tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long"); |
| 843 | 848 | tcc_define_symbol(s, "__LLP64__", NULL); |
| 844 | −#elif PTR_SIZE == 8 | |
| 849 | +#else | |
| 845 | 850 | /* Other 64bit systems. */ |
| 846 | 851 | tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long"); |
| 847 | 852 | tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long"); |
| 848 | 853 | tcc_define_symbol(s, "__LP64__", NULL); |
| 849 | −#else | |
| 850 | − /* Other 32bit systems. */ | |
| 851 | − tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); | |
| 852 | − tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); | |
| 853 | − tcc_define_symbol(s, "__ILP32__", NULL); | |
| 854 | 854 | #endif |
| 855 | 855 | |
| 856 | 856 | #if defined(TCC_MUSL) |
| @@ -361,6 +361,12 @@ extern long double strtold (const char *__nptr, char **__endptr); · 360 unmodified lines | ||
| 361 | 361 | /* target address type */ |
| 362 | 362 | #define addr_t ElfW(Addr) |
| 363 | 363 | |
| 364 | +#if PTR_SIZE == 8 && !defined TCC_TARGET_PE | |
| 365 | +# define LONG_SIZE 8 | |
| 366 | +#else | |
| 367 | +# define LONG_SIZE 4 | |
| 368 | +#endif | |
| 369 | + | |
| 364 | 370 | /* -------------------------------------------- */ |
| 365 | 371 | |
| 366 | 372 | #define INCLUDE_STACK_SIZE 32 |
| @@ -880,14 +886,14 @@ struct filespec { · 513 unmodified lines | ||
| 880 | 886 | #define VT_CONSTANT 0x0100 /* const modifier */ |
| 881 | 887 | #define VT_VOLATILE 0x0200 /* volatile modifier */ |
| 882 | 888 | #define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */ |
| 883 | −#define VT_LONG 0x0800 | |
| 889 | +#define VT_LONG 0x0800 /* long type (also has VT_INT rsp. VT_LLONG) */ | |
| 884 | 890 | |
| 885 | 891 | /* storage */ |
| 886 | 892 | #define VT_EXTERN 0x00001000 /* extern definition */ |
| 887 | 893 | #define VT_STATIC 0x00002000 /* static variable */ |
| 888 | 894 | #define VT_TYPEDEF 0x00004000 /* typedef definition */ |
| 889 | 895 | #define VT_INLINE 0x00008000 /* inline definition */ |
| 890 | −/* currently unused: 0x0800, 0x000[1248]0000 */ | |
| 896 | +/* currently unused: 0x000[1248]0000 */ | |
| 891 | 897 | |
| 892 | 898 | #define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */ |
| 893 | 899 | #define VT_STRUCT_MASK (((1 << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD) |
| @@ -906,7 +912,6 @@ struct filespec { · 12 unmodified lines | ||
| 906 | 912 | #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE) |
| 907 | 913 | #define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK)) |
| 908 | 914 | |
| 909 | − | |
| 910 | 915 | /* token values */ |
| 911 | 916 | |
| 912 | 917 | /* warning: the following compare tokens depend on i386 asm code */ |
| @@ -947,6 +952,7 @@ struct filespec { · 34 unmodified lines | ||
| 947 | 952 | #define TOK_PPNUM 0xbe /* preprocessor number */ |
| 948 | 953 | #define TOK_PPSTR 0xbf /* preprocessor string */ |
| 949 | 954 | #define TOK_LINENUM 0xc0 /* line number info */ |
| 955 | +#define TOK_TWODOTS 0xa8 /* C++ token ? */ | |
| 950 | 956 | /* <-- */ |
| 951 | 957 | |
| 952 | 958 | #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ |
| @@ -961,15 +967,8 @@ struct filespec { · 8 unmodified lines | ||
| 961 | 967 | #define TOK_PLCHLDR 0xcb /* placeholder token as defined in C99 */ |
| 962 | 968 | #define TOK_NOSUBST 0xcc /* means following token has already been pp'd */ |
| 963 | 969 | #define TOK_PPJOIN 0xcd /* A '##' in the right position to mean pasting */ |
| 964 | − | |
| 965 | −#define TOK_CLONG 0xce /* long constant */ | |
| 966 | −#define TOK_CULONG 0xcf /* unsigned long constant */ | |
| 967 | − | |
| 968 | − | |
| 969 | −#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE | |
| 970 | − #define TCC_LONG_ARE_64_BIT | |
| 971 | −#endif | |
| 972 | − | |
| 970 | +#define TOK_CLONG 0xce /* long constant */ | |
| 971 | +#define TOK_CULONG 0xcf /* unsigned long constant */ | |
| 973 | 972 | |
| 974 | 973 | #define TOK_SHL 0x01 /* shift left */ |
| 975 | 974 | #define TOK_SAR 0x02 /* signed shift right */ |
| @@ -61,7 +61,7 @@ ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc · 60 unmodified lines | ||
| 61 | 61 | ST_DATA const char *funcname; |
| 62 | 62 | ST_DATA int g_debug; |
| 63 | 63 | |
| 64 | −ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; | |
| 64 | +ST_DATA CType char_pointer_type, func_old_type, int_type, size_type, ptrdiff_type; | |
| 65 | 65 | |
| 66 | 66 | ST_DATA struct switch_t { |
| 67 | 67 | struct case_t { |
| @@ -240,9 +240,14 @@ ST_FUNC int tccgen_compile(TCCState *s1) · 172 unmodified lines | ||
| 240 | 240 | char_pointer_type.t = VT_BYTE; |
| 241 | 241 | mk_pointer(&char_pointer_type); |
| 242 | 242 | #if PTR_SIZE == 4 |
| 243 | − size_type.t = VT_INT; | |
| 243 | + size_type.t = VT_INT | VT_UNSIGNED; | |
| 244 | + ptrdiff_type.t = VT_INT; | |
| 245 | +#elif LONG_SIZE == 4 | |
| 246 | + size_type.t = VT_LLONG | VT_UNSIGNED; | |
| 247 | + ptrdiff_type.t = VT_LLONG; | |
| 244 | 248 | #else |
| 245 | − size_type.t = VT_LLONG; | |
| 249 | + size_type.t = VT_LONG | VT_LLONG | VT_UNSIGNED; | |
| 250 | + ptrdiff_type.t = VT_LONG | VT_LLONG; | |
| 246 | 251 | #endif |
| 247 | 252 | func_old_type.t = VT_FUNC; |
| 248 | 253 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); |
| @@ -2127,12 +2132,7 @@ redo: · 1878 unmodified lines | ||
| 2127 | 2132 | } |
| 2128 | 2133 | vrott(3); |
| 2129 | 2134 | gen_opic(op); |
| 2130 | − /* set to integer type */ | |
| 2131 | −#if PTR_SIZE == 8 | |
| 2132 | − vtop->type.t = VT_LLONG; | |
| 2133 | −#else | |
| 2134 | − vtop->type.t = VT_INT; | |
| 2135 | −#endif | |
| 2135 | + vtop->type.t = ptrdiff_type.t; | |
| 2136 | 2136 | vswap(); |
| 2137 | 2137 | gen_op(TOK_PDIV); |
| 2138 | 2138 | } else { |
| @@ -2218,14 +2218,15 @@ redo: · 79 unmodified lines | ||
| 2218 | 2218 | t = bt1 == VT_LLONG ? VT_LLONG : VT_INT; |
| 2219 | 2219 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (t | VT_UNSIGNED)) |
| 2220 | 2220 | t |= VT_UNSIGNED; |
| 2221 | + t |= (VT_LONG & t1); | |
| 2221 | 2222 | goto std_op; |
| 2222 | 2223 | } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) { |
| 2223 | 2224 | /* cast to biggest op */ |
| 2224 | − t = VT_LLONG; | |
| 2225 | − /* check if we need to keep type as long or as long long */ | |
| 2226 | − if ((t1 & VT_LONG && (t2 & (VT_BTYPE | VT_LONG)) != VT_LLONG) || | |
| 2227 | − (t2 & VT_LONG && (t1 & (VT_BTYPE | VT_LONG)) != VT_LLONG)) | |
| 2228 | − t |= VT_LONG; | |
| 2225 | + t = VT_LLONG | VT_LONG; | |
| 2226 | + if (bt1 == VT_LLONG) | |
| 2227 | + t &= t1; | |
| 2228 | + if (bt2 == VT_LLONG) | |
| 2229 | + t &= t2; | |
| 2229 | 2230 | /* convert to unsigned if it does not fit in a long long */ |
| 2230 | 2231 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) || |
| 2231 | 2232 | (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED)) |
| @@ -2233,12 +2234,8 @@ redo: · 1 unmodified line | ||
| 2233 | 2234 | goto std_op; |
| 2234 | 2235 | } else { |
| 2235 | 2236 | /* integer operations */ |
| 2236 | − t = VT_INT; | |
| 2237 | − | |
| 2238 | − if ((t1 & VT_LONG) || (t2 & VT_LONG)) | |
| 2239 | − t |= VT_LONG; | |
| 2240 | − | |
| 2241 | − /* convert to unsigned if it does not fit in an integer */ | |
| 2237 | + t = VT_INT | (VT_LONG & (t1 | t2)); | |
| 2238 | + /* convert to unsigned if it does not fit in an integer */ | |
| 2242 | 2239 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) || |
| 2243 | 2240 | (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED)) |
| 2244 | 2241 | t |= VT_UNSIGNED; |
| @@ -2741,7 +2738,6 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 496 unmodified lines | ||
| 2741 | 2738 | t1 &= ~VT_DEFSIGN; |
| 2742 | 2739 | t2 &= ~VT_DEFSIGN; |
| 2743 | 2740 | } |
| 2744 | − | |
| 2745 | 2741 | /* XXX: bitfields ? */ |
| 2746 | 2742 | if (t1 != t2) |
| 2747 | 2743 | return 0; |
| @@ -2790,14 +2786,7 @@ static void type_to_str(char *buf, int buf_size, · 42 unmodified lines | ||
| 2790 | 2786 | t = type->t; |
| 2791 | 2787 | bt = t & VT_BTYPE; |
| 2792 | 2788 | buf[0] = '\0'; |
| 2793 | − if (t & VT_CONSTANT) | |
| 2794 | − pstrcat(buf, buf_size, "const "); | |
| 2795 | − if (t & VT_VOLATILE) | |
| 2796 | − pstrcat(buf, buf_size, "volatile "); | |
| 2797 | − if ((t & (VT_DEFSIGN | VT_UNSIGNED)) == (VT_DEFSIGN | VT_UNSIGNED)) | |
| 2798 | − pstrcat(buf, buf_size, "unsigned "); | |
| 2799 | − else if (t & VT_DEFSIGN) | |
| 2800 | − pstrcat(buf, buf_size, "signed "); | |
| 2789 | + | |
| 2801 | 2790 | if (t & VT_EXTERN) |
| 2802 | 2791 | pstrcat(buf, buf_size, "extern "); |
| 2803 | 2792 | if (t & VT_STATIC) |
| @@ -2806,17 +2795,20 @@ static void type_to_str(char *buf, int buf_size, · 2 unmodified lines | ||
| 2806 | 2795 | pstrcat(buf, buf_size, "typedef "); |
| 2807 | 2796 | if (t & VT_INLINE) |
| 2808 | 2797 | pstrcat(buf, buf_size, "inline "); |
| 2798 | + if (t & VT_VOLATILE) | |
| 2799 | + pstrcat(buf, buf_size, "volatile "); | |
| 2800 | + if (t & VT_CONSTANT) | |
| 2801 | + pstrcat(buf, buf_size, "const "); | |
| 2802 | + | |
| 2803 | + if (((t & VT_DEFSIGN) && bt == VT_BYTE) | |
| 2804 | + || ((t & VT_UNSIGNED) | |
| 2805 | + && (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG) | |
| 2806 | + && !IS_ENUM(t) | |
| 2807 | + )) | |
| 2808 | + pstrcat(buf, buf_size, (t & VT_UNSIGNED) ? "unsigned " : "signed "); | |
| 2809 | + | |
| 2809 | 2810 | buf_size -= strlen(buf); |
| 2810 | 2811 | buf += strlen(buf); |
| 2811 | − if (IS_ENUM(t)) { | |
| 2812 | − tstr = "enum "; | |
| 2813 | − goto tstruct; | |
| 2814 | − } | |
| 2815 | − | |
| 2816 | − if (!bt && VT_LONG & t) { | |
| 2817 | − tstr = "long"; | |
| 2818 | − goto add_tstr; | |
| 2819 | − } | |
| 2820 | 2812 | |
| 2821 | 2813 | switch(bt) { |
| 2822 | 2814 | case VT_VOID: |
| @@ -2833,10 +2825,16 @@ static void type_to_str(char *buf, int buf_size, · 10 unmodified lines | ||
| 2833 | 2825 | goto add_tstr; |
| 2834 | 2826 | case VT_INT: |
| 2835 | 2827 | tstr = "int"; |
| 2836 | − goto add_tstr; | |
| 2828 | + goto maybe_long; | |
| 2837 | 2829 | case VT_LLONG: |
| 2838 | 2830 | tstr = "long long"; |
| 2839 | − goto add_tstr; | |
| 2831 | + maybe_long: | |
| 2832 | + if (t & VT_LONG) | |
| 2833 | + tstr = "long"; | |
| 2834 | + if (!IS_ENUM(t)) | |
| 2835 | + goto add_tstr; | |
| 2836 | + tstr = "enum "; | |
| 2837 | + goto tstruct; | |
| 2840 | 2838 | case VT_FLOAT: |
| 2841 | 2839 | tstr = "float"; |
| 2842 | 2840 | goto add_tstr; |
| @@ -2902,7 +2900,7 @@ static void type_to_str(char *buf, int buf_size, · 59 unmodified lines | ||
| 2902 | 2900 | casts if needed. */ |
| 2903 | 2901 | static void gen_assign_cast(CType *dt) |
| 2904 | 2902 | { |
| 2905 | − CType *st, *type1, *type2, tmp_type1, tmp_type2; | |
| 2903 | + CType *st, *type1, *type2; | |
| 2906 | 2904 | char buf1[256], buf2[256]; |
| 2907 | 2905 | int dbt, sbt; |
| 2908 | 2906 | |
| @@ -2958,7 +2956,7 @@ static void gen_assign_cast(CType *dt) · 49 unmodified lines | ||
| 2958 | 2956 | in pointer target signedness. Do warn for different |
| 2959 | 2957 | base types, though, in particular for unsigned enums |
| 2960 | 2958 | and signed int targets. */ |
| 2961 | − if ((type1->t & VT_BTYPE) != (type2->t & VT_BTYPE) | |
| 2959 | + if ((type1->t & (VT_BTYPE|VT_LONG)) != (type2->t & (VT_BTYPE|VT_LONG)) | |
| 2962 | 2960 | || IS_ENUM(type1->t) || IS_ENUM(type2->t) |
| 2963 | 2961 | ) |
| 2964 | 2962 | tcc_warning("assignment from incompatible pointer type"); |
| @@ -2982,11 +2980,7 @@ static void gen_assign_cast(CType *dt) · 17 unmodified lines | ||
| 2982 | 2980 | break; |
| 2983 | 2981 | case VT_STRUCT: |
| 2984 | 2982 | case_VT_STRUCT: |
| 2985 | − tmp_type1 = *dt; | |
| 2986 | − tmp_type2 = *st; | |
| 2987 | − tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE); | |
| 2988 | − tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE); | |
| 2989 | − if (!is_compatible_types(&tmp_type1, &tmp_type2)) { | |
| 2983 | + if (!is_compatible_unqualified_types(dt, st)) { | |
| 2990 | 2984 | error: |
| 2991 | 2985 | type_to_str(buf1, sizeof(buf1), st, NULL); |
| 2992 | 2986 | type_to_str(buf2, sizeof(buf2), dt, NULL); |
| @@ -3775,10 +3769,10 @@ do_decl: · 782 unmodified lines | ||
| 3775 | 3769 | t.t = VT_INT; |
| 3776 | 3770 | if (nl >= 0) { |
| 3777 | 3771 | if (pl != (unsigned)pl) |
| 3778 | − t.t = VT_LLONG; | |
| 3772 | + t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); | |
| 3779 | 3773 | t.t |= VT_UNSIGNED; |
| 3780 | 3774 | } else if (pl != (int)pl || nl != (int)nl) |
| 3781 | − t.t = VT_LLONG; | |
| 3775 | + t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); | |
| 3782 | 3776 | s->type.t = type->t = t.t | VT_ENUM; |
| 3783 | 3777 | s->c = 0; |
| 3784 | 3778 | /* set type for enum members */ |
| @@ -3791,7 +3785,8 @@ do_decl: · 6 unmodified lines | ||
| 3791 | 3785 | if (ll == (unsigned)ll) |
| 3792 | 3786 | continue; |
| 3793 | 3787 | } |
| 3794 | − ss->type.t = (ss->type.t & ~VT_BTYPE) | VT_LLONG; | |
| 3788 | + ss->type.t = (ss->type.t & ~VT_BTYPE) | |
| 3789 | + | (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG); | |
| 3795 | 3790 | } |
| 3796 | 3791 | } else { |
| 3797 | 3792 | c = 0; |
| @@ -3964,7 +3959,7 @@ static int parse_btype(CType *type, AttributeDef *ad) · 166 unmodified lines | ||
| 3964 | 3959 | bt = u; |
| 3965 | 3960 | } |
| 3966 | 3961 | if (u != VT_INT) |
| 3967 | − t = (t & ~VT_BTYPE) | u; | |
| 3962 | + t = (t & ~(VT_BTYPE|VT_LONG)) | u; | |
| 3968 | 3963 | typespec_found = 1; |
| 3969 | 3964 | break; |
| 3970 | 3965 | case TOK_VOID: |
| @@ -3978,11 +3973,9 @@ static int parse_btype(CType *type, AttributeDef *ad) · 7 unmodified lines | ||
| 3978 | 3973 | goto basic_type; |
| 3979 | 3974 | case TOK_LONG: |
| 3980 | 3975 | if ((t & VT_BTYPE) == VT_DOUBLE) { |
| 3981 | −#ifndef TCC_TARGET_PE | |
| 3982 | − t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LDOUBLE; | |
| 3983 | −#endif | |
| 3984 | − } else if (t & VT_LONG) { | |
| 3985 | − t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LLONG; | |
| 3976 | + t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE; | |
| 3977 | + } else if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) { | |
| 3978 | + t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LLONG; | |
| 3986 | 3979 | } else { |
| 3987 | 3980 | u = VT_LONG; |
| 3988 | 3981 | goto basic_type; |
| @@ -4003,12 +3996,8 @@ static int parse_btype(CType *type, AttributeDef *ad) · 14 unmodified lines | ||
| 4003 | 3996 | u = VT_FLOAT; |
| 4004 | 3997 | goto basic_type; |
| 4005 | 3998 | case TOK_DOUBLE: |
| 4006 | − if (t & VT_LONG) { | |
| 4007 | −#ifdef TCC_TARGET_PE | |
| 4008 | − t = (t & ~(VT_LONG | VT_BTYPE)) | VT_DOUBLE; | |
| 4009 | −#else | |
| 4010 | − t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LDOUBLE; | |
| 4011 | −#endif | |
| 3999 | + if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) { | |
| 4000 | + t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE; | |
| 4012 | 4001 | } else { |
| 4013 | 4002 | u = VT_DOUBLE; |
| 4014 | 4003 | goto basic_type; |
| @@ -4098,7 +4087,7 @@ static int parse_btype(CType *type, AttributeDef *ad) · 83 unmodified lines | ||
| 4098 | 4087 | parse_attribute(ad); |
| 4099 | 4088 | if (ad->attr_mode) { |
| 4100 | 4089 | u = ad->attr_mode -1; |
| 4101 | − t = (t & ~VT_BTYPE) | u; | |
| 4090 | + t = (t & ~(VT_BTYPE|VT_LONG)) | u; | |
| 4102 | 4091 | } |
| 4103 | 4092 | break; |
| 4104 | 4093 | /* GNUC typeof */ |
| @@ -4118,7 +4107,7 @@ static int parse_btype(CType *type, AttributeDef *ad) · 13 unmodified lines | ||
| 4118 | 4107 | s = sym_find(tok); |
| 4119 | 4108 | if (!s || !(s->type.t & VT_TYPEDEF)) |
| 4120 | 4109 | goto the_end; |
| 4121 | − t &= ~VT_BTYPE; | |
| 4110 | + t &= ~(VT_BTYPE|VT_LONG); | |
| 4122 | 4111 | u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u; |
| 4123 | 4112 | type->t = (s->type.t & ~VT_TYPEDEF) | u; |
| 4124 | 4113 | type->ref = s->type.ref; |
| @@ -4139,13 +4128,13 @@ the_end: · 14 unmodified lines | ||
| 4139 | 4128 | if ((t & (VT_DEFSIGN|VT_BTYPE)) == VT_BYTE) |
| 4140 | 4129 | t |= VT_UNSIGNED; |
| 4141 | 4130 | } |
| 4142 | − | |
| 4143 | − /* long is never used as type */ | |
| 4144 | − if (t & VT_LONG) | |
| 4145 | −#if PTR_SIZE == 8 && !defined TCC_TARGET_PE | |
| 4146 | − t = (t & ~VT_BTYPE) | VT_LLONG; | |
| 4147 | −#else | |
| 4148 | − t = (t & ~VT_BTYPE) | VT_INT; | |
| 4131 | + /* VT_LONG is used just as a modifier for VT_INT / VT_LLONG */ | |
| 4132 | + bt = t & (VT_BTYPE|VT_LONG); | |
| 4133 | + if (bt == VT_LONG) | |
| 4134 | + t |= LONG_SIZE == 8 ? VT_LLONG : VT_INT; | |
| 4135 | +#ifdef TCC_TARGET_PE | |
| 4136 | + if (bt == VT_LDOUBLE) | |
| 4137 | + t = (t & ~(VT_BTYPE|VT_LONG)) | VT_DOUBLE; | |
| 4149 | 4138 | #endif |
| 4150 | 4139 | type->t = t; |
| 4151 | 4140 | return type_found; |
| @@ -4544,9 +4533,13 @@ ST_FUNC void unary(void) · 392 unmodified lines | ||
| 4544 | 4533 | case TOK_EXTENSION: |
| 4545 | 4534 | next(); |
| 4546 | 4535 | goto tok_next; |
| 4536 | + case TOK_LCHAR: | |
| 4537 | +#ifdef TCC_TARGET_PE | |
| 4538 | + t = VT_SHORT|VT_UNSIGNED; | |
| 4539 | + goto push_tokc; | |
| 4540 | +#endif | |
| 4547 | 4541 | case TOK_CINT: |
| 4548 | 4542 | case TOK_CCHAR: |
| 4549 | − case TOK_LCHAR: | |
| 4550 | 4543 | t = VT_INT; |
| 4551 | 4544 | push_tokc: |
| 4552 | 4545 | type.t = t; |
| @@ -4572,14 +4565,10 @@ ST_FUNC void unary(void) · 19 unmodified lines | ||
| 4572 | 4565 | t = VT_LDOUBLE; |
| 4573 | 4566 | goto push_tokc; |
| 4574 | 4567 | case TOK_CLONG: |
| 4568 | + t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG; | |
| 4569 | + goto push_tokc; | |
| 4575 | 4570 | case TOK_CULONG: |
| 4576 | − #ifdef TCC_LONG_ARE_64_BIT | |
| 4577 | − t = VT_LLONG | VT_LONG; | |
| 4578 | − #else | |
| 4579 | − t = VT_INT | VT_LONG; | |
| 4580 | − #endif | |
| 4581 | − if (tok == TOK_CULONG) | |
| 4582 | − t |= VT_UNSIGNED; | |
| 4571 | + t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED; | |
| 4583 | 4572 | goto push_tokc; |
| 4584 | 4573 | case TOK___FUNCTION__: |
| 4585 | 4574 | if (!gnu_ext) |
| @@ -5491,7 +5480,11 @@ static void expr_cond(void) · 905 unmodified lines | ||
| 5491 | 5480 | } |
| 5492 | 5481 | } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) { |
| 5493 | 5482 | /* cast to biggest op */ |
| 5494 | − type.t = VT_LLONG; | |
| 5483 | + type.t = VT_LLONG | VT_LONG; | |
| 5484 | + if (bt1 == VT_LLONG) | |
| 5485 | + type.t &= t1; | |
| 5486 | + if (bt2 == VT_LLONG) | |
| 5487 | + type.t &= t2; | |
| 5495 | 5488 | /* convert to unsigned if it does not fit in a long long */ |
| 5496 | 5489 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) || |
| 5497 | 5490 | (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED)) |
| @@ -5518,7 +5511,7 @@ static void expr_cond(void) · 20 unmodified lines | ||
| 5518 | 5511 | type.t = VT_VOID; |
| 5519 | 5512 | } else { |
| 5520 | 5513 | /* integer operations */ |
| 5521 | − type.t = VT_INT; | |
| 5514 | + type.t = VT_INT | (VT_LONG & (t1 | t2)); | |
| 5522 | 5515 | /* convert to unsigned if it does not fit in an integer */ |
| 5523 | 5516 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) || |
| 5524 | 5517 | (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED)) |
| @@ -6490,20 +6483,20 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 965 unmodified lines | ||
| 6490 | 6483 | *(double *)ptr = vtop->c.d; |
| 6491 | 6484 | break; |
| 6492 | 6485 | case VT_LDOUBLE: |
| 6493 | − if (sizeof(long double) == LDOUBLE_SIZE) | |
| 6494 | − *(long double *)ptr = vtop->c.ld; | |
| 6495 | − else if (sizeof(double) == LDOUBLE_SIZE) | |
| 6496 | − *(double *)ptr = (double)vtop->c.ld; | |
| 6497 | 6486 | #if (defined __i386__ || defined __x86_64__) && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64) |
| 6498 | − else if (sizeof (long double) >= 10) | |
| 6499 | − memcpy(memset(ptr, 0, LDOUBLE_SIZE), &vtop->c.ld, 10); | |
| 6487 | + if (sizeof (long double) >= 10) /* zero pad ten-byte LD */ | |
| 6488 | + memcpy(ptr, &vtop->c.ld, 10); | |
| 6500 | 6489 | #ifdef __TINYC__ |
| 6501 | 6490 | else if (sizeof (long double) == sizeof (double)) |
| 6502 | − __asm__("fldl %1\nfstpt %0\n" : "=m" | |
| 6503 | − (memset(ptr, 0, LDOUBLE_SIZE), ptr) : "m" (vtop->c.ld)); | |
| 6491 | + __asm__("fldl %1\nfstpt %0\n" : "=m" (ptr) : "m" (vtop->c.ld)); | |
| 6504 | 6492 | #endif |
| 6493 | + else | |
| 6505 | 6494 | #endif |
| 6506 | − else | |
| 6495 | + if (sizeof(long double) == LDOUBLE_SIZE) | |
| 6496 | + *(long double*)ptr = vtop->c.ld; | |
| 6497 | + else if (sizeof(double) == LDOUBLE_SIZE) | |
| 6498 | + *(double *)ptr = (double)vtop->c.ld; | |
| 6499 | + else | |
| 6507 | 6500 | tcc_error("can't cross compile long double constants"); |
| 6508 | 6501 | break; |
| 6509 | 6502 | #if PTR_SIZE != 8 |
| @@ -89,7 +89,7 @@ static const unsigned char tok_two_chars[] = · 88 unmodified lines | ||
| 89 | 89 | '^','=', TOK_A_XOR, |
| 90 | 90 | '|','=', TOK_A_OR, |
| 91 | 91 | '-','>', TOK_ARROW, |
| 92 | − '.','.', 0xa8, // C++ token ? | |
| 92 | + '.','.', TOK_TWODOTS, | |
| 93 | 93 | '#','#', TOK_TWOSHARPS, |
| 94 | 94 | 0 |
| 95 | 95 | }; |
| @@ -1017,23 +1017,18 @@ static inline int tok_size(const int *p) · 921 unmodified lines | ||
| 1017 | 1017 | case TOK_LCHAR: |
| 1018 | 1018 | case TOK_CFLOAT: |
| 1019 | 1019 | case TOK_LINENUM: |
| 1020 | −#ifndef TCC_LONG_ARE_64_BIT | |
| 1021 | − case TOK_CLONG; | |
| 1022 | − case TOK_CULONG; | |
| 1023 | −#endif | |
| 1024 | 1020 | return 1 + 1; |
| 1025 | 1021 | case TOK_STR: |
| 1026 | 1022 | case TOK_LSTR: |
| 1027 | 1023 | case TOK_PPNUM: |
| 1028 | 1024 | case TOK_PPSTR: |
| 1029 | 1025 | return 1 + ((sizeof(CString) + ((CString *)(p+1))->size + 3) >> 2); |
| 1026 | + case TOK_CLONG: | |
| 1027 | + case TOK_CULONG: | |
| 1028 | + return 1 + LONG_SIZE / 4; | |
| 1030 | 1029 | case TOK_CDOUBLE: |
| 1031 | 1030 | case TOK_CLLONG: |
| 1032 | 1031 | case TOK_CULLONG: |
| 1033 | −#ifdef TCC_LONG_ARE_64_BIT | |
| 1034 | − case TOK_CLONG; | |
| 1035 | − case TOK_CULONG; | |
| 1036 | −#endif | |
| 1037 | 1032 | return 1 + 2; |
| 1038 | 1033 | case TOK_CLDOUBLE: |
| 1039 | 1034 | return 1 + LDOUBLE_SIZE / 4; |
| @@ -1149,7 +1144,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) · 109 unmodified lines | ||
| 1149 | 1144 | case TOK_LCHAR: |
| 1150 | 1145 | case TOK_CFLOAT: |
| 1151 | 1146 | case TOK_LINENUM: |
| 1152 | −#ifndef TCC_LONG_ARE_64_BIT | |
| 1147 | +#if LONG_SIZE == 4 | |
| 1153 | 1148 | case TOK_CLONG: |
| 1154 | 1149 | case TOK_CULONG: |
| 1155 | 1150 | #endif |
| @@ -1173,7 +1168,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) · 17 unmodified lines | ||
| 1173 | 1168 | case TOK_CDOUBLE: |
| 1174 | 1169 | case TOK_CLLONG: |
| 1175 | 1170 | case TOK_CULLONG: |
| 1176 | −#ifdef TCC_LONG_ARE_64_BIT | |
| 1171 | +#if LONG_SIZE == 8 | |
| 1177 | 1172 | case TOK_CLONG: |
| 1178 | 1173 | case TOK_CULONG: |
| 1179 | 1174 | #endif |
| @@ -1227,17 +1222,20 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) · 47 unmodified lines | ||
| 1227 | 1222 | |
| 1228 | 1223 | tab = cv->tab; |
| 1229 | 1224 | switch(*t = *p++) { |
| 1225 | +#if LONG_SIZE == 4 | |
| 1226 | + case TOK_CLONG: | |
| 1227 | +#endif | |
| 1230 | 1228 | case TOK_CINT: |
| 1231 | − case TOK_CUINT: | |
| 1232 | 1229 | case TOK_CCHAR: |
| 1233 | 1230 | case TOK_LCHAR: |
| 1234 | 1231 | case TOK_LINENUM: |
| 1235 | −#ifndef TCC_LONG_ARE_64_BIT | |
| 1236 | − case TOK_CLONG: | |
| 1232 | + cv->i = *p++; | |
| 1233 | + break; | |
| 1234 | +#if LONG_SIZE == 4 | |
| 1237 | 1235 | case TOK_CULONG: |
| 1238 | 1236 | #endif |
| 1239 | − tab[0] = *p++; | |
| 1240 | − cv->i = (*t == TOK_CUINT) ? (unsigned)cv->i : (int)cv->i; | |
| 1237 | + case TOK_CUINT: | |
| 1238 | + cv->i = (unsigned)*p++; | |
| 1241 | 1239 | break; |
| 1242 | 1240 | case TOK_CFLOAT: |
| 1243 | 1241 | tab[0] = *p++; |
| @@ -1253,7 +1251,7 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) · 9 unmodified lines | ||
| 1253 | 1251 | case TOK_CDOUBLE: |
| 1254 | 1252 | case TOK_CLLONG: |
| 1255 | 1253 | case TOK_CULLONG: |
| 1256 | −#ifdef TCC_LONG_ARE_64_BIT | |
| 1254 | +#if LONG_SIZE == 8 | |
| 1257 | 1255 | case TOK_CLONG: |
| 1258 | 1256 | case TOK_CULONG: |
| 1259 | 1257 | #endif |
| @@ -2206,23 +2204,24 @@ static void parse_string(const char *s, int len) · 946 unmodified lines | ||
| 2206 | 2204 | tcc_free(p); |
| 2207 | 2205 | |
| 2208 | 2206 | if (sep == '\'') { |
| 2209 | − int char_size; | |
| 2207 | + int char_size, i, n, c; | |
| 2210 | 2208 | /* XXX: make it portable */ |
| 2211 | 2209 | if (!is_long) |
| 2212 | − char_size = 1; | |
| 2210 | + tok = TOK_CCHAR, char_size = 1; | |
| 2213 | 2211 | else |
| 2214 | − char_size = sizeof(nwchar_t); | |
| 2215 | − if (tokcstr.size <= char_size) | |
| 2212 | + tok = TOK_LCHAR, char_size = sizeof(nwchar_t); | |
| 2213 | + n = tokcstr.size / char_size - 1; | |
| 2214 | + if (n < 1) | |
| 2216 | 2215 | tcc_error("empty character constant"); |
| 2217 | − if (tokcstr.size > 2 * char_size) | |
| 2216 | + if (n > 1) | |
| 2218 | 2217 | tcc_warning("multi-character character constant"); |
| 2219 | − if (!is_long) { | |
| 2220 | − tokc.i = *(int8_t *)tokcstr.data; | |
| 2221 | − tok = TOK_CCHAR; | |
| 2222 | − } else { | |
| 2223 | − tokc.i = *(nwchar_t *)tokcstr.data; | |
| 2224 | − tok = TOK_LCHAR; | |
| 2218 | + for (c = i = 0; i < n; ++i) { | |
| 2219 | + if (is_long) | |
| 2220 | + c = ((nwchar_t *)tokcstr.data)[i]; | |
| 2221 | + else | |
| 2222 | + c = (c << 8) | ((char *)tokcstr.data)[i]; | |
| 2225 | 2223 | } |
| 2224 | + tokc.i = c; | |
| 2226 | 2225 | } else { |
| 2227 | 2226 | tokc.str.size = tokcstr.size; |
| 2228 | 2227 | tokc.str.data = tokcstr.data; |
| @@ -2456,7 +2455,7 @@ static void parse_number(const char *p) · 227 unmodified lines | ||
| 2456 | 2455 | } |
| 2457 | 2456 | } else { |
| 2458 | 2457 | unsigned long long n, n1; |
| 2459 | − int lcount, ucount, must_64bit; | |
| 2458 | + int lcount, ucount, ov = 0; | |
| 2460 | 2459 | const char *p1; |
| 2461 | 2460 | |
| 2462 | 2461 | /* integer number */ |
| @@ -2483,14 +2482,13 @@ static void parse_number(const char *p) · 20 unmodified lines | ||
| 2483 | 2482 | n1 = n; |
| 2484 | 2483 | n = n * b + t; |
| 2485 | 2484 | /* detect overflow */ |
| 2486 | − /* XXX: this test is not reliable */ | |
| 2487 | − if (n < n1) | |
| 2488 | − tcc_error("integer constant overflow"); | |
| 2485 | + if (n1 >= 0x1000000000000000ULL && n / b != n1) | |
| 2486 | + ov = 1; | |
| 2489 | 2487 | } |
| 2490 | 2488 | |
| 2491 | 2489 | /* Determine the characteristics (unsigned and/or 64bit) the type of |
| 2492 | 2490 | the constant must have according to the constant suffix(es) */ |
| 2493 | − lcount = ucount = must_64bit = 0; | |
| 2491 | + lcount = ucount = 0; | |
| 2494 | 2492 | p1 = p; |
| 2495 | 2493 | for(;;) { |
| 2496 | 2494 | t = toup(ch); |
| @@ -2500,8 +2498,6 @@ static void parse_number(const char *p) · 3 unmodified lines | ||
| 2500 | 2498 | if (lcount && *(p - 1) != ch) |
| 2501 | 2499 | tcc_error("incorrect integer suffix: %s", p1); |
| 2502 | 2500 | lcount++; |
| 2503 | − if (lcount == 2) | |
| 2504 | − must_64bit = 1; | |
| 2505 | 2501 | ch = *p++; |
| 2506 | 2502 | } else if (t == 'U') { |
| 2507 | 2503 | if (ucount >= 1) |
| @@ -2513,38 +2509,36 @@ static void parse_number(const char *p) · 5 unmodified lines | ||
| 2513 | 2509 | } |
| 2514 | 2510 | } |
| 2515 | 2511 | |
| 2516 | − /* Whether 64 bits are needed to hold the constant's value */ | |
| 2517 | − if (n & 0xffffffff00000000LL || must_64bit) { | |
| 2518 | − tok = TOK_CLLONG; | |
| 2519 | − n1 = n >> 32; | |
| 2520 | − } else if (lcount) { | |
| 2521 | −#ifdef TCC_LONG_ARE_64_BIT | |
| 2522 | − n1 = n >> 32; | |
| 2523 | −#else | |
| 2524 | − n1 = n; | |
| 2525 | −#endif | |
| 2526 | − tok = TOK_CLONG; | |
| 2527 | − } else { | |
| 2528 | − tok = TOK_CINT; | |
| 2529 | − n1 = n; | |
| 2512 | + /* Determine if it needs 64 bits and/or unsigned in order to fit */ | |
| 2513 | + if (ucount == 0 && b == 10) { | |
| 2514 | + if (lcount <= (LONG_SIZE == 4)) { | |
| 2515 | + if (n >= 0x80000000U) | |
| 2516 | + lcount = (LONG_SIZE == 4) + 1; | |
| 2517 | + } | |
| 2518 | + if (n >= 0x8000000000000000ULL) | |
| 2519 | + ov = 1, ucount = 1; | |
| 2520 | + } else { | |
| 2521 | + if (lcount <= (LONG_SIZE == 4)) { | |
| 2522 | + if (n >= 0x100000000ULL) | |
| 2523 | + lcount = (LONG_SIZE == 4) + 1; | |
| 2524 | + else if (n >= 0x80000000U) | |
| 2525 | + ucount = 1; | |
| 2526 | + } | |
| 2527 | + if (n >= 0x8000000000000000ULL) | |
| 2528 | + ucount = 1; | |
| 2530 | 2529 | } |
| 2531 | 2530 | |
| 2532 | − /* Whether type must be unsigned to hold the constant's value */ | |
| 2533 | − if (ucount || ((n1 >> 31) && (b != 10))) { | |
| 2534 | − if (tok == TOK_CLLONG) | |
| 2535 | − tok = TOK_CULLONG; | |
| 2536 | − else if (tok == TOK_CLONG) | |
| 2537 | − tok = TOK_CULONG; | |
| 2538 | − else | |
| 2539 | − tok = TOK_CUINT; | |
| 2540 | − /* If decimal and no unsigned suffix, bump to 64 bits or throw error */ | |
| 2541 | − } else if (n1 >> 31) { | |
| 2542 | − if (tok == TOK_CINT) | |
| 2543 | − tok = TOK_CLLONG; | |
| 2544 | − else | |
| 2545 | − tcc_error("integer constant overflow"); | |
| 2546 | − } | |
| 2531 | + if (ov) | |
| 2532 | + tcc_warning("integer constant overflow"); | |
| 2547 | 2533 | |
| 2534 | + tok = TOK_CINT; | |
| 2535 | + if (lcount) { | |
| 2536 | + tok = TOK_CLONG; | |
| 2537 | + if (lcount == 2) | |
| 2538 | + tok = TOK_CLLONG; | |
| 2539 | + } | |
| 2540 | + if (ucount) | |
| 2541 | + ++tok; /* TOK_CU... */ | |
| 2548 | 2542 | tokc.i = n; |
| 2549 | 2543 | } |
| 2550 | 2544 | if (ch) |
| @@ -113,7 +113,7 @@ for %%f in (*tcc.exe *tcc.dll) do @del %%f · 112 unmodified lines | ||
| 113 | 113 | :compiler |
| 114 | 114 | %CC% -o libtcc.dll -shared ..\libtcc.c %D% -DLIBTCC_AS_DLL |
| 115 | 115 | @if errorlevel 1 goto :the_end |
| 116 | −%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE=0 | |
| 116 | +%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0" | |
| 117 | 117 | %CC% -o %PX%-tcc.exe ..\tcc.c %DX% |
| 118 | 118 | |
| 119 | 119 | @if (%TCC_FILES%)==(no) goto :files-done |