This was going wrong (case TOK_LAND in unary: computed labels) - vset(&s->type, VT_CONST | VT_SYM, 0); - vtop->sym = s; This does the right thing and is shorter: + vpushsym(&s->type, s); Test case was: int main(int argc, char **argv) { int x; static void *label_return = &&lbl_return; printf("label_return = %p\n", label_return); goto *label_return; //<<<<< here segfault on linux X86_64 without the memset on vset printf("unreachable\n"); lbl_return: return 0; } Also:: - Rename "void* CValue.ptr" to more usable "addr_t ptr_offset" and start to use it in obvious cases. - use __attribute__ ((noreturn)) only with gnu compiler - Revert CValue memsets ("After several days searching ...") commit 4bc83ac3933efa565ae3326b55fcd711b63c073d Doesn't mean that the vsetX/vpush thingy isn't brittle and there still might be bugs as to differences in how the CValue union was set and is then interpreted later on. However the big memset hammer was just too slow (-3% overall).
Unified · Split
| @@ -55,18 +55,27 @@ · 54 unmodified lines | ||
| 55 | 55 | # ifndef CONFIG_TCC_STATIC |
| 56 | 56 | # include <dlfcn.h> |
| 57 | 57 | # endif |
| 58 | −#else | |
| 58 | +/* XXX: need to define this to use them in non ISOC99 context */ | |
| 59 | + extern float strtof (const char *__nptr, char **__endptr); | |
| 60 | + extern long double strtold (const char *__nptr, char **__endptr); | |
| 61 | +#else /* on _WIN32: */ | |
| 59 | 62 | # include <windows.h> |
| 60 | 63 | # include <sys/timeb.h> |
| 61 | 64 | # include <io.h> /* open, close etc. */ |
| 62 | 65 | # include <direct.h> /* getcwd */ |
| 63 | 66 | # ifdef __GNUC__ |
| 64 | 67 | # include <stdint.h> |
| 65 | −# else | |
| 66 | − typedef UINT_PTR uintptr_t; | |
| 67 | 68 | # endif |
| 68 | 69 | # define inline __inline |
| 69 | 70 | # define inp next_inp |
| 71 | +# define snprintf _snprintf | |
| 72 | +# define vsnprintf _vsnprintf | |
| 73 | +# ifndef __GNUC__ | |
| 74 | +# define strtold (long double)strtod | |
| 75 | +# define strtof (float)strtod | |
| 76 | +# define strtoll _strtoi64 | |
| 77 | +# define strtoull _strtoui64 | |
| 78 | +# endif | |
| 70 | 79 | # ifdef LIBTCC_AS_DLL |
| 71 | 80 | # define LIBTCCAPI __declspec(dllexport) |
| 72 | 81 | # define PUB_FUNC LIBTCCAPI |
| @@ -79,6 +88,30 @@ · 6 unmodified lines | ||
| 79 | 88 | # define O_BINARY 0 |
| 80 | 89 | #endif |
| 81 | 90 | |
| 91 | +#ifdef __GNUC__ | |
| 92 | +# define NORETURN __attribute__ ((noreturn)) | |
| 93 | +#elif defined _MSC_VER | |
| 94 | +# define NORETURN __declspec(noreturn) | |
| 95 | +#else | |
| 96 | +# define NORETURN | |
| 97 | +#endif | |
| 98 | + | |
| 99 | +#ifdef _WIN32 | |
| 100 | +# define IS_DIRSEP(c) (c == '/' || c == '\\') | |
| 101 | +# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) | |
| 102 | +# define PATHCMP stricmp | |
| 103 | +#else | |
| 104 | +# define IS_DIRSEP(c) (c == '/') | |
| 105 | +# define IS_ABSPATH(p) IS_DIRSEP(p[0]) | |
| 106 | +# define PATHCMP strcmp | |
| 107 | +#endif | |
| 108 | + | |
| 109 | +#ifdef TCC_TARGET_PE | |
| 110 | +#define PATHSEP ';' | |
| 111 | +#else | |
| 112 | +#define PATHSEP ':' | |
| 113 | +#endif | |
| 114 | + | |
| 82 | 115 | #include "elf.h" |
| 83 | 116 | #ifdef TCC_TARGET_X86_64 |
| 84 | 117 | # define ELFCLASSW ELFCLASS64 |
| @@ -315,7 +348,7 @@ typedef union CValue { · 230 unmodified lines | ||
| 315 | 348 | long long ll; |
| 316 | 349 | unsigned long long ull; |
| 317 | 350 | struct CString *cstr; |
| 318 | − void *ptr; | |
| 351 | + addr_t ptr_offset; | |
| 319 | 352 | int tab[LDOUBLE_SIZE/4]; |
| 320 | 353 | } CValue; |
| 321 | 354 | |
| @@ -938,37 +971,6 @@ enum tcc_token { · 616 unmodified lines | ||
| 938 | 971 | |
| 939 | 972 | #define TOK_UIDENT TOK_DEFINE |
| 940 | 973 | |
| 941 | −#ifdef _WIN32 | |
| 942 | −#define snprintf _snprintf | |
| 943 | −#define vsnprintf _vsnprintf | |
| 944 | −#ifndef __GNUC__ | |
| 945 | −# define strtold (long double)strtod | |
| 946 | −# define strtof (float)strtod | |
| 947 | −# define strtoll _strtoi64 | |
| 948 | −# define strtoull _strtoui64 | |
| 949 | −#endif | |
| 950 | −#else | |
| 951 | −/* XXX: need to define this to use them in non ISOC99 context */ | |
| 952 | −extern float strtof (const char *__nptr, char **__endptr); | |
| 953 | −extern long double strtold (const char *__nptr, char **__endptr); | |
| 954 | −#endif | |
| 955 | − | |
| 956 | −#ifdef _WIN32 | |
| 957 | −#define IS_DIRSEP(c) (c == '/' || c == '\\') | |
| 958 | −#define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) | |
| 959 | −#define PATHCMP stricmp | |
| 960 | −#else | |
| 961 | −#define IS_DIRSEP(c) (c == '/') | |
| 962 | −#define IS_ABSPATH(p) IS_DIRSEP(p[0]) | |
| 963 | −#define PATHCMP strcmp | |
| 964 | −#endif | |
| 965 | − | |
| 966 | −#ifdef TCC_TARGET_PE | |
| 967 | −#define PATHSEP ';' | |
| 968 | −#else | |
| 969 | −#define PATHSEP ':' | |
| 970 | −#endif | |
| 971 | − | |
| 972 | 974 | /* space exlcuding newline */ |
| 973 | 975 | static inline int is_space(int ch) |
| 974 | 976 | { |
| @@ -1045,7 +1047,7 @@ PUB_FUNC char *tcc_strdup(const char *str); · 70 unmodified lines | ||
| 1045 | 1047 | #define strdup(s) use_tcc_strdup(s) |
| 1046 | 1048 | PUB_FUNC void tcc_memstats(void); |
| 1047 | 1049 | PUB_FUNC void tcc_error_noabort(const char *fmt, ...); |
| 1048 | −PUB_FUNC void tcc_error(const char *fmt, ...) __attribute__ ((noreturn)); | |
| 1050 | +PUB_FUNC NORETURN void tcc_error(const char *fmt, ...); | |
| 1049 | 1051 | PUB_FUNC void tcc_warning(const char *fmt, ...); |
| 1050 | 1052 | |
| 1051 | 1053 | /* other utilities */ |
| @@ -1143,7 +1145,7 @@ ST_FUNC void preprocess_init(TCCState *s1); · 91 unmodified lines | ||
| 1143 | 1145 | ST_FUNC void preprocess_new(void); |
| 1144 | 1146 | ST_FUNC int tcc_preprocess(TCCState *s1); |
| 1145 | 1147 | ST_FUNC void skip(int c); |
| 1146 | −ST_FUNC void expect(const char *msg) __attribute__ ((noreturn)); | |
| 1148 | +ST_FUNC NORETURN void expect(const char *msg); | |
| 1147 | 1149 | |
| 1148 | 1150 | /* ------------ tccgen.c ------------ */ |
| 1149 | 1151 | |
| @@ -329,7 +329,6 @@ static void vsetc(CType *type, int r, CValue *vc) · 328 unmodified lines | ||
| 329 | 329 | void vpush(CType *type) |
| 330 | 330 | { |
| 331 | 331 | CValue cval; |
| 332 | − memset(&cval, 0, sizeof(CValue)); | |
| 333 | 332 | vsetc(type, VT_CONST, &cval); |
| 334 | 333 | } |
| 335 | 334 | |
| @@ -337,29 +336,23 @@ void vpush(CType *type) · 1 unmodified line | ||
| 337 | 336 | ST_FUNC void vpushi(int v) |
| 338 | 337 | { |
| 339 | 338 | CValue cval; |
| 340 | − memset(&cval, 0, sizeof(CValue)); | |
| 341 | 339 | cval.i = v; |
| 342 | 340 | vsetc(&int_type, VT_CONST, &cval); |
| 343 | 341 | } |
| 344 | 342 | |
| 345 | 343 | /* push a pointer sized constant */ |
| 346 | −static void vpushs(long long v) | |
| 344 | +static void vpushs(addr_t v) | |
| 347 | 345 | { |
| 348 | 346 | CValue cval; |
| 349 | − memset(&cval, 0, sizeof(CValue)); | |
| 350 | − if (PTR_SIZE == 4) | |
| 351 | − cval.i = (int)v; | |
| 352 | − else | |
| 353 | − cval.ull = v; | |
| 347 | + cval.ptr_offset = v; | |
| 354 | 348 | vsetc(&size_type, VT_CONST, &cval); |
| 355 | 349 | } |
| 356 | 350 | |
| 357 | 351 | /* push arbitrary 64bit constant */ |
| 358 | 352 | void vpush64(int ty, unsigned long long v) |
| 359 | 353 | { |
| 360 | − CType ctype; | |
| 361 | 354 | CValue cval; |
| 362 | − memset(&cval, 0, sizeof(CValue)); | |
| 355 | + CType ctype; | |
| 363 | 356 | ctype.t = ty; |
| 364 | 357 | ctype.ref = NULL; |
| 365 | 358 | cval.ull = v; |
| @@ -376,9 +369,7 @@ static inline void vpushll(long long v) · 10 unmodified lines | ||
| 376 | 369 | static inline void vpushsym(CType *type, Sym *sym) |
| 377 | 370 | { |
| 378 | 371 | CValue cval; |
| 379 | − memset(&cval, 0, sizeof(CValue)); | |
| 380 | − | |
| 381 | − cval.ull = 0; | |
| 372 | + cval.ptr_offset = 0; | |
| 382 | 373 | vsetc(type, VT_CONST | VT_SYM, &cval); |
| 383 | 374 | vtop->sym = sym; |
| 384 | 375 | } |
| @@ -451,7 +442,6 @@ ST_FUNC void vpush_global_sym(CType *type, int v) · 66 unmodified lines | ||
| 451 | 442 | ST_FUNC void vset(CType *type, int r, int v) |
| 452 | 443 | { |
| 453 | 444 | CValue cval; |
| 454 | − memset(&cval, 0, sizeof(CValue)); | |
| 455 | 445 | |
| 456 | 446 | cval.i = v; |
| 457 | 447 | vsetc(type, r, &cval); |
| @@ -737,7 +727,6 @@ ST_FUNC int gv(int rc) · 279 unmodified lines | ||
| 737 | 727 | unsigned long offset; |
| 738 | 728 | #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) |
| 739 | 729 | CValue check; |
| 740 | − memset(&check, 0, sizeof(CValue)); | |
| 741 | 730 | #endif |
| 742 | 731 | |
| 743 | 732 | /* XXX: unify with initializers handling ? */ |
| @@ -770,7 +759,7 @@ ST_FUNC int gv(int rc) · 26 unmodified lines | ||
| 770 | 759 | sym = get_sym_ref(&vtop->type, data_section, offset, size << 2); |
| 771 | 760 | vtop->r |= VT_LVAL | VT_SYM; |
| 772 | 761 | vtop->sym = sym; |
| 773 | − vtop->c.ull = 0; | |
| 762 | + vtop->c.ptr_offset = 0; | |
| 774 | 763 | } |
| 775 | 764 | #ifdef CONFIG_TCC_BCHECK |
| 776 | 765 | if (vtop->r & VT_MUSTBOUND) |
| @@ -1581,7 +1570,7 @@ static inline int is_null_pointer(SValue *p) · 804 unmodified lines | ||
| 1581 | 1570 | return 0; |
| 1582 | 1571 | return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || |
| 1583 | 1572 | ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || |
| 1584 | − ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr == 0); | |
| 1573 | + ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0); | |
| 1585 | 1574 | } |
| 1586 | 1575 | |
| 1587 | 1576 | static inline int is_integer_btype(int bt) |
| @@ -3886,8 +3875,7 @@ ST_FUNC void unary(void) · 2298 unmodified lines | ||
| 3886 | 3875 | mk_pointer(&s->type); |
| 3887 | 3876 | s->type.t |= VT_STATIC; |
| 3888 | 3877 | } |
| 3889 | − vset(&s->type, VT_CONST | VT_SYM, 0); | |
| 3890 | − vtop->sym = s; | |
| 3878 | + vpushsym(&s->type, s); | |
| 3891 | 3879 | next(); |
| 3892 | 3880 | break; |
| 3893 | 3881 | |
| @@ -3939,7 +3927,7 @@ ST_FUNC void unary(void) · 45 unmodified lines | ||
| 3939 | 3927 | /* if forward reference, we must point to s */ |
| 3940 | 3928 | if (vtop->r & VT_SYM) { |
| 3941 | 3929 | vtop->sym = s; |
| 3942 | − vtop->c.ull = 0; | |
| 3930 | + vtop->c.ptr_offset = 0; | |
| 3943 | 3931 | } |
| 3944 | 3932 | break; |
| 3945 | 3933 | } |
| @@ -5157,7 +5145,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 1211 unmodified lines | ||
| 5157 | 5145 | if (vtop->r & VT_SYM) { |
| 5158 | 5146 | greloc(sec, vtop->sym, c, R_DATA_PTR); |
| 5159 | 5147 | } |
| 5160 | − *(addr_t *)ptr |= (vtop->c.ull & bit_mask) << bit_pos; | |
| 5148 | + *(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos; | |
| 5161 | 5149 | break; |
| 5162 | 5150 | default: |
| 5163 | 5151 | if (vtop->r & VT_SYM) { |
| @@ -974,7 +974,6 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) · 973 unmodified lines | ||
| 974 | 974 | ST_FUNC void tok_str_add_tok(TokenString *s) |
| 975 | 975 | { |
| 976 | 976 | CValue cval; |
| 977 | − memset(&cval, 0, sizeof(CValue)); | |
| 978 | 977 | |
| 979 | 978 | /* save line number info */ |
| 980 | 979 | if (file->line_num != s->last_line_num) { |
| @@ -1038,9 +1037,8 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) · 57 unmodified lines | ||
| 1038 | 1037 | static int macro_is_equal(const int *a, const int *b) |
| 1039 | 1038 | { |
| 1040 | 1039 | char buf[STRING_MAX_SIZE + 1]; |
| 1041 | − int t; | |
| 1042 | 1040 | CValue cv; |
| 1043 | − memset(&cv, 0, sizeof(CValue)); | |
| 1041 | + int t; | |
| 1044 | 1042 | while (*a && *b) { |
| 1045 | 1043 | TOK_GET(&t, &a, &cv); |
| 1046 | 1044 | pstrcpy(buf, sizeof buf, get_tok_str(t, &cv)); |
| @@ -1199,7 +1197,6 @@ static void tok_print(int *str) · 152 unmodified lines | ||
| 1199 | 1197 | { |
| 1200 | 1198 | int t; |
| 1201 | 1199 | CValue cval; |
| 1202 | − memset(&cval, 0, sizeof(CValue)); | |
| 1203 | 1200 | |
| 1204 | 1201 | printf("<"); |
| 1205 | 1202 | while (1) { |
| @@ -2566,10 +2563,9 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 1360 unmodified lines | ||
| 2566 | 2563 | int last_tok, t, spc; |
| 2567 | 2564 | const int *st; |
| 2568 | 2565 | Sym *s; |
| 2566 | + CValue cval; | |
| 2569 | 2567 | TokenString str; |
| 2570 | 2568 | CString cstr; |
| 2571 | − CValue cval; | |
| 2572 | − memset(&cval, 0, sizeof(CValue)); | |
| 2573 | 2569 | |
| 2574 | 2570 | tok_str_new(&str); |
| 2575 | 2571 | last_tok = 0; |
| @@ -2671,10 +2667,9 @@ static int macro_subst_tok(TokenString *tok_str, · 95 unmodified lines | ||
| 2671 | 2667 | const int *p; |
| 2672 | 2668 | TokenString str; |
| 2673 | 2669 | char *cstrval; |
| 2670 | + CValue cval; | |
| 2674 | 2671 | CString cstr; |
| 2675 | 2672 | char buf[32]; |
| 2676 | − CValue cval; | |
| 2677 | − memset(&cval, 0, sizeof(CValue)); | |
| 2678 | 2673 | |
| 2679 | 2674 | /* if symbol is a macro, prepare substitution */ |
| 2680 | 2675 | /* special macros */ |
| @@ -2849,7 +2844,6 @@ static inline int *macro_twosharps(const int *macro_str) · 168 unmodified lines | ||
| 2849 | 2844 | /* we search the first '##' */ |
| 2850 | 2845 | for(ptr = macro_str;;) { |
| 2851 | 2846 | CValue cval; |
| 2852 | − memset(&cval, 0, sizeof(CValue)); | |
| 2853 | 2847 | TOK_GET(&t, &ptr, &cval); |
| 2854 | 2848 | if (t == TOK_TWOSHARPS) |
| 2855 | 2849 | break; |
| @@ -2880,7 +2874,6 @@ static inline int *macro_twosharps(const int *macro_str) · 24 unmodified lines | ||
| 2880 | 2874 | t = *++ptr; |
| 2881 | 2875 | if (t && t != TOK_TWOSHARPS) { |
| 2882 | 2876 | CValue cval; |
| 2883 | − memset(&cval, 0, sizeof(CValue)); | |
| 2884 | 2877 | TOK_GET(&t, &ptr, &cval); |
| 2885 | 2878 | /* We concatenate the two tokens */ |
| 2886 | 2879 | cstr_new(&cstr); |
| @@ -2922,10 +2915,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 35 unmodified lines | ||
| 2922 | 2915 | int *macro_str1; |
| 2923 | 2916 | const int *ptr; |
| 2924 | 2917 | int t, ret, spc; |
| 2918 | + CValue cval; | |
| 2925 | 2919 | struct macro_level ml; |
| 2926 | 2920 | int force_blank; |
| 2927 | − CValue cval; | |
| 2928 | − memset(&cval, 0, sizeof(CValue)); | |
| 2929 | 2921 | |
| 2930 | 2922 | /* first scan for '##' operator handling */ |
| 2931 | 2923 | ptr = macro_str; |