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 | # ifndef CONFIG_TCC_STATIC | 55 | # ifndef CONFIG_TCC_STATIC |
| 56 | # include <dlfcn.h> | 56 | # include <dlfcn.h> |
| 57 | # endif | 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 | # include <windows.h> | 62 | # include <windows.h> |
| 60 | # include <sys/timeb.h> | 63 | # include <sys/timeb.h> |
| 61 | # include <io.h> /* open, close etc. */ | 64 | # include <io.h> /* open, close etc. */ |
| 62 | # include <direct.h> /* getcwd */ | 65 | # include <direct.h> /* getcwd */ |
| 63 | # ifdef __GNUC__ | 66 | # ifdef __GNUC__ |
| 64 | # include <stdint.h> | 67 | # include <stdint.h> |
| 65 | # else | ||
| 66 | typedef UINT_PTR uintptr_t; | ||
| 67 | # endif | 68 | # endif |
| 68 | # define inline __inline | 69 | # define inline __inline |
| 69 | # define inp next_inp | 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 | # ifdef LIBTCC_AS_DLL | 79 | # ifdef LIBTCC_AS_DLL |
| 71 | # define LIBTCCAPI __declspec(dllexport) | 80 | # define LIBTCCAPI __declspec(dllexport) |
| 72 | # define PUB_FUNC LIBTCCAPI | 81 | # define PUB_FUNC LIBTCCAPI |
| @@ -79,6 +88,30 @@ · 6 unmodified lines | |||
| 79 | # define O_BINARY 0 | 88 | # define O_BINARY 0 |
| 80 | #endif | 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 | #include "elf.h" | 115 | #include "elf.h" |
| 83 | #ifdef TCC_TARGET_X86_64 | 116 | #ifdef TCC_TARGET_X86_64 |
| 84 | # define ELFCLASSW ELFCLASS64 | 117 | # define ELFCLASSW ELFCLASS64 |
| @@ -315,7 +348,7 @@ typedef union CValue { · 230 unmodified lines | |||
| 315 | long long ll; | 348 | long long ll; |
| 316 | unsigned long long ull; | 349 | unsigned long long ull; |
| 317 | struct CString *cstr; | 350 | struct CString *cstr; |
| 318 | void *ptr; | 351 | addr_t ptr_offset; |
| 319 | int tab[LDOUBLE_SIZE/4]; | 352 | int tab[LDOUBLE_SIZE/4]; |
| 320 | } CValue; | 353 | } CValue; |
| 321 | 354 | ||
| @@ -938,37 +971,6 @@ enum tcc_token { · 616 unmodified lines | |||
| 938 | 971 | ||
| 939 | #define TOK_UIDENT TOK_DEFINE | 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 | /* space exlcuding newline */ | 974 | /* space exlcuding newline */ |
| 973 | static inline int is_space(int ch) | 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 | #define strdup(s) use_tcc_strdup(s) | 1047 | #define strdup(s) use_tcc_strdup(s) |
| 1046 | PUB_FUNC void tcc_memstats(void); | 1048 | PUB_FUNC void tcc_memstats(void); |
| 1047 | PUB_FUNC void tcc_error_noabort(const char *fmt, ...); | 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 | PUB_FUNC void tcc_warning(const char *fmt, ...); | 1051 | PUB_FUNC void tcc_warning(const char *fmt, ...); |
| 1050 | 1052 | ||
| 1051 | /* other utilities */ | 1053 | /* other utilities */ |
| @@ -1143,7 +1145,7 @@ ST_FUNC void preprocess_init(TCCState *s1); · 91 unmodified lines | |||
| 1143 | ST_FUNC void preprocess_new(void); | 1145 | ST_FUNC void preprocess_new(void); |
| 1144 | ST_FUNC int tcc_preprocess(TCCState *s1); | 1146 | ST_FUNC int tcc_preprocess(TCCState *s1); |
| 1145 | ST_FUNC void skip(int c); | 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 | /* ------------ tccgen.c ------------ */ | 1150 | /* ------------ tccgen.c ------------ */ |
| 1149 | 1151 | ||
| @@ -329,7 +329,6 @@ static void vsetc(CType *type, int r, CValue *vc) · 328 unmodified lines | |||
| 329 | void vpush(CType *type) | 329 | void vpush(CType *type) |
| 330 | { | 330 | { |
| 331 | CValue cval; | 331 | CValue cval; |
| 332 | memset(&cval, 0, sizeof(CValue)); | ||
| 333 | vsetc(type, VT_CONST, &cval); | 332 | vsetc(type, VT_CONST, &cval); |
| 334 | } | 333 | } |
| 335 | 334 | ||
| @@ -337,29 +336,23 @@ void vpush(CType *type) · 1 unmodified line | |||
| 337 | ST_FUNC void vpushi(int v) | 336 | ST_FUNC void vpushi(int v) |
| 338 | { | 337 | { |
| 339 | CValue cval; | 338 | CValue cval; |
| 340 | memset(&cval, 0, sizeof(CValue)); | ||
| 341 | cval.i = v; | 339 | cval.i = v; |
| 342 | vsetc(&int_type, VT_CONST, &cval); | 340 | vsetc(&int_type, VT_CONST, &cval); |
| 343 | } | 341 | } |
| 344 | 342 | ||
| 345 | /* push a pointer sized constant */ | 343 | /* push a pointer sized constant */ |
| 346 | static void vpushs(long long v) | 344 | static void vpushs(addr_t v) |
| 347 | { | 345 | { |
| 348 | CValue cval; | 346 | CValue cval; |
| 349 | memset(&cval, 0, sizeof(CValue)); | 347 | cval.ptr_offset = v; |
| 350 | if (PTR_SIZE == 4) | ||
| 351 | cval.i = (int)v; | ||
| 352 | else | ||
| 353 | cval.ull = v; | ||
| 354 | vsetc(&size_type, VT_CONST, &cval); | 348 | vsetc(&size_type, VT_CONST, &cval); |
| 355 | } | 349 | } |
| 356 | 350 | ||
| 357 | /* push arbitrary 64bit constant */ | 351 | /* push arbitrary 64bit constant */ |
| 358 | void vpush64(int ty, unsigned long long v) | 352 | void vpush64(int ty, unsigned long long v) |
| 359 | { | 353 | { |
| 360 | CType ctype; | ||
| 361 | CValue cval; | 354 | CValue cval; |
| 362 | memset(&cval, 0, sizeof(CValue)); | 355 | CType ctype; |
| 363 | ctype.t = ty; | 356 | ctype.t = ty; |
| 364 | ctype.ref = NULL; | 357 | ctype.ref = NULL; |
| 365 | cval.ull = v; | 358 | cval.ull = v; |
| @@ -376,9 +369,7 @@ static inline void vpushll(long long v) · 10 unmodified lines | |||
| 376 | static inline void vpushsym(CType *type, Sym *sym) | 369 | static inline void vpushsym(CType *type, Sym *sym) |
| 377 | { | 370 | { |
| 378 | CValue cval; | 371 | CValue cval; |
| 379 | memset(&cval, 0, sizeof(CValue)); | 372 | cval.ptr_offset = 0; |
| 380 | |||
| 381 | cval.ull = 0; | ||
| 382 | vsetc(type, VT_CONST | VT_SYM, &cval); | 373 | vsetc(type, VT_CONST | VT_SYM, &cval); |
| 383 | vtop->sym = sym; | 374 | vtop->sym = sym; |
| 384 | } | 375 | } |
| @@ -451,7 +442,6 @@ ST_FUNC void vpush_global_sym(CType *type, int v) · 66 unmodified lines | |||
| 451 | ST_FUNC void vset(CType *type, int r, int v) | 442 | ST_FUNC void vset(CType *type, int r, int v) |
| 452 | { | 443 | { |
| 453 | CValue cval; | 444 | CValue cval; |
| 454 | memset(&cval, 0, sizeof(CValue)); | ||
| 455 | 445 | ||
| 456 | cval.i = v; | 446 | cval.i = v; |
| 457 | vsetc(type, r, &cval); | 447 | vsetc(type, r, &cval); |
| @@ -737,7 +727,6 @@ ST_FUNC int gv(int rc) · 279 unmodified lines | |||
| 737 | unsigned long offset; | 727 | unsigned long offset; |
| 738 | #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) | 728 | #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) |
| 739 | CValue check; | 729 | CValue check; |
| 740 | memset(&check, 0, sizeof(CValue)); | ||
| 741 | #endif | 730 | #endif |
| 742 | 731 | ||
| 743 | /* XXX: unify with initializers handling ? */ | 732 | /* XXX: unify with initializers handling ? */ |
| @@ -770,7 +759,7 @@ ST_FUNC int gv(int rc) · 26 unmodified lines | |||
| 770 | sym = get_sym_ref(&vtop->type, data_section, offset, size << 2); | 759 | sym = get_sym_ref(&vtop->type, data_section, offset, size << 2); |
| 771 | vtop->r |= VT_LVAL | VT_SYM; | 760 | vtop->r |= VT_LVAL | VT_SYM; |
| 772 | vtop->sym = sym; | 761 | vtop->sym = sym; |
| 773 | vtop->c.ull = 0; | 762 | vtop->c.ptr_offset = 0; |
| 774 | } | 763 | } |
| 775 | #ifdef CONFIG_TCC_BCHECK | 764 | #ifdef CONFIG_TCC_BCHECK |
| 776 | if (vtop->r & VT_MUSTBOUND) | 765 | if (vtop->r & VT_MUSTBOUND) |
| @@ -1581,7 +1570,7 @@ static inline int is_null_pointer(SValue *p) · 804 unmodified lines | |||
| 1581 | return 0; | 1570 | return 0; |
| 1582 | return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || | 1571 | return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || |
| 1583 | ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || | 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 | static inline int is_integer_btype(int bt) | 1576 | static inline int is_integer_btype(int bt) |
| @@ -3886,8 +3875,7 @@ ST_FUNC void unary(void) · 2298 unmodified lines | |||
| 3886 | mk_pointer(&s->type); | 3875 | mk_pointer(&s->type); |
| 3887 | s->type.t |= VT_STATIC; | 3876 | s->type.t |= VT_STATIC; |
| 3888 | } | 3877 | } |
| 3889 | vset(&s->type, VT_CONST | VT_SYM, 0); | 3878 | vpushsym(&s->type, s); |
| 3890 | vtop->sym = s; | ||
| 3891 | next(); | 3879 | next(); |
| 3892 | break; | 3880 | break; |
| 3893 | 3881 | ||
| @@ -3939,7 +3927,7 @@ ST_FUNC void unary(void) · 45 unmodified lines | |||
| 3939 | /* if forward reference, we must point to s */ | 3927 | /* if forward reference, we must point to s */ |
| 3940 | if (vtop->r & VT_SYM) { | 3928 | if (vtop->r & VT_SYM) { |
| 3941 | vtop->sym = s; | 3929 | vtop->sym = s; |
| 3942 | vtop->c.ull = 0; | 3930 | vtop->c.ptr_offset = 0; |
| 3943 | } | 3931 | } |
| 3944 | break; | 3932 | break; |
| 3945 | } | 3933 | } |
| @@ -5157,7 +5145,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c, · 1211 unmodified lines | |||
| 5157 | if (vtop->r & VT_SYM) { | 5145 | if (vtop->r & VT_SYM) { |
| 5158 | greloc(sec, vtop->sym, c, R_DATA_PTR); | 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 | break; | 5149 | break; |
| 5162 | default: | 5150 | default: |
| 5163 | if (vtop->r & VT_SYM) { | 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 | ST_FUNC void tok_str_add_tok(TokenString *s) | 974 | ST_FUNC void tok_str_add_tok(TokenString *s) |
| 975 | { | 975 | { |
| 976 | CValue cval; | 976 | CValue cval; |
| 977 | memset(&cval, 0, sizeof(CValue)); | ||
| 978 | 977 | ||
| 979 | /* save line number info */ | 978 | /* save line number info */ |
| 980 | if (file->line_num != s->last_line_num) { | 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 | static int macro_is_equal(const int *a, const int *b) | 1037 | static int macro_is_equal(const int *a, const int *b) |
| 1039 | { | 1038 | { |
| 1040 | char buf[STRING_MAX_SIZE + 1]; | 1039 | char buf[STRING_MAX_SIZE + 1]; |
| 1041 | int t; | ||
| 1042 | CValue cv; | 1040 | CValue cv; |
| 1043 | memset(&cv, 0, sizeof(CValue)); | 1041 | int t; |
| 1044 | while (*a && *b) { | 1042 | while (*a && *b) { |
| 1045 | TOK_GET(&t, &a, &cv); | 1043 | TOK_GET(&t, &a, &cv); |
| 1046 | pstrcpy(buf, sizeof buf, get_tok_str(t, &cv)); | 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 | int t; | 1198 | int t; |
| 1201 | CValue cval; | 1199 | CValue cval; |
| 1202 | memset(&cval, 0, sizeof(CValue)); | ||
| 1203 | 1200 | ||
| 1204 | printf("<"); | 1201 | printf("<"); |
| 1205 | while (1) { | 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 | int last_tok, t, spc; | 2563 | int last_tok, t, spc; |
| 2567 | const int *st; | 2564 | const int *st; |
| 2568 | Sym *s; | 2565 | Sym *s; |
| 2566 | CValue cval; | ||
| 2569 | TokenString str; | 2567 | TokenString str; |
| 2570 | CString cstr; | 2568 | CString cstr; |
| 2571 | CValue cval; | ||
| 2572 | memset(&cval, 0, sizeof(CValue)); | ||
| 2573 | 2569 | ||
| 2574 | tok_str_new(&str); | 2570 | tok_str_new(&str); |
| 2575 | last_tok = 0; | 2571 | last_tok = 0; |
| @@ -2671,10 +2667,9 @@ static int macro_subst_tok(TokenString *tok_str, · 95 unmodified lines | |||
| 2671 | const int *p; | 2667 | const int *p; |
| 2672 | TokenString str; | 2668 | TokenString str; |
| 2673 | char *cstrval; | 2669 | char *cstrval; |
| 2670 | CValue cval; | ||
| 2674 | CString cstr; | 2671 | CString cstr; |
| 2675 | char buf[32]; | 2672 | char buf[32]; |
| 2676 | CValue cval; | ||
| 2677 | memset(&cval, 0, sizeof(CValue)); | ||
| 2678 | 2673 | ||
| 2679 | /* if symbol is a macro, prepare substitution */ | 2674 | /* if symbol is a macro, prepare substitution */ |
| 2680 | /* special macros */ | 2675 | /* special macros */ |
| @@ -2849,7 +2844,6 @@ static inline int *macro_twosharps(const int *macro_str) · 168 unmodified lines | |||
| 2849 | /* we search the first '##' */ | 2844 | /* we search the first '##' */ |
| 2850 | for(ptr = macro_str;;) { | 2845 | for(ptr = macro_str;;) { |
| 2851 | CValue cval; | 2846 | CValue cval; |
| 2852 | memset(&cval, 0, sizeof(CValue)); | ||
| 2853 | TOK_GET(&t, &ptr, &cval); | 2847 | TOK_GET(&t, &ptr, &cval); |
| 2854 | if (t == TOK_TWOSHARPS) | 2848 | if (t == TOK_TWOSHARPS) |
| 2855 | break; | 2849 | break; |
| @@ -2880,7 +2874,6 @@ static inline int *macro_twosharps(const int *macro_str) · 24 unmodified lines | |||
| 2880 | t = *++ptr; | 2874 | t = *++ptr; |
| 2881 | if (t && t != TOK_TWOSHARPS) { | 2875 | if (t && t != TOK_TWOSHARPS) { |
| 2882 | CValue cval; | 2876 | CValue cval; |
| 2883 | memset(&cval, 0, sizeof(CValue)); | ||
| 2884 | TOK_GET(&t, &ptr, &cval); | 2877 | TOK_GET(&t, &ptr, &cval); |
| 2885 | /* We concatenate the two tokens */ | 2878 | /* We concatenate the two tokens */ |
| 2886 | cstr_new(&cstr); | 2879 | cstr_new(&cstr); |
| @@ -2922,10 +2915,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 35 unmodified lines | |||
| 2922 | int *macro_str1; | 2915 | int *macro_str1; |
| 2923 | const int *ptr; | 2916 | const int *ptr; |
| 2924 | int t, ret, spc; | 2917 | int t, ret, spc; |
| 2918 | CValue cval; | ||
| 2925 | struct macro_level ml; | 2919 | struct macro_level ml; |
| 2926 | int force_blank; | 2920 | int force_blank; |
| 2927 | CValue cval; | ||
| 2928 | memset(&cval, 0, sizeof(CValue)); | ||
| 2929 | 2921 | ||
| 2930 | /* first scan for '##' operator handling */ | 2922 | /* first scan for '##' operator handling */ |
| 2931 | ptr = macro_str; | 2923 | ptr = macro_str; |