tcc.c: - be nice to leak checkers tcctools.c: - remove unused TCCState params tccrun.c: - call bound_exit() after signals to let it free mem tccelf.c: - use section_add() instead of section_ptr_add() when more appropriate tccpp.c: - use size_t to align tal_header naturally - 'POINTER_SIZE' and 'PTR_SIZE' in the same source is confusing - "char file_name[TAL_DEBUG_FILE_LEN + 1];" looks silly. - next_nomacro(): skip UTF8 BOM at BOF tccgen.c: - get rid of STMT_EXPR clause on top of block - warn with useless type like 'int;' - move skip()'s in block() for better error line-info - BIT_SIZE bits are meaningful only with VT_BITFIELD (not with enums for example) workflow/test-win32: - build with MSVC using build-tcc.bat also alloca.S: - fix 'off by one' problem on win32 (must touch current page too because the 'push %edx' at the end could touch the next page) - must not align greater than 4 when used for struct args (i386-gen.c:gfunc_call()) libtcc.c: - accept -g1dwarf (dwarf output, only line info)
Unified · Split
| @@ -31,7 +31,7 @@ jobs: · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | test-x86_64-win32: | 32 | test-x86_64-win32: |
| 33 | runs-on: windows-2025 | 33 | runs-on: windows-2025 |
| 34 | timeout-minutes: 4 | 34 | timeout-minutes: 6 |
| 35 | steps: | 35 | steps: |
| 36 | - uses: actions/checkout@v4 | 36 | - uses: actions/checkout@v4 |
| 37 | - name: make & test tcc (x86_64-win32) | 37 | - name: make & test tcc (x86_64-win32) |
| @@ -44,10 +44,22 @@ jobs: · 6 unmodified lines | |||
| 44 | C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc" | 44 | C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc" |
| 45 | echo ::endgroup:: | 45 | echo ::endgroup:: |
| 46 | C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k" | 46 | C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k" |
| 47 | - uses: ilammy/msvc-dev-cmd@v1 | ||
| 48 | with: | ||
| 49 | arch: amd64 | ||
| 50 | - name: build with MSVC (x86_64-win32) | ||
| 51 | shell: cmd | ||
| 52 | run: | | ||
| 53 | echo ::group:: run build-tcc.bat | ||
| 54 | cd win32 | ||
| 55 | call build-tcc.bat -t 64 -c cl | ||
| 56 | echo ::endgroup:: | ||
| 57 | .\tcc -I.. libtcc.dll -v ../tests/libtcc_test.c -o libtest.exe && .\libtest.exe | ||
| 58 | .\tcc -I.. libtcc.dll -run ../tests/libtcc_test.c | ||
| 47 | 59 | ||
| 48 | test-i386-win32: | 60 | test-i386-win32: |
| 49 | runs-on: windows-2025 | 61 | runs-on: windows-2025 |
| 50 | timeout-minutes: 4 | 62 | timeout-minutes: 6 |
| 51 | steps: | 63 | steps: |
| 52 | - uses: actions/checkout@v4 | 64 | - uses: actions/checkout@v4 |
| 53 | - name: make & test tcc (i386-win32) | 65 | - name: make & test tcc (i386-win32) |
| @@ -59,7 +71,19 @@ jobs: · 5 unmodified lines | |||
| 59 | set CHERE_INVOKING=yes | 71 | set CHERE_INVOKING=yes |
| 60 | C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc" | 72 | C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc" |
| 61 | echo ::endgroup:: | 73 | echo ::endgroup:: |
| 62 | C:\msys64\usr\bin\bash -l -c "./configure && make all && make test -k" | 74 | C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k" |
| 75 | - uses: ilammy/msvc-dev-cmd@v1 | ||
| 76 | with: | ||
| 77 | arch: x86 | ||
| 78 | - name: build with MSVC (i386-win32) | ||
| 79 | shell: cmd | ||
| 80 | run: | | ||
| 81 | echo ::group:: run build-tcc.bat | ||
| 82 | cd win32 | ||
| 83 | call build-tcc.bat -t 32 -c cl | ||
| 84 | echo ::endgroup:: | ||
| 85 | .\tcc -I.. libtcc.dll -v ../tests/libtcc_test.c -o libtest.exe && .\libtest.exe | ||
| 86 | .\tcc -I.. libtcc.dll -run ../tests/libtcc_test.c | ||
| 63 | 87 | ||
| 64 | test-armv7-linux: | 88 | test-armv7-linux: |
| 65 | runs-on: ubuntu-22.04 | 89 | runs-on: ubuntu-22.04 |
| @@ -417,6 +417,7 @@ ST_FUNC void gfunc_call(int nb_args) · 416 unmodified lines | |||
| 417 | /* allocate the necessary size on stack */ | 417 | /* allocate the necessary size on stack */ |
| 418 | #ifdef TCC_TARGET_PE | 418 | #ifdef TCC_TARGET_PE |
| 419 | if (size >= 4096) { | 419 | if (size >= 4096) { |
| 420 | save_reg(TREG_EDX); | ||
| 420 | r = get_reg(RC_EAX); | 421 | r = get_reg(RC_EAX); |
| 421 | oad(0x68, size); // push size | 422 | oad(0x68, size); // push size |
| 422 | /* cannot call normal 'alloca' with bound checking */ | 423 | /* cannot call normal 'alloca' with bound checking */ |
| @@ -17,13 +17,13 @@ _(__bound_alloca): · 16 unmodified lines | |||
| 17 | mov %eax, %ecx | 17 | mov %eax, %ecx |
| 18 | test %eax,%eax | 18 | test %eax,%eax |
| 19 | jz p6 | 19 | jz p6 |
| 20 | add $15+1,%eax | 20 | add $3 + 1,%eax |
| 21 | and $-16,%eax | 21 | and $-4,%eax |
| 22 | 22 | ||
| 23 | #ifdef _WIN32 | 23 | #ifdef _WIN32 |
| 24 | p4: | 24 | p4: |
| 25 | cmp $4096,%eax | 25 | cmp $4096,%eax |
| 26 | jbe p5 | 26 | jb p5 |
| 27 | test %eax,-4096(%esp) | 27 | test %eax,-4096(%esp) |
| 28 | sub $4096,%esp | 28 | sub $4096,%esp |
| 29 | sub $4096,%eax | 29 | sub $4096,%eax |
| @@ -33,7 +33,6 @@ p5: · 3 unmodified lines | |||
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | sub %eax,%esp | 35 | sub %eax,%esp |
| 36 | and $-16,%esp | ||
| 37 | mov %esp,%eax | 36 | mov %esp,%eax |
| 38 | 37 | ||
| 39 | push %edx | 38 | push %edx |
| @@ -72,12 +71,11 @@ _(__bound_alloca_nr): · 32 unmodified lines | |||
| 72 | #else | 71 | #else |
| 73 | pop %rdx | 72 | pop %rdx |
| 74 | mov %rdi,%rax | 73 | mov %rdi,%rax |
| 74 | and %eax,%eax | ||
| 75 | jz p3 | ||
| 75 | mov %rax,%rsi # size, a second parm to the __bound_new_region | 76 | mov %rax,%rsi # size, a second parm to the __bound_new_region |
| 76 | |||
| 77 | add $15 + 1,%rax # add one extra to separate regions | 77 | add $15 + 1,%rax # add one extra to separate regions |
| 78 | and $-16,%rax | 78 | and $-16,%rax |
| 79 | jz p3 | ||
| 80 | |||
| 81 | 79 | ||
| 82 | sub %rax,%rsp | 80 | sub %rax,%rsp |
| 83 | mov %rsp,%rdi # pointer, a first parm to the __bound_new_region | 81 | mov %rsp,%rdi # pointer, a first parm to the __bound_new_region |
| @@ -15,14 +15,14 @@ _(alloca): · 14 unmodified lines | |||
| 15 | _(__alloca): | 15 | _(__alloca): |
| 16 | pop %edx | 16 | pop %edx |
| 17 | pop %eax | 17 | pop %eax |
| 18 | add $15,%eax | 18 | add $3,%eax |
| 19 | and $-16,%eax | 19 | and $-4,%eax |
| 20 | jz p3 | 20 | jz p3 |
| 21 | 21 | ||
| 22 | #ifdef _WIN32 | 22 | #ifdef _WIN32 |
| 23 | p1: | 23 | p1: |
| 24 | cmp $4096,%eax | 24 | cmp $4096,%eax |
| 25 | jbe p2 | 25 | jb p2 |
| 26 | test %eax,-4096(%esp) | 26 | test %eax,-4096(%esp) |
| 27 | sub $4096,%esp | 27 | sub $4096,%esp |
| 28 | sub $4096,%eax | 28 | sub $4096,%eax |
| @@ -30,7 +30,6 @@ p1: · 1 unmodified line | |||
| 30 | p2: | 30 | p2: |
| 31 | #endif | 31 | #endif |
| 32 | sub %eax,%esp | 32 | sub %eax,%esp |
| 33 | and $-16,%esp | ||
| 34 | mov %esp,%eax | 33 | mov %esp,%eax |
| 35 | p3: | 34 | p3: |
| 36 | push %edx | 35 | push %edx |
| @@ -55,7 +54,7 @@ _(alloca): · 18 unmodified lines | |||
| 55 | #ifdef _WIN32 | 54 | #ifdef _WIN32 |
| 56 | p1: | 55 | p1: |
| 57 | cmp $4096,%rax | 56 | cmp $4096,%rax |
| 58 | jbe p2 | 57 | jb p2 |
| 59 | test %rax,-4096(%rsp) | 58 | test %rax,-4096(%rsp) |
| 60 | sub $4096,%rsp | 59 | sub $4096,%rsp |
| 61 | sub $4096,%rax | 60 | sub $4096,%rax |
| @@ -804,7 +804,6 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd) · 803 unmodified lines | |||
| 804 | s1->error_set_jmp_enabled = 1; | 804 | s1->error_set_jmp_enabled = 1; |
| 805 | 805 | ||
| 806 | if (setjmp(s1->error_jmp_buf) == 0) { | 806 | if (setjmp(s1->error_jmp_buf) == 0) { |
| 807 | s1->nb_errors = 0; | ||
| 808 | 807 | ||
| 809 | if (fd == -1) { | 808 | if (fd == -1) { |
| 810 | int len = strlen(str); | 809 | int len = strlen(str); |
| @@ -1816,8 +1815,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 1005 unmodified lines | |||
| 1816 | const TCCOption *popt; | 1815 | const TCCOption *popt; |
| 1817 | const char *optarg, *r; | 1816 | const char *optarg, *r; |
| 1818 | const char *run = NULL; | 1817 | const char *run = NULL; |
| 1819 | int x; | 1818 | int optind = 1, empty = 1, x; |
| 1820 | int tool = 0, arg_start = 0, not_empty = 0, optind = 1; | ||
| 1821 | char **argv = *pargv; | 1819 | char **argv = *pargv; |
| 1822 | int argc = *pargc; | 1820 | int argc = *pargc; |
| 1823 | 1821 | ||
| @@ -1836,21 +1834,16 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 12 unmodified lines | |||
| 1836 | continue; | 1834 | continue; |
| 1837 | } | 1835 | } |
| 1838 | optind++; | 1836 | optind++; |
| 1839 | if (tool) { /* ignore all except -v and @listfile */ | ||
| 1840 | s->verbose += !strcmp(r, "-v"); | ||
| 1841 | continue; | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | if (r[0] != '-' || r[1] == '\0') { /* file or '-' (stdin) */ | 1837 | if (r[0] != '-' || r[1] == '\0') { /* file or '-' (stdin) */ |
| 1845 | args_parser_add_file(s, r, s->filetype); | 1838 | args_parser_add_file(s, r, s->filetype); |
| 1846 | not_empty = 1; | 1839 | empty = 0; |
| 1847 | dorun: | 1840 | dorun: |
| 1848 | if (run) { | 1841 | if (run) { |
| 1849 | /* tcc -run <file> <args...> */ | 1842 | /* tcc -run <file> <args...> */ |
| 1850 | if (tcc_set_options(s, run)) | 1843 | if (tcc_set_options(s, run) < 0) |
| 1851 | return -1; | 1844 | return -1; |
| 1852 | arg_start = optind - 1; /* argv[0] will be <file> */ | 1845 | x = 0; |
| 1853 | break; | 1846 | goto extra_action; |
| 1854 | } | 1847 | } |
| 1855 | continue; | 1848 | continue; |
| 1856 | } | 1849 | } |
| @@ -1923,14 +1916,16 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 66 unmodified lines | |||
| 1923 | case TCC_OPTION_g: | 1916 | case TCC_OPTION_g: |
| 1924 | s->do_debug = 2; | 1917 | s->do_debug = 2; |
| 1925 | s->dwarf = CONFIG_DWARF_VERSION; | 1918 | s->dwarf = CONFIG_DWARF_VERSION; |
| 1919 | g_redo: | ||
| 1926 | if (strstart("dwarf", &optarg)) { | 1920 | if (strstart("dwarf", &optarg)) { |
| 1927 | s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION; | 1921 | s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION; |
| 1928 | } else if (0 == strcmp("stabs", optarg)) { | 1922 | } else if (0 == strcmp("stabs", optarg)) { |
| 1929 | s->dwarf = 0; | 1923 | s->dwarf = 0; |
| 1930 | } else if (isnum(*optarg)) { | 1924 | } else if (isnum(*optarg)) { |
| 1931 | x = *optarg - '0'; | 1925 | x = *optarg++ - '0'; |
| 1932 | /* -g0 = no info, -g1 = lines/functions only, -g2 = full info */ | 1926 | /* -g0 = no info, -g1 = lines/functions only, -g2 = full info */ |
| 1933 | s->do_debug = x > 2 ? 2 : x == 0 && s->do_backtrace ? 1 : x; | 1927 | s->do_debug = x > 2 ? 2 : x == 0 && s->do_backtrace ? 1 : x; |
| 1928 | goto g_redo; | ||
| 1934 | #ifdef TCC_TARGET_PE | 1929 | #ifdef TCC_TARGET_PE |
| 1935 | } else if (0 == strcmp(".pdb", optarg)) { | 1930 | } else if (0 == strcmp(".pdb", optarg)) { |
| 1936 | s->dwarf = 5, s->do_debug |= 16; | 1931 | s->dwarf = 5, s->do_debug |= 16; |
| @@ -2030,7 +2025,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 93 unmodified lines | |||
| 2030 | } | 2025 | } |
| 2031 | break; | 2026 | break; |
| 2032 | case TCC_OPTION_W: | 2027 | case TCC_OPTION_W: |
| 2033 | s->warn_none = 0; | ||
| 2034 | if (optarg[0] && set_flag(s, options_W, optarg) < 0) | 2028 | if (optarg[0] && set_flag(s, options_W, optarg) < 0) |
| 2035 | goto unsupported_option; | 2029 | goto unsupported_option; |
| 2036 | break; | 2030 | break; |
| @@ -2141,29 +2135,24 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 104 unmodified lines | |||
| 2141 | case TCC_OPTION_ar: | 2135 | case TCC_OPTION_ar: |
| 2142 | x = OPT_AR; | 2136 | x = OPT_AR; |
| 2143 | extra_action: | 2137 | extra_action: |
| 2144 | arg_start = optind - 1; | 2138 | if (NULL == argv[0]) /* from tcc_set_options() */ |
| 2145 | if (not_empty) | 2139 | return -1; |
| 2140 | if (!empty && x) | ||
| 2146 | return tcc_error_noabort("cannot parse %s here", r); | 2141 | return tcc_error_noabort("cannot parse %s here", r); |
| 2147 | tool = x; | 2142 | --optind; |
| 2148 | break; | 2143 | *pargc = argc - optind; |
| 2144 | *pargv = argv + optind; | ||
| 2145 | return x; | ||
| 2149 | default: | 2146 | default: |
| 2150 | unsupported_option: | 2147 | unsupported_option: |
| 2151 | tcc_warning_c(warn_unsupported)("unsupported option '%s'", r); | 2148 | tcc_warning_c(warn_unsupported)("unsupported option '%s'", r); |
| 2152 | break; | 2149 | break; |
| 2153 | } | 2150 | } |
| 2154 | not_empty = 1; | 2151 | empty = 0; |
| 2155 | } | 2152 | } |
| 2156 | |||
| 2157 | if (s->link_optind < s->link_argc) | 2153 | if (s->link_optind < s->link_argc) |
| 2158 | return tcc_error_noabort("argument to '-Wl,%s' is missing", s->link_argv[s->link_optind]); | 2154 | return tcc_error_noabort("argument to '-Wl,%s' is missing", s->link_argv[s->link_optind]); |
| 2159 | if (NULL == argv[0]) /* from tcc_set_options() */ | 2155 | if (!empty) |
| 2160 | return 0; | ||
| 2161 | if (arg_start) { | ||
| 2162 | *pargc = argc - arg_start; | ||
| 2163 | *pargv = argv + arg_start; | ||
| 2164 | return tool; | ||
| 2165 | } | ||
| 2166 | if (not_empty) | ||
| 2167 | return 0; | 2156 | return 0; |
| 2168 | if (s->verbose == 2) | 2157 | if (s->verbose == 2) |
| 2169 | return OPT_PRINT_DIRS; | 2158 | return OPT_PRINT_DIRS; |
| @@ -283,51 +283,51 @@ static unsigned getclock_ms(void) · 282 unmodified lines | |||
| 283 | #endif | 283 | #endif |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | int main(int argc0, char **argv0) | 286 | int main(int argc, char **argv) |
| 287 | { | 287 | { |
| 288 | TCCState *s, *s1; | 288 | TCCState *s, *s1; |
| 289 | int ret, opt, n = 0, t = 0, done; | 289 | int ret, opt, n = 0, t = 0, done; |
| 290 | unsigned start_time = 0, end_time = 0; | 290 | unsigned start_time = 0, end_time = 0; |
| 291 | const char *first_file; | 291 | const char *first_file; |
| 292 | int argc; char **argv; | 292 | int argc0 = argc; |
| 293 | char **argv0 = argv; | ||
| 293 | FILE *ppfp = stdout; | 294 | FILE *ppfp = stdout; |
| 294 | 295 | ||
| 295 | redo: | 296 | redo: |
| 296 | argc = argc0, argv = argv0; | 297 | argc = argc0, argv = argv0; |
| 297 | s = s1 = tcc_new(); | 298 | s = s1 = tcc_new(); |
| 298 | opt = tcc_parse_args(s, &argc, &argv); | 299 | opt = tcc_parse_args(s, &argc, &argv); |
| 299 | if (opt < 0) | ||
| 300 | return 1; | ||
| 301 | 300 | ||
| 302 | if (n == 0) { | 301 | if (n == 0) { |
| 302 | ret = 0; | ||
| 303 | if (opt == OPT_HELP) { | 303 | if (opt == OPT_HELP) { |
| 304 | fputs(help, stdout); | 304 | fputs(help, stdout); |
| 305 | if (!s->verbose) | 305 | if (s->verbose) |
| 306 | return 0; | 306 | goto help2; |
| 307 | ++opt; | 307 | } else if (opt == OPT_HELP2) { |
| 308 | } | 308 | help2: fputs(help2, stdout); |
| 309 | if (opt == OPT_HELP2) { | 309 | } else if (opt == OPT_M32 || opt == OPT_M64) { |
| 310 | fputs(help2, stdout); | 310 | ret = tcc_tool_cross(argv, opt); |
| 311 | return 0; | 311 | } else if (s->verbose) |
| 312 | } | ||
| 313 | if (opt == OPT_M32 || opt == OPT_M64) | ||
| 314 | return tcc_tool_cross(s, argv, opt); | ||
| 315 | if (s->verbose) | ||
| 316 | printf("%s", version); | 312 | printf("%s", version); |
| 313 | |||
| 317 | if (opt == OPT_AR) | 314 | if (opt == OPT_AR) |
| 318 | return tcc_tool_ar(s, argc, argv); | 315 | ret = tcc_tool_ar(argc, argv); |
| 319 | #ifdef TCC_TARGET_PE | 316 | #ifdef TCC_TARGET_PE |
| 320 | if (opt == OPT_IMPDEF) | 317 | if (opt == OPT_IMPDEF) |
| 321 | return tcc_tool_impdef(s, argc, argv); | 318 | ret = tcc_tool_impdef(argc, argv); |
| 322 | #endif | 319 | #endif |
| 323 | if (opt == OPT_V) | ||
| 324 | return 0; | ||
| 325 | if (opt == OPT_PRINT_DIRS) { | 320 | if (opt == OPT_PRINT_DIRS) { |
| 326 | /* initialize search dirs */ | 321 | /* initialize search dirs */ |
| 327 | set_environment(s); | 322 | set_environment(s); |
| 328 | tcc_set_output_type(s, TCC_OUTPUT_MEMORY); | 323 | tcc_set_output_type(s, TCC_OUTPUT_MEMORY); |
| 329 | print_search_dirs(s); | 324 | print_search_dirs(s); |
| 330 | return 0; | 325 | } |
| 326 | if (opt < 0) err: | ||
| 327 | ret = 1; | ||
| 328 | if (opt) { | ||
| 329 | tcc_delete(s); | ||
| 330 | return ret; | ||
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | if (s->nb_files == 0) { | 333 | if (s->nb_files == 0) { |
| @@ -345,7 +345,7 @@ redo: · 11 unmodified lines | |||
| 345 | tcc_error_noabort("cannot specify output file with -c many files"); | 345 | tcc_error_noabort("cannot specify output file with -c many files"); |
| 346 | } | 346 | } |
| 347 | if (s->nb_errors) | 347 | if (s->nb_errors) |
| 348 | return 1; | 348 | goto err; |
| 349 | if (s->do_bench) | 349 | if (s->do_bench) |
| 350 | start_time = getclock_ms(); | 350 | start_time = getclock_ms(); |
| 351 | } | 351 | } |
| @@ -419,7 +419,6 @@ redo: · 67 unmodified lines | |||
| 419 | tcc_print_stats(s, end_time - start_time); | 419 | tcc_print_stats(s, end_time - start_time); |
| 420 | 420 | ||
| 421 | tcc_delete(s); | 421 | tcc_delete(s); |
| 422 | |||
| 423 | if (!done) | 422 | if (!done) |
| 424 | goto redo; | 423 | goto redo; |
| 425 | if (ppfp && ppfp != stdout) | 424 | if (ppfp && ppfp != stdout) |
| @@ -95,15 +95,14 @@ extern long double strtold (const char *__nptr, char **__endptr); · 94 unmodified lines | |||
| 95 | # define O_BINARY 0 | 95 | # define O_BINARY 0 |
| 96 | #endif | 96 | #endif |
| 97 | 97 | ||
| 98 | #ifndef offsetof | ||
| 99 | #define offsetof(type, field) ((size_t) &((type *)0)->field) | ||
| 100 | #endif | ||
| 101 | |||
| 102 | #ifdef __clang__ // clang -fsanitize compains about: NULL+value | 98 | #ifdef __clang__ // clang -fsanitize compains about: NULL+value |
| 103 | #undef offsetof | ||
| 104 | #define offsetof(type, field) __builtin_offsetof(type, field) | 99 | #define offsetof(type, field) __builtin_offsetof(type, field) |
| 105 | #endif | 100 | #endif |
| 106 | 101 | ||
| 102 | #ifndef offsetof | ||
| 103 | #define offsetof(type, field) ((size_t) &((type *)0)->field) | ||
| 104 | #endif | ||
| 105 | |||
| 107 | #ifndef countof | 106 | #ifndef countof |
| 108 | #define countof(tab) (sizeof(tab) / sizeof((tab)[0])) | 107 | #define countof(tab) (sizeof(tab) / sizeof((tab)[0])) |
| 109 | #endif | 108 | #endif |
| @@ -318,8 +318,7 @@ ST_FUNC size_t section_add(Section *sec, addr_t size, int align) · 317 unmodified lines | |||
| 318 | ST_FUNC void *section_ptr_add(Section *sec, addr_t size) | 318 | ST_FUNC void *section_ptr_add(Section *sec, addr_t size) |
| 319 | { | 319 | { |
| 320 | size_t offset = section_add(sec, size, 1); | 320 | size_t offset = section_add(sec, size, 1); |
| 321 | // clang -fsanitize compains about: NULL+value | 321 | return sec->data + offset; |
| 322 | return sec->data ? sec->data + offset : (void *)offset; | ||
| 323 | } | 322 | } |
| 324 | 323 | ||
| 325 | #ifndef ELF_OBJ_ONLY | 324 | #ifndef ELF_OBJ_ONLY |
| @@ -1598,7 +1597,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 1272 unmodified lines | |||
| 1598 | 1597 | ||
| 1599 | s = data_section; | 1598 | s = data_section; |
| 1600 | /* Align to PTR_SIZE */ | 1599 | /* Align to PTR_SIZE */ |
| 1601 | section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1)); | 1600 | section_add(s, 0, PTR_SIZE); |
| 1602 | o = s->data_offset; | 1601 | o = s->data_offset; |
| 1603 | /* create a struct rt_context (see tccrun.c) */ | 1602 | /* create a struct rt_context (see tccrun.c) */ |
| 1604 | if (s1->dwarf) { | 1603 | if (s1->dwarf) { |
| @@ -2837,7 +2836,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 1232 unmodified lines | |||
| 2837 | int textrel, got_sym, dt_flags_1; | 2836 | int textrel, got_sym, dt_flags_1; |
| 2838 | 2837 | ||
| 2839 | file_type = s1->output_type; | 2838 | file_type = s1->output_type; |
| 2840 | s1->nb_errors = 0; | ||
| 2841 | ret = -1; | 2839 | ret = -1; |
| 2842 | interp = dynstr = dynamic = NULL; | 2840 | interp = dynstr = dynamic = NULL; |
| 2843 | sec_order = NULL; | 2841 | sec_order = NULL; |
| @@ -3030,7 +3028,6 @@ static int elf_output_obj(TCCState *s1, const char *filename) · 186 unmodified lines | |||
| 3030 | { | 3028 | { |
| 3031 | Section *s; | 3029 | Section *s; |
| 3032 | int i, ret, file_offset; | 3030 | int i, ret, file_offset; |
| 3033 | s1->nb_errors = 0; | ||
| 3034 | /* Allocate strings for section names */ | 3031 | /* Allocate strings for section names */ |
| 3035 | alloc_sec_names(s1, 1); | 3032 | alloc_sec_names(s1, 1); |
| 3036 | file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4; | 3033 | file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4; |
| @@ -3049,6 +3046,7 @@ static int elf_output_obj(TCCState *s1, const char *filename) · 12 unmodified lines | |||
| 3049 | 3046 | ||
| 3050 | LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) | 3047 | LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) |
| 3051 | { | 3048 | { |
| 3049 | s->nb_errors = 0; | ||
| 3052 | if (s->test_coverage) | 3050 | if (s->test_coverage) |
| 3053 | tcc_tcov_add_file(s, filename); | 3051 | tcc_tcov_add_file(s, filename); |
| 3054 | if (s->output_type == TCC_OUTPUT_OBJ) | 3052 | if (s->output_type == TCC_OUTPUT_OBJ) |
| @@ -3254,21 +3252,19 @@ invalid: · 199 unmodified lines | |||
| 3254 | s->sh_entsize = sh->sh_entsize; | 3252 | s->sh_entsize = sh->sh_entsize; |
| 3255 | sm_table[i].new_section = 1; | 3253 | sm_table[i].new_section = 1; |
| 3256 | found: | 3254 | found: |
| 3255 | size = sh->sh_size; | ||
| 3257 | /* align start of section */ | 3256 | /* align start of section */ |
| 3258 | s->data_offset += -s->data_offset & (sh->sh_addralign - 1); | 3257 | offset = section_add(s, size, sh->sh_addralign); |
| 3259 | if (sh->sh_addralign > s->sh_addralign) | 3258 | if (sh->sh_addralign > s->sh_addralign) |
| 3260 | s->sh_addralign = sh->sh_addralign; | 3259 | s->sh_addralign = sh->sh_addralign; |
| 3261 | sm_table[i].offset = s->data_offset; | 3260 | sm_table[i].offset = offset; |
| 3262 | sm_table[i].s = s; | 3261 | sm_table[i].s = s; |
| 3263 | /* concatenate sections */ | 3262 | /* concatenate sections */ |
| 3264 | size = sh->sh_size; | 3263 | if (sh->sh_type != SHT_NOBITS && size) { |
| 3265 | if (sh->sh_type != SHT_NOBITS) { | ||
| 3266 | unsigned char *ptr; | 3264 | unsigned char *ptr; |
| 3267 | lseek(fd, file_offset + sh->sh_offset, SEEK_SET); | 3265 | lseek(fd, file_offset + sh->sh_offset, SEEK_SET); |
| 3268 | ptr = section_ptr_add(s, size); | 3266 | ptr = s->data + offset; |
| 3269 | full_read(fd, ptr, size); | 3267 | full_read(fd, ptr, size); |
| 3270 | } else { | ||
| 3271 | s->data_offset += size; | ||
| 3272 | } | 3268 | } |
| 3273 | #if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 | 3269 | #if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 |
| 3274 | /* align code sections to instruction lenght */ | 3270 | /* align code sections to instruction lenght */ |
| @@ -3310,6 +3306,9 @@ invalid: · 35 unmodified lines | |||
| 3310 | } | 3306 | } |
| 3311 | } | 3307 | } |
| 3312 | 3308 | ||
| 3309 | if (!symtab) | ||
| 3310 | goto done; | ||
| 3311 | |||
| 3313 | /* resolve symbols */ | 3312 | /* resolve symbols */ |
| 3314 | old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int)); | 3313 | old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int)); |
| 3315 | 3314 | ||
| @@ -3405,7 +3404,7 @@ invalid: · 89 unmodified lines | |||
| 3405 | break; | 3404 | break; |
| 3406 | } | 3405 | } |
| 3407 | } | 3406 | } |
| 3408 | 3407 | done: | |
| 3409 | ret = 0; | 3408 | ret = 0; |
| 3410 | the_end: | 3409 | the_end: |
| 3411 | tcc_free(symtab); | 3410 | tcc_free(symtab); |
| @@ -2963,13 +2963,13 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 2962 unmodified lines | |||
| 2963 | (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) | 2963 | (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) |
| 2964 | type.t |= VT_UNSIGNED; | 2964 | type.t |= VT_UNSIGNED; |
| 2965 | } else { | 2965 | } else { |
| 2966 | int t1_bit = BIT_SIZE(t1) <= 31 ? VT_BITFIELD : 0; | ||
| 2967 | int t2_bit = BIT_SIZE(t2) <= 31 ? VT_BITFIELD : 0; | ||
| 2968 | /* integer operations */ | 2966 | /* integer operations */ |
| 2969 | type.t = VT_INT | (VT_LONG & (t1 | t2)); | 2967 | type.t = VT_INT | (VT_LONG & (t1 | t2)); |
| 2970 | /* convert to unsigned if it does not fit in an integer */ | 2968 | /* convert to unsigned if it does not fit in an integer */ |
| 2971 | if ((t1 & (VT_BTYPE | VT_UNSIGNED | t1_bit)) == (VT_INT | VT_UNSIGNED) || | 2969 | if (((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) |
| 2972 | (t2 & (VT_BTYPE | VT_UNSIGNED | t2_bit)) == (VT_INT | VT_UNSIGNED)) | 2970 | && (!(t1 & VT_BITFIELD) || BIT_SIZE(t1) == 32)) |
| 2971 | || ((t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) | ||
| 2972 | && (!(t2 & VT_BITFIELD) || BIT_SIZE(t2) == 32))) | ||
| 2973 | type.t |= VT_UNSIGNED; | 2973 | type.t |= VT_UNSIGNED; |
| 2974 | } | 2974 | } |
| 2975 | if (dest) | 2975 | if (dest) |
| @@ -5615,6 +5615,8 @@ ST_FUNC void unary(void) · 2639 unmodified lines | |||
| 5615 | as statement expressions can't ever be entered from the | 5615 | as statement expressions can't ever be entered from the |
| 5616 | outside, so any reactivation of code emission (from labels | 5616 | outside, so any reactivation of code emission (from labels |
| 5617 | or loop heads) can be disabled again after the end of it. */ | 5617 | or loop heads) can be disabled again after the end of it. */ |
| 5618 | /* default return value is (void) */ | ||
| 5619 | vpushi(0), vtop->type.t = VT_VOID; | ||
| 5618 | block(STMT_EXPR); | 5620 | block(STMT_EXPR); |
| 5619 | /* If the statement expr can be entered, then we retain the current | 5621 | /* If the statement expr can be entered, then we retain the current |
| 5620 | nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr). | 5622 | nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr). |
| @@ -7036,12 +7038,6 @@ static void block(int flags) · 1415 unmodified lines | |||
| 7036 | struct scope o; | 7038 | struct scope o; |
| 7037 | Sym *s; | 7039 | Sym *s; |
| 7038 | 7040 | ||
| 7039 | if (flags & STMT_EXPR) { | ||
| 7040 | /* default return value is (void) */ | ||
| 7041 | vpushi(0); | ||
| 7042 | vtop->type.t = VT_VOID; | ||
| 7043 | } | ||
| 7044 | |||
| 7045 | again: | 7041 | again: |
| 7046 | t = tok; | 7042 | t = tok; |
| 7047 | /* If the token carries a value, next() might destroy it. Only with | 7043 | /* If the token carries a value, next() might destroy it. Only with |
| @@ -7057,8 +7053,8 @@ again: · 9 unmodified lines | |||
| 7057 | new_scope_s(&o); | 7053 | new_scope_s(&o); |
| 7058 | skip('('); | 7054 | skip('('); |
| 7059 | gexpr(); | 7055 | gexpr(); |
| 7060 | skip(')'); | ||
| 7061 | a = gvtst(1, 0); | 7056 | a = gvtst(1, 0); |
| 7057 | skip(')'); | ||
| 7062 | block(0); | 7058 | block(0); |
| 7063 | if (tok == TOK_ELSE) { | 7059 | if (tok == TOK_ELSE) { |
| 7064 | d = gjmp(0); | 7060 | d = gjmp(0); |
| @@ -7076,8 +7072,8 @@ again: · 11 unmodified lines | |||
| 7076 | d = gind(); | 7072 | d = gind(); |
| 7077 | skip('('); | 7073 | skip('('); |
| 7078 | gexpr(); | 7074 | gexpr(); |
| 7079 | skip(')'); | ||
| 7080 | a = gvtst(1, 0); | 7075 | a = gvtst(1, 0); |
| 7076 | skip(')'); | ||
| 7081 | b = 0; | 7077 | b = 0; |
| 7082 | lblock(&a, &b); | 7078 | lblock(&a, &b); |
| 7083 | gjmp_addr(d); | 7079 | gjmp_addr(d); |
| @@ -7105,8 +7101,6 @@ again: · 21 unmodified lines | |||
| 7105 | while (tok != '}') { | 7101 | while (tok != '}') { |
| 7106 | decl(VT_LOCAL); | 7102 | decl(VT_LOCAL); |
| 7107 | if (tok != '}') { | 7103 | if (tok != '}') { |
| 7108 | if (flags & STMT_EXPR) | ||
| 7109 | vpop(); | ||
| 7110 | block(flags | STMT_COMPOUND); | 7104 | block(flags | STMT_COMPOUND); |
| 7111 | } | 7105 | } |
| 7112 | } | 7106 | } |
| @@ -7208,9 +7202,9 @@ again: · 95 unmodified lines | |||
| 7208 | skip(TOK_WHILE); | 7202 | skip(TOK_WHILE); |
| 7209 | skip('('); | 7203 | skip('('); |
| 7210 | gexpr(); | 7204 | gexpr(); |
| 7205 | c = gvtst(0, 0); | ||
| 7211 | skip(')'); | 7206 | skip(')'); |
| 7212 | skip(';'); | 7207 | skip(';'); |
| 7213 | c = gvtst(0, 0); | ||
| 7214 | gsym_addr(c, d); | 7208 | gsym_addr(c, d); |
| 7215 | gsym(a); | 7209 | gsym(a); |
| 7216 | prev_scope_s(&o); | 7210 | prev_scope_s(&o); |
| @@ -7228,9 +7222,9 @@ again: · 11 unmodified lines | |||
| 7228 | new_scope_s(&o); | 7222 | new_scope_s(&o); |
| 7229 | skip('('); | 7223 | skip('('); |
| 7230 | gexpr(); | 7224 | gexpr(); |
| 7231 | skip(')'); | ||
| 7232 | if (!is_integer_btype(vtop->type.t & VT_BTYPE)) | 7225 | if (!is_integer_btype(vtop->type.t & VT_BTYPE)) |
| 7233 | tcc_error("switch value not an integer"); | 7226 | tcc_error("switch value not an integer"); |
| 7227 | skip(')'); | ||
| 7234 | sw->sv = *vtop--; /* save switch value */ | 7228 | sw->sv = *vtop--; /* save switch value */ |
| 7235 | a = 0; | 7229 | a = 0; |
| 7236 | b = gjmp(0); /* jump to first case */ | 7230 | b = gjmp(0); /* jump to first case */ |
| @@ -8294,6 +8288,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 1057 unmodified lines | |||
| 8294 | if (type->t & VT_VLA) { | 8288 | if (type->t & VT_VLA) { |
| 8295 | int a; | 8289 | int a; |
| 8296 | 8290 | ||
| 8291 | if (has_init) | ||
| 8292 | tcc_error("variable length array cannot be initialized"); | ||
| 8293 | |||
| 8297 | if (NODATA_WANTED) | 8294 | if (NODATA_WANTED) |
| 8298 | goto no_alloc; | 8295 | goto no_alloc; |
| 8299 | 8296 | ||
| @@ -8513,6 +8510,27 @@ static void do_Static_assert(void) · 213 unmodified lines | |||
| 8513 | skip(';'); | 8510 | skip(';'); |
| 8514 | } | 8511 | } |
| 8515 | 8512 | ||
| 8513 | #ifdef TCC_TARGET_PE | ||
| 8514 | static void pe_check_linkage(CType *type, AttributeDef *ad) | ||
| 8515 | { | ||
| 8516 | if (!ad->a.dllimport && !ad->a.dllexport) | ||
| 8517 | return; | ||
| 8518 | if (type->t & VT_STATIC) | ||
| 8519 | tcc_error("cannot have dll linkage with static"); | ||
| 8520 | if (type->t & VT_TYPEDEF) { | ||
| 8521 | const char *m = ad->a.dllimport ? "im" : "ex"; | ||
| 8522 | tcc_warning("'dll%sport' attribute ignored for typedef", m); | ||
| 8523 | ad->a.dllimport = 0; | ||
| 8524 | ad->a.dllexport = 0; | ||
| 8525 | } else if (ad->a.dllimport) { | ||
| 8526 | if ((type->t & VT_BTYPE) == VT_FUNC) | ||
| 8527 | ad->a.dllimport = 0; | ||
| 8528 | else | ||
| 8529 | type->t |= VT_EXTERN; | ||
| 8530 | } | ||
| 8531 | } | ||
| 8532 | #endif | ||
| 8533 | |||
| 8516 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type | 8534 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type |
| 8517 | or VT_CMP if parsing old style parameter list | 8535 | or VT_CMP if parsing old style parameter list |
| 8518 | or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */ | 8536 | or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */ |
| @@ -8559,17 +8577,17 @@ static int decl(int l) · 40 unmodified lines | |||
| 8559 | } | 8577 | } |
| 8560 | 8578 | ||
| 8561 | if (tok == ';') { | 8579 | if (tok == ';') { |
| 8562 | if ((btype.t & VT_BTYPE) == VT_STRUCT) { | 8580 | if ((btype.t & VT_BTYPE) == VT_STRUCT |
| 8563 | v = btype.ref->v; | 8581 | && (btype.ref->v & ~SYM_STRUCT) < SYM_FIRST_ANOM) |
| 8564 | if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) | 8582 | ; /* struct decl with named tag */ |
| 8565 | tcc_warning("unnamed struct/union that defines no instances"); | 8583 | else if (IS_ENUM(btype.t)) |
| 8566 | next(); | 8584 | ; /* enum decl */ |
| 8567 | continue; | 8585 | else |
| 8568 | } | 8586 | tcc_warning("useless type defines no instances"); |
| 8569 | if (IS_ENUM(btype.t)) { | 8587 | if (l == VT_JMP) |
| 8570 | next(); | 8588 | return 1; |
| 8571 | continue; | 8589 | next(); |
| 8572 | } | 8590 | continue; |
| 8573 | } | 8591 | } |
| 8574 | 8592 | ||
| 8575 | while (1) { /* iterate thru each declaration */ | 8593 | while (1) { /* iterate thru each declaration */ |
| @@ -8637,20 +8655,7 @@ static int decl(int l) · 61 unmodified lines | |||
| 8637 | } | 8655 | } |
| 8638 | 8656 | ||
| 8639 | #ifdef TCC_TARGET_PE | 8657 | #ifdef TCC_TARGET_PE |
| 8640 | if (ad.a.dllimport || ad.a.dllexport) { | 8658 | pe_check_linkage(&type, &ad); |
| 8641 | if (type.t & VT_STATIC) | ||
| 8642 | tcc_error("cannot have dll linkage with static"); | ||
| 8643 | if (type.t & VT_TYPEDEF) { | ||
| 8644 | tcc_warning("'%s' attribute ignored for typedef", | ||
| 8645 | ad.a.dllimport ? (ad.a.dllimport = 0, "dllimport") : | ||
| 8646 | (ad.a.dllexport = 0, "dllexport")); | ||
| 8647 | } else if (ad.a.dllimport) { | ||
| 8648 | if ((type.t & VT_BTYPE) == VT_FUNC) | ||
| 8649 | ad.a.dllimport = 0; | ||
| 8650 | else | ||
| 8651 | type.t |= VT_EXTERN; | ||
| 8652 | } | ||
| 8653 | } | ||
| 8654 | #endif | 8659 | #endif |
| 8655 | if (tok == '{') { | 8660 | if (tok == '{') { |
| 8656 | if (l != VT_CONST) | 8661 | if (l != VT_CONST) |
| @@ -8700,6 +8705,7 @@ static int decl(int l) · 43 unmodified lines | |||
| 8700 | } | 8705 | } |
| 8701 | break; | 8706 | break; |
| 8702 | } else { | 8707 | } else { |
| 8708 | has_init = 0; | ||
| 8703 | if (l == VT_CMP) { | 8709 | if (l == VT_CMP) { |
| 8704 | /* find parameter in function parameter list */ | 8710 | /* find parameter in function parameter list */ |
| 8705 | for (sym = func_vt.ref->next; sym; sym = sym->next) | 8711 | for (sym = func_vt.ref->next; sym; sym = sym->next) |
| @@ -8747,9 +8753,9 @@ static int decl(int l) · 41 unmodified lines | |||
| 8747 | /* not lvalue if array */ | 8753 | /* not lvalue if array */ |
| 8748 | r |= VT_LVAL; | 8754 | r |= VT_LVAL; |
| 8749 | } | 8755 | } |
| 8750 | has_init = (tok == '='); | 8756 | |
| 8751 | if (has_init && (type.t & VT_VLA)) | 8757 | if (tok == '=') |
| 8752 | tcc_error("variable length array cannot be initialized"); | 8758 | has_init = 1; |
| 8753 | 8759 | ||
| 8754 | if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST)) | 8760 | if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST)) |
| 8755 | || (type.t & VT_BTYPE) == VT_FUNC | 8761 | || (type.t & VT_BTYPE) == VT_FUNC |
| @@ -8789,7 +8795,7 @@ static int decl(int l) · 33 unmodified lines | |||
| 8789 | } | 8795 | } |
| 8790 | if (tok != ',') { | 8796 | if (tok != ',') { |
| 8791 | if (l == VT_JMP) | 8797 | if (l == VT_JMP) |
| 8792 | return 1; | 8798 | return has_init ? v : 1; |
| 8793 | skip(';'); | 8799 | skip(';'); |
| 8794 | break; | 8800 | break; |
| 8795 | } | 8801 | } |
| @@ -117,16 +117,6 @@ ST_FUNC void expect(const char *msg) · 116 unmodified lines | |||
| 117 | 117 | ||
| 118 | #define USE_TAL | 118 | #define USE_TAL |
| 119 | 119 | ||
| 120 | #ifdef _MSC_VER | ||
| 121 | # if defined _M_AMD64 || defined _M_ARM64 || defined _M_ARM64EC || defined _M_IA64 || defined _M_X64 | ||
| 122 | # define POINTER_SIZE 8 | ||
| 123 | # else | ||
| 124 | # define POINTER_SIZE 4 | ||
| 125 | # endif | ||
| 126 | #else | ||
| 127 | # define POINTER_SIZE sizeof(void *) | ||
| 128 | #endif | ||
| 129 | |||
| 130 | #ifndef USE_TAL | 120 | #ifndef USE_TAL |
| 131 | #define tal_free(al, p) tcc_free(p) | 121 | #define tal_free(al, p) tcc_free(p) |
| 132 | #define tal_realloc(al, p, size) tcc_realloc(p, size) | 122 | #define tal_realloc(al, p, size) tcc_realloc(p, size) |
| @@ -143,7 +133,6 @@ ST_FUNC void expect(const char *msg) · 10 unmodified lines | |||
| 143 | #define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__) | 133 | #define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__) |
| 144 | #define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__) | 134 | #define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__) |
| 145 | #define TAL_DEBUG_PARAMS , const char *file, int line | 135 | #define TAL_DEBUG_PARAMS , const char *file, int line |
| 146 | #define TAL_DEBUG_FILE_LEN 40 | ||
| 147 | #endif | 136 | #endif |
| 148 | 137 | ||
| 149 | #define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */ | 138 | #define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */ |
| @@ -167,13 +156,16 @@ typedef struct TinyAlloc { · 17 unmodified lines | |||
| 167 | } TinyAlloc; | 156 | } TinyAlloc; |
| 168 | 157 | ||
| 169 | typedef struct tal_header_t { | 158 | typedef struct tal_header_t { |
| 170 | ALIGNED(POINTER_SIZE) unsigned size; | 159 | size_t size; /* word align */ |
| 171 | #ifdef TAL_DEBUG | 160 | #ifdef TAL_DEBUG |
| 172 | int line_num; /* negative line_num used for double free check */ | 161 | int line_num; /* negative line_num used for double free check */ |
| 173 | char file_name[TAL_DEBUG_FILE_LEN + 1]; | 162 | char file_name[40]; |
| 174 | #endif | 163 | #endif |
| 175 | } tal_header_t; | 164 | } tal_header_t; |
| 176 | 165 | ||
| 166 | #define TAL_ALIGN(size) \ | ||
| 167 | (((size) + (sizeof (size_t) - 1)) & ~(sizeof (size_t) - 1)) | ||
| 168 | |||
| 177 | /* ------------------------------------------------------------------------- */ | 169 | /* ------------------------------------------------------------------------- */ |
| 178 | 170 | ||
| 179 | static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size) | 171 | static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size) |
| @@ -208,7 +200,7 @@ tail_call: · 28 unmodified lines | |||
| 208 | tal_header_t *header = (tal_header_t *)p; | 200 | tal_header_t *header = (tal_header_t *)p; |
| 209 | if (header->line_num > 0) { | 201 | if (header->line_num > 0) { |
| 210 | fprintf(stderr, "%s:%d: chunk of %d bytes leaked\n", | 202 | fprintf(stderr, "%s:%d: chunk of %d bytes leaked\n", |
| 211 | header->file_name, header->line_num, header->size); | 203 | header->file_name, header->line_num, (int)header->size); |
| 212 | } | 204 | } |
| 213 | p += header->size + sizeof(tal_header_t); | 205 | p += header->size + sizeof(tal_header_t); |
| 214 | } | 206 | } |
| @@ -256,7 +248,7 @@ static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_ · 41 unmodified lines | |||
| 256 | tal_header_t *header; | 248 | tal_header_t *header; |
| 257 | void *ret; | 249 | void *ret; |
| 258 | int is_own; | 250 | int is_own; |
| 259 | unsigned adj_size = (size + POINTER_SIZE - 1) & -POINTER_SIZE; | 251 | unsigned adj_size = TAL_ALIGN(size); |
| 260 | TinyAlloc *al = *pal; | 252 | TinyAlloc *al = *pal; |
| 261 | 253 | ||
| 262 | tail_call: | 254 | tail_call: |
| @@ -266,9 +258,8 @@ tail_call: · 3 unmodified lines | |||
| 266 | header = (tal_header_t *)al->p; | 258 | header = (tal_header_t *)al->p; |
| 267 | header->size = adj_size; | 259 | header->size = adj_size; |
| 268 | #ifdef TAL_DEBUG | 260 | #ifdef TAL_DEBUG |
| 269 | { int ofs = strlen(file) - TAL_DEBUG_FILE_LEN; | 261 | { int ofs = strlen(file) + 1 - sizeof header->file_name; |
| 270 | strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN); | 262 | strcpy(header->file_name, file + (ofs > 0 ? ofs : 0)); |
| 271 | header->file_name[TAL_DEBUG_FILE_LEN] = 0; | ||
| 272 | header->line_num = line; } | 263 | header->line_num = line; } |
| 273 | #endif | 264 | #endif |
| 274 | ret = al->p + sizeof(tal_header_t); | 265 | ret = al->p + sizeof(tal_header_t); |
| @@ -2986,6 +2977,11 @@ maybe_newline: · 2711 unmodified lines | |||
| 2986 | tok = c; | 2977 | tok = c; |
| 2987 | p++; | 2978 | p++; |
| 2988 | break; | 2979 | break; |
| 2980 | case 0xEF: /* UTF8 BOM ? */ | ||
| 2981 | if (p[1] == 0xBB && p[2] == 0xBF && p == file->buffer) { | ||
| 2982 | p += 3; | ||
| 2983 | goto redo_no_start; | ||
| 2984 | } | ||
| 2989 | default: | 2985 | default: |
| 2990 | if (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */ | 2986 | if (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */ |
| 2991 | goto parse_ident_fast; | 2987 | goto parse_ident_fast; |
| @@ -312,6 +312,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) · 311 unmodified lines | |||
| 312 | addr_t mem, addr; | 312 | addr_t mem, addr; |
| 313 | 313 | ||
| 314 | if (NULL == ptr) { | 314 | if (NULL == ptr) { |
| 315 | s1->nb_errors = 0; | ||
| 315 | #ifdef TCC_TARGET_PE | 316 | #ifdef TCC_TARGET_PE |
| 316 | pe_output_file(s1, NULL); | 317 | pe_output_file(s1, NULL); |
| 317 | #else | 318 | #else |
| @@ -495,10 +496,6 @@ static void bt_link(TCCState *s1) · 177 unmodified lines | |||
| 495 | { | 496 | { |
| 496 | #ifdef CONFIG_TCC_BACKTRACE | 497 | #ifdef CONFIG_TCC_BACKTRACE |
| 497 | rt_context *rc; | 498 | rt_context *rc; |
| 498 | #ifdef CONFIG_TCC_BCHECK | ||
| 499 | void *p; | ||
| 500 | #endif | ||
| 501 | |||
| 502 | if (!s1->do_backtrace) | 499 | if (!s1->do_backtrace) |
| 503 | return; | 500 | return; |
| 504 | rc = tcc_get_symbol(s1, "__rt_info"); | 501 | rc = tcc_get_symbol(s1, "__rt_info"); |
| @@ -511,6 +508,7 @@ static void bt_link(TCCState *s1) · 6 unmodified lines | |||
| 511 | rc->prog_base &= 0xffffffff00000000ULL; | 508 | rc->prog_base &= 0xffffffff00000000ULL; |
| 512 | #ifdef CONFIG_TCC_BCHECK | 509 | #ifdef CONFIG_TCC_BCHECK |
| 513 | if (s1->do_bounds_check) { | 510 | if (s1->do_bounds_check) { |
| 511 | void *p; | ||
| 514 | if ((p = tcc_get_symbol(s1, "__bound_init"))) | 512 | if ((p = tcc_get_symbol(s1, "__bound_init"))) |
| 515 | ((void(*)(void*,int))p)(rc->bounds_start, 1); | 513 | ((void(*)(void*,int))p)(rc->bounds_start, 1); |
| 516 | } | 514 | } |
| @@ -599,6 +597,13 @@ static void rt_exit(rt_frame *f, int code) · 82 unmodified lines | |||
| 599 | s = rt_find_state(f); | 597 | s = rt_find_state(f); |
| 600 | rt_post_sem(); | 598 | rt_post_sem(); |
| 601 | if (s && s->run_lj) { | 599 | if (s && s->run_lj) { |
| 600 | #ifdef CONFIG_TCC_BCHECK | ||
| 601 | if (f->fp) { /* called from signal */ | ||
| 602 | void *p = tcc_get_symbol(s, "__bound_exit"); | ||
| 603 | if (p) | ||
| 604 | ((void (*)(void))p)(); | ||
| 605 | } | ||
| 606 | #endif | ||
| 602 | if (code == 0) | 607 | if (code == 0) |
| 603 | code = RT_EXIT_ZERO; | 608 | code = RT_EXIT_ZERO; |
| 604 | ((void(*)(void*,int))s->run_lj)(s->run_jb, code); | 609 | ((void(*)(void*,int))s->run_lj)(s->run_jb, code); |
| @@ -54,7 +54,7 @@ static int ar_usage(int ret) { · 53 unmodified lines | |||
| 54 | return ret; | 54 | return ret; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) | 57 | ST_FUNC int tcc_tool_ar(int argc, char **argv) |
| 58 | { | 58 | { |
| 59 | static const ArHdr arhdr_init = { | 59 | static const ArHdr arhdr_init = { |
| 60 | "/ ", | 60 | "/ ", |
| @@ -360,7 +360,7 @@ the_end: · 299 unmodified lines | |||
| 360 | 360 | ||
| 361 | #ifdef TCC_TARGET_PE | 361 | #ifdef TCC_TARGET_PE |
| 362 | 362 | ||
| 363 | ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv) | 363 | ST_FUNC int tcc_tool_impdef(int argc, char **argv) |
| 364 | { | 364 | { |
| 365 | int ret, v, i; | 365 | int ret, v, i; |
| 366 | char infile[260]; | 366 | char infile[260]; |
| @@ -487,9 +487,9 @@ the_end: · 120 unmodified lines | |||
| 487 | 487 | ||
| 488 | #if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64 | 488 | #if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64 |
| 489 | 489 | ||
| 490 | ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option) | 490 | ST_FUNC int tcc_tool_cross(char **argv, int option) |
| 491 | { | 491 | { |
| 492 | tcc_error_noabort("-m%d not implemented.", option); | 492 | fprintf(stderr, "tcc -m%d not implemented\n", option); |
| 493 | return 1; | 493 | return 1; |
| 494 | } | 494 | } |
| 495 | 495 | ||
| @@ -546,7 +546,7 @@ static int execvp_win32(const char *prog, char **argv) · 50 unmodified lines | |||
| 546 | #define execvp execvp_win32 | 546 | #define execvp execvp_win32 |
| 547 | #endif /* _WIN32 */ | 547 | #endif /* _WIN32 */ |
| 548 | 548 | ||
| 549 | ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target) | 549 | ST_FUNC int tcc_tool_cross(char **argv, int target) |
| 550 | { | 550 | { |
| 551 | char program[4096]; | 551 | char program[4096]; |
| 552 | char *a0 = argv[0]; | 552 | char *a0 = argv[0]; |
| @@ -565,7 +565,7 @@ ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target) · 12 unmodified lines | |||
| 565 | 565 | ||
| 566 | if (strcmp(a0, program)) | 566 | if (strcmp(a0, program)) |
| 567 | execvp(argv[0] = program, argv); | 567 | execvp(argv[0] = program, argv); |
| 568 | tcc_error_noabort("could not run '%s'", program); | 568 | fprintf(stderr, "tcc: could not run '%s'\n", program); |
| 569 | return 1; | 569 | return 1; |
| 570 | } | 570 | } |
| 571 | 571 | ||
| @@ -79,7 +79,7 @@ endif · 78 unmodified lines | |||
| 79 | 79 | ||
| 80 | all test : | 80 | all test : |
| 81 | @echo ------------ version ------------ | 81 | @echo ------------ version ------------ |
| 82 | @ASAN_OPTIONS=detect_leaks=0 $(TCC_LOCAL) -v | 82 | @$(TCC_LOCAL) -v |
| 83 | @$(MAKE) --no-print-directory -s clean | 83 | @$(MAKE) --no-print-directory -s clean |
| 84 | @$(MAKE) --no-print-directory -s -r _all | 84 | @$(MAKE) --no-print-directory -s -r _all |
| 85 | 85 | ||
| @@ -102,7 +102,6 @@ GEN-ALWAYS = · 101 unmodified lines | |||
| 102 | 112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \ | 102 | 112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \ |
| 103 | -e 's;[0-9A-Fa-fx]\{5,\};........;g' \ | 103 | -e 's;[0-9A-Fa-fx]\{5,\};........;g' \ |
| 104 | -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g' | 104 | -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g' |
| 105 | 112_backtrace.test: LEAK=ASAN_OPTIONS=detect_leaks=0 | ||
| 106 | 105 | ||
| 107 | # this test creates two DLLs and an EXE | 106 | # this test creates two DLLs and an EXE |
| 108 | 113_btdll.test: T1 = \ | 107 | 113_btdll.test: T1 = \ |
| @@ -137,7 +136,7 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS)) · 28 unmodified lines | |||
| 137 | @echo Test: $*... | 136 | @echo Test: $*... |
| 138 | @$(call T1,$<) $(T3) | 137 | @$(call T1,$<) $(T3) |
| 139 | 138 | ||
| 140 | T1 = $(LEAK) $(TCC) $(FLAGS) $(T2) $(ARGS) | 139 | T1 = $(TCC) $(FLAGS) $(T2) $(ARGS) |
| 141 | T2 = $(if $(NORUN),$1 -o $(basename $@).exe && ./$(basename $@).exe,-run $1) | 140 | T2 = $(if $(NORUN),$1 -o $(basename $@).exe && ./$(basename $@).exe,-run $1) |
| 142 | T3 = $(FILTER) >$*.output 2>&1 || true \ | 141 | T3 = $(FILTER) >$*.output 2>&1 || true \ |
| 143 | && diff -Nbu $(filter %.expect,$^) $*.output \ | 142 | && diff -Nbu $(filter %.expect,$^) $*.output \ |
| @@ -132,6 +132,10 @@ if %TX%==32 echo>> ..\config.h #ifdef TCC_TARGET_I386 · 131 unmodified lines | |||
| 132 | echo>> ..\config.h #define CONFIG_TCC_CROSSPREFIX "%PX%-" | 132 | echo>> ..\config.h #define CONFIG_TCC_CROSSPREFIX "%PX%-" |
| 133 | echo>> ..\config.h #endif | 133 | echo>> ..\config.h #endif |
| 134 | 134 | ||
| 135 | @rem echo>> ..\config.h #define CONFIG_TCC_PREDEFS 1 | ||
| 136 | @rem %CC% -DC2STR ..\conftest.c -o c2str.exe | ||
| 137 | @rem .\c2str.exe ../include/tccdefs.h ../tccdefs_.h | ||
| 138 | |||
| 135 | for %%f in (*tcc.exe *tcc.dll) do @del %%f | 139 | for %%f in (*tcc.exe *tcc.dll) do @del %%f |
| 136 | 140 | ||
| 137 | @if _%TCC_C%_==__ goto compiler_2parts | 141 | @if _%TCC_C%_==__ goto compiler_2parts |
| @@ -200,8 +204,9 @@ exit /B %ERRORLEVEL% · 62 unmodified lines | |||
| 200 | .\tcc -B. -m%1 -c ../lib/alloca.S | 204 | .\tcc -B. -m%1 -c ../lib/alloca.S |
| 201 | .\tcc -B. -m%1 -c ../lib/alloca-bt.S | 205 | .\tcc -B. -m%1 -c ../lib/alloca-bt.S |
| 202 | .\tcc -B. -m%1 -c ../lib/stdatomic.c | 206 | .\tcc -B. -m%1 -c ../lib/stdatomic.c |
| 207 | .\tcc -B. -m%1 -c ../lib/atomic.S | ||
| 203 | .\tcc -B. -m%1 -c ../lib/builtin.c | 208 | .\tcc -B. -m%1 -c ../lib/builtin.c |
| 204 | .\tcc -B. -m%1 -ar lib/%2libtcc1.a libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o alloca.o alloca-bt.o stdatomic.o builtin.o | 209 | .\tcc -B. -m%1 -ar lib/%2libtcc1.a libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o |
| 205 | .\tcc -B. -m%1 -c ../lib/bcheck.c -o lib/%2bcheck.o -bt -I.. | 210 | .\tcc -B. -m%1 -c ../lib/bcheck.c -o lib/%2bcheck.o -bt -I.. |
| 206 | .\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o | 211 | .\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o |
| 207 | .\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o | 212 | .\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o |
| @@ -376,10 +376,16 @@ extern "C" { · 375 unmodified lines | |||
| 376 | _CRTIMP int __cdecl _set_error_mode(int _Mode); | 376 | _CRTIMP int __cdecl _set_error_mode(int _Mode); |
| 377 | void __cdecl srand(unsigned int _Seed); | 377 | void __cdecl srand(unsigned int _Seed); |
| 378 | double __cdecl strtod(const char *_Str,char **_EndPtr); | 378 | double __cdecl strtod(const char *_Str,char **_EndPtr); |
| 379 | float __cdecl strtof(const char *nptr, char **endptr); | ||
| 380 | #if !defined __NO_ISOCEXT /* in libmingwex.a */ | 379 | #if !defined __NO_ISOCEXT /* in libmingwex.a */ |
| 380 | #if __TINYC__ | ||
| 381 | __CRT_INLINE float __cdecl strtof (const char *p, char ** e) { return strtod(p, e); } | ||
| 382 | __CRT_INLINE long double __cdecl strtold(const char *p, char ** e) { return strtod(p, e); } | ||
| 383 | #else | ||
| 381 | float __cdecl strtof (const char * __restrict__, char ** __restrict__); | 384 | float __cdecl strtof (const char * __restrict__, char ** __restrict__); |
| 382 | long double __cdecl strtold(const char * __restrict__, char ** __restrict__); | 385 | long double __cdecl strtold(const char * __restrict__, char ** __restrict__); |
| 386 | #endif | ||
| 387 | #else | ||
| 388 | float __cdecl strtof(const char *nptr, char **endptr); | ||
| 383 | #endif /* __NO_ISOCEXT */ | 389 | #endif /* __NO_ISOCEXT */ |
| 384 | _CRTIMP double __cdecl _strtod_l(const char *_Str,char **_EndPtr,_locale_t _Locale); | 390 | _CRTIMP double __cdecl _strtod_l(const char *_Str,char **_EndPtr,_locale_t _Locale); |
| 385 | long __cdecl strtol(const char *_Str,char **_EndPtr,int _Radix); | 391 | long __cdecl strtol(const char *_Str,char **_EndPtr,int _Radix); |
| @@ -859,7 +859,7 @@ extern "C" { · 858 unmodified lines | |||
| 859 | } | 859 | } |
| 860 | #endif | 860 | #endif |
| 861 | 861 | ||
| 862 | #ifndef !defined (InterlockedAnd64) | 862 | #ifndef InterlockedAnd64 |
| 863 | #define InterlockedAnd64 InterlockedAnd64_Inline | 863 | #define InterlockedAnd64 InterlockedAnd64_Inline |
| 864 | 864 | ||
| 865 | __CRT_INLINE LONGLONG InterlockedAnd64_Inline (LONGLONG volatile *Destination,LONGLONG Value) { | 865 | __CRT_INLINE LONGLONG InterlockedAnd64_Inline (LONGLONG volatile *Destination,LONGLONG Value) { |