History

tcc.c:main() free all & etc...

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)

grischka committed 1 year ago

Commit deb7a3f1 parent 8845b6c17 files · +187 −162Browse files

Unified · Split

17 files
  1. .github/workflows/build.yml +27 −3
  2. i386-gen.c +1 −0
  3. lib/alloca-bt.S +5 −7
  4. lib/alloca.S +4 −5
  5. libtcc.c +17 −28
  6. tcc.c +21 −22
  7. tcc.h +4 −5
  8. tccelf.c +12 −13
  9. tccgen.c +51 −45
  10. tccpp.c +14 −18
  11. tccrun.c +9 −4
  12. tcctools.c +6 −6
  13. tests/Makefile +1 −1
  14. tests/tests2/Makefile +1 −2
  15. win32/build-tcc.bat +6 −1
  16. win32/include/stdlib.h +7 −1
  17. win32/include/winapi/winbase.h +1 −1
.github/workflows/build.yml+27−3
@@ -31,7 +31,7 @@ jobs: · 30 unmodified lines
3131
3232 test-x86_64-win32:
3333 runs-on: windows-2025
34− timeout-minutes: 4
34+ timeout-minutes: 6
3535 steps:
3636 - uses: actions/checkout@v4
3737 - name: make & test tcc (x86_64-win32)
@@ -44,10 +44,22 @@ jobs: · 6 unmodified lines
4444 C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc"
4545 echo ::endgroup::
4646 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
4759
4860 test-i386-win32:
4961 runs-on: windows-2025
50− timeout-minutes: 4
62+ timeout-minutes: 6
5163 steps:
5264 - uses: actions/checkout@v4
5365 - name: make & test tcc (i386-win32)
@@ -59,7 +71,19 @@ jobs: · 5 unmodified lines
5971 set CHERE_INVOKING=yes
6072 C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc"
6173 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
6387
6488 test-armv7-linux:
6589 runs-on: ubuntu-22.04
i386-gen.c+1−0
@@ -417,6 +417,7 @@ ST_FUNC void gfunc_call(int nb_args) · 416 unmodified lines
417417 /* allocate the necessary size on stack */
418418 #ifdef TCC_TARGET_PE
419419 if (size >= 4096) {
420+ save_reg(TREG_EDX);
420421 r = get_reg(RC_EAX);
421422 oad(0x68, size); // push size
422423 /* cannot call normal 'alloca' with bound checking */
lib/alloca-bt.S+5−7
@@ -17,13 +17,13 @@ _(__bound_alloca): · 16 unmodified lines
1717 mov %eax, %ecx
1818 test %eax,%eax
1919 jz p6
20− add $15+1,%eax
21− and $-16,%eax
20+ add $3 + 1,%eax
21+ and $-4,%eax
2222
2323 #ifdef _WIN32
2424 p4:
2525 cmp $4096,%eax
26− jbe p5
26+ jb p5
2727 test %eax,-4096(%esp)
2828 sub $4096,%esp
2929 sub $4096,%eax
@@ -33,7 +33,6 @@ p5: · 3 unmodified lines
3333 #endif
3434
3535 sub %eax,%esp
36− and $-16,%esp
3736 mov %esp,%eax
3837
3938 push %edx
@@ -72,12 +71,11 @@ _(__bound_alloca_nr): · 32 unmodified lines
7271 #else
7372 pop %rdx
7473 mov %rdi,%rax
74+ and %eax,%eax
75+ jz p3
7576 mov %rax,%rsi # size, a second parm to the __bound_new_region
76−
7777 add $15 + 1,%rax # add one extra to separate regions
7878 and $-16,%rax
79− jz p3
80−
8179
8280 sub %rax,%rsp
8381 mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
lib/alloca.S+4−5
@@ -15,14 +15,14 @@ _(alloca): · 14 unmodified lines
1515 _(__alloca):
1616 pop %edx
1717 pop %eax
18− add $15,%eax
19− and $-16,%eax
18+ add $3,%eax
19+ and $-4,%eax
2020 jz p3
2121
2222 #ifdef _WIN32
2323 p1:
2424 cmp $4096,%eax
25− jbe p2
25+ jb p2
2626 test %eax,-4096(%esp)
2727 sub $4096,%esp
2828 sub $4096,%eax
@@ -30,7 +30,6 @@ p1: · 1 unmodified line
3030 p2:
3131 #endif
3232 sub %eax,%esp
33− and $-16,%esp
3433 mov %esp,%eax
3534 p3:
3635 push %edx
@@ -55,7 +54,7 @@ _(alloca): · 18 unmodified lines
5554 #ifdef _WIN32
5655 p1:
5756 cmp $4096,%rax
58− jbe p2
57+ jb p2
5958 test %rax,-4096(%rsp)
6059 sub $4096,%rsp
6160 sub $4096,%rax
libtcc.c+17−28
@@ -804,7 +804,6 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd) · 803 unmodified lines
804804 s1->error_set_jmp_enabled = 1;
805805
806806 if (setjmp(s1->error_jmp_buf) == 0) {
807− s1->nb_errors = 0;
808807
809808 if (fd == -1) {
810809 int len = strlen(str);
@@ -1816,8 +1815,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 1005 unmodified lines
18161815 const TCCOption *popt;
18171816 const char *optarg, *r;
18181817 const char *run = NULL;
1819− int x;
1820− int tool = 0, arg_start = 0, not_empty = 0, optind = 1;
1818+ int optind = 1, empty = 1, x;
18211819 char **argv = *pargv;
18221820 int argc = *pargc;
18231821
@@ -1836,21 +1834,16 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 12 unmodified lines
18361834 continue;
18371835 }
18381836 optind++;
1839− if (tool) { /* ignore all except -v and @listfile */
1840− s->verbose += !strcmp(r, "-v");
1841− continue;
1842− }
1843−
18441837 if (r[0] != '-' || r[1] == '\0') { /* file or '-' (stdin) */
18451838 args_parser_add_file(s, r, s->filetype);
1846− not_empty = 1;
1839+ empty = 0;
18471840 dorun:
18481841 if (run) {
18491842 /* tcc -run <file> <args...> */
1850− if (tcc_set_options(s, run))
1843+ if (tcc_set_options(s, run) < 0)
18511844 return -1;
1852− arg_start = optind - 1; /* argv[0] will be <file> */
1853− break;
1845+ x = 0;
1846+ goto extra_action;
18541847 }
18551848 continue;
18561849 }
@@ -1923,14 +1916,16 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 66 unmodified lines
19231916 case TCC_OPTION_g:
19241917 s->do_debug = 2;
19251918 s->dwarf = CONFIG_DWARF_VERSION;
1919+ g_redo:
19261920 if (strstart("dwarf", &optarg)) {
19271921 s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;
19281922 } else if (0 == strcmp("stabs", optarg)) {
19291923 s->dwarf = 0;
19301924 } else if (isnum(*optarg)) {
1931− x = *optarg - '0';
1925+ x = *optarg++ - '0';
19321926 /* -g0 = no info, -g1 = lines/functions only, -g2 = full info */
19331927 s->do_debug = x > 2 ? 2 : x == 0 && s->do_backtrace ? 1 : x;
1928+ goto g_redo;
19341929 #ifdef TCC_TARGET_PE
19351930 } else if (0 == strcmp(".pdb", optarg)) {
19361931 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
20302025 }
20312026 break;
20322027 case TCC_OPTION_W:
2033− s->warn_none = 0;
20342028 if (optarg[0] && set_flag(s, options_W, optarg) < 0)
20352029 goto unsupported_option;
20362030 break;
@@ -2141,29 +2135,24 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) · 104 unmodified lines
21412135 case TCC_OPTION_ar:
21422136 x = OPT_AR;
21432137 extra_action:
2144− arg_start = optind - 1;
2145− if (not_empty)
2138+ if (NULL == argv[0]) /* from tcc_set_options() */
2139+ return -1;
2140+ if (!empty && x)
21462141 return tcc_error_noabort("cannot parse %s here", r);
2147− tool = x;
2148− break;
2142+ --optind;
2143+ *pargc = argc - optind;
2144+ *pargv = argv + optind;
2145+ return x;
21492146 default:
21502147 unsupported_option:
21512148 tcc_warning_c(warn_unsupported)("unsupported option '%s'", r);
21522149 break;
21532150 }
2154− not_empty = 1;
2151+ empty = 0;
21552152 }
2156−
21572153 if (s->link_optind < s->link_argc)
21582154 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() */
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)
2155+ if (!empty)
21672156 return 0;
21682157 if (s->verbose == 2)
21692158 return OPT_PRINT_DIRS;
tcc.c+21−22
@@ -283,51 +283,51 @@ static unsigned getclock_ms(void) · 282 unmodified lines
283283 #endif
284284 }
285285
286−int main(int argc0, char **argv0)
286+int main(int argc, char **argv)
287287 {
288288 TCCState *s, *s1;
289289 int ret, opt, n = 0, t = 0, done;
290290 unsigned start_time = 0, end_time = 0;
291291 const char *first_file;
292− int argc; char **argv;
292+ int argc0 = argc;
293+ char **argv0 = argv;
293294 FILE *ppfp = stdout;
294295
295296 redo:
296297 argc = argc0, argv = argv0;
297298 s = s1 = tcc_new();
298299 opt = tcc_parse_args(s, &argc, &argv);
299− if (opt < 0)
300− return 1;
301300
302301 if (n == 0) {
302+ ret = 0;
303303 if (opt == OPT_HELP) {
304304 fputs(help, stdout);
305− if (!s->verbose)
306− return 0;
307− ++opt;
308− }
309− if (opt == OPT_HELP2) {
310− fputs(help2, stdout);
311− return 0;
312− }
313− if (opt == OPT_M32 || opt == OPT_M64)
314− return tcc_tool_cross(s, argv, opt);
315− if (s->verbose)
305+ if (s->verbose)
306+ goto help2;
307+ } else if (opt == OPT_HELP2) {
308+ help2: fputs(help2, stdout);
309+ } else if (opt == OPT_M32 || opt == OPT_M64) {
310+ ret = tcc_tool_cross(argv, opt);
311+ } else if (s->verbose)
316312 printf("%s", version);
313+
317314 if (opt == OPT_AR)
318− return tcc_tool_ar(s, argc, argv);
315+ ret = tcc_tool_ar(argc, argv);
319316 #ifdef TCC_TARGET_PE
320317 if (opt == OPT_IMPDEF)
321− return tcc_tool_impdef(s, argc, argv);
318+ ret = tcc_tool_impdef(argc, argv);
322319 #endif
323− if (opt == OPT_V)
324− return 0;
325320 if (opt == OPT_PRINT_DIRS) {
326321 /* initialize search dirs */
327322 set_environment(s);
328323 tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
329324 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;
331331 }
332332
333333 if (s->nb_files == 0) {
@@ -345,7 +345,7 @@ redo: · 11 unmodified lines
345345 tcc_error_noabort("cannot specify output file with -c many files");
346346 }
347347 if (s->nb_errors)
348− return 1;
348+ goto err;
349349 if (s->do_bench)
350350 start_time = getclock_ms();
351351 }
@@ -419,7 +419,6 @@ redo: · 67 unmodified lines
419419 tcc_print_stats(s, end_time - start_time);
420420
421421 tcc_delete(s);
422−
423422 if (!done)
424423 goto redo;
425424 if (ppfp && ppfp != stdout)
tcc.h+4−5
@@ -95,15 +95,14 @@ extern long double strtold (const char *__nptr, char **__endptr); · 94 unmodified lines
9595 # define O_BINARY 0
9696 #endif
9797
98−#ifndef offsetof
99−#define offsetof(type, field) ((size_t) &((type *)0)->field)
100−#endif
101−
10298 #ifdef __clang__ // clang -fsanitize compains about: NULL+value
103−#undef offsetof
10499 #define offsetof(type, field) __builtin_offsetof(type, field)
105100 #endif
106101
102+#ifndef offsetof
103+#define offsetof(type, field) ((size_t) &((type *)0)->field)
104+#endif
105+
107106 #ifndef countof
108107 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
109108 #endif
tccelf.c+12−13
@@ -318,8 +318,7 @@ ST_FUNC size_t section_add(Section *sec, addr_t size, int align) · 317 unmodified lines
318318 ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
319319 {
320320 size_t offset = section_add(sec, size, 1);
321− // clang -fsanitize compains about: NULL+value
322− return sec->data ? sec->data + offset : (void *)offset;
321+ return sec->data + offset;
323322 }
324323
325324 #ifndef ELF_OBJ_ONLY
@@ -1598,7 +1597,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1) · 1272 unmodified lines
15981597
15991598 s = data_section;
16001599 /* Align to PTR_SIZE */
1601− section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
1600+ section_add(s, 0, PTR_SIZE);
16021601 o = s->data_offset;
16031602 /* create a struct rt_context (see tccrun.c) */
16041603 if (s1->dwarf) {
@@ -2837,7 +2836,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 1232 unmodified lines
28372836 int textrel, got_sym, dt_flags_1;
28382837
28392838 file_type = s1->output_type;
2840− s1->nb_errors = 0;
28412839 ret = -1;
28422840 interp = dynstr = dynamic = NULL;
28432841 sec_order = NULL;
@@ -3030,7 +3028,6 @@ static int elf_output_obj(TCCState *s1, const char *filename) · 186 unmodified lines
30303028 {
30313029 Section *s;
30323030 int i, ret, file_offset;
3033− s1->nb_errors = 0;
30343031 /* Allocate strings for section names */
30353032 alloc_sec_names(s1, 1);
30363033 file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4;
@@ -3049,6 +3046,7 @@ static int elf_output_obj(TCCState *s1, const char *filename) · 12 unmodified lines
30493046
30503047 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
30513048 {
3049+ s->nb_errors = 0;
30523050 if (s->test_coverage)
30533051 tcc_tcov_add_file(s, filename);
30543052 if (s->output_type == TCC_OUTPUT_OBJ)
@@ -3254,21 +3252,19 @@ invalid: · 199 unmodified lines
32543252 s->sh_entsize = sh->sh_entsize;
32553253 sm_table[i].new_section = 1;
32563254 found:
3255+ size = sh->sh_size;
32573256 /* align start of section */
3258− s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
3257+ offset = section_add(s, size, sh->sh_addralign);
32593258 if (sh->sh_addralign > s->sh_addralign)
32603259 s->sh_addralign = sh->sh_addralign;
3261− sm_table[i].offset = s->data_offset;
3260+ sm_table[i].offset = offset;
32623261 sm_table[i].s = s;
32633262 /* concatenate sections */
3264− size = sh->sh_size;
3265− if (sh->sh_type != SHT_NOBITS) {
3263+ if (sh->sh_type != SHT_NOBITS && size) {
32663264 unsigned char *ptr;
32673265 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
3268− ptr = section_ptr_add(s, size);
3266+ ptr = s->data + offset;
32693267 full_read(fd, ptr, size);
3270− } else {
3271− s->data_offset += size;
32723268 }
32733269 #if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
32743270 /* align code sections to instruction lenght */
@@ -3310,6 +3306,9 @@ invalid: · 35 unmodified lines
33103306 }
33113307 }
33123308
3309+ if (!symtab)
3310+ goto done;
3311+
33133312 /* resolve symbols */
33143313 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
33153314
@@ -3405,7 +3404,7 @@ invalid: · 89 unmodified lines
34053404 break;
34063405 }
34073406 }
3408−
3407+ done:
34093408 ret = 0;
34103409 the_end:
34113410 tcc_free(symtab);
tccgen.c+51−45
@@ -2963,13 +2963,13 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) · 2962 unmodified lines
29632963 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
29642964 type.t |= VT_UNSIGNED;
29652965 } else {
2966− int t1_bit = BIT_SIZE(t1) <= 31 ? VT_BITFIELD : 0;
2967− int t2_bit = BIT_SIZE(t2) <= 31 ? VT_BITFIELD : 0;
29682966 /* integer operations */
29692967 type.t = VT_INT | (VT_LONG & (t1 | t2));
29702968 /* convert to unsigned if it does not fit in an integer */
2971− if ((t1 & (VT_BTYPE | VT_UNSIGNED | t1_bit)) == (VT_INT | VT_UNSIGNED) ||
2972− (t2 & (VT_BTYPE | VT_UNSIGNED | t2_bit)) == (VT_INT | VT_UNSIGNED))
2969+ if (((t1 & (VT_BTYPE | VT_UNSIGNED)) == (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)))
29732973 type.t |= VT_UNSIGNED;
29742974 }
29752975 if (dest)
@@ -5615,6 +5615,8 @@ ST_FUNC void unary(void) · 2639 unmodified lines
56155615 as statement expressions can't ever be entered from the
56165616 outside, so any reactivation of code emission (from labels
56175617 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;
56185620 block(STMT_EXPR);
56195621 /* If the statement expr can be entered, then we retain the current
56205622 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
70367038 struct scope o;
70377039 Sym *s;
70387040
7039− if (flags & STMT_EXPR) {
7040− /* default return value is (void) */
7041− vpushi(0);
7042− vtop->type.t = VT_VOID;
7043− }
7044−
70457041 again:
70467042 t = tok;
70477043 /* If the token carries a value, next() might destroy it. Only with
@@ -7057,8 +7053,8 @@ again: · 9 unmodified lines
70577053 new_scope_s(&o);
70587054 skip('(');
70597055 gexpr();
7060− skip(')');
70617056 a = gvtst(1, 0);
7057+ skip(')');
70627058 block(0);
70637059 if (tok == TOK_ELSE) {
70647060 d = gjmp(0);
@@ -7076,8 +7072,8 @@ again: · 11 unmodified lines
70767072 d = gind();
70777073 skip('(');
70787074 gexpr();
7079− skip(')');
70807075 a = gvtst(1, 0);
7076+ skip(')');
70817077 b = 0;
70827078 lblock(&a, &b);
70837079 gjmp_addr(d);
@@ -7105,8 +7101,6 @@ again: · 21 unmodified lines
71057101 while (tok != '}') {
71067102 decl(VT_LOCAL);
71077103 if (tok != '}') {
7108− if (flags & STMT_EXPR)
7109− vpop();
71107104 block(flags | STMT_COMPOUND);
71117105 }
71127106 }
@@ -7208,9 +7202,9 @@ again: · 95 unmodified lines
72087202 skip(TOK_WHILE);
72097203 skip('(');
72107204 gexpr();
7205+ c = gvtst(0, 0);
72117206 skip(')');
72127207 skip(';');
7213− c = gvtst(0, 0);
72147208 gsym_addr(c, d);
72157209 gsym(a);
72167210 prev_scope_s(&o);
@@ -7228,9 +7222,9 @@ again: · 11 unmodified lines
72287222 new_scope_s(&o);
72297223 skip('(');
72307224 gexpr();
7231− skip(')');
72327225 if (!is_integer_btype(vtop->type.t & VT_BTYPE))
72337226 tcc_error("switch value not an integer");
7227+ skip(')');
72347228 sw->sv = *vtop--; /* save switch value */
72357229 a = 0;
72367230 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
82948288 if (type->t & VT_VLA) {
82958289 int a;
82968290
8291+ if (has_init)
8292+ tcc_error("variable length array cannot be initialized");
8293+
82978294 if (NODATA_WANTED)
82988295 goto no_alloc;
82998296
@@ -8513,6 +8510,27 @@ static void do_Static_assert(void) · 213 unmodified lines
85138510 skip(';');
85148511 }
85158512
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+
85168534 /* 'l' is VT_LOCAL or VT_CONST to define default storage type
85178535 or VT_CMP if parsing old style parameter list
85188536 or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */
@@ -8559,17 +8577,17 @@ static int decl(int l) · 40 unmodified lines
85598577 }
85608578
85618579 if (tok == ';') {
8562− if ((btype.t & VT_BTYPE) == VT_STRUCT) {
8563− v = btype.ref->v;
8564− if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
8565− tcc_warning("unnamed struct/union that defines no instances");
8566− next();
8567− continue;
8568− }
8569− if (IS_ENUM(btype.t)) {
8570− next();
8571− continue;
8572− }
8580+ if ((btype.t & VT_BTYPE) == VT_STRUCT
8581+ && (btype.ref->v & ~SYM_STRUCT) < SYM_FIRST_ANOM)
8582+ ; /* struct decl with named tag */
8583+ else if (IS_ENUM(btype.t))
8584+ ; /* enum decl */
8585+ else
8586+ tcc_warning("useless type defines no instances");
8587+ if (l == VT_JMP)
8588+ return 1;
8589+ next();
8590+ continue;
85738591 }
85748592
85758593 while (1) { /* iterate thru each declaration */
@@ -8637,20 +8655,7 @@ static int decl(int l) · 61 unmodified lines
86378655 }
86388656
86398657 #ifdef TCC_TARGET_PE
8640− if (ad.a.dllimport || ad.a.dllexport) {
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− }
8658+ pe_check_linkage(&type, &ad);
86548659 #endif
86558660 if (tok == '{') {
86568661 if (l != VT_CONST)
@@ -8700,6 +8705,7 @@ static int decl(int l) · 43 unmodified lines
87008705 }
87018706 break;
87028707 } else {
8708+ has_init = 0;
87038709 if (l == VT_CMP) {
87048710 /* find parameter in function parameter list */
87058711 for (sym = func_vt.ref->next; sym; sym = sym->next)
@@ -8747,9 +8753,9 @@ static int decl(int l) · 41 unmodified lines
87478753 /* not lvalue if array */
87488754 r |= VT_LVAL;
87498755 }
8750− has_init = (tok == '=');
8751− if (has_init && (type.t & VT_VLA))
8752− tcc_error("variable length array cannot be initialized");
8756+
8757+ if (tok == '=')
8758+ has_init = 1;
87538759
87548760 if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST))
87558761 || (type.t & VT_BTYPE) == VT_FUNC
@@ -8789,7 +8795,7 @@ static int decl(int l) · 33 unmodified lines
87898795 }
87908796 if (tok != ',') {
87918797 if (l == VT_JMP)
8792− return 1;
8798+ return has_init ? v : 1;
87938799 skip(';');
87948800 break;
87958801 }
tccpp.c+14−18
@@ -117,16 +117,6 @@ ST_FUNC void expect(const char *msg) · 116 unmodified lines
117117
118118 #define USE_TAL
119119
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−
130120 #ifndef USE_TAL
131121 #define tal_free(al, p) tcc_free(p)
132122 #define tal_realloc(al, p, size) tcc_realloc(p, size)
@@ -143,7 +133,6 @@ ST_FUNC void expect(const char *msg) · 10 unmodified lines
143133 #define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
144134 #define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__)
145135 #define TAL_DEBUG_PARAMS , const char *file, int line
146−#define TAL_DEBUG_FILE_LEN 40
147136 #endif
148137
149138 #define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */
@@ -167,13 +156,16 @@ typedef struct TinyAlloc { · 17 unmodified lines
167156 } TinyAlloc;
168157
169158 typedef struct tal_header_t {
170− ALIGNED(POINTER_SIZE) unsigned size;
159+ size_t size; /* word align */
171160 #ifdef TAL_DEBUG
172161 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];
174163 #endif
175164 } tal_header_t;
176165
166+#define TAL_ALIGN(size) \
167+ (((size) + (sizeof (size_t) - 1)) & ~(sizeof (size_t) - 1))
168+
177169 /* ------------------------------------------------------------------------- */
178170
179171 static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size)
@@ -208,7 +200,7 @@ tail_call: · 28 unmodified lines
208200 tal_header_t *header = (tal_header_t *)p;
209201 if (header->line_num > 0) {
210202 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);
212204 }
213205 p += header->size + sizeof(tal_header_t);
214206 }
@@ -256,7 +248,7 @@ static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_ · 41 unmodified lines
256248 tal_header_t *header;
257249 void *ret;
258250 int is_own;
259− unsigned adj_size = (size + POINTER_SIZE - 1) & -POINTER_SIZE;
251+ unsigned adj_size = TAL_ALIGN(size);
260252 TinyAlloc *al = *pal;
261253
262254 tail_call:
@@ -266,9 +258,8 @@ tail_call: · 3 unmodified lines
266258 header = (tal_header_t *)al->p;
267259 header->size = adj_size;
268260 #ifdef TAL_DEBUG
269− { int ofs = strlen(file) - TAL_DEBUG_FILE_LEN;
270− strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN);
271− header->file_name[TAL_DEBUG_FILE_LEN] = 0;
261+ { int ofs = strlen(file) + 1 - sizeof header->file_name;
262+ strcpy(header->file_name, file + (ofs > 0 ? ofs : 0));
272263 header->line_num = line; }
273264 #endif
274265 ret = al->p + sizeof(tal_header_t);
@@ -2986,6 +2977,11 @@ maybe_newline: · 2711 unmodified lines
29862977 tok = c;
29872978 p++;
29882979 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+ }
29892985 default:
29902986 if (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */
29912987 goto parse_ident_fast;
tccrun.c+9−4
@@ -312,6 +312,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff) · 311 unmodified lines
312312 addr_t mem, addr;
313313
314314 if (NULL == ptr) {
315+ s1->nb_errors = 0;
315316 #ifdef TCC_TARGET_PE
316317 pe_output_file(s1, NULL);
317318 #else
@@ -495,10 +496,6 @@ static void bt_link(TCCState *s1) · 177 unmodified lines
495496 {
496497 #ifdef CONFIG_TCC_BACKTRACE
497498 rt_context *rc;
498−#ifdef CONFIG_TCC_BCHECK
499− void *p;
500−#endif
501−
502499 if (!s1->do_backtrace)
503500 return;
504501 rc = tcc_get_symbol(s1, "__rt_info");
@@ -511,6 +508,7 @@ static void bt_link(TCCState *s1) · 6 unmodified lines
511508 rc->prog_base &= 0xffffffff00000000ULL;
512509 #ifdef CONFIG_TCC_BCHECK
513510 if (s1->do_bounds_check) {
511+ void *p;
514512 if ((p = tcc_get_symbol(s1, "__bound_init")))
515513 ((void(*)(void*,int))p)(rc->bounds_start, 1);
516514 }
@@ -599,6 +597,13 @@ static void rt_exit(rt_frame *f, int code) · 82 unmodified lines
599597 s = rt_find_state(f);
600598 rt_post_sem();
601599 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
602607 if (code == 0)
603608 code = RT_EXIT_ZERO;
604609 ((void(*)(void*,int))s->run_lj)(s->run_jb, code);
tcctools.c+6−6
@@ -54,7 +54,7 @@ static int ar_usage(int ret) { · 53 unmodified lines
5454 return ret;
5555 }
5656
57−ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
57+ST_FUNC int tcc_tool_ar(int argc, char **argv)
5858 {
5959 static const ArHdr arhdr_init = {
6060 "/ ",
@@ -360,7 +360,7 @@ the_end: · 299 unmodified lines
360360
361361 #ifdef TCC_TARGET_PE
362362
363−ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
363+ST_FUNC int tcc_tool_impdef(int argc, char **argv)
364364 {
365365 int ret, v, i;
366366 char infile[260];
@@ -487,9 +487,9 @@ the_end: · 120 unmodified lines
487487
488488 #if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
489489
490−ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option)
490+ST_FUNC int tcc_tool_cross(char **argv, int option)
491491 {
492− tcc_error_noabort("-m%d not implemented.", option);
492+ fprintf(stderr, "tcc -m%d not implemented\n", option);
493493 return 1;
494494 }
495495
@@ -546,7 +546,7 @@ static int execvp_win32(const char *prog, char **argv) · 50 unmodified lines
546546 #define execvp execvp_win32
547547 #endif /* _WIN32 */
548548
549−ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target)
549+ST_FUNC int tcc_tool_cross(char **argv, int target)
550550 {
551551 char program[4096];
552552 char *a0 = argv[0];
@@ -565,7 +565,7 @@ ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target) · 12 unmodified lines
565565
566566 if (strcmp(a0, program))
567567 execvp(argv[0] = program, argv);
568− tcc_error_noabort("could not run '%s'", program);
568+ fprintf(stderr, "tcc: could not run '%s'\n", program);
569569 return 1;
570570 }
571571
tests/Makefile+1−1
@@ -79,7 +79,7 @@ endif · 78 unmodified lines
7979
8080 all test :
8181 @echo ------------ version ------------
82− @ASAN_OPTIONS=detect_leaks=0 $(TCC_LOCAL) -v
82+ @$(TCC_LOCAL) -v
8383 @$(MAKE) --no-print-directory -s clean
8484 @$(MAKE) --no-print-directory -s -r _all
8585
tests/tests2/Makefile+1−2
@@ -102,7 +102,6 @@ GEN-ALWAYS = · 101 unmodified lines
102102 112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \
103103 -e 's;[0-9A-Fa-fx]\{5,\};........;g' \
104104 -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g'
105−112_backtrace.test: LEAK=ASAN_OPTIONS=detect_leaks=0
106105
107106 # this test creates two DLLs and an EXE
108107 113_btdll.test: T1 = \
@@ -137,7 +136,7 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS)) · 28 unmodified lines
137136 @echo Test: $*...
138137 @$(call T1,$<) $(T3)
139138
140−T1 = $(LEAK) $(TCC) $(FLAGS) $(T2) $(ARGS)
139+T1 = $(TCC) $(FLAGS) $(T2) $(ARGS)
141140 T2 = $(if $(NORUN),$1 -o $(basename $@).exe && ./$(basename $@).exe,-run $1)
142141 T3 = $(FILTER) >$*.output 2>&1 || true \
143142 && diff -Nbu $(filter %.expect,$^) $*.output \
win32/build-tcc.bat+6−1
@@ -132,6 +132,10 @@ if %TX%==32 echo>> ..\config.h #ifdef TCC_TARGET_I386 · 131 unmodified lines
132132 echo>> ..\config.h #define CONFIG_TCC_CROSSPREFIX "%PX%-"
133133 echo>> ..\config.h #endif
134134
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+
135139 for %%f in (*tcc.exe *tcc.dll) do @del %%f
136140
137141 @if _%TCC_C%_==__ goto compiler_2parts
@@ -200,8 +204,9 @@ exit /B %ERRORLEVEL% · 62 unmodified lines
200204 .\tcc -B. -m%1 -c ../lib/alloca.S
201205 .\tcc -B. -m%1 -c ../lib/alloca-bt.S
202206 .\tcc -B. -m%1 -c ../lib/stdatomic.c
207+.\tcc -B. -m%1 -c ../lib/atomic.S
203208 .\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
205210 .\tcc -B. -m%1 -c ../lib/bcheck.c -o lib/%2bcheck.o -bt -I..
206211 .\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o
207212 .\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o
win32/include/stdlib.h+7−1
@@ -376,10 +376,16 @@ extern "C" { · 375 unmodified lines
376376 _CRTIMP int __cdecl _set_error_mode(int _Mode);
377377 void __cdecl srand(unsigned int _Seed);
378378 double __cdecl strtod(const char *_Str,char **_EndPtr);
379− float __cdecl strtof(const char *nptr, char **endptr);
380379 #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
381384 float __cdecl strtof (const char * __restrict__, char ** __restrict__);
382385 long double __cdecl strtold(const char * __restrict__, char ** __restrict__);
386+#endif
387+#else
388+ float __cdecl strtof(const char *nptr, char **endptr);
383389 #endif /* __NO_ISOCEXT */
384390 _CRTIMP double __cdecl _strtod_l(const char *_Str,char **_EndPtr,_locale_t _Locale);
385391 long __cdecl strtol(const char *_Str,char **_EndPtr,int _Radix);
win32/include/winapi/winbase.h+1−1
@@ -859,7 +859,7 @@ extern "C" { · 858 unmodified lines
859859 }
860860 #endif
861861
862−#ifndef !defined (InterlockedAnd64)
862+#ifndef InterlockedAnd64
863863 #define InterlockedAnd64 InterlockedAnd64_Inline
864864
865865 __CRT_INLINE LONGLONG InterlockedAnd64_Inline (LONGLONG volatile *Destination,LONGLONG Value) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t